241 lines
8.6 KiB
SQL
241 lines
8.6 KiB
SQL
-- =============================================================================
|
||
-- app schema DDL — 面向外部访问的视图/函数 + RLS 策略
|
||
-- 说明:以视图封装 DWS/Core 层数据,所有视图启用 RLS,以 site_id 过滤
|
||
-- 不存储实际数据,仅做访问层
|
||
-- =============================================================================
|
||
|
||
CREATE SCHEMA IF NOT EXISTS app;
|
||
SET search_path TO app;
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 应用角色(供 FDW 和外部应用使用)
|
||
-- -----------------------------------------------------------------------------
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app_reader') THEN
|
||
CREATE ROLE app_reader;
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
GRANT USAGE ON SCHEMA app TO app_reader;
|
||
GRANT USAGE ON SCHEMA core TO app_reader;
|
||
GRANT USAGE ON SCHEMA dws TO app_reader;
|
||
|
||
-- =============================================================================
|
||
-- 第一部分:基于 Core 层的视图
|
||
-- =============================================================================
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 1. v_site — 门店视图
|
||
-- -----------------------------------------------------------------------------
|
||
CREATE OR REPLACE VIEW app.v_site AS
|
||
SELECT
|
||
s.site_id,
|
||
s.tenant_id,
|
||
s.shop_name,
|
||
s.site_label,
|
||
s.shop_status
|
||
FROM core.dim_site s;
|
||
|
||
COMMENT ON VIEW app.v_site IS '门店视图:封装 core.dim_site,供外部应用访问。';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 2. v_member — 会员视图
|
||
-- -----------------------------------------------------------------------------
|
||
CREATE OR REPLACE VIEW app.v_member AS
|
||
SELECT
|
||
m.member_id,
|
||
m.system_member_id,
|
||
m.tenant_id,
|
||
m.register_site_id AS site_id,
|
||
m.mobile,
|
||
m.nickname,
|
||
m.member_card_grade_name,
|
||
m.status
|
||
FROM core.dim_member m;
|
||
|
||
COMMENT ON VIEW app.v_member IS '会员视图:封装 core.dim_member,以 register_site_id 作为 site_id。';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 3. v_assistant — 助教视图
|
||
-- -----------------------------------------------------------------------------
|
||
CREATE OR REPLACE VIEW app.v_assistant AS
|
||
SELECT
|
||
a.assistant_id,
|
||
a.tenant_id,
|
||
a.site_id,
|
||
a.real_name,
|
||
a.nickname,
|
||
a.mobile,
|
||
a.level,
|
||
a.assistant_status,
|
||
a.leave_status
|
||
FROM core.dim_assistant a;
|
||
|
||
COMMENT ON VIEW app.v_assistant IS '助教视图:封装 core.dim_assistant。';
|
||
|
||
-- =============================================================================
|
||
-- 第二部分:基于 DWS 层的汇总视图
|
||
-- =============================================================================
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 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_count,
|
||
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;
|
||
|
||
COMMENT ON VIEW app.v_assistant_daily IS '助教日明细视图:封装 dws.dws_assistant_daily_detail。';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 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.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;
|
||
|
||
COMMENT ON VIEW app.v_finance_daily IS '财务日报视图:封装 dws.dws_finance_daily_summary。';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 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.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;
|
||
|
||
COMMENT ON VIEW app.v_member_consumption IS '会员消费汇总视图:封装 dws.dws_member_consumption_summary。';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 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.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;
|
||
|
||
COMMENT ON VIEW app.v_order_summary IS '订单汇总视图:封装 dws.dws_order_summary。';
|
||
|
||
-- =============================================================================
|
||
-- 第三部分:RLS 策略
|
||
-- 说明:所有视图基于 site_id 隔离,通过会话变量 app.current_site_id 过滤
|
||
-- 使用方式:SET app.current_site_id = '2790685415443269';
|
||
-- =============================================================================
|
||
|
||
-- 对视图底层表启用 RLS(视图本身不支持 RLS,需在底层表上设置)
|
||
-- 由于 app schema 的视图引用 core/dws 表,RLS 需在源表上配置
|
||
|
||
-- core 层 RLS
|
||
ALTER TABLE core.dim_site ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE core.dim_member ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE core.dim_assistant ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE core.dim_table ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE core.fact_settlement ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE core.fact_payment ENABLE ROW LEVEL SECURITY;
|
||
|
||
-- core 层策略
|
||
CREATE POLICY site_isolation_dim_site ON core.dim_site
|
||
FOR SELECT TO app_reader
|
||
USING (site_id = current_setting('app.current_site_id')::bigint);
|
||
|
||
CREATE POLICY site_isolation_dim_member ON core.dim_member
|
||
FOR SELECT TO app_reader
|
||
USING (register_site_id = current_setting('app.current_site_id')::bigint);
|
||
|
||
CREATE POLICY site_isolation_dim_assistant ON core.dim_assistant
|
||
FOR SELECT TO app_reader
|
||
USING (site_id = current_setting('app.current_site_id')::bigint);
|
||
|
||
CREATE POLICY site_isolation_dim_table ON core.dim_table
|
||
FOR SELECT TO app_reader
|
||
USING (site_id = current_setting('app.current_site_id')::bigint);
|
||
|
||
CREATE POLICY site_isolation_fact_settlement ON core.fact_settlement
|
||
FOR SELECT TO app_reader
|
||
USING (site_id = current_setting('app.current_site_id')::bigint);
|
||
|
||
CREATE POLICY site_isolation_fact_payment ON core.fact_payment
|
||
FOR SELECT TO app_reader
|
||
USING (site_id = current_setting('app.current_site_id')::bigint);
|
||
|
||
-- =============================================================================
|
||
-- 第四部分:授权
|
||
-- =============================================================================
|
||
|
||
-- 授予 app_reader 对 core 表的 SELECT 权限
|
||
GRANT SELECT ON ALL TABLES IN SCHEMA core TO app_reader;
|
||
GRANT SELECT ON ALL TABLES IN SCHEMA app TO app_reader;
|
||
|
||
-- 授予对 dws 表的 SELECT 权限(视图需要)
|
||
GRANT SELECT ON ALL TABLES IN SCHEMA dws TO app_reader;
|
||
|
||
-- 设置默认权限(未来新建的表自动授权)
|
||
ALTER DEFAULT PRIVILEGES IN SCHEMA core GRANT SELECT ON TABLES TO app_reader;
|
||
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT ON TABLES TO app_reader;
|
||
ALTER DEFAULT PRIVILEGES IN SCHEMA dws GRANT SELECT ON TABLES TO app_reader;
|