feat: P1-P3 全栈集成 — 数据库基础 + DWS 扩展 + 小程序鉴权 + 工程化体系
## P1 数据库基础 - zqyy_app: 创建 auth/biz schema、FDW 连接 etl_feiqiu - etl_feiqiu: 创建 app schema RLS 视图、商品库存预警表 - 清理 assistant_abolish 残留数据 ## P2 ETL/DWS 扩展 - 新增 DWS 助教订单贡献度表 (dws.assistant_order_contribution) - 新增 assistant_order_contribution_task 任务及 RLS 视图 - member_consumption 增加充值字段、assistant_daily 增加处罚字段 - 更新 ODS/DWD/DWS 任务文档及业务规则文档 - 更新 consistency_checker、flow_runner、task_registry 等核心模块 ## P3 小程序鉴权系统 - 新增 xcx_auth 路由/schema(微信登录 + JWT) - 新增 wechat/role/matching/application 服务层 - zqyy_app 鉴权表迁移 + 角色权限种子数据 - auth/dependencies.py 支持小程序 JWT 鉴权 ## 文档与审计 - 新增 DOCUMENTATION-MAP 文档导航 - 新增 7 份 BD_Manual 数据库变更文档 - 更新 DDL 基线快照(etl_feiqiu 6 schema + zqyy_app auth) - 新增全栈集成审计记录、部署检查清单更新 - 新增 BACKLOG 路线图、FDW→Core 迁移计划 ## Kiro 工程化 - 新增 5 个 Spec(P1/P2/P3/全栈集成/核心业务) - 新增审计自动化脚本(agent_on_stop/build_audit_context/compliance_prescan) - 新增 6 个 Hook(合规检查/会话日志/提交审计等) - 新增 doc-map steering 文件 ## 运维与测试 - 新增 ops 脚本:迁移验证/API 健康检查/ETL 监控/集成报告 - 新增属性测试:test_dws_contribution / test_auth_system - 清理过期 export 报告文件 - 更新 .gitignore 排除规则
This commit is contained in:
280
db/zqyy_app/migrations/2026-02-25__p3_create_auth_tables.sql
Normal file
280
db/zqyy_app/migrations/2026-02-25__p3_create_auth_tables.sql
Normal file
@@ -0,0 +1,280 @@
|
||||
-- =============================================================================
|
||||
-- 迁移脚本:创建 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;
|
||||
Reference in New Issue
Block a user