Files
medical-mall/doc_mall/consumer/sql/promotion_system_tables.sql

289 lines
10 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =====================================================
-- 推销模式功能 - 数据库脚本(第一阶段)
-- 包含:用户余额系统、分享免单系统、会员等级系统
-- 创建日期: 2026-03-06
-- 注意请在Supabase SQL编辑器中分段执行
-- =====================================================
-- =====================================================
-- 0. 启用必要扩展
-- =====================================================
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- =====================================================
-- 一、用户余额系统
-- =====================================================
-- 1. 用户余额表
DROP TABLE IF EXISTS ml_user_balance CASCADE;
CREATE TABLE ml_user_balance (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID NOT NULL,
balance DECIMAL(10,2) DEFAULT 0,
frozen_balance DECIMAL(10,2) DEFAULT 0,
total_earned DECIMAL(10,2) DEFAULT 0,
total_withdrawn DECIMAL(10,2) DEFAULT 0,
updated_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id)
);
CREATE INDEX IF NOT EXISTS idx_user_balance_user_id ON ml_user_balance(user_id);
COMMENT ON TABLE ml_user_balance IS '用户余额表';
COMMENT ON COLUMN ml_user_balance.balance IS '可用余额';
COMMENT ON COLUMN ml_user_balance.frozen_balance IS '冻结余额';
COMMENT ON COLUMN ml_user_balance.total_earned IS '累计获得';
COMMENT ON COLUMN ml_user_balance.total_withdrawn IS '累计提现';
-- 2. 余额变动记录表
DROP TABLE IF EXISTS ml_balance_records CASCADE;
CREATE TABLE ml_balance_records (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID NOT NULL,
type VARCHAR(50) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
balance_before DECIMAL(10,2) NOT NULL DEFAULT 0,
balance_after DECIMAL(10,2) NOT NULL DEFAULT 0,
related_id UUID,
description VARCHAR(200),
operator_id UUID,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_balance_records_user_id ON ml_balance_records(user_id);
CREATE INDEX IF NOT EXISTS idx_balance_records_type ON ml_balance_records(type);
CREATE INDEX IF NOT EXISTS idx_balance_records_created_at ON ml_balance_records(created_at);
COMMENT ON TABLE ml_balance_records IS '余额变动记录表';
COMMENT ON COLUMN ml_balance_records.type IS '类型free_order-免单奖励rebate-返利withdraw-提现clear-清零manual-手动调整';
-- =====================================================
-- 二、分享免单系统
-- =====================================================
-- 1. 分享记录表
DROP TABLE IF EXISTS ml_share_records CASCADE;
CREATE TABLE ml_share_records (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID NOT NULL,
product_id UUID NOT NULL,
order_id UUID NOT NULL,
order_item_id UUID,
share_code VARCHAR(20) NOT NULL UNIQUE,
product_name VARCHAR(200),
product_image VARCHAR(500),
product_price DECIMAL(10,2),
required_count INT DEFAULT 4,
current_count INT DEFAULT 0,
status INT DEFAULT 0,
reward_amount DECIMAL(10,2),
created_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ,
expired_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_share_records_user_id ON ml_share_records(user_id);
CREATE INDEX IF NOT EXISTS idx_share_records_share_code ON ml_share_records(share_code);
CREATE INDEX IF NOT EXISTS idx_share_records_status ON ml_share_records(status);
COMMENT ON TABLE ml_share_records IS '分享免单记录表';
COMMENT ON COLUMN ml_share_records.status IS '状态0-进行中1-已完成2-已失效3-已过期';
-- 2. 二级购买记录表
DROP TABLE IF EXISTS ml_secondary_purchases CASCADE;
CREATE TABLE ml_secondary_purchases (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
share_record_id UUID NOT NULL,
buyer_id UUID NOT NULL,
order_id UUID NOT NULL,
quantity INT DEFAULT 1,
unit_price DECIMAL(10,2),
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(order_id, share_record_id)
);
CREATE INDEX IF NOT EXISTS idx_secondary_purchases_share_record_id ON ml_secondary_purchases(share_record_id);
CREATE INDEX IF NOT EXISTS idx_secondary_purchases_buyer_id ON ml_secondary_purchases(buyer_id);
COMMENT ON TABLE ml_secondary_purchases IS '二级用户购买记录表';
-- 3. 免单奖励记录表
DROP TABLE IF EXISTS ml_free_order_rewards CASCADE;
CREATE TABLE ml_free_order_rewards (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID NOT NULL,
share_record_id UUID NOT NULL,
amount DECIMAL(10,2) NOT NULL,
status INT DEFAULT 0,
balance_record_id UUID,
cleared_at TIMESTAMPTZ,
cleared_by UUID,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_free_order_rewards_user_id ON ml_free_order_rewards(user_id);
CREATE INDEX IF NOT EXISTS idx_free_order_rewards_status ON ml_free_order_rewards(status);
COMMENT ON TABLE ml_free_order_rewards IS '免单奖励记录表';
COMMENT ON COLUMN ml_free_order_rewards.status IS '状态0-待发放1-已发放2-已清零';
-- =====================================================
-- 三、会员等级系统
-- =====================================================
-- 1. 会员等级配置表
DROP TABLE IF EXISTS ml_member_levels CASCADE;
CREATE TABLE ml_member_levels (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
min_amount DECIMAL(10,2) DEFAULT 0,
discount DECIMAL(5,4) DEFAULT 1.0000,
icon VARCHAR(200),
description TEXT,
sort_order INT DEFAULT 0,
status INT DEFAULT 1,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE ml_member_levels IS '会员等级配置表';
COMMENT ON COLUMN ml_member_levels.discount IS '折扣率0.85表示85折';
-- 初始化会员等级数据
INSERT INTO ml_member_levels (id, name, min_amount, discount, description, sort_order) VALUES
(0, '普通会员', 0, 1.0000, '注册即可成为普通会员', 0),
(1, '铜牌会员', 500, 0.9800, '累计消费500元升级', 1),
(2, '银牌会员', 2000, 0.9500, '累计消费2000元升级', 2),
(3, '金牌会员', 5000, 0.9200, '累计消费5000元升级', 3),
(4, '钻石会员', 10000, 0.8800, '累计消费10000元升级', 4),
(5, 'VIP会员', 0, 0.8500, '商家特邀会员', 5);
-- 2. 会员等级变更记录表
DROP TABLE IF EXISTS ml_member_level_logs CASCADE;
CREATE TABLE ml_member_level_logs (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID NOT NULL,
old_level INT DEFAULT 0,
new_level INT NOT NULL,
reason VARCHAR(200),
operator_id UUID,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_member_level_logs_user_id ON ml_member_level_logs(user_id);
COMMENT ON TABLE ml_member_level_logs IS '会员等级变更记录表';
-- =====================================================
-- 四、RLS 策略
-- =====================================================
-- 用户余额表 RLS
ALTER TABLE ml_user_balance ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can view own balance" ON ml_user_balance;
CREATE POLICY "Users can view own balance"
ON ml_user_balance FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
DROP POLICY IF EXISTS "Users can insert own balance" ON ml_user_balance;
CREATE POLICY "Users can insert own balance"
ON ml_user_balance FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = user_id);
DROP POLICY IF EXISTS "Users can update own balance" ON ml_user_balance;
CREATE POLICY "Users can update own balance"
ON ml_user_balance FOR UPDATE
TO authenticated
USING (auth.uid() = user_id);
-- 余额记录表 RLS
ALTER TABLE ml_balance_records ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can view own balance records" ON ml_balance_records;
CREATE POLICY "Users can view own balance records"
ON ml_balance_records FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
DROP POLICY IF EXISTS "Users can insert own balance records" ON ml_balance_records;
CREATE POLICY "Users can insert own balance records"
ON ml_balance_records FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = user_id);
-- 分享记录表 RLS
ALTER TABLE ml_share_records ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can view own share records" ON ml_share_records;
CREATE POLICY "Users can view own share records"
ON ml_share_records FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
DROP POLICY IF EXISTS "Users can insert own share records" ON ml_share_records;
CREATE POLICY "Users can insert own share records"
ON ml_share_records FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = user_id);
DROP POLICY IF EXISTS "Users can update own share records" ON ml_share_records;
CREATE POLICY "Users can update own share records"
ON ml_share_records FOR UPDATE
TO authenticated
USING (auth.uid() = user_id);
-- 允许通过分享码查询
DROP POLICY IF EXISTS "Anyone can view by share code" ON ml_share_records;
CREATE POLICY "Anyone can view by share code"
ON ml_share_records FOR SELECT
TO authenticated, anon
USING (share_code IS NOT NULL);
-- 二级购买记录表 RLS
ALTER TABLE ml_secondary_purchases ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can view own secondary purchases" ON ml_secondary_purchases;
CREATE POLICY "Users can view own secondary purchases"
ON ml_secondary_purchases FOR SELECT
TO authenticated
USING (buyer_id = auth.uid() OR EXISTS (
SELECT 1 FROM ml_share_records WHERE id = share_record_id AND user_id = auth.uid()
));
DROP POLICY IF EXISTS "Users can insert secondary purchases" ON ml_secondary_purchases;
CREATE POLICY "Users can insert secondary purchases"
ON ml_secondary_purchases FOR INSERT
TO authenticated
WITH CHECK (true);
-- 免单奖励记录表 RLS
ALTER TABLE ml_free_order_rewards ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can view own rewards" ON ml_free_order_rewards;
CREATE POLICY "Users can view own rewards"
ON ml_free_order_rewards FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
-- 会员等级配置表 RLS
ALTER TABLE ml_member_levels ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Anyone can view member levels" ON ml_member_levels;
CREATE POLICY "Anyone can view member levels"
ON ml_member_levels FOR SELECT
TO authenticated, anon
USING (status = 1);
-- 会员等级变更记录表 RLS
ALTER TABLE ml_member_level_logs ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can view own level logs" ON ml_member_level_logs;
CREATE POLICY "Users can view own level logs"
ON ml_member_level_logs FOR SELECT
TO authenticated
USING (auth.uid() = user_id);