-- -*- coding: utf-8 -*- -- Feiqiu-ETL schema (JSON-first alignment) CREATE SCHEMA IF NOT EXISTS billiards; CREATE SCHEMA IF NOT EXISTS billiards_ods; CREATE SCHEMA IF NOT EXISTS etl_admin; COMMENT ON SCHEMA billiards IS '门店业务数据 Schema,存放维度/事实层(与 JSON 字段对应)'; COMMENT ON SCHEMA etl_admin IS 'ETL 调度、游标与运行记录 Schema'; -- ========================= -- Billiards ODS tables -- ========================= CREATE TABLE IF NOT EXISTS billiards_ods.ods_order_settle ( store_id bigint NOT NULL, order_settle_id bigint NOT NULL, order_trade_no bigint, page_no integer, page_size integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, order_settle_id) ); COMMENT ON TABLE billiards_ods.ods_order_settle IS '订单/结算 ODS(/order/list、ticket 接口原始 JSON)'; COMMENT ON COLUMN billiards_ods.ods_order_settle.store_id IS '门店 ID'; COMMENT ON COLUMN billiards_ods.ods_order_settle.order_settle_id IS '结算单 ID (order_settle_id)'; COMMENT ON COLUMN billiards_ods.ods_order_settle.order_trade_no IS '订单交易号 (order_trade_no)'; COMMENT ON COLUMN billiards_ods.ods_order_settle.page_no IS '来源分页序号'; COMMENT ON COLUMN billiards_ods.ods_order_settle.page_size IS '来源分页大小'; COMMENT ON COLUMN billiards_ods.ods_order_settle.source_file IS '离线导出文件名/路径'; COMMENT ON COLUMN billiards_ods.ods_order_settle.fetched_at IS '入 ODS 时间'; COMMENT ON COLUMN billiards_ods.ods_order_settle.payload IS '原始 JSON 负载'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_table_use_detail ( store_id bigint NOT NULL, ledger_id bigint NOT NULL, order_trade_no bigint, order_settle_id bigint, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, ledger_id) ); COMMENT ON TABLE billiards_ods.ods_table_use_detail IS '台费/开台流水 ODS(siteTableUseDetailsList 等接口)'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_ledger ( store_id bigint NOT NULL, ledger_id bigint NOT NULL, order_trade_no bigint, order_settle_id bigint, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, ledger_id) ); COMMENT ON TABLE billiards_ods.ods_assistant_ledger IS '助教流水 ODS(orderAssistantDetails 等接口)'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_abolish ( store_id bigint NOT NULL, abolish_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, abolish_id) ); COMMENT ON TABLE billiards_ods.ods_assistant_abolish IS '助教作废记录 ODS'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_goods_ledger ( store_id bigint NOT NULL, order_goods_id bigint NOT NULL, order_trade_no bigint, order_settle_id bigint, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, order_goods_id) ); COMMENT ON TABLE billiards_ods.ods_goods_ledger IS '商品销售流水 ODS(orderGoodsLedgers/orderGoodsList)'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_payment ( store_id bigint NOT NULL, pay_id bigint NOT NULL, relate_type varchar(50), relate_id bigint, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, pay_id) ); COMMENT ON TABLE billiards_ods.ods_payment IS '支付流水 ODS(payRecord/payList)'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_refund ( store_id bigint NOT NULL, refund_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, refund_id) ); COMMENT ON TABLE billiards_ods.ods_refund IS '退款流水 ODS'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_coupon_verify ( store_id bigint NOT NULL, coupon_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, coupon_id) ); COMMENT ON TABLE billiards_ods.ods_coupon_verify IS '团购/验券流水 ODS'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_member ( store_id bigint NOT NULL, member_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, member_id) ); COMMENT ON TABLE billiards_ods.ods_member IS '会员档案 ODS'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_member_card ( store_id bigint NOT NULL, card_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, card_id) ); COMMENT ON TABLE billiards_ods.ods_member_card IS '储值卡/会员卡 ODS'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_package_coupon ( store_id bigint NOT NULL, package_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, package_id) ); COMMENT ON TABLE billiards_ods.ods_package_coupon IS '团购套餐定义 ODS'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_inventory_stock ( store_id bigint NOT NULL, site_goods_id bigint NOT NULL, snapshot_key varchar(100) NOT NULL DEFAULT 'default', page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, site_goods_id, snapshot_key) ); COMMENT ON TABLE billiards_ods.ods_inventory_stock IS '库存汇总 ODS(inventorySummary 等接口)'; CREATE TABLE IF NOT EXISTS billiards_ods.ods_inventory_change ( store_id bigint NOT NULL, change_id bigint NOT NULL, page_no integer, source_file varchar(255), fetched_at timestamptz NOT NULL DEFAULT now(), payload jsonb NOT NULL, PRIMARY KEY (store_id, change_id) ); COMMENT ON TABLE billiards_ods.ods_inventory_change IS '库存变动记录 ODS'; -- ========================= -- Billiards dimension tables -- ========================= CREATE TABLE IF NOT EXISTS billiards.dim_store ( store_id bigint PRIMARY KEY, store_name varchar(200), tenant_id bigint, region_code varchar(30), address varchar(500), contact_name varchar(100), contact_phone varchar(30), created_time timestamptz, updated_time timestamptz, remark text, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb ); COMMENT ON TABLE billiards.dim_store IS '门店/场馆维度(siteProfile 信息快照)'; COMMENT ON COLUMN billiards.dim_store.store_id IS '门店 ID,主键(API storeId)'; COMMENT ON COLUMN billiards.dim_store.store_name IS '门店名称 (shop_name)'; COMMENT ON COLUMN billiards.dim_store.tenant_id IS '租户 ID (tenant_id)'; COMMENT ON COLUMN billiards.dim_store.region_code IS '区域编码/城市代码 (tenant_site_region_id)'; COMMENT ON COLUMN billiards.dim_store.address IS '完整地址 (full_address/address)'; COMMENT ON COLUMN billiards.dim_store.contact_name IS '联系人(可扩展)'; COMMENT ON COLUMN billiards.dim_store.contact_phone IS '联系电话 (business_tel)'; COMMENT ON COLUMN billiards.dim_store.created_time IS '创建时间'; COMMENT ON COLUMN billiards.dim_store.updated_time IS '更新时间'; COMMENT ON COLUMN billiards.dim_store.remark IS '备注'; COMMENT ON COLUMN billiards.dim_store.raw_data IS '原始 JSON 快照'; CREATE TABLE IF NOT EXISTS billiards.dim_assistant ( store_id bigint NOT NULL, assistant_id bigint NOT NULL, assistant_no varchar(64), nickname varchar(100), real_name varchar(100), gender varchar(20), mobile varchar(30), level varchar(50), team_id bigint, team_name varchar(100), assistant_status varchar(30), work_status varchar(30), entry_time timestamptz, resign_time timestamptz, start_time timestamptz, end_time timestamptz, create_time timestamptz, update_time timestamptz, system_role_id bigint, online_status varchar(30), allow_cx integer, charge_way varchar(30), pd_unit_price numeric(14,2), cx_unit_price numeric(14,2), is_guaranteed integer, is_team_leader integer, serial_number varchar(64), show_sort integer, is_delete integer, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, assistant_id) ); COMMENT ON TABLE billiards.dim_assistant IS '助教/技师维度(Assistant/List)'; COMMENT ON COLUMN billiards.dim_assistant.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_assistant.assistant_id IS '助教 ID (id)'; COMMENT ON COLUMN billiards.dim_assistant.assistant_no IS '助教编号 (assistant_no)'; COMMENT ON COLUMN billiards.dim_assistant.nickname IS '昵称 (nickname)'; COMMENT ON COLUMN billiards.dim_assistant.real_name IS '真实姓名 (real_name)'; COMMENT ON COLUMN billiards.dim_assistant.gender IS '性别'; COMMENT ON COLUMN billiards.dim_assistant.mobile IS '手机号'; COMMENT ON COLUMN billiards.dim_assistant.level IS '等级/段位 (level)'; COMMENT ON COLUMN billiards.dim_assistant.team_id IS '团队 ID (team_id)'; COMMENT ON COLUMN billiards.dim_assistant.team_name IS '团队名称 (team_name)'; COMMENT ON COLUMN billiards.dim_assistant.assistant_status IS '账号状态 (assistant_status)'; COMMENT ON COLUMN billiards.dim_assistant.work_status IS '工作状态 (work_status)'; COMMENT ON COLUMN billiards.dim_assistant.entry_time IS '入职时间 (entry_time)'; COMMENT ON COLUMN billiards.dim_assistant.resign_time IS '离职时间 (resign_time)'; COMMENT ON COLUMN billiards.dim_assistant.start_time IS '可服务开始时间 (start_time)'; COMMENT ON COLUMN billiards.dim_assistant.end_time IS '可服务结束时间 (end_time)'; COMMENT ON COLUMN billiards.dim_assistant.create_time IS '创建时间 (create_time)'; COMMENT ON COLUMN billiards.dim_assistant.update_time IS '最近更新时间 (update_time)'; COMMENT ON COLUMN billiards.dim_assistant.system_role_id IS '系统角色 ID'; COMMENT ON COLUMN billiards.dim_assistant.online_status IS '在线/离线状态'; COMMENT ON COLUMN billiards.dim_assistant.allow_cx IS '是否允许撤销/重开'; COMMENT ON COLUMN billiards.dim_assistant.charge_way IS '计费方式 (charge_way)'; COMMENT ON COLUMN billiards.dim_assistant.pd_unit_price IS '陪打单价 (pd_unit_price)'; COMMENT ON COLUMN billiards.dim_assistant.cx_unit_price IS '拆洗/其它单价 (cx_unit_price)'; COMMENT ON COLUMN billiards.dim_assistant.is_guaranteed IS '是否保底'; COMMENT ON COLUMN billiards.dim_assistant.is_team_leader IS '是否队长'; COMMENT ON COLUMN billiards.dim_assistant.serial_number IS '序列号/展示码 (serial_number)'; COMMENT ON COLUMN billiards.dim_assistant.show_sort IS '展示排序 (show_sort)'; COMMENT ON COLUMN billiards.dim_assistant.is_delete IS '删除标记'; COMMENT ON COLUMN billiards.dim_assistant.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.dim_assistant.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.dim_member ( store_id bigint NOT NULL, member_id bigint NOT NULL, member_name varchar(100), phone varchar(30), balance numeric(18,4), status varchar(30), register_time timestamptz, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, member_id) ); COMMENT ON TABLE billiards.dim_member IS '会员维度(MemberProfile/GetTenantMemberList)'; COMMENT ON COLUMN billiards.dim_member.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_member.member_id IS '会员 ID (memberId)'; COMMENT ON COLUMN billiards.dim_member.member_name IS '会员名称 (memberName)'; COMMENT ON COLUMN billiards.dim_member.phone IS '手机号 (phone)'; COMMENT ON COLUMN billiards.dim_member.balance IS '储值余额 (balance)'; COMMENT ON COLUMN billiards.dim_member.status IS '会员状态 (status)'; COMMENT ON COLUMN billiards.dim_member.register_time IS '注册时间 (registerTime)'; COMMENT ON COLUMN billiards.dim_member.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.dim_member.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.dim_package_coupon ( store_id bigint NOT NULL, package_id bigint NOT NULL, package_code varchar(100), package_name varchar(200), table_area_id bigint, table_area_name varchar(100), selling_price numeric(14,2), duration_seconds integer, start_time timestamptz, end_time timestamptz, type varchar(50), is_enabled integer, is_delete integer, usable_count integer, creator_name varchar(100), date_type varchar(50), group_type varchar(50), coupon_money numeric(14,2), area_tag_type varchar(50), system_group_type varchar(50), card_type_ids text, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, package_id) ); COMMENT ON TABLE billiards.dim_package_coupon IS '团购/套餐定义维度(Package/List)'; COMMENT ON COLUMN billiards.dim_package_coupon.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_package_coupon.package_id IS '套餐主键 (id)'; COMMENT ON COLUMN billiards.dim_package_coupon.package_code IS '套餐编码 (package_id 或自定义编码)'; COMMENT ON COLUMN billiards.dim_package_coupon.package_name IS '套餐名称 (package_name)'; COMMENT ON COLUMN billiards.dim_package_coupon.table_area_id IS '适用台桌区域 ID'; COMMENT ON COLUMN billiards.dim_package_coupon.table_area_name IS '适用台桌区域名称'; COMMENT ON COLUMN billiards.dim_package_coupon.selling_price IS '售卖价格 (selling_price)'; COMMENT ON COLUMN billiards.dim_package_coupon.duration_seconds IS '可用时长(秒)(duration)'; COMMENT ON COLUMN billiards.dim_package_coupon.start_time IS '可用时间起'; COMMENT ON COLUMN billiards.dim_package_coupon.end_time IS '可用时间止'; COMMENT ON COLUMN billiards.dim_package_coupon.type IS '套餐类型 (type/group_type)'; COMMENT ON COLUMN billiards.dim_package_coupon.is_enabled IS '是否启用 (is_enabled)'; COMMENT ON COLUMN billiards.dim_package_coupon.is_delete IS '删除标记 (is_delete)'; COMMENT ON COLUMN billiards.dim_package_coupon.usable_count IS '可使用次数 (usable_count)'; COMMENT ON COLUMN billiards.dim_package_coupon.creator_name IS '创建人 (creator_name)'; COMMENT ON COLUMN billiards.dim_package_coupon.date_type IS '日期限制 (date_type)'; COMMENT ON COLUMN billiards.dim_package_coupon.group_type IS '渠道/团购类型 (group_type)'; COMMENT ON COLUMN billiards.dim_package_coupon.coupon_money IS '券面额 (coupon_money)'; COMMENT ON COLUMN billiards.dim_package_coupon.area_tag_type IS '区域标签类型'; COMMENT ON COLUMN billiards.dim_package_coupon.system_group_type IS '系统套餐类型 (system_group_type)'; COMMENT ON COLUMN billiards.dim_package_coupon.card_type_ids IS '适用会员卡类型列表 (card_type_ids)'; COMMENT ON COLUMN billiards.dim_package_coupon.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.dim_package_coupon.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.dim_product ( store_id bigint NOT NULL, product_id bigint NOT NULL, site_product_id bigint, product_name varchar(200) NOT NULL, category_id bigint, category_name varchar(100), second_category_id bigint, unit varchar(20), cost_price numeric(14,4), sale_price numeric(14,4), allow_discount boolean, status varchar(30), supplier_id bigint, barcode varchar(128), is_combo boolean, created_time timestamptz, updated_time timestamptz, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, product_id) ); COMMENT ON TABLE billiards.dim_product IS '商品维度(TenantGoods/QueryTenantGoods)'; COMMENT ON COLUMN billiards.dim_product.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_product.product_id IS '商品 ID (siteGoodsId/tenantGoodsId)'; COMMENT ON COLUMN billiards.dim_product.site_product_id IS '站点/门店商品 ID (siteGoodsId)'; COMMENT ON COLUMN billiards.dim_product.product_name IS '商品名称 (goodsName/productName)'; COMMENT ON COLUMN billiards.dim_product.category_id IS '一级分类 ID (goodsCategoryId)'; COMMENT ON COLUMN billiards.dim_product.category_name IS '一级分类名称 (categoryName)'; COMMENT ON COLUMN billiards.dim_product.second_category_id IS '二级分类 ID (goodsSecondCategoryId)'; COMMENT ON COLUMN billiards.dim_product.unit IS '计量单位 (goodsUnit)'; COMMENT ON COLUMN billiards.dim_product.cost_price IS '成本价 (costPrice)'; COMMENT ON COLUMN billiards.dim_product.sale_price IS '销售价 (goodsPrice/salePrice)'; COMMENT ON COLUMN billiards.dim_product.allow_discount IS '是否允许折扣 (able_discount)'; COMMENT ON COLUMN billiards.dim_product.status IS '商品状态 (goodsState/status)'; COMMENT ON COLUMN billiards.dim_product.supplier_id IS '供应商 ID'; COMMENT ON COLUMN billiards.dim_product.barcode IS '条码 (barcode)'; COMMENT ON COLUMN billiards.dim_product.is_combo IS '是否组合/套餐商品 (isCombo)'; COMMENT ON COLUMN billiards.dim_product.created_time IS '创建时间 (createTime)'; COMMENT ON COLUMN billiards.dim_product.updated_time IS '更新时间 (updateTime)'; COMMENT ON COLUMN billiards.dim_product.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.dim_product.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.dim_product_price_scd ( product_scd_id bigserial PRIMARY KEY, store_id bigint NOT NULL, product_id bigint NOT NULL, product_name varchar(200), category_id bigint, category_name varchar(100), second_category_id bigint, cost_price numeric(14,4), sale_price numeric(14,4), allow_discount boolean, status varchar(30), valid_from timestamptz NOT NULL DEFAULT now(), valid_to timestamptz, is_current boolean NOT NULL DEFAULT true, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, CONSTRAINT fk_dpps_product FOREIGN KEY (store_id, product_id) REFERENCES billiards.dim_product(store_id, product_id) ON DELETE CASCADE, CONSTRAINT ck_dpps_range CHECK ( valid_from < COALESCE(valid_to, '9999-12-31 00:00:00+00'::timestamptz) ), CONSTRAINT uq_dpps_current UNIQUE (store_id, product_id) WHERE (is_current) ); COMMENT ON TABLE billiards.dim_product_price_scd IS '商品维度价格 SCD(记录价格/分类变动历史)'; COMMENT ON COLUMN billiards.dim_product_price_scd.product_scd_id IS '价格 SCD 主键'; COMMENT ON COLUMN billiards.dim_product_price_scd.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_product_price_scd.product_id IS '商品 ID'; COMMENT ON COLUMN billiards.dim_product_price_scd.product_name IS '商品名称(冗余,方便简单查询)'; COMMENT ON COLUMN billiards.dim_product_price_scd.category_id IS '一级分类 ID'; COMMENT ON COLUMN billiards.dim_product_price_scd.category_name IS '一级分类名称'; COMMENT ON COLUMN billiards.dim_product_price_scd.second_category_id IS '二级分类 ID'; COMMENT ON COLUMN billiards.dim_product_price_scd.cost_price IS '成本价'; COMMENT ON COLUMN billiards.dim_product_price_scd.sale_price IS '销售价'; COMMENT ON COLUMN billiards.dim_product_price_scd.allow_discount IS '是否允许折扣'; COMMENT ON COLUMN billiards.dim_product_price_scd.status IS '商品状态 (上/下架)'; COMMENT ON COLUMN billiards.dim_product_price_scd.valid_from IS '生效时间'; COMMENT ON COLUMN billiards.dim_product_price_scd.valid_to IS '失效时间,NULL 表示当前版本'; COMMENT ON COLUMN billiards.dim_product_price_scd.is_current IS '当前有效版本标记'; COMMENT ON COLUMN billiards.dim_product_price_scd.raw_data IS '原始 JSON 快照'; CREATE VIEW IF NOT EXISTS billiards.dim_product_price_current AS SELECT product_scd_id, store_id, product_id, product_name, category_id, category_name, second_category_id, cost_price, sale_price, allow_discount, status, valid_from, valid_to, raw_data FROM billiards.dim_product_price_scd WHERE is_current; COMMENT ON VIEW billiards.dim_product_price_current IS '商品价格 SCD 当前有效版本视图'; COMMENT ON COLUMN billiards.dim_product_price_current.product_scd_id IS '价格 SCD 主键'; COMMENT ON COLUMN billiards.dim_product_price_current.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_product_price_current.product_id IS '商品 ID'; COMMENT ON COLUMN billiards.dim_product_price_current.product_name IS '商品名称'; COMMENT ON COLUMN billiards.dim_product_price_current.category_id IS '一级分类 ID'; COMMENT ON COLUMN billiards.dim_product_price_current.category_name IS '一级分类名称'; COMMENT ON COLUMN billiards.dim_product_price_current.second_category_id IS '二级分类 ID'; COMMENT ON COLUMN billiards.dim_product_price_current.cost_price IS '成本价'; COMMENT ON COLUMN billiards.dim_product_price_current.sale_price IS '销售价'; COMMENT ON COLUMN billiards.dim_product_price_current.allow_discount IS '是否允许折扣'; COMMENT ON COLUMN billiards.dim_product_price_current.status IS '商品状态'; COMMENT ON COLUMN billiards.dim_product_price_current.valid_from IS '生效时间'; COMMENT ON COLUMN billiards.dim_product_price_current.valid_to IS '失效时间'; COMMENT ON COLUMN billiards.dim_product_price_current.raw_data IS '原始 JSON'; CREATE TABLE IF NOT EXISTS billiards.dim_table ( store_id bigint NOT NULL, table_id bigint NOT NULL, site_id bigint, area_id bigint, area_name varchar(100), table_name varchar(100) NOT NULL, table_price numeric(14,4), table_status varchar(30), table_status_name varchar(50), light_status integer, is_rest_area integer, show_status integer, virtual_table integer, charge_free integer, only_allow_groupon integer, is_online_reservation integer, created_time timestamptz, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, table_id) ); COMMENT ON TABLE billiards.dim_table IS '台桌档案维度(Table/GetSiteTables)'; COMMENT ON COLUMN billiards.dim_table.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.dim_table.table_id IS '台桌 ID (id)'; COMMENT ON COLUMN billiards.dim_table.site_id IS '场馆/站点 ID (site_id)'; COMMENT ON COLUMN billiards.dim_table.area_id IS '区域 ID (site_table_area_id)'; COMMENT ON COLUMN billiards.dim_table.area_name IS '区域名称 (areaName)'; COMMENT ON COLUMN billiards.dim_table.table_name IS '台桌名称 (table_name)'; COMMENT ON COLUMN billiards.dim_table.table_price IS '台费单价 (table_price)'; COMMENT ON COLUMN billiards.dim_table.table_status IS '台桌状态代码 (table_status)'; COMMENT ON COLUMN billiards.dim_table.table_status_name IS '台桌状态名称 (tableStatusName)'; COMMENT ON COLUMN billiards.dim_table.light_status IS '灯光状态 (light_status)'; COMMENT ON COLUMN billiards.dim_table.is_rest_area IS '是否休息区 (is_rest_area)'; COMMENT ON COLUMN billiards.dim_table.show_status IS '是否展示 (show_status)'; COMMENT ON COLUMN billiards.dim_table.virtual_table IS '是否虚拟台 (virtual_table)'; COMMENT ON COLUMN billiards.dim_table.charge_free IS '是否免收费 (charge_free)'; COMMENT ON COLUMN billiards.dim_table.only_allow_groupon IS '是否仅限团购 (only_allow_groupon)'; COMMENT ON COLUMN billiards.dim_table.is_online_reservation IS '是否可线上预约 (is_online_reservation)'; COMMENT ON COLUMN billiards.dim_table.created_time IS '创建时间 (create_time)'; COMMENT ON COLUMN billiards.dim_table.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.dim_table.updated_at IS 'ETL 更新时间'; -- ========================= -- Billiards fact tables -- ========================= CREATE TABLE IF NOT EXISTS billiards.fact_assistant_abolish ( store_id bigint NOT NULL, abolish_id bigint NOT NULL, table_id bigint, table_name varchar(100), table_area_id bigint, table_area varchar(100), assistant_no varchar(64), assistant_name varchar(100), charge_minutes integer, abolish_amount numeric(14,4), create_time timestamptz, trash_reason text, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, abolish_id) ); COMMENT ON TABLE billiards.fact_assistant_abolish IS '助教作废/撤单流水(Assistant/AbolishList)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_assistant_abolish.abolish_id IS '作废记录 ID (id)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.table_id IS '台桌 ID (tableId)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.table_name IS '台桌名称'; COMMENT ON COLUMN billiards.fact_assistant_abolish.table_area_id IS '台桌区域 ID'; COMMENT ON COLUMN billiards.fact_assistant_abolish.table_area IS '台桌区域名称'; COMMENT ON COLUMN billiards.fact_assistant_abolish.assistant_no IS '助教编号 (assistantOn)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.assistant_name IS '助教姓名'; COMMENT ON COLUMN billiards.fact_assistant_abolish.charge_minutes IS '计费分钟 (pdChargeMinutes)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.abolish_amount IS '作废金额 (assistantAbolishAmount)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.create_time IS '创建时间 (createTime)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.trash_reason IS '作废原因 (trashReason)'; COMMENT ON COLUMN billiards.fact_assistant_abolish.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_assistant_abolish.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_assistant_ledger ( store_id bigint NOT NULL, ledger_id bigint NOT NULL, assistant_no varchar(64), assistant_name varchar(100), nickname varchar(100), level_name varchar(50), table_name varchar(100), ledger_unit_price numeric(14,4), ledger_count numeric(14,4), ledger_amount numeric(14,4), projected_income numeric(14,4), service_money numeric(14,4), member_discount_amount numeric(14,4), manual_discount_amount numeric(14,4), coupon_deduct_money numeric(14,4), order_trade_no bigint, order_settle_id bigint, operator_id bigint, operator_name varchar(100), assistant_team_id bigint, assistant_level varchar(50), site_table_id bigint, order_assistant_id bigint, site_assistant_id bigint, user_id bigint, ledger_start_time timestamptz, ledger_end_time timestamptz, start_use_time timestamptz, last_use_time timestamptz, income_seconds integer, real_use_seconds integer, is_trash integer, trash_reason text, is_confirm integer, ledger_status varchar(30), create_time timestamptz, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, ledger_id) ); COMMENT ON TABLE billiards.fact_assistant_ledger IS '助教陪打计费流水(Assistant/LedgerList)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_id IS '流水 ID (id)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.assistant_no IS '助教编号'; COMMENT ON COLUMN billiards.fact_assistant_ledger.assistant_name IS '助教姓名'; COMMENT ON COLUMN billiards.fact_assistant_ledger.nickname IS '昵称'; COMMENT ON COLUMN billiards.fact_assistant_ledger.level_name IS '等级名称'; COMMENT ON COLUMN billiards.fact_assistant_ledger.table_name IS '服务台桌名称'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_unit_price IS '计费单价 (ledger_unit_price)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_count IS '计费数量 (ledger_count)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_amount IS '计费金额 (ledger_amount)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.projected_income IS '预计收益 (projected_income)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.service_money IS '服务费 (service_money)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.member_discount_amount IS '会员折扣金额'; COMMENT ON COLUMN billiards.fact_assistant_ledger.manual_discount_amount IS '手动折扣金额'; COMMENT ON COLUMN billiards.fact_assistant_ledger.coupon_deduct_money IS '券抵扣金额'; COMMENT ON COLUMN billiards.fact_assistant_ledger.order_trade_no IS '订单交易号 (order_trade_no)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.order_settle_id IS '结算单 ID (order_settle_id)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.operator_id IS '操作人 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.operator_name IS '操作人姓名'; COMMENT ON COLUMN billiards.fact_assistant_ledger.assistant_team_id IS '助教团队 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.assistant_level IS '助教等级'; COMMENT ON COLUMN billiards.fact_assistant_ledger.site_table_id IS '台桌 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.order_assistant_id IS '订单内助教 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.site_assistant_id IS '场馆助教 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.user_id IS '会员/顾客 ID'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_start_time IS '计费开始时间'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_end_time IS '计费结束时间'; COMMENT ON COLUMN billiards.fact_assistant_ledger.start_use_time IS '开始使用时间'; COMMENT ON COLUMN billiards.fact_assistant_ledger.last_use_time IS '最后使用时间'; COMMENT ON COLUMN billiards.fact_assistant_ledger.income_seconds IS '计费秒数 (income_seconds)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.real_use_seconds IS '实际使用秒数 (real_use_seconds)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.is_trash IS '是否作废 (is_trash)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.trash_reason IS '作废原因 (trash_reason)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.is_confirm IS '是否确认 (is_confirm)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.ledger_status IS '状态 (ledger_status)'; COMMENT ON COLUMN billiards.fact_assistant_ledger.create_time IS '创建时间'; COMMENT ON COLUMN billiards.fact_assistant_ledger.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_assistant_ledger.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_inventory_change ( store_id bigint NOT NULL, change_id bigint NOT NULL, site_goods_id bigint, stock_type varchar(50), goods_name varchar(200), change_time timestamptz, start_qty numeric(18,4), end_qty numeric(18,4), change_qty numeric(18,4), unit varchar(20), price numeric(14,4), operator_name varchar(100), remark text, goods_category_id bigint, goods_second_category_id bigint, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, change_id) ); COMMENT ON TABLE billiards.fact_inventory_change IS '库存变更流水(Inventory/ChangeList)'; COMMENT ON COLUMN billiards.fact_inventory_change.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_inventory_change.change_id IS '库存变动 ID (siteGoodsStockId)'; COMMENT ON COLUMN billiards.fact_inventory_change.site_goods_id IS '门店商品 ID (siteGoodsId)'; COMMENT ON COLUMN billiards.fact_inventory_change.stock_type IS '变动类型 (stockType)'; COMMENT ON COLUMN billiards.fact_inventory_change.goods_name IS '商品名称 (goodsName)'; COMMENT ON COLUMN billiards.fact_inventory_change.change_time IS '变动时间 (createTime)'; COMMENT ON COLUMN billiards.fact_inventory_change.start_qty IS '变动前数量 (startNum)'; COMMENT ON COLUMN billiards.fact_inventory_change.end_qty IS '变动后数量 (endNum)'; COMMENT ON COLUMN billiards.fact_inventory_change.change_qty IS '变化数量 (changeNum)'; COMMENT ON COLUMN billiards.fact_inventory_change.unit IS '单位 (unit)'; COMMENT ON COLUMN billiards.fact_inventory_change.price IS '单价 (price)'; COMMENT ON COLUMN billiards.fact_inventory_change.operator_name IS '操作人 (operatorName)'; COMMENT ON COLUMN billiards.fact_inventory_change.remark IS '备注 (remark)'; COMMENT ON COLUMN billiards.fact_inventory_change.goods_category_id IS '一级分类 ID'; COMMENT ON COLUMN billiards.fact_inventory_change.goods_second_category_id IS '二级分类 ID'; COMMENT ON COLUMN billiards.fact_inventory_change.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_inventory_change.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_order ( store_id bigint NOT NULL, order_id bigint NOT NULL, order_no varchar(64), member_id bigint, table_id bigint, order_time timestamptz, end_time timestamptz, total_amount numeric(14,4), discount_amount numeric(14,4), final_amount numeric(14,4), pay_status varchar(30), order_status varchar(30), remark text, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, order_id) ); COMMENT ON TABLE billiards.fact_order IS '订单事实表(/order/list 返回的结账记录)'; COMMENT ON COLUMN billiards.fact_order.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_order.order_id IS '订单 ID (orderId)'; COMMENT ON COLUMN billiards.fact_order.order_no IS '订单编号 (orderNo)'; COMMENT ON COLUMN billiards.fact_order.member_id IS '会员 ID (memberId)'; COMMENT ON COLUMN billiards.fact_order.table_id IS '台桌 ID (tableId)'; COMMENT ON COLUMN billiards.fact_order.order_time IS '开单时间/开始时间 (orderTime)'; COMMENT ON COLUMN billiards.fact_order.end_time IS '结账时间 (endTime)'; COMMENT ON COLUMN billiards.fact_order.total_amount IS '订单总金额 (totalAmount)'; COMMENT ON COLUMN billiards.fact_order.discount_amount IS '折扣金额 (discountAmount)'; COMMENT ON COLUMN billiards.fact_order.final_amount IS '应付金额 (finalAmount)'; COMMENT ON COLUMN billiards.fact_order.pay_status IS '支付状态 (payStatus)'; COMMENT ON COLUMN billiards.fact_order.order_status IS '订单状态 (orderStatus)'; COMMENT ON COLUMN billiards.fact_order.remark IS '备注 (remark)'; COMMENT ON COLUMN billiards.fact_order.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_order.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_payment ( store_id bigint NOT NULL, pay_id bigint NOT NULL, order_id bigint, order_settle_id bigint, relate_type varchar(50), relate_id bigint, site_id bigint, tenant_id bigint, pay_time timestamptz, create_time timestamptz, pay_amount numeric(14,4), pay_type varchar(50), payment_method varchar(50), online_pay_channel varchar(50), pay_status varchar(30), pay_terminal varchar(50), remark text, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, pay_id) ); COMMENT ON TABLE billiards.fact_payment IS '支付流水(pay/records)'; COMMENT ON COLUMN billiards.fact_payment.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_payment.pay_id IS '支付记录 ID (payId)'; COMMENT ON COLUMN billiards.fact_payment.order_id IS '旧版订单 ID (orderId),保留兼容'; COMMENT ON COLUMN billiards.fact_payment.order_settle_id IS '结算单 ID (relate_id 当 relate_type=2)'; COMMENT ON COLUMN billiards.fact_payment.relate_type IS '关联类型 (relate_type)'; COMMENT ON COLUMN billiards.fact_payment.relate_id IS '关联 ID (relate_id)'; COMMENT ON COLUMN billiards.fact_payment.site_id IS '门店 ID(冗余自 payload)'; COMMENT ON COLUMN billiards.fact_payment.tenant_id IS '租户 ID'; COMMENT ON COLUMN billiards.fact_payment.pay_time IS '支付时间 (payTime)'; COMMENT ON COLUMN billiards.fact_payment.create_time IS '创建时间 (create_time)'; COMMENT ON COLUMN billiards.fact_payment.pay_amount IS '支付金额 (payAmount)'; COMMENT ON COLUMN billiards.fact_payment.pay_type IS '支付渠道 (payType)'; COMMENT ON COLUMN billiards.fact_payment.payment_method IS '支付方式 (payment_method)'; COMMENT ON COLUMN billiards.fact_payment.online_pay_channel IS '线上支付渠道 (online_pay_channel)'; COMMENT ON COLUMN billiards.fact_payment.pay_status IS '支付状态 (payStatus)'; COMMENT ON COLUMN billiards.fact_payment.pay_terminal IS '支付终端 (pay_terminal)'; COMMENT ON COLUMN billiards.fact_payment.remark IS '备注'; COMMENT ON COLUMN billiards.fact_payment.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_payment.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_refund ( store_id bigint NOT NULL, refund_id bigint NOT NULL, site_id bigint, tenant_id bigint, pay_amount numeric(14,4), pay_status varchar(30), pay_time timestamptz, create_time timestamptz, relate_type varchar(50), relate_id bigint, payment_method varchar(50), refund_amount numeric(14,4), action_type varchar(30), pay_terminal varchar(50), operator_id bigint, channel_pay_no varchar(100), channel_fee numeric(14,4), is_delete integer, member_id bigint, member_card_id bigint, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, refund_id) ); COMMENT ON TABLE billiards.fact_refund IS '退款流水(Pay/RefundList)'; COMMENT ON COLUMN billiards.fact_refund.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_refund.refund_id IS '退款记录 ID (id)'; COMMENT ON COLUMN billiards.fact_refund.site_id IS '场地 ID (site_id)'; COMMENT ON COLUMN billiards.fact_refund.tenant_id IS '租户 ID (tenant_id)'; COMMENT ON COLUMN billiards.fact_refund.pay_amount IS '原支付金额 (pay_amount)'; COMMENT ON COLUMN billiards.fact_refund.pay_status IS '支付状态 (pay_status)'; COMMENT ON COLUMN billiards.fact_refund.pay_time IS '支付时间 (pay_time)'; COMMENT ON COLUMN billiards.fact_refund.create_time IS '创建时间 (create_time)'; COMMENT ON COLUMN billiards.fact_refund.relate_type IS '关联对象类型 (relate_type)'; COMMENT ON COLUMN billiards.fact_refund.relate_id IS '关联对象 ID (relate_id)'; COMMENT ON COLUMN billiards.fact_refund.payment_method IS '支付方式 (payment_method)'; COMMENT ON COLUMN billiards.fact_refund.refund_amount IS '退款金额 (refund_amount)'; COMMENT ON COLUMN billiards.fact_refund.action_type IS '操作类型 (action_type)'; COMMENT ON COLUMN billiards.fact_refund.pay_terminal IS '终端类型 (pay_terminal)'; COMMENT ON COLUMN billiards.fact_refund.operator_id IS '操作人 ID (operator_id)'; COMMENT ON COLUMN billiards.fact_refund.channel_pay_no IS '渠道支付单号 (channel_pay_no)'; COMMENT ON COLUMN billiards.fact_refund.channel_fee IS '渠道手续费 (channel_fee)'; COMMENT ON COLUMN billiards.fact_refund.is_delete IS '删除标记 (is_delete)'; COMMENT ON COLUMN billiards.fact_refund.member_id IS '会员 ID (member_id)'; COMMENT ON COLUMN billiards.fact_refund.member_card_id IS '会员卡 ID (member_card_id)'; COMMENT ON COLUMN billiards.fact_refund.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_refund.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_table_discount ( store_id bigint NOT NULL, discount_id bigint NOT NULL, adjust_type varchar(50), applicant_id bigint, applicant_name varchar(100), operator_id bigint, operator_name varchar(100), ledger_amount numeric(14,4), ledger_count numeric(14,4), ledger_name varchar(100), ledger_status varchar(30), order_settle_id bigint, order_trade_no bigint, site_table_id bigint, table_area_id bigint, table_area_name varchar(100), create_time timestamptz, is_delete integer, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, discount_id) ); COMMENT ON TABLE billiards.fact_table_discount IS '台费调价/折扣记录(Table/AdjustList)'; COMMENT ON COLUMN billiards.fact_table_discount.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_table_discount.discount_id IS '调价记录 ID (id)'; COMMENT ON COLUMN billiards.fact_table_discount.adjust_type IS '调价类型 (adjust_type/adjustType)'; COMMENT ON COLUMN billiards.fact_table_discount.applicant_id IS '申请人 ID (applicant_id)'; COMMENT ON COLUMN billiards.fact_table_discount.applicant_name IS '申请人姓名 (applicant_name)'; COMMENT ON COLUMN billiards.fact_table_discount.operator_id IS '操作人 ID (operator_id)'; COMMENT ON COLUMN billiards.fact_table_discount.operator_name IS '操作人姓名 (operator_name)'; COMMENT ON COLUMN billiards.fact_table_discount.ledger_amount IS '台费金额调整 (ledger_amount)'; COMMENT ON COLUMN billiards.fact_table_discount.ledger_count IS '台费数量调整 (ledger_count)'; COMMENT ON COLUMN billiards.fact_table_discount.ledger_name IS '科目名称 (ledger_name)'; COMMENT ON COLUMN billiards.fact_table_discount.ledger_status IS '记录状态 (ledger_status)'; COMMENT ON COLUMN billiards.fact_table_discount.order_settle_id IS '结算单 ID (order_settle_id)'; COMMENT ON COLUMN billiards.fact_table_discount.order_trade_no IS '订单号 (order_trade_no)'; COMMENT ON COLUMN billiards.fact_table_discount.site_table_id IS '台桌 ID (site_table_id)'; COMMENT ON COLUMN billiards.fact_table_discount.table_area_id IS '台桌区域 ID'; COMMENT ON COLUMN billiards.fact_table_discount.table_area_name IS '台桌区域名称'; COMMENT ON COLUMN billiards.fact_table_discount.create_time IS '创建时间 (create_time)'; COMMENT ON COLUMN billiards.fact_table_discount.is_delete IS '删除标记 (is_delete)'; COMMENT ON COLUMN billiards.fact_table_discount.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_table_discount.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_topup ( store_id bigint NOT NULL, topup_id bigint NOT NULL, member_id bigint, member_name varchar(100), member_phone varchar(30), card_id bigint, card_type_name varchar(100), pay_amount numeric(14,4), consume_money numeric(14,4), settle_status varchar(30), settle_type varchar(30), settle_name varchar(100), settle_relate_id bigint, pay_time timestamptz, create_time timestamptz, operator_id bigint, operator_name varchar(100), payment_method varchar(50), refund_amount numeric(14,4), cash_amount numeric(14,4), card_amount numeric(14,4), balance_amount numeric(14,4), online_amount numeric(14,4), rounding_amount numeric(14,4), adjust_amount numeric(14,4), goods_money numeric(14,4), table_charge_money numeric(14,4), service_money numeric(14,4), coupon_amount numeric(14,4), order_remark text, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, topup_id) ); COMMENT ON TABLE billiards.fact_topup IS '储值充值结算流水(Topup/SettleList)'; COMMENT ON COLUMN billiards.fact_topup.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_topup.topup_id IS '充值记录 ID (id)'; COMMENT ON COLUMN billiards.fact_topup.member_id IS '会员 ID (memberId)'; COMMENT ON COLUMN billiards.fact_topup.member_name IS '会员姓名 (memberName)'; COMMENT ON COLUMN billiards.fact_topup.member_phone IS '会员手机号 (memberPhone)'; COMMENT ON COLUMN billiards.fact_topup.card_id IS '会员卡 ID (tenantMemberCardId)'; COMMENT ON COLUMN billiards.fact_topup.card_type_name IS '会员卡类型名称 (memberCardTypeName)'; COMMENT ON COLUMN billiards.fact_topup.pay_amount IS '支付金额 (payAmount)'; COMMENT ON COLUMN billiards.fact_topup.consume_money IS '可消费金额/储值 (consumeMoney)'; COMMENT ON COLUMN billiards.fact_topup.settle_status IS '结算状态 (settleStatus)'; COMMENT ON COLUMN billiards.fact_topup.settle_type IS '结算方式 (settleType)'; COMMENT ON COLUMN billiards.fact_topup.settle_name IS '结算名称 (settleName)'; COMMENT ON COLUMN billiards.fact_topup.settle_relate_id IS '结算关联 ID (settleRelateId)'; COMMENT ON COLUMN billiards.fact_topup.pay_time IS '支付时间 (payTime)'; COMMENT ON COLUMN billiards.fact_topup.create_time IS '创建时间 (createTime)'; COMMENT ON COLUMN billiards.fact_topup.operator_id IS '操作人 ID (operatorId)'; COMMENT ON COLUMN billiards.fact_topup.operator_name IS '操作人姓名 (operatorName)'; COMMENT ON COLUMN billiards.fact_topup.payment_method IS '支付方式 (paymentMethod)'; COMMENT ON COLUMN billiards.fact_topup.refund_amount IS '退款金额 (refundAmount)'; COMMENT ON COLUMN billiards.fact_topup.cash_amount IS '现金金额 (cashAmount)'; COMMENT ON COLUMN billiards.fact_topup.card_amount IS '银行卡金额 (cardAmount)'; COMMENT ON COLUMN billiards.fact_topup.balance_amount IS '余额抵扣金额 (balanceAmount)'; COMMENT ON COLUMN billiards.fact_topup.online_amount IS '在线支付金额 (onlineAmount)'; COMMENT ON COLUMN billiards.fact_topup.rounding_amount IS '抹零金额 (roundingAmount)'; COMMENT ON COLUMN billiards.fact_topup.adjust_amount IS '调整金额 (adjustAmount)'; COMMENT ON COLUMN billiards.fact_topup.goods_money IS '商品金额 (goodsMoney)'; COMMENT ON COLUMN billiards.fact_topup.table_charge_money IS '台费金额 (tableChargeMoney)'; COMMENT ON COLUMN billiards.fact_topup.service_money IS '服务费 (serviceMoney)'; COMMENT ON COLUMN billiards.fact_topup.coupon_amount IS '券抵扣金额 (couponAmount)'; COMMENT ON COLUMN billiards.fact_topup.order_remark IS '备注 (orderRemark)'; COMMENT ON COLUMN billiards.fact_topup.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_topup.updated_at IS 'ETL 更新时间'; CREATE TABLE IF NOT EXISTS billiards.fact_coupon_usage ( store_id bigint NOT NULL, usage_id bigint NOT NULL, coupon_code varchar(100), coupon_channel varchar(50), coupon_name varchar(200), sale_price numeric(14,4), coupon_money numeric(14,4), coupon_free_time integer, use_status varchar(30), create_time timestamptz, consume_time timestamptz, operator_id bigint, operator_name varchar(100), table_id bigint, site_order_id bigint, group_package_id bigint, coupon_remark text, deal_id varchar(100), certificate_id varchar(100), verify_id varchar(100), is_delete integer, raw_data jsonb NOT NULL DEFAULT '{}'::jsonb, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (store_id, usage_id) ); COMMENT ON TABLE billiards.fact_coupon_usage IS '平台券验券/核销流水(Coupon/UsageList)'; COMMENT ON COLUMN billiards.fact_coupon_usage.store_id IS '门店 ID'; COMMENT ON COLUMN billiards.fact_coupon_usage.usage_id IS '核销记录 ID (id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.coupon_code IS '券码 (coupon_code)'; COMMENT ON COLUMN billiards.fact_coupon_usage.coupon_channel IS '券渠道 (coupon_channel)'; COMMENT ON COLUMN billiards.fact_coupon_usage.coupon_name IS '券名称 (coupon_name)'; COMMENT ON COLUMN billiards.fact_coupon_usage.sale_price IS '售卖价 (sale_price)'; COMMENT ON COLUMN billiards.fact_coupon_usage.coupon_money IS '券面额 (coupon_money)'; COMMENT ON COLUMN billiards.fact_coupon_usage.coupon_free_time IS '赠送/免单时长 (coupon_free_time)'; COMMENT ON COLUMN billiards.fact_coupon_usage.use_status IS '核销状态 (use_status)'; COMMENT ON COLUMN billiards.fact_coupon_usage.create_time IS '创建时间 (create_time)'; COMMENT ON COLUMN billiards.fact_coupon_usage.consume_time IS '核销时间 (consume_time)'; COMMENT ON COLUMN billiards.fact_coupon_usage.operator_id IS '操作人 ID (operator_id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.operator_name IS '操作人姓名 (operator_name)'; COMMENT ON COLUMN billiards.fact_coupon_usage.table_id IS '台桌 ID (table_id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.site_order_id IS '场馆订单 ID (site_order_id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.group_package_id IS '套餐 ID (group_package_id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.coupon_remark IS '备注 (coupon_remark)'; COMMENT ON COLUMN billiards.fact_coupon_usage.deal_id IS '团购/渠道 deal_id'; COMMENT ON COLUMN billiards.fact_coupon_usage.certificate_id IS '凭证号 (certificate_id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.verify_id IS '核销流水号 (verify_id)'; COMMENT ON COLUMN billiards.fact_coupon_usage.is_delete IS '删除标记 (is_delete)'; COMMENT ON COLUMN billiards.fact_coupon_usage.raw_data IS '原始 JSON'; COMMENT ON COLUMN billiards.fact_coupon_usage.updated_at IS 'ETL 更新时间'; -- ========================= -- ETL admin tables -- ========================= CREATE TYPE IF NOT EXISTS etl_admin.run_status_enum AS ENUM ('SUCC', 'FAIL', 'PARTIAL'); COMMENT ON TYPE etl_admin.run_status_enum IS 'ETL 运行状态枚举(成功/失败/部分成功)'; CREATE TABLE IF NOT EXISTS etl_admin.etl_task ( task_id bigserial PRIMARY KEY, store_id bigint NOT NULL, task_code varchar(50) NOT NULL, description text, enabled boolean NOT NULL DEFAULT true, cursor_field varchar(100), window_minutes_default integer DEFAULT 60, overlap_seconds integer DEFAULT 120, page_size integer DEFAULT 200, retry_max integer DEFAULT 3, params jsonb NOT NULL DEFAULT '{}'::jsonb, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), UNIQUE (store_id, task_code) ); COMMENT ON TABLE etl_admin.etl_task IS 'ETL 任务配置(启停、窗口、分页参数等)'; COMMENT ON COLUMN etl_admin.etl_task.task_id IS '任务 ID(自增主键)'; COMMENT ON COLUMN etl_admin.etl_task.store_id IS '门店 ID(任务所属门店)'; COMMENT ON COLUMN etl_admin.etl_task.task_code IS '任务代码(如 PRODUCTS、ORDERS)'; COMMENT ON COLUMN etl_admin.etl_task.description IS '任务描述'; COMMENT ON COLUMN etl_admin.etl_task.enabled IS '是否启用'; COMMENT ON COLUMN etl_admin.etl_task.cursor_field IS '游标使用的字段(如时间或 ID)'; 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 'API 分页大小'; 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, extra jsonb NOT NULL DEFAULT '{}'::jsonb, last_run_id bigint, updated_at timestamptz NOT NULL DEFAULT now(), UNIQUE (task_id, store_id) ); COMMENT ON TABLE etl_admin.etl_cursor IS 'ETL 游标存储(记录每个任务的上次窗口与 ID)'; COMMENT ON COLUMN etl_admin.etl_cursor.cursor_id IS '游标主键'; COMMENT ON COLUMN etl_admin.etl_cursor.task_id IS '关联任务 ID'; COMMENT ON COLUMN etl_admin.etl_cursor.store_id IS '门店 ID'; 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 '上次处理的 ID(适用于基于 ID 的翻页)'; COMMENT ON COLUMN etl_admin.etl_cursor.extra IS '额外游标信息 (JSON)'; COMMENT ON COLUMN etl_admin.etl_cursor.last_run_id IS '最后一次运行 run_id'; 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 varchar(64) NOT NULL, task_id bigint NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE, store_id bigint NOT NULL, status etl_admin.run_status_enum NOT NULL DEFAULT 'SUCC', started_at timestamptz NOT NULL DEFAULT now(), ended_at timestamptz, window_start timestamptz, window_end timestamptz, window_minutes integer, overlap_seconds integer, fetched_count integer DEFAULT 0, loaded_count integer DEFAULT 0, updated_count integer DEFAULT 0, skipped_count integer DEFAULT 0, error_count integer DEFAULT 0, unknown_fields integer DEFAULT 0, export_dir text, log_path text, request_params jsonb NOT NULL DEFAULT '{}'::jsonb, manifest jsonb NOT NULL DEFAULT '{}'::jsonb, error_message text, extra jsonb NOT NULL DEFAULT '{}'::jsonb ); CREATE INDEX IF NOT EXISTS idx_etl_run_task ON etl_admin.etl_run(task_id, started_at DESC); CREATE INDEX IF NOT EXISTS idx_etl_run_status ON etl_admin.etl_run(status); COMMENT ON TABLE etl_admin.etl_run IS 'ETL 运行记录(针对每次任务执行)'; COMMENT ON COLUMN etl_admin.etl_run.run_id IS '运行记录 ID'; COMMENT ON COLUMN etl_admin.etl_run.run_uuid IS '运行批次 UUID'; COMMENT ON COLUMN etl_admin.etl_run.task_id IS '任务 ID'; COMMENT ON COLUMN etl_admin.etl_run.store_id IS '门店 ID'; 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 '导出 manifest (JSON)'; COMMENT ON COLUMN etl_admin.etl_run.error_message IS '错误信息'; COMMENT ON COLUMN etl_admin.etl_run.extra IS '额外信息 (JSON)';