-- ============================================================================= -- 迁移脚本:创建 auth Schema 认证业务表 -- 日期:2026-02-25 -- 目标库:test_zqyy_app(通过 APP_DB_DSN 连接) -- 说明:在 auth Schema 下创建用户认证系统所需的 8 张业务表: -- users、user_applications、site_code_mapping、roles、permissions、 -- role_permissions、user_site_roles、user_assistant_binding -- 包含字段定义、约束、索引、外键。使用 IF NOT EXISTS 幂等语法。 -- 前提:auth Schema 已由 P1 迁移脚本创建 -- (2026-02-24__p1_create_auth_biz_schemas.sql) -- 需求:1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10 -- ============================================================================= -- 确保 auth Schema 存在(幂等) CREATE SCHEMA IF NOT EXISTS auth; -- --------------------------------------------------------------------------- -- 1. users — 微信用户主表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.users ( id SERIAL PRIMARY KEY, wx_openid VARCHAR(128) NOT NULL, wx_union_id VARCHAR(128), wx_avatar_url VARCHAR(512), nickname VARCHAR(50), phone VARCHAR(20), status VARCHAR(20) NOT NULL DEFAULT 'pending', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- wx_openid 唯一约束(幂等:先检查再添加) DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_users_wx_openid' AND conrelid = 'auth.users'::regclass ) THEN ALTER TABLE auth.users ADD CONSTRAINT uq_users_wx_openid UNIQUE (wx_openid); END IF; END $$; -- 索引 CREATE INDEX IF NOT EXISTS ix_users_wx_openid ON auth.users (wx_openid); -- --------------------------------------------------------------------------- -- 2. site_code_mapping — 球房ID与门店映射表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.site_code_mapping ( id SERIAL PRIMARY KEY, site_code VARCHAR(10) NOT NULL, site_id BIGINT NOT NULL, site_name VARCHAR(100), tenant_id INT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- site_code 唯一约束(格式:2字母+3数字,如 AB123) DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_site_code_mapping_site_code' AND conrelid = 'auth.site_code_mapping'::regclass ) THEN ALTER TABLE auth.site_code_mapping ADD CONSTRAINT uq_site_code_mapping_site_code UNIQUE (site_code); END IF; END $$; -- site_id 唯一约束 DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_site_code_mapping_site_id' AND conrelid = 'auth.site_code_mapping'::regclass ) THEN ALTER TABLE auth.site_code_mapping ADD CONSTRAINT uq_site_code_mapping_site_id UNIQUE (site_id); END IF; END $$; -- 索引 CREATE INDEX IF NOT EXISTS ix_site_code_mapping_site_code ON auth.site_code_mapping (site_code); -- --------------------------------------------------------------------------- -- 3. roles — 角色定义表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.roles ( id SERIAL PRIMARY KEY, code VARCHAR(50) NOT NULL, name VARCHAR(100), description TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_roles_code' AND conrelid = 'auth.roles'::regclass ) THEN ALTER TABLE auth.roles ADD CONSTRAINT uq_roles_code UNIQUE (code); END IF; END $$; -- --------------------------------------------------------------------------- -- 4. permissions — 权限定义表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.permissions ( id SERIAL PRIMARY KEY, code VARCHAR(50) NOT NULL, name VARCHAR(100), description TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_permissions_code' AND conrelid = 'auth.permissions'::regclass ) THEN ALTER TABLE auth.permissions ADD CONSTRAINT uq_permissions_code UNIQUE (code); END IF; END $$; -- --------------------------------------------------------------------------- -- 5. role_permissions — 角色-权限关联表(联合主键) -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.role_permissions ( role_id INT NOT NULL, permission_id INT NOT NULL, PRIMARY KEY (role_id, permission_id) ); -- 外键(幂等添加) DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_role_permissions_role_id' AND conrelid = 'auth.role_permissions'::regclass ) THEN ALTER TABLE auth.role_permissions ADD CONSTRAINT fk_role_permissions_role_id FOREIGN KEY (role_id) REFERENCES auth.roles (id) ON DELETE CASCADE; END IF; IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_role_permissions_permission_id' AND conrelid = 'auth.role_permissions'::regclass ) THEN ALTER TABLE auth.role_permissions ADD CONSTRAINT fk_role_permissions_permission_id FOREIGN KEY (permission_id) REFERENCES auth.permissions (id) ON DELETE CASCADE; END IF; END $$; -- --------------------------------------------------------------------------- -- 6. user_applications — 用户入驻申请表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.user_applications ( id SERIAL PRIMARY KEY, user_id INT NOT NULL, site_code VARCHAR(10) NOT NULL, site_id BIGINT, applied_role_text VARCHAR(100) NOT NULL, employee_number VARCHAR(50), phone VARCHAR(20) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', reviewer_id INT, review_note TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), reviewed_at TIMESTAMPTZ ); -- 外键 DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_user_applications_user_id' AND conrelid = 'auth.user_applications'::regclass ) THEN ALTER TABLE auth.user_applications ADD CONSTRAINT fk_user_applications_user_id FOREIGN KEY (user_id) REFERENCES auth.users (id) ON DELETE CASCADE; END IF; END $$; -- 索引 CREATE INDEX IF NOT EXISTS ix_user_applications_user_id ON auth.user_applications (user_id); CREATE INDEX IF NOT EXISTS ix_user_applications_status ON auth.user_applications (status); -- --------------------------------------------------------------------------- -- 7. user_site_roles — 用户-门店-角色关联表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.user_site_roles ( id SERIAL PRIMARY KEY, user_id INT NOT NULL, site_id BIGINT NOT NULL, role_id INT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- 外键 DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_user_site_roles_user_id' AND conrelid = 'auth.user_site_roles'::regclass ) THEN ALTER TABLE auth.user_site_roles ADD CONSTRAINT fk_user_site_roles_user_id FOREIGN KEY (user_id) REFERENCES auth.users (id) ON DELETE CASCADE; END IF; IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_user_site_roles_role_id' AND conrelid = 'auth.user_site_roles'::regclass ) THEN ALTER TABLE auth.user_site_roles ADD CONSTRAINT fk_user_site_roles_role_id FOREIGN KEY (role_id) REFERENCES auth.roles (id) ON DELETE CASCADE; END IF; END $$; -- 唯一约束:同一用户在同一门店下不能重复分配同一角色 DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'uq_user_site_roles_user_site_role' AND conrelid = 'auth.user_site_roles'::regclass ) THEN ALTER TABLE auth.user_site_roles ADD CONSTRAINT uq_user_site_roles_user_site_role UNIQUE (user_id, site_id, role_id); END IF; END $$; -- 索引 CREATE INDEX IF NOT EXISTS ix_user_site_roles_user_site ON auth.user_site_roles (user_id, site_id); -- --------------------------------------------------------------------------- -- 8. user_assistant_binding — 用户-人员绑定表 -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS auth.user_assistant_binding ( id SERIAL PRIMARY KEY, user_id INT NOT NULL, site_id BIGINT NOT NULL, assistant_id BIGINT, staff_id BIGINT, binding_type VARCHAR(20) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- 外键 DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_user_assistant_binding_user_id' AND conrelid = 'auth.user_assistant_binding'::regclass ) THEN ALTER TABLE auth.user_assistant_binding ADD CONSTRAINT fk_user_assistant_binding_user_id FOREIGN KEY (user_id) REFERENCES auth.users (id) ON DELETE CASCADE; END IF; END $$; -- --------------------------------------------------------------------------- -- 授予 app_user 对新表的 SEQUENCE 使用权限(SERIAL 字段需要) -- --------------------------------------------------------------------------- GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA auth TO app_user; -- ============================================================================= -- 回滚脚本(按逆序执行) -- ============================================================================= -- DROP TABLE IF EXISTS auth.user_assistant_binding CASCADE; -- DROP TABLE IF EXISTS auth.user_site_roles CASCADE; -- DROP TABLE IF EXISTS auth.user_applications CASCADE; -- DROP TABLE IF EXISTS auth.role_permissions CASCADE; -- DROP TABLE IF EXISTS auth.permissions CASCADE; -- DROP TABLE IF EXISTS auth.roles CASCADE; -- DROP TABLE IF EXISTS auth.site_code_mapping CASCADE; -- DROP TABLE IF EXISTS auth.users CASCADE;