282 lines
14 KiB
SQL
282 lines
14 KiB
SQL
-- ============================================
|
||
-- 1. member_user 表(会员表)
|
||
-- ============================================
|
||
|
||
-- Step 1: 删除已存在的表(如果需要重建)
|
||
-- DROP TABLE IF EXISTS member_user CASCADE;
|
||
|
||
-- Step 2: 创建 member_user 表
|
||
CREATE TABLE IF NOT EXISTS member_user (
|
||
-- ========== 主键和基础字段(来自BaseEntity)==========
|
||
id BIGSERIAL PRIMARY KEY, -- 主键ID,自增
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间
|
||
|
||
-- ========== 会员核心字段 ==========
|
||
member_no VARCHAR(50) NOT NULL UNIQUE, -- 会员编号(唯一)
|
||
nickname VARCHAR(100), -- 昵称
|
||
phone VARCHAR(255), -- 手机号(AES加密存储)
|
||
gender INTEGER DEFAULT 0, -- 性别:0-未知,1-男,2-女
|
||
birthday DATE, -- 生日
|
||
address VARCHAR(500), -- 地址
|
||
avatar VARCHAR(500), -- 头像URL
|
||
subscribed BOOLEAN DEFAULT FALSE, -- 是否关注服务号
|
||
last_login_at TIMESTAMP, -- 最后登录时间
|
||
|
||
-- ========== 微信相关字段 ==========
|
||
union_id VARCHAR(100), -- 微信UnionID(跨应用唯一标识)
|
||
miniapp_open_id VARCHAR(100), -- 小程序OpenID
|
||
official_open_id VARCHAR(100), -- 服务号OpenID
|
||
|
||
-- ========== 软删除字段 ==========
|
||
is_deleted BOOLEAN DEFAULT FALSE -- 是否删除(软删除标记)
|
||
);
|
||
|
||
-- Step 3: 创建索引
|
||
-- 会员编号索引(唯一索引,加速查询)
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_member_user_member_no ON member_user(member_no);
|
||
|
||
-- UnionID索引(加速跨平台用户查找)
|
||
CREATE INDEX IF NOT EXISTS idx_member_user_union_id ON member_user(union_id);
|
||
|
||
-- 小程序OpenID索引(加速小程序登录查询)
|
||
CREATE INDEX IF NOT EXISTS idx_member_user_miniapp_openid ON member_user(miniapp_open_id);
|
||
|
||
-- 服务号OpenID索引(加速服务号事件处理)
|
||
CREATE INDEX IF NOT EXISTS idx_member_user_official_openid ON member_user(official_open_id);
|
||
|
||
-- 手机号索引(加速手机号查询和去重)
|
||
CREATE INDEX IF NOT EXISTS idx_member_user_phone ON member_user(phone);
|
||
|
||
-- 软删除索引(加速查询未删除的记录)
|
||
CREATE INDEX IF NOT EXISTS idx_member_user_is_deleted ON member_user(is_deleted);
|
||
|
||
-- Step 4: 添加注释
|
||
COMMENT ON TABLE member_user IS '会员表';
|
||
|
||
COMMENT ON COLUMN member_user.id IS '主键ID';
|
||
COMMENT ON COLUMN member_user.created_at IS '创建时间';
|
||
COMMENT ON COLUMN member_user.updated_at IS '更新时间';
|
||
|
||
COMMENT ON COLUMN member_user.member_no IS '会员编号(唯一,格式:MEM + 8位随机字符)';
|
||
COMMENT ON COLUMN member_user.nickname IS '昵称';
|
||
COMMENT ON COLUMN member_user.phone IS '手机号(AES-128-CBC加密存储)';
|
||
COMMENT ON COLUMN member_user.gender IS '性别:0-未知,1-男,2-女';
|
||
COMMENT ON COLUMN member_user.birthday IS '生日';
|
||
COMMENT ON COLUMN member_user.address IS '地址';
|
||
COMMENT ON COLUMN member_user.avatar IS '头像URL';
|
||
COMMENT ON COLUMN member_user.subscribed IS '是否关注服务号:true-已关注,false-未关注';
|
||
COMMENT ON COLUMN member_user.last_login_at IS '最后登录时间';
|
||
|
||
COMMENT ON COLUMN member_user.union_id IS '微信UnionID(用户在开放平台的唯一标识,跨应用相同)';
|
||
COMMENT ON COLUMN member_user.miniapp_open_id IS '小程序OpenID(用户在当前小程序的唯一标识)';
|
||
COMMENT ON COLUMN member_user.official_open_id IS '服务号OpenID(用户在当前服务号的唯一标识)';
|
||
|
||
COMMENT ON COLUMN member_user.is_deleted IS '是否删除(软删除标记):false-正常,true-已删除';
|
||
|
||
|
||
-- ============================================
|
||
-- 2. wechat_user 表(微信用户表)
|
||
-- ============================================
|
||
|
||
-- Step 1: 删除已存在的表(如果需要重建)
|
||
-- DROP TABLE IF EXISTS wechat_user CASCADE;
|
||
|
||
-- Step 2: 创建 wechat_user 表
|
||
CREATE TABLE IF NOT EXISTS wechat_user (
|
||
-- ========== 主键和基础字段(来自BaseEntity)==========
|
||
id BIGSERIAL PRIMARY KEY, -- 主键ID,自增
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间
|
||
|
||
-- ========== 关联字段 ==========
|
||
member_id BIGINT NOT NULL, -- 会员ID(外键)
|
||
|
||
-- ========== 微信标识字段 ==========
|
||
union_id VARCHAR(100), -- 微信UnionID
|
||
miniapp_openid VARCHAR(100), -- 小程序OpenID
|
||
mp_openid VARCHAR(100), -- 服务号OpenID
|
||
|
||
-- ========== 关注状态字段 ==========
|
||
is_subscribed BOOLEAN DEFAULT FALSE, -- 是否关注服务号
|
||
subscribe_time TIMESTAMP, -- 首次关注时间
|
||
unsubscribe_time TIMESTAMP -- 最后一次取消关注时间
|
||
);
|
||
|
||
-- Step 3: 创建外键约束
|
||
ALTER TABLE wechat_user
|
||
ADD CONSTRAINT fk_wechat_user_member
|
||
FOREIGN KEY (member_id) REFERENCES member_user(id) ON DELETE CASCADE;
|
||
|
||
-- Step 4: 创建索引
|
||
-- UnionID索引(加速跨平台用户查找)
|
||
CREATE INDEX IF NOT EXISTS idx_wechat_user_union_id ON wechat_user(union_id);
|
||
|
||
-- 小程序OpenID索引(加速小程序登录查询)
|
||
CREATE INDEX IF NOT EXISTS idx_wechat_user_miniapp_openid ON wechat_user(miniapp_openid);
|
||
|
||
-- 服务号OpenID索引(加速服务号事件处理)
|
||
CREATE INDEX IF NOT EXISTS idx_wechat_user_mp_openid ON wechat_user(mp_openid);
|
||
|
||
-- 会员ID索引(加速关联查询)
|
||
CREATE INDEX IF NOT EXISTS idx_wechat_user_member_id ON wechat_user(member_id);
|
||
|
||
-- Step 5: 添加注释
|
||
COMMENT ON TABLE wechat_user IS '微信用户表';
|
||
|
||
COMMENT ON COLUMN wechat_user.id IS '主键ID';
|
||
COMMENT ON COLUMN wechat_user.created_at IS '创建时间';
|
||
COMMENT ON COLUMN wechat_user.updated_at IS '更新时间';
|
||
|
||
COMMENT ON COLUMN wechat_user.member_id IS '会员ID(关联 member_user 表的 id 字段)';
|
||
COMMENT ON COLUMN wechat_user.union_id IS '微信UnionID(用户在开放平台的唯一标识)';
|
||
COMMENT ON COLUMN wechat_user.miniapp_openid IS '小程序OpenID(用户在当前小程序的唯一标识)';
|
||
COMMENT ON COLUMN wechat_user.mp_openid IS '服务号OpenID(用户在当前服务号的唯一标识)';
|
||
|
||
COMMENT ON COLUMN wechat_user.is_subscribed IS '是否关注服务号:true-已关注,false-未关注';
|
||
COMMENT ON COLUMN wechat_user.subscribe_time IS '首次关注时间';
|
||
COMMENT ON COLUMN wechat_user.unsubscribe_time IS '最后一次取消关注时间';
|
||
|
||
|
||
-- ============================================
|
||
-- 3. member_card 表(会员卡类型表)
|
||
-- ============================================
|
||
CREATE TABLE IF NOT EXISTS member_card (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
deleted_at TIMESTAMP,
|
||
|
||
member_card_id BIGSERIAL,
|
||
member_card_name VARCHAR(100) NOT NULL,
|
||
member_card_type VARCHAR(20) NOT NULL,
|
||
member_card_price DECIMAL(10, 2) NOT NULL,
|
||
member_card_validity_days INTEGER,
|
||
member_card_total_times INTEGER,
|
||
member_card_amount DECIMAL(10, 2),
|
||
member_card_status INTEGER DEFAULT 1 NOT NULL,
|
||
extra_config TEXT DEFAULT '{}'
|
||
);
|
||
|
||
COMMENT ON TABLE member_card IS '会员卡类型表';
|
||
COMMENT ON COLUMN member_card.member_card_id IS '会员卡ID';
|
||
COMMENT ON COLUMN member_card.member_card_name IS '会员卡名称';
|
||
COMMENT ON COLUMN member_card.member_card_type IS '会员卡类型:TIME_CARD-时长卡, COUNT_CARD-次卡, STORED_VALUE_CARD-储值卡';
|
||
COMMENT ON COLUMN member_card.member_card_price IS '会员卡价格';
|
||
COMMENT ON COLUMN member_card.member_card_validity_days IS '有效天数(时长卡用)';
|
||
COMMENT ON COLUMN member_card.member_card_total_times IS '总次数(次卡用)';
|
||
COMMENT ON COLUMN member_card.member_card_amount IS '面额(储值卡用)';
|
||
COMMENT ON COLUMN member_card.member_card_status IS '状态:0-下架, 1-上架';
|
||
COMMENT ON COLUMN member_card.extra_config IS '扩展配置(JSON格式)';
|
||
|
||
|
||
-- ============================================
|
||
-- 4. member_card_record 表(会员卡记录表)
|
||
-- ============================================
|
||
CREATE TABLE IF NOT EXISTS member_card_record (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
deleted_at TIMESTAMP,
|
||
|
||
member_card_record_id BIGSERIAL,
|
||
member_id BIGINT NOT NULL,
|
||
member_card_id BIGINT NOT NULL,
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
|
||
remaining_times INTEGER DEFAULT 0,
|
||
remaining_amount DECIMAL(10, 2) DEFAULT 0.00,
|
||
expire_time TIMESTAMP,
|
||
source_order_id BIGINT,
|
||
purchase_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
version INTEGER DEFAULT 0 NOT NULL,
|
||
card_composition TEXT
|
||
);
|
||
|
||
-- 索引优化
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_record_member_id ON member_card_record(member_id);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_record_status ON member_card_record(status);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_record_expire_time ON member_card_record(expire_time);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_record_member_status ON member_card_record(member_id, status);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_record_status_expire ON member_card_record(status, expire_time)
|
||
WHERE status = 'ACTIVE';
|
||
|
||
COMMENT ON TABLE member_card_record IS '会员卡记录表(会员持有的卡)';
|
||
COMMENT ON COLUMN member_card_record.member_card_record_id IS '会员卡记录ID';
|
||
COMMENT ON COLUMN member_card_record.member_id IS '会员ID';
|
||
COMMENT ON COLUMN member_card_record.member_card_id IS '会员卡类型ID';
|
||
COMMENT ON COLUMN member_card_record.status IS '状态:ACTIVE-有效, USED_UP-用完, EXPIRED-过期, REFUNDED-已退款';
|
||
COMMENT ON COLUMN member_card_record.remaining_times IS '剩余次数';
|
||
COMMENT ON COLUMN member_card_record.remaining_amount IS '剩余金额';
|
||
COMMENT ON COLUMN member_card_record.expire_time IS '到期时间';
|
||
COMMENT ON COLUMN member_card_record.source_order_id IS '来源订单ID';
|
||
COMMENT ON COLUMN member_card_record.purchase_time IS '购买时间';
|
||
COMMENT ON COLUMN member_card_record.version IS '乐观锁版本号';
|
||
COMMENT ON COLUMN member_card_record.card_composition IS '卡片组成(JSON格式,用于组合卡)';
|
||
|
||
|
||
-- ============================================
|
||
-- 5. member_card_transactions 表(会员卡交易流水表)
|
||
-- ============================================
|
||
CREATE TABLE IF NOT EXISTS member_card_transactions (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
member_card_record_id BIGINT NOT NULL,
|
||
member_id BIGINT NOT NULL,
|
||
member_card_id BIGINT NOT NULL,
|
||
operation_type VARCHAR(20) NOT NULL,
|
||
change_amount INTEGER DEFAULT 0,
|
||
change_balance DECIMAL(10, 2) DEFAULT 0.00,
|
||
after_remaining_count INTEGER DEFAULT 0,
|
||
after_remaining_balance DECIMAL(10, 2) DEFAULT 0.00,
|
||
related_biz_type VARCHAR(20),
|
||
source_order_id BIGINT,
|
||
remark VARCHAR(500),
|
||
is_archived BOOLEAN DEFAULT FALSE,
|
||
archived_at TIMESTAMP
|
||
);
|
||
|
||
-- 索引优化
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_member_id ON member_card_transactions(member_id);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_record_id ON member_card_transactions(member_card_record_id);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_created_at ON member_card_transactions(created_at);
|
||
CREATE INDEX IF NOT EXISTS idx_member_card_transactions_member_type_time
|
||
ON member_card_transactions(member_id, operation_type, created_at);
|
||
|
||
COMMENT ON TABLE member_card_transactions IS '会员卡交易流水表';
|
||
COMMENT ON COLUMN member_card_transactions.operation_type IS '操作类型:PURCHASE-购买, DEDUCT-扣次/扣费, RENEW-续费, REFUND-退款, EXPIRE-过期';
|
||
COMMENT ON COLUMN member_card_transactions.change_amount IS '变动次数';
|
||
COMMENT ON COLUMN member_card_transactions.change_balance IS '变动金额';
|
||
COMMENT ON COLUMN member_card_transactions.after_remaining_count IS '变动后剩余次数';
|
||
COMMENT ON COLUMN member_card_transactions.after_remaining_balance IS '变动后剩余金额';
|
||
COMMENT ON COLUMN member_card_transactions.related_biz_type IS '关联业务类型:GROUP_CLASS-团课, PT_CLASS-私教, CHECK_IN-签到';
|
||
COMMENT ON COLUMN member_card_transactions.is_archived IS '是否已归档';
|
||
COMMENT ON COLUMN member_card_transactions.archived_at IS '归档时间';
|
||
|
||
|
||
-- ============================================
|
||
-- 6. refund_application 表(退款申请表)
|
||
-- ============================================
|
||
CREATE TABLE IF NOT EXISTS refund_application (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
deleted_at TIMESTAMP,
|
||
|
||
record_id BIGINT NOT NULL,
|
||
member_id BIGINT NOT NULL,
|
||
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||
reason VARCHAR(500),
|
||
apply_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
audit_time TIMESTAMP,
|
||
auditor_id BIGINT,
|
||
audit_remark VARCHAR(500),
|
||
refund_amount DECIMAL(10, 2)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_refund_application_record_id ON refund_application(record_id);
|
||
CREATE INDEX IF NOT EXISTS idx_refund_application_status ON refund_application(status);
|
||
|
||
COMMENT ON TABLE refund_application IS '退款申请表';
|
||
COMMENT ON COLUMN refund_application.status IS '状态:PENDING-待审核, APPROVED-已批准, REJECTED-已拒绝, PROCESSING-处理中, SUCCESS-成功, FAILED-失败';
|