在准备环境前提交次全部更改。
This commit is contained in:
@@ -10,19 +10,21 @@
|
||||
|
||||
## DDL Schema 文件
|
||||
|
||||
| 文件 | Schema | 说明 |
|
||||
|------|--------|------|
|
||||
| `schema_ODS_doc.sql` | `billiards_ods` | ODS 层表结构(含字段注释) |
|
||||
| `schema_dwd_doc.sql` | `billiards_dwd` | DWD 层表结构(维度 + 事实,含 SCD2 列) |
|
||||
| `schema_dws.sql` | `billiards_dws` | DWS 层表结构(汇总表 + 配置表) |
|
||||
| `schema_etl_admin.sql` | `etl_admin` | ETL 元数据(任务注册、游标、运行记录) |
|
||||
> CHANGE 2026-02-15 | 对齐新库 etl_feiqiu 六层架构,旧 schema 名已弃用
|
||||
|
||||
| 文件 | Schema(新) | 说明 |
|
||||
|------|-------------|------|
|
||||
| `schema_ODS_doc.sql` | `ods` | ODS 层表结构(含字段注释) |
|
||||
| `schema_dwd_doc.sql` | `dwd` | DWD 层表结构(维度 + 事实,含 SCD2 列) |
|
||||
| `schema_dws.sql` | `dws` | DWS 层表结构(汇总表 + 配置表) |
|
||||
| `schema_etl_admin.sql` | `meta` | ETL 元数据(任务注册、游标、运行记录) |
|
||||
| `schema_verify_perf_indexes.sql` | 各 Schema | 校验性能索引(仅索引 + ANALYZE) |
|
||||
|
||||
## 种子脚本
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `seed_ods_tasks.sql` | 注册 ODS 任务到 `etl_admin.etl_task` |
|
||||
| `seed_ods_tasks.sql` | 注册 ODS 任务到 `meta.etl_task` |
|
||||
| `seed_scheduler_tasks.sql` | 初始化调度任务配置 |
|
||||
| `seed_dws_config.sql` | DWS 配置数据(绩效档位、等级定价、技能映射等) |
|
||||
| `seed_index_parameters.sql` | 指数算法参数(WBI/NCI/RS/OS/MS/ML) |
|
||||
@@ -44,7 +46,7 @@ migrations/
|
||||
## Schema 约定
|
||||
|
||||
- 所有 DDL 使用 `CREATE TABLE IF NOT EXISTS`,支持幂等执行
|
||||
- 表名小写蛇形,带 Schema 前缀(如 `billiards_dwd.dim_member`)
|
||||
- 表名小写蛇形,带 Schema 前缀(如 `dwd.dim_member`)
|
||||
- 维度表包含 SCD2 列:`scd2_start_time`、`scd2_end_time`、`scd2_is_current`、`scd2_version`
|
||||
- ODS 表包含元数据列:`content_hash`、`payload`、`fetched_at`、`source_file`
|
||||
- 金额字段统一 `NUMERIC(12,2)`,ID 字段统一 `BIGINT`
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
-- 迁移脚本:为 ODS 表添加"取最新版本"复合索引
|
||||
-- 支持 DISTINCT ON (pk) ORDER BY pk, fetched_at DESC 查询模式
|
||||
-- 注意:CREATE INDEX CONCURRENTLY 不能在事务块内执行,需逐条手动运行或用支持单语句模式的工具
|
||||
-- 日期:2026-02-17
|
||||
-- 关联需求:ods-dedup-standardize Requirements 6.1, 6.2, 6.3
|
||||
|
||||
-- 1. assistant_accounts_master (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_assistant_accounts_master_latest
|
||||
ON ods.assistant_accounts_master (id, fetched_at DESC);
|
||||
|
||||
-- 2. settlement_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_settlement_records_latest
|
||||
ON ods.settlement_records (id, fetched_at DESC);
|
||||
|
||||
-- 3. table_fee_transactions (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_table_fee_transactions_latest
|
||||
ON ods.table_fee_transactions (id, fetched_at DESC);
|
||||
|
||||
-- 4. assistant_service_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_assistant_service_records_latest
|
||||
ON ods.assistant_service_records (id, fetched_at DESC);
|
||||
|
||||
-- 5. assistant_cancellation_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_assistant_cancellation_records_latest
|
||||
ON ods.assistant_cancellation_records (id, fetched_at DESC);
|
||||
|
||||
-- 6. store_goods_sales_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_store_goods_sales_records_latest
|
||||
ON ods.store_goods_sales_records (id, fetched_at DESC);
|
||||
|
||||
-- 7. payment_transactions (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_payment_transactions_latest
|
||||
ON ods.payment_transactions (id, fetched_at DESC);
|
||||
|
||||
-- 8. refund_transactions (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_refund_transactions_latest
|
||||
ON ods.refund_transactions (id, fetched_at DESC);
|
||||
|
||||
-- 9. platform_coupon_redemption_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_platform_coupon_redemption_records_latest
|
||||
ON ods.platform_coupon_redemption_records (id, fetched_at DESC);
|
||||
|
||||
-- 10. member_profiles (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_member_profiles_latest
|
||||
ON ods.member_profiles (id, fetched_at DESC);
|
||||
|
||||
-- 11. member_stored_value_cards (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_member_stored_value_cards_latest
|
||||
ON ods.member_stored_value_cards (id, fetched_at DESC);
|
||||
|
||||
-- 12. member_balance_changes (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_member_balance_changes_latest
|
||||
ON ods.member_balance_changes (id, fetched_at DESC);
|
||||
|
||||
-- 13. recharge_settlements (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_recharge_settlements_latest
|
||||
ON ods.recharge_settlements (id, fetched_at DESC);
|
||||
|
||||
-- 14. group_buy_packages (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_group_buy_packages_latest
|
||||
ON ods.group_buy_packages (id, fetched_at DESC);
|
||||
|
||||
-- 15. group_buy_redemption_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_group_buy_redemption_records_latest
|
||||
ON ods.group_buy_redemption_records (id, fetched_at DESC);
|
||||
|
||||
-- 16. goods_stock_summary (pk: siteGoodsId)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_goods_stock_summary_latest
|
||||
ON ods.goods_stock_summary (siteGoodsId, fetched_at DESC);
|
||||
|
||||
-- 17. goods_stock_movements (pk: siteGoodsStockId)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_goods_stock_movements_latest
|
||||
ON ods.goods_stock_movements (siteGoodsStockId, fetched_at DESC);
|
||||
|
||||
-- 18. site_tables_master (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_site_tables_master_latest
|
||||
ON ods.site_tables_master (id, fetched_at DESC);
|
||||
|
||||
-- 19. stock_goods_category_tree (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_stock_goods_category_tree_latest
|
||||
ON ods.stock_goods_category_tree (id, fetched_at DESC);
|
||||
|
||||
-- 20. store_goods_master (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_store_goods_master_latest
|
||||
ON ods.store_goods_master (id, fetched_at DESC);
|
||||
|
||||
-- 21. table_fee_discount_records (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_table_fee_discount_records_latest
|
||||
ON ods.table_fee_discount_records (id, fetched_at DESC);
|
||||
|
||||
-- 22. tenant_goods_master (pk: id)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_tenant_goods_master_latest
|
||||
ON ods.tenant_goods_master (id, fetched_at DESC);
|
||||
|
||||
-- 23. settlement_ticket_details (pk: orderSettleId)
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_ods_settlement_ticket_details_latest
|
||||
ON ods.settlement_ticket_details (orderSettleId, fetched_at DESC);
|
||||
@@ -82,18 +82,23 @@ COMMENT ON VIEW app.v_assistant IS '助教视图:封装 core.dim_assistant。'
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 4. v_assistant_daily — 助教日明细视图
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- CHANGE 2026-02-15 | 修复视图列名,对齐 dws.dws_assistant_daily_detail 实际表结构
|
||||
CREATE OR REPLACE VIEW app.v_assistant_daily AS
|
||||
SELECT
|
||||
d.id,
|
||||
d.site_id,
|
||||
d.tenant_id,
|
||||
d.assistant_id,
|
||||
d.assistant_nickname,
|
||||
d.stat_date,
|
||||
d.total_service_hours,
|
||||
d.total_service_count,
|
||||
d.total_revenue,
|
||||
d.basic_hours,
|
||||
d.extra_hours,
|
||||
d.tip_hours,
|
||||
d.total_hours,
|
||||
d.base_hours,
|
||||
d.bonus_hours,
|
||||
d.room_hours,
|
||||
d.total_ledger_amount,
|
||||
d.unique_customers,
|
||||
d.unique_tables,
|
||||
d.created_at
|
||||
FROM dws.dws_assistant_daily_detail d;
|
||||
|
||||
@@ -102,18 +107,27 @@ COMMENT ON VIEW app.v_assistant_daily IS '助教日明细视图:封装 dws.dws
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 5. v_finance_daily — 财务日报视图
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- CHANGE 2026-02-15 | 修复视图列名,对齐 dws.dws_finance_daily_summary 实际表结构
|
||||
CREATE OR REPLACE VIEW app.v_finance_daily AS
|
||||
SELECT
|
||||
f.id,
|
||||
f.site_id,
|
||||
f.tenant_id,
|
||||
f.stat_date,
|
||||
f.total_revenue,
|
||||
f.table_fee_revenue,
|
||||
f.goods_revenue,
|
||||
f.assistant_revenue,
|
||||
f.recharge_revenue,
|
||||
f.total_orders,
|
||||
f.total_customers,
|
||||
f.gross_amount,
|
||||
f.table_fee_amount,
|
||||
f.goods_amount,
|
||||
f.assistant_pd_amount,
|
||||
f.assistant_cx_amount,
|
||||
f.discount_total,
|
||||
f.confirmed_income,
|
||||
f.cash_inflow_total,
|
||||
f.recharge_count,
|
||||
f.recharge_total,
|
||||
f.order_count,
|
||||
f.member_order_count,
|
||||
f.guest_order_count,
|
||||
f.avg_order_amount,
|
||||
f.created_at
|
||||
FROM dws.dws_finance_daily_summary f;
|
||||
|
||||
@@ -122,16 +136,23 @@ COMMENT ON VIEW app.v_finance_daily IS '财务日报视图:封装 dws.dws_fina
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 6. v_member_consumption — 会员消费汇总视图
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- CHANGE 2026-02-15 | 修复视图列名,对齐 dws.dws_member_consumption_summary 实际表结构
|
||||
CREATE OR REPLACE VIEW app.v_member_consumption AS
|
||||
SELECT
|
||||
mc.id,
|
||||
mc.site_id,
|
||||
mc.tenant_id,
|
||||
mc.member_id,
|
||||
mc.total_visits,
|
||||
mc.total_consumption,
|
||||
mc.last_visit_date,
|
||||
mc.first_visit_date,
|
||||
mc.avg_consumption,
|
||||
mc.stat_date,
|
||||
mc.member_nickname,
|
||||
mc.card_grade_name,
|
||||
mc.total_visit_count,
|
||||
mc.total_consume_amount,
|
||||
mc.total_recharge_amount,
|
||||
mc.last_consume_date,
|
||||
mc.first_consume_date,
|
||||
mc.days_since_last,
|
||||
mc.customer_tier,
|
||||
mc.created_at
|
||||
FROM dws.dws_member_consumption_summary mc;
|
||||
|
||||
@@ -140,16 +161,21 @@ COMMENT ON VIEW app.v_member_consumption IS '会员消费汇总视图:封装 d
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 7. v_order_summary — 订单汇总视图
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- CHANGE 2026-02-15 | 修复视图列名,对齐 dws.dws_order_summary 实际表结构
|
||||
CREATE OR REPLACE VIEW app.v_order_summary AS
|
||||
SELECT
|
||||
os.site_id,
|
||||
os.order_settle_id,
|
||||
os.order_trade_no,
|
||||
os.order_date,
|
||||
os.tenant_id,
|
||||
os.member_id,
|
||||
os.total_amount,
|
||||
os.actual_amount,
|
||||
os.settle_time,
|
||||
os.pay_status,
|
||||
os.member_flag,
|
||||
os.order_original_amount,
|
||||
os.order_final_amount,
|
||||
os.total_paid_amount,
|
||||
os.refund_amount,
|
||||
os.net_income,
|
||||
os.created_at
|
||||
FROM dws.dws_order_summary os;
|
||||
|
||||
|
||||
@@ -2048,8 +2048,89 @@ COMMENT ON COLUMN ods.store_goods_sales_records.source_endpoint IS '【说明】
|
||||
COMMENT ON COLUMN ods.store_goods_sales_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- "取最新版本"复合索引
|
||||
-- 支持 DISTINCT ON (pk) ORDER BY pk, fetched_at DESC 查询模式
|
||||
-- 迁移脚本:migrations/2026-02-17__add_ods_latest_version_indexes.sql
|
||||
-- ============================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_member_profiles_latest
|
||||
ON ods.member_profiles (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_member_balance_changes_latest
|
||||
ON ods.member_balance_changes (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_member_stored_value_cards_latest
|
||||
ON ods.member_stored_value_cards (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_recharge_settlements_latest
|
||||
ON ods.recharge_settlements (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_settlement_records_latest
|
||||
ON ods.settlement_records (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_assistant_cancellation_records_latest
|
||||
ON ods.assistant_cancellation_records (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_assistant_accounts_master_latest
|
||||
ON ods.assistant_accounts_master (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_assistant_service_records_latest
|
||||
ON ods.assistant_service_records (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_site_tables_master_latest
|
||||
ON ods.site_tables_master (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_table_fee_discount_records_latest
|
||||
ON ods.table_fee_discount_records (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_table_fee_transactions_latest
|
||||
ON ods.table_fee_transactions (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_goods_stock_movements_latest
|
||||
ON ods.goods_stock_movements (siteGoodsStockId, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_stock_goods_category_tree_latest
|
||||
ON ods.stock_goods_category_tree (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_goods_stock_summary_latest
|
||||
ON ods.goods_stock_summary (siteGoodsId, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_payment_transactions_latest
|
||||
ON ods.payment_transactions (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_refund_transactions_latest
|
||||
ON ods.refund_transactions (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_platform_coupon_redemption_records_latest
|
||||
ON ods.platform_coupon_redemption_records (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_tenant_goods_master_latest
|
||||
ON ods.tenant_goods_master (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_group_buy_packages_latest
|
||||
ON ods.group_buy_packages (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_group_buy_redemption_records_latest
|
||||
ON ods.group_buy_redemption_records (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_settlement_ticket_details_latest
|
||||
ON ods.settlement_ticket_details (orderSettleId, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_store_goods_master_latest
|
||||
ON ods.store_goods_master (id, fetched_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ods_store_goods_sales_records_latest
|
||||
ON ods.store_goods_sales_records (id, fetched_at DESC);
|
||||
|
||||
|
||||
-- AI_CHANGELOG:
|
||||
-- - 日期: 2026-02-17
|
||||
-- - Prompt: ods-dedup-standardize Task 5.1
|
||||
-- - 直接原因: ODS 去重标准化需要 DISTINCT ON (pk) ORDER BY pk, fetched_at DESC 查询模式的索引支持
|
||||
-- - 变更摘要: 为全部 23 张 ODS 表添加 (业务主键, fetched_at DESC) 复合索引定义
|
||||
-- - 风险与验证: DDL 文档性文件,新环境初始化时自动创建索引;已有环境通过迁移脚本部署
|
||||
--
|
||||
-- - 日期: 2026-02-14
|
||||
-- - Prompt: P20260214-070000 — ODS 清理与文档标注(5 项任务)
|
||||
-- - 直接原因: option_name(store_goods_sales_records)和 able_site_transfer(member_stored_value_cards)在 API 中不存在且全 NULL,需从 DDL 中注释化
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
-- 3档 优秀档 180≤ H <210 10 30% 6
|
||||
-- 4档 销冠竞争 H ≥210 8 25% 休假自由
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE billiards_dws.cfg_performance_tier RESTART IDENTITY CASCADE;
|
||||
TRUNCATE TABLE dws.cfg_performance_tier RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO billiards_dws.cfg_performance_tier (
|
||||
INSERT INTO dws.cfg_performance_tier (
|
||||
tier_code, tier_name, tier_level,
|
||||
min_hours, max_hours,
|
||||
base_deduction, bonus_deduction_ratio, vacation_days, vacation_unlimited,
|
||||
@@ -123,9 +123,9 @@ INSERT INTO billiards_dws.cfg_performance_tier (
|
||||
-- - 包厢课基础课统一138元/小时(不随等级变化)
|
||||
-- - 数据来源:DWS 数据库处理需求.md
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE billiards_dws.cfg_assistant_level_price RESTART IDENTITY CASCADE;
|
||||
TRUNCATE TABLE dws.cfg_assistant_level_price RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO billiards_dws.cfg_assistant_level_price (
|
||||
INSERT INTO dws.cfg_assistant_level_price (
|
||||
level_code, level_name,
|
||||
base_course_price, bonus_course_price,
|
||||
effective_from, effective_to, description
|
||||
@@ -167,9 +167,9 @@ INSERT INTO billiards_dws.cfg_assistant_level_price (
|
||||
-- - SPRINT: 冲刺奖金(历史口径,至2026-02-28)
|
||||
-- - TOP_RANK: Top3排名奖金(2026-03-01起)
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE billiards_dws.cfg_bonus_rules RESTART IDENTITY CASCADE;
|
||||
TRUNCATE TABLE dws.cfg_bonus_rules RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO billiards_dws.cfg_bonus_rules (
|
||||
INSERT INTO dws.cfg_bonus_rules (
|
||||
rule_type, rule_code, rule_name,
|
||||
threshold_hours, rank_position, bonus_amount,
|
||||
is_cumulative, priority,
|
||||
@@ -226,9 +226,9 @@ INSERT INTO billiards_dws.cfg_bonus_rules (
|
||||
-- - SPECIAL: 特殊(补时长等)
|
||||
-- - OTHER: 其他
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE billiards_dws.cfg_area_category RESTART IDENTITY CASCADE;
|
||||
TRUNCATE TABLE dws.cfg_area_category RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO billiards_dws.cfg_area_category (
|
||||
INSERT INTO dws.cfg_area_category (
|
||||
source_area_name, category_code, category_name,
|
||||
match_type, match_priority, is_active, description
|
||||
) VALUES
|
||||
@@ -299,9 +299,9 @@ INSERT INTO billiards_dws.cfg_area_category (
|
||||
-- - 附加课/超休: skill_id = 2807440316432197
|
||||
-- - 避免依赖 skill_name 文本匹配
|
||||
-- =============================================================================
|
||||
TRUNCATE TABLE billiards_dws.cfg_skill_type RESTART IDENTITY CASCADE;
|
||||
TRUNCATE TABLE dws.cfg_skill_type RESTART IDENTITY CASCADE;
|
||||
|
||||
INSERT INTO billiards_dws.cfg_skill_type (
|
||||
INSERT INTO dws.cfg_skill_type (
|
||||
skill_id, skill_name,
|
||||
course_type_code, course_type_name,
|
||||
is_active, description
|
||||
@@ -372,11 +372,11 @@ DECLARE
|
||||
v_area_count INTEGER;
|
||||
v_skill_count INTEGER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO v_tier_count FROM billiards_dws.cfg_performance_tier;
|
||||
SELECT COUNT(*) INTO v_price_count FROM billiards_dws.cfg_assistant_level_price;
|
||||
SELECT COUNT(*) INTO v_bonus_count FROM billiards_dws.cfg_bonus_rules;
|
||||
SELECT COUNT(*) INTO v_area_count FROM billiards_dws.cfg_area_category;
|
||||
SELECT COUNT(*) INTO v_skill_count FROM billiards_dws.cfg_skill_type;
|
||||
SELECT COUNT(*) INTO v_tier_count FROM dws.cfg_performance_tier;
|
||||
SELECT COUNT(*) INTO v_price_count FROM dws.cfg_assistant_level_price;
|
||||
SELECT COUNT(*) INTO v_bonus_count FROM dws.cfg_bonus_rules;
|
||||
SELECT COUNT(*) INTO v_area_count FROM dws.cfg_area_category;
|
||||
SELECT COUNT(*) INTO v_skill_count FROM dws.cfg_skill_type;
|
||||
|
||||
RAISE NOTICE '配置数据初始化完成:';
|
||||
RAISE NOTICE ' - cfg_performance_tier: % 条', v_tier_count;
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
-- =============================================================================
|
||||
|
||||
-- 清理旧版指数参数
|
||||
DELETE FROM billiards_dws.cfg_index_parameters WHERE index_type IN ('RECALL', 'INTIMACY');
|
||||
DELETE FROM dws.cfg_index_parameters WHERE index_type IN ('RECALL', 'INTIMACY');
|
||||
-- 清理 ML 已废弃参数
|
||||
DELETE FROM billiards_dws.cfg_index_parameters WHERE index_type = 'ML' AND param_name IN ('source_mode', 'recharge_attribute_hours');
|
||||
DELETE FROM dws.cfg_index_parameters WHERE index_type = 'ML' AND param_name IN ('source_mode', 'recharge_attribute_hours');
|
||||
|
||||
INSERT INTO billiards_dws.cfg_index_parameters
|
||||
INSERT INTO dws.cfg_index_parameters
|
||||
(index_type, param_name, param_value, description, effective_from)
|
||||
VALUES
|
||||
('NCI', 'active_new_penalty', 0.200000, 'active-new suppression multiplier', DATE '2026-02-06'),
|
||||
@@ -82,7 +82,7 @@ ON CONFLICT (index_type, param_name, effective_from) DO UPDATE SET
|
||||
-- 生效时间:北京时间 2026-01-01(按数据库日期管理)
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO billiards_dws.cfg_index_parameters
|
||||
INSERT INTO dws.cfg_index_parameters
|
||||
(index_type, param_name, param_value, description, effective_from)
|
||||
VALUES
|
||||
-- RS(关系强度)
|
||||
@@ -149,27 +149,27 @@ DECLARE
|
||||
wbi_count INTEGER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO rs_count
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'RS';
|
||||
|
||||
SELECT COUNT(*) INTO os_count
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'OS';
|
||||
|
||||
SELECT COUNT(*) INTO ms_count
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'MS';
|
||||
|
||||
SELECT COUNT(*) INTO ml_count
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'ML';
|
||||
|
||||
SELECT COUNT(*) INTO nci_count
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'NCI';
|
||||
|
||||
SELECT COUNT(*) INTO wbi_count
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
WHERE index_type = 'WBI';
|
||||
|
||||
RAISE NOTICE 'RS 参数数量: %', rs_count;
|
||||
@@ -186,5 +186,5 @@ SELECT
|
||||
param_value,
|
||||
description,
|
||||
effective_from
|
||||
FROM billiards_dws.cfg_index_parameters
|
||||
FROM dws.cfg_index_parameters
|
||||
ORDER BY index_type, param_name, effective_from;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
-- 将新的 ODS 任务注册到 etl_admin.etl_task(按需替换 store_id)。
|
||||
-- 使用方式(示例):
|
||||
-- psql "$PG_DSN" -f etl_billiards/database/seed_ods_tasks.sql
|
||||
-- 或在 psql 中直接执行本文件内容。
|
||||
-- CHANGE 2026-02-15 | 修复 schema 引用:etl_admin → meta(对齐新库 etl_feiqiu 六层架构)
|
||||
-- 将新的 ODS 任务注册到 meta.etl_task(按需替换 store_id)。
|
||||
|
||||
WITH target_store AS (
|
||||
SELECT 2790685415443269::bigint AS store_id -- TODO: 替换为实际 store_id
|
||||
@@ -34,7 +32,7 @@ task_codes AS (
|
||||
'ODS_SETTLEMENT_TICKET'
|
||||
]) AS task_code
|
||||
)
|
||||
INSERT INTO etl_admin.etl_task (task_code, store_id, enabled)
|
||||
INSERT INTO meta.etl_task (task_code, store_id, enabled)
|
||||
SELECT t.task_code, s.store_id, TRUE
|
||||
FROM task_codes t CROSS JOIN target_store s
|
||||
ON CONFLICT (task_code, store_id) DO UPDATE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Seed scheduler-compatible tasks into etl_admin.etl_task.
|
||||
-- AI_CHANGELOG [2026-02-13] 移除 DWS_RECALL_INDEX/DWS_INTIMACY_INDEX 任务种子
|
||||
-- CHANGE 2026-02-15 | 修复 schema 引用:etl_admin → meta(对齐新库 etl_feiqiu 六层架构)
|
||||
-- Seed scheduler-compatible tasks into meta.etl_task.
|
||||
--
|
||||
-- Notes:
|
||||
-- - These task_code values must match orchestration/task_registry.py.
|
||||
@@ -46,7 +46,7 @@ task_codes AS (
|
||||
'DWS_ML_MANUAL_IMPORT'
|
||||
]) AS task_code
|
||||
)
|
||||
INSERT INTO etl_admin.etl_task (task_code, store_id, enabled)
|
||||
INSERT INTO meta.etl_task (task_code, store_id, enabled)
|
||||
SELECT t.task_code, s.store_id, TRUE
|
||||
FROM task_codes t CROSS JOIN target_store s
|
||||
ON CONFLICT (task_code, store_id) DO UPDATE
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
-- =============================================================================
|
||||
-- FDW 映射配置 — 在 zqyy_app 数据库中执行
|
||||
-- FDW 映射配置(生产环境)— 在 zqyy_app 数据库中执行
|
||||
-- 用途:通过 postgres_fdw 将 etl_feiqiu.app schema 只读映射到 zqyy_app,
|
||||
-- 使业务后端无需直接连接 ETL 数据库即可读取汇总/维度数据。
|
||||
-- 前提:etl_feiqiu 数据库已部署 app schema 及 app_reader 角色(见 app.sql)
|
||||
-- 测试环境版本:setup_fdw_test.sql(指向 test_etl_feiqiu / test_zqyy_app)
|
||||
-- Requirements: 8.3, 8.4, 8.5
|
||||
-- =============================================================================
|
||||
|
||||
|
||||
63
db/fdw/setup_fdw_test.sql
Normal file
63
db/fdw/setup_fdw_test.sql
Normal file
@@ -0,0 +1,63 @@
|
||||
-- =============================================================================
|
||||
-- FDW 映射配置(测试环境)— 在 test_zqyy_app 数据库中执行
|
||||
-- 用途:通过 postgres_fdw 将 test_etl_feiqiu.app schema 只读映射到 test_zqyy_app,
|
||||
-- 使业务后端在测试环境下无需直接连接 ETL 测试库即可读取汇总/维度数据。
|
||||
-- 前提:test_etl_feiqiu 数据库已部署 app schema 及 app_reader 角色
|
||||
-- 基于 setup_fdw.sql,仅将目标库替换为测试库
|
||||
-- =============================================================================
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 1. 安装 postgres_fdw 扩展
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE EXTENSION IF NOT EXISTS postgres_fdw;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 2. 创建外部服务器(指向 test_etl_feiqiu 测试库)
|
||||
-- 部署时按实际环境替换 host / port
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE SERVER IF NOT EXISTS test_etl_feiqiu_server
|
||||
FOREIGN DATA WRAPPER postgres_fdw
|
||||
OPTIONS (host 'localhost', dbname 'test_etl_feiqiu', port '5432');
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 3. 创建用户映射(只读角色)
|
||||
-- app_user = test_zqyy_app 侧的应用连接角色
|
||||
-- app_reader = test_etl_feiqiu 侧的只读角色
|
||||
-- 密码占位符 '***',部署时替换为真实凭据
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE USER MAPPING IF NOT EXISTS FOR app_user
|
||||
SERVER test_etl_feiqiu_server
|
||||
OPTIONS (user 'app_reader', password '***');
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 4. 创建目标 schema(存放外部表)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE SCHEMA IF NOT EXISTS fdw_etl;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 5. 导入 test_etl_feiqiu.app schema 的所有外部表到 fdw_etl
|
||||
-- -----------------------------------------------------------------------------
|
||||
IMPORT FOREIGN SCHEMA app
|
||||
FROM SERVER test_etl_feiqiu_server
|
||||
INTO fdw_etl;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 6. 授权:允许 app_user 访问 fdw_etl schema 及其外部表
|
||||
-- -----------------------------------------------------------------------------
|
||||
GRANT USAGE ON SCHEMA fdw_etl TO app_user;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA fdw_etl TO app_user;
|
||||
|
||||
-- 未来新导入的外部表自动授权
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_etl GRANT SELECT ON TABLES TO app_user;
|
||||
|
||||
|
||||
-- =============================================================================
|
||||
-- 回滚脚本(按逆序执行)
|
||||
-- =============================================================================
|
||||
-- ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_etl REVOKE SELECT ON TABLES FROM app_user;
|
||||
-- REVOKE SELECT ON ALL TABLES IN SCHEMA fdw_etl FROM app_user;
|
||||
-- REVOKE USAGE ON SCHEMA fdw_etl FROM app_user;
|
||||
-- DROP SCHEMA IF EXISTS fdw_etl CASCADE;
|
||||
-- DROP USER MAPPING IF EXISTS FOR app_user SERVER test_etl_feiqiu_server;
|
||||
-- DROP SERVER IF EXISTS test_etl_feiqiu_server CASCADE;
|
||||
-- DROP EXTENSION IF EXISTS postgres_fdw;
|
||||
107
db/zqyy_app/migrations/20250715_create_admin_web_tables.sql
Normal file
107
db/zqyy_app/migrations/20250715_create_admin_web_tables.sql
Normal file
@@ -0,0 +1,107 @@
|
||||
-- =============================================================================
|
||||
-- 迁移脚本:创建 Web 管理后台所需的 4 张表
|
||||
-- 数据库:zqyy_app
|
||||
-- 关联需求:Requirements 1.1(用户认证)、4.1(任务队列)、5.1(调度任务)
|
||||
-- =============================================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- admin_users 表:管理后台操作员账户
|
||||
-- 每个 Operator 绑定一个门店(site_id),登录后 JWT 携带 site_id
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS admin_users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(256) NOT NULL,
|
||||
display_name VARCHAR(128),
|
||||
site_id BIGINT NOT NULL, -- 绑定的门店 ID
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_admin_users_site
|
||||
ON admin_users(site_id);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- task_queue 表:ETL 任务执行队列
|
||||
-- 状态流转:pending → running → success / failed / cancelled
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS task_queue (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
site_id BIGINT NOT NULL, -- 门店隔离
|
||||
config JSONB NOT NULL, -- 序列化的 TaskConfig
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
started_at TIMESTAMPTZ,
|
||||
finished_at TIMESTAMPTZ,
|
||||
exit_code INTEGER,
|
||||
error_message TEXT
|
||||
);
|
||||
|
||||
-- 按状态查询(如获取所有 running 任务)
|
||||
CREATE INDEX IF NOT EXISTS idx_task_queue_status
|
||||
ON task_queue(status);
|
||||
|
||||
-- 按门店 + 位置查询待执行任务(部分索引,仅 pending 状态)
|
||||
CREATE INDEX IF NOT EXISTS idx_task_queue_site_position
|
||||
ON task_queue(site_id, position)
|
||||
WHERE status = 'pending';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- task_execution_log 表:任务执行历史记录
|
||||
-- 每次执行(无论来自队列还是直接触发)都记录一条日志
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS task_execution_log (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
queue_id UUID REFERENCES task_queue(id),
|
||||
site_id BIGINT NOT NULL, -- 门店隔离
|
||||
task_codes TEXT[] NOT NULL,
|
||||
status VARCHAR(20) NOT NULL,
|
||||
started_at TIMESTAMPTZ NOT NULL,
|
||||
finished_at TIMESTAMPTZ,
|
||||
exit_code INTEGER,
|
||||
duration_ms INTEGER,
|
||||
command TEXT, -- 实际执行的 CLI 命令
|
||||
output_log TEXT, -- stdout 完整日志
|
||||
error_log TEXT, -- stderr 日志
|
||||
summary JSONB, -- 执行摘要
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 按门店 + 开始时间倒序查询(执行历史列表)
|
||||
CREATE INDEX IF NOT EXISTS idx_execution_log_site_started
|
||||
ON task_execution_log(site_id, started_at DESC);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- scheduled_tasks 表:定时调度任务
|
||||
-- 支持一次性 / 固定间隔 / 每日 / 每周 / Cron 五种调度类型
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS scheduled_tasks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
site_id BIGINT NOT NULL, -- 门店隔离
|
||||
name VARCHAR(256) NOT NULL,
|
||||
task_codes TEXT[] NOT NULL,
|
||||
task_config JSONB NOT NULL, -- 序列化的 TaskConfig
|
||||
schedule_config JSONB NOT NULL, -- 序列化的 ScheduleConfig
|
||||
enabled BOOLEAN DEFAULT TRUE,
|
||||
last_run_at TIMESTAMPTZ,
|
||||
next_run_at TIMESTAMPTZ,
|
||||
run_count INTEGER DEFAULT 0,
|
||||
last_status VARCHAR(20),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 按门店查询调度任务
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_site
|
||||
ON scheduled_tasks(site_id);
|
||||
|
||||
-- 查询到期的已启用调度任务(部分索引)
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_next_run
|
||||
ON scheduled_tasks(next_run_at)
|
||||
WHERE enabled = TRUE;
|
||||
|
||||
COMMIT;
|
||||
@@ -1,4 +1,4 @@
|
||||
-- =============================================================================
|
||||
-- =============================================================================
|
||||
-- zqyy_app 数据库 Schema DDL
|
||||
-- 业务应用数据库:用户管理、RBAC 权限、任务管理、审批流程
|
||||
-- 所有业务表包含 site_id 字段以支持多门店隔离(Requirements 13.1)
|
||||
|
||||
18
db/zqyy_app/seeds/admin_web_seed.sql
Normal file
18
db/zqyy_app/seeds/admin_web_seed.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- =============================================================================
|
||||
-- 种子数据:Web 管理后台默认管理员账号
|
||||
-- 数据库:zqyy_app
|
||||
-- 关联需求:Requirements 1.1(用户认证)
|
||||
-- =============================================================================
|
||||
-- 默认密码:admin123(bcrypt hash,cost=12)
|
||||
-- 生产环境部署后务必立即修改密码
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO admin_users (username, password_hash, display_name, site_id, is_active)
|
||||
VALUES (
|
||||
'admin',
|
||||
'$2b$12$2MTWlJKL0HTgHIkv5Rmpie2pQ9PkeJu0iciLbzPEpPcA94ZakIQzq',
|
||||
'默认管理员',
|
||||
1,
|
||||
TRUE
|
||||
)
|
||||
ON CONFLICT (username) DO NOTHING;
|
||||
Reference in New Issue
Block a user