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:
164
db/zqyy_app/README.md
Normal file
164
db/zqyy_app/README.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# db/zqyy_app — 业务数据库
|
||||
|
||||
`zqyy_app` 是 NeoZQYY 的业务数据库,存储用户认证、任务队列、调度配置、执行日志等数据。
|
||||
测试库:`test_zqyy_app`(开发和测试环境默认连接)。
|
||||
|
||||
## Schema 架构
|
||||
|
||||
| Schema | 用途 | 状态 |
|
||||
|--------|------|------|
|
||||
| `auth` | 用户认证与权限(微信用户、角色、权限、申请、绑定) | 已建表 |
|
||||
| `biz` | 业务数据(预留,未来存储门店业务数据) | 已创建,待建表 |
|
||||
| `public` | 管理后台(admin_users、task_queue、scheduled_tasks、task_execution_log) | 已建表 |
|
||||
|
||||
## auth Schema — 认证系统(8 张表)
|
||||
|
||||
### auth.users — 微信用户主表
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| wx_openid | VARCHAR(128) UNIQUE | 微信 OpenID |
|
||||
| wx_union_id | VARCHAR(128) | 微信 UnionID |
|
||||
| wx_avatar_url | VARCHAR(512) | 头像 URL |
|
||||
| nickname | VARCHAR(50) | 昵称 |
|
||||
| phone | VARCHAR(20) | 手机号 |
|
||||
| status | VARCHAR(20) | 状态:pending / approved / rejected / disabled |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
| updated_at | TIMESTAMPTZ | 更新时间 |
|
||||
|
||||
### auth.site_code_mapping — 球房ID与门店映射
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| site_code | VARCHAR(10) UNIQUE | 球房ID(格式:2字母+3数字,如 AB123) |
|
||||
| site_id | BIGINT UNIQUE | 门店 ID(对应 ETL 库的 site_id) |
|
||||
| site_name | VARCHAR(100) | 门店名称 |
|
||||
| tenant_id | INT | 租户 ID |
|
||||
|
||||
### auth.roles — 角色定义
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| code | VARCHAR(50) UNIQUE | 角色编码 |
|
||||
| name | VARCHAR(100) | 角色名称 |
|
||||
| description | TEXT | 描述 |
|
||||
|
||||
预置角色:
|
||||
| code | name | 权限 |
|
||||
|------|------|------|
|
||||
| `coach` | 助教 | view_tasks, view_board_coach |
|
||||
| `staff` | 员工 | view_tasks, view_board |
|
||||
| `site_admin` | 店铺管理员 | 全部 5 个权限 |
|
||||
| `tenant_admin` | 租户管理员 | 全部 5 个权限 |
|
||||
|
||||
### auth.permissions — 权限定义
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| code | VARCHAR(50) UNIQUE | 权限编码 |
|
||||
| name | VARCHAR(100) | 权限名称 |
|
||||
| description | TEXT | 描述 |
|
||||
|
||||
预置权限:
|
||||
| code | name |
|
||||
|------|------|
|
||||
| `view_tasks` | 查看任务 |
|
||||
| `view_board` | 查看看板 |
|
||||
| `view_board_finance` | 查看财务看板 |
|
||||
| `view_board_customer` | 查看客户看板 |
|
||||
| `view_board_coach` | 查看助教看板 |
|
||||
|
||||
### auth.role_permissions — 角色-权限关联
|
||||
联合主键 `(role_id, permission_id)`,外键级联删除。
|
||||
|
||||
### auth.user_applications — 用户入驻申请
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| user_id | INT FK | 关联 auth.users |
|
||||
| site_code | VARCHAR(10) | 球房ID |
|
||||
| site_id | BIGINT | 门店 ID(后端自动填充) |
|
||||
| applied_role_text | VARCHAR(100) | 申请身份文本 |
|
||||
| employee_number | VARCHAR(50) | 员工编号 |
|
||||
| phone | VARCHAR(20) | 手机号 |
|
||||
| status | VARCHAR(20) | pending / approved / rejected |
|
||||
| reviewer_id | INT | 审核人 |
|
||||
| review_note | TEXT | 审核备注 |
|
||||
| created_at | TIMESTAMPTZ | 申请时间 |
|
||||
| reviewed_at | TIMESTAMPTZ | 审核时间 |
|
||||
|
||||
### auth.user_site_roles — 用户-门店-角色关联
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| user_id | INT FK | 关联 auth.users |
|
||||
| site_id | BIGINT | 门店 ID |
|
||||
| role_id | INT FK | 关联 auth.roles |
|
||||
|
||||
唯一约束:`(user_id, site_id, role_id)` — 同一用户在同一门店下不能重复分配同一角色。
|
||||
|
||||
### auth.user_assistant_binding — 用户-人员绑定
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | SERIAL PK | 自增主键 |
|
||||
| user_id | INT FK | 关联 auth.users |
|
||||
| site_id | BIGINT | 门店 ID |
|
||||
| assistant_id | BIGINT | 助教 ID(ETL 库) |
|
||||
| staff_id | BIGINT | 员工 ID(ETL 库) |
|
||||
| binding_type | VARCHAR(20) | 绑定类型 |
|
||||
|
||||
## public Schema — 管理后台
|
||||
|
||||
### admin_users — 管理后台用户
|
||||
用于管理后台(`apps/admin-web/`)的用户名密码登录。
|
||||
|
||||
默认种子数据:`admin / admin123`(生产环境部署后务必修改)。
|
||||
|
||||
### task_queue — 任务执行队列
|
||||
存储待执行和执行中的 ETL 任务,按 `site_id` 隔离。
|
||||
|
||||
### scheduled_tasks — 调度任务配置
|
||||
存储定时调度规则,由后端 `Scheduler` 服务消费。
|
||||
|
||||
### task_execution_log — 任务执行日志
|
||||
记录每次 ETL 任务执行的状态、耗时、日志输出。
|
||||
|
||||
## FDW 跨库访问
|
||||
|
||||
`zqyy_app` 通过 Foreign Data Wrapper(FDW)只读访问 `etl_feiqiu` 数据库:
|
||||
- 迁移脚本:`2026-02-24__p1_setup_fdw_etl.sql`
|
||||
- 用途:小程序认证时的人员匹配(查询 ETL 库中的助教/员工记录)
|
||||
- 安全:FDW 连接使用只读用户
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
db/zqyy_app/
|
||||
├── migrations/ # 迁移脚本(日期前缀)
|
||||
│ ├── 2026-02-24__p1_create_auth_biz_schemas.sql # 创建 auth + biz Schema
|
||||
│ ├── 2026-02-24__p1_setup_fdw_etl.sql # 设置 FDW 跨库访问
|
||||
│ ├── 2026-02-25__p3_create_auth_tables.sql # 创建 auth 8 张表
|
||||
│ └── 2026-02-25__p3_seed_roles_permissions.sql # 预置角色和权限
|
||||
├── schemas/ # Schema DDL(待补充)
|
||||
├── seeds/
|
||||
│ └── admin_web_seed.sql # 管理后台默认管理员
|
||||
├── scripts/
|
||||
│ └── create_test_db.sql # 创建测试库脚本
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 迁移执行顺序
|
||||
|
||||
1. `p1_create_auth_biz_schemas.sql` — 创建 Schema
|
||||
2. `p1_setup_fdw_etl.sql` — 设置 FDW
|
||||
3. `p3_create_auth_tables.sql` — 创建认证表
|
||||
4. `p3_seed_roles_permissions.sql` — 插入种子数据
|
||||
|
||||
所有迁移脚本使用 `IF NOT EXISTS` / `ON CONFLICT DO NOTHING` 幂等语法,可重复执行。
|
||||
|
||||
## 与其他模块的关系
|
||||
|
||||
- `apps/backend/` — 通过 `get_connection()` 读写此库
|
||||
- `apps/miniprogram/` — 通过后端 API 间接访问
|
||||
- `apps/admin-web/` — 通过后端 API 间接访问
|
||||
- `db/etl_feiqiu/` — 通过 FDW 被此库只读引用
|
||||
@@ -0,0 +1,53 @@
|
||||
-- =============================================================================
|
||||
-- 迁移脚本:创建 auth/biz Schema 与 app_user 权限配置
|
||||
-- 日期:2026-02-24
|
||||
-- 目标库:test_zqyy_app(通过 APP_DB_DSN 连接)
|
||||
-- 说明:在业务库中创建 auth(用户认证)和 biz(业务数据)两个 Schema,
|
||||
-- 并授予 app_user 角色完整的 CRUD 权限(含未来新表自动授权)。
|
||||
-- 不操作 public Schema,保留其中现有系统管理表不受影响。
|
||||
-- 前提:app_user 角色已由 DBA 预创建
|
||||
-- 需求:1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 4.2, 4.3, 4.4, 4.5, 4.6
|
||||
-- =============================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 1. 创建 auth Schema(用户认证、权限、映射)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SCHEMA IF NOT EXISTS auth;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 2. 创建 biz Schema(业务数据)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SCHEMA IF NOT EXISTS biz;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. 授予 app_user 对 auth Schema 的 USAGE + CRUD 权限
|
||||
-- ---------------------------------------------------------------------------
|
||||
GRANT USAGE ON SCHEMA auth TO app_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA auth TO app_user;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 4. 授予 app_user 对 biz Schema 的 USAGE + CRUD 权限
|
||||
-- ---------------------------------------------------------------------------
|
||||
GRANT USAGE ON SCHEMA biz TO app_user;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA biz TO app_user;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 5. 设置 ALTER DEFAULT PRIVILEGES:未来新表自动授权
|
||||
-- ---------------------------------------------------------------------------
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA auth
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
|
||||
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA biz
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
|
||||
|
||||
-- =============================================================================
|
||||
-- 回滚脚本(按逆序执行)
|
||||
-- =============================================================================
|
||||
-- ALTER DEFAULT PRIVILEGES IN SCHEMA biz REVOKE SELECT, INSERT, UPDATE, DELETE ON TABLES FROM app_user;
|
||||
-- ALTER DEFAULT PRIVILEGES IN SCHEMA auth REVOKE SELECT, INSERT, UPDATE, DELETE ON TABLES FROM app_user;
|
||||
-- REVOKE SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA biz FROM app_user;
|
||||
-- REVOKE USAGE ON SCHEMA biz FROM app_user;
|
||||
-- REVOKE SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA auth FROM app_user;
|
||||
-- REVOKE USAGE ON SCHEMA auth FROM app_user;
|
||||
-- DROP SCHEMA IF EXISTS biz CASCADE;
|
||||
-- DROP SCHEMA IF EXISTS auth CASCADE;
|
||||
71
db/zqyy_app/migrations/2026-02-24__p1_setup_fdw_etl.sql
Normal file
71
db/zqyy_app/migrations/2026-02-24__p1_setup_fdw_etl.sql
Normal file
@@ -0,0 +1,71 @@
|
||||
-- =============================================================================
|
||||
-- 迁移脚本:配置 FDW 跨库映射(ETL 库 → 业务库)
|
||||
-- 日期:2026-02-24
|
||||
-- 目标库:test_zqyy_app(通过 APP_DB_DSN 连接)
|
||||
-- 说明:通过 postgres_fdw 将 ETL 库 app Schema 的 RLS 视图映射为业务库
|
||||
-- fdw_etl Schema 的只读外部表,使后端无需直连 ETL 库即可读取汇总/维度数据。
|
||||
-- 前提:
|
||||
-- 1. ETL 库已部署 app Schema 及 RLS 视图(2026-02-24__p1_create_app_schema_rls_views.sql)
|
||||
-- 2. ETL 库已创建 app_reader 只读角色
|
||||
-- 3. 业务库已创建 app_user 角色
|
||||
-- 需求:3.1, 3.2, 3.3, 3.4, 3.7, 4.2, 4.3, 4.4, 4.5, 4.6
|
||||
-- =============================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 1. 安装 postgres_fdw 扩展
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE EXTENSION IF NOT EXISTS postgres_fdw;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 2. 创建外部服务器(指向 ETL 库)
|
||||
-- host / dbname / port 使用占位符 '***',部署时按环境替换
|
||||
-- 服务器名使用通用名(不含环境前缀),通过连接参数区分环境
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SERVER IF NOT EXISTS etl_feiqiu_server
|
||||
FOREIGN DATA WRAPPER postgres_fdw
|
||||
OPTIONS (host '***', dbname '***', port '***');
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. 创建用户映射(只读角色)
|
||||
-- app_user = test_zqyy_app 侧的应用连接角色
|
||||
-- app_reader = ETL 库侧的只读角色
|
||||
-- 密码占位符 '***',部署时替换为真实凭据
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE USER MAPPING IF NOT EXISTS FOR app_user
|
||||
SERVER etl_feiqiu_server
|
||||
OPTIONS (user 'app_reader', password '***');
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 4. 创建 fdw_etl Schema(幂等处理:先 DROP 再重建)
|
||||
-- IMPORT FOREIGN SCHEMA 不是幂等的(外部表已存在会报错),
|
||||
-- 因此采用 DROP CASCADE + 重建的方式确保可重复执行。
|
||||
-- ---------------------------------------------------------------------------
|
||||
DROP SCHEMA IF EXISTS fdw_etl CASCADE;
|
||||
CREATE SCHEMA fdw_etl;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 5. 批量导入 ETL 库 app Schema 的所有外部表到 fdw_etl
|
||||
-- ---------------------------------------------------------------------------
|
||||
IMPORT FOREIGN SCHEMA app
|
||||
FROM SERVER etl_feiqiu_server
|
||||
INTO fdw_etl;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 6. 授权:允许 app_user 访问 fdw_etl Schema 及其外部表
|
||||
-- ---------------------------------------------------------------------------
|
||||
GRANT USAGE ON SCHEMA fdw_etl TO app_user;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA fdw_etl TO app_user;
|
||||
|
||||
-- 未来新导入的外部表自动授权
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_etl GRANT SELECT ON TABLES TO app_user;
|
||||
|
||||
-- =============================================================================
|
||||
-- 回滚脚本(按逆序执行)
|
||||
-- =============================================================================
|
||||
-- ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_etl REVOKE SELECT ON TABLES FROM app_user;
|
||||
-- REVOKE SELECT ON ALL TABLES IN SCHEMA fdw_etl FROM app_user;
|
||||
-- REVOKE USAGE ON SCHEMA fdw_etl FROM app_user;
|
||||
-- DROP SCHEMA IF EXISTS fdw_etl CASCADE;
|
||||
-- DROP USER MAPPING IF EXISTS FOR app_user SERVER etl_feiqiu_server;
|
||||
-- DROP SERVER IF EXISTS etl_feiqiu_server CASCADE;
|
||||
-- DROP EXTENSION IF EXISTS postgres_fdw;
|
||||
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;
|
||||
@@ -0,0 +1,75 @@
|
||||
-- =============================================================================
|
||||
-- 种子数据脚本:预置权限列表、默认角色、角色-权限映射
|
||||
-- 日期:2026-02-25
|
||||
-- 目标库:test_zqyy_app(通过 APP_DB_DSN 连接)
|
||||
-- 说明:在 auth Schema 的 permissions、roles、role_permissions 表中插入种子数据。
|
||||
-- 使用 ON CONFLICT DO NOTHING 幂等语法,重复执行不会产生重复数据。
|
||||
-- 前提:auth.roles、auth.permissions、auth.role_permissions 表已由
|
||||
-- 2026-02-25__p3_create_auth_tables.sql 创建
|
||||
-- 需求:2.1, 2.2, 2.3, 2.4
|
||||
-- =============================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 1. 插入固定权限(5 条)
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO auth.permissions (code, name, description) VALUES
|
||||
('view_tasks', '查看任务', '允许查看任务列表和任务详情'),
|
||||
('view_board', '查看看板', '允许查看数据看板概览'),
|
||||
('view_board_finance', '查看财务看板', '允许查看财务相关的数据看板'),
|
||||
('view_board_customer', '查看客户看板', '允许查看客户相关的数据看板'),
|
||||
('view_board_coach', '查看助教看板', '允许查看助教相关的数据看板')
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 2. 插入默认角色(4 条)
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO auth.roles (code, name, description) VALUES
|
||||
('coach', '助教', '球房助教,可查看任务和助教看板'),
|
||||
('staff', '员工', '球房员工,可查看任务和数据看板'),
|
||||
('site_admin', '店铺管理员', '单店管理员,可查看所有看板'),
|
||||
('tenant_admin', '租户管理员', '租户级管理员,拥有全部权限')
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. 插入角色-权限映射
|
||||
-- coach: view_tasks, view_board_coach
|
||||
-- staff: view_tasks, view_board
|
||||
-- site_admin: view_tasks, view_board, view_board_finance, view_board_customer, view_board_coach
|
||||
-- tenant_admin: 全部 5 个权限
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO auth.role_permissions (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM auth.roles r
|
||||
CROSS JOIN auth.permissions p
|
||||
WHERE (r.code, p.code) IN (
|
||||
-- coach: 2 个权限
|
||||
('coach', 'view_tasks'),
|
||||
('coach', 'view_board_coach'),
|
||||
-- staff: 2 个权限
|
||||
('staff', 'view_tasks'),
|
||||
('staff', 'view_board'),
|
||||
-- site_admin: 5 个权限
|
||||
('site_admin', 'view_tasks'),
|
||||
('site_admin', 'view_board'),
|
||||
('site_admin', 'view_board_finance'),
|
||||
('site_admin', 'view_board_customer'),
|
||||
('site_admin', 'view_board_coach'),
|
||||
-- tenant_admin: 5 个权限
|
||||
('tenant_admin', 'view_tasks'),
|
||||
('tenant_admin', 'view_board'),
|
||||
('tenant_admin', 'view_board_finance'),
|
||||
('tenant_admin', 'view_board_customer'),
|
||||
('tenant_admin', 'view_board_coach')
|
||||
)
|
||||
ON CONFLICT (role_id, permission_id) DO NOTHING;
|
||||
|
||||
-- =============================================================================
|
||||
-- 回滚脚本(按逆序执行)
|
||||
-- =============================================================================
|
||||
-- DELETE FROM auth.role_permissions
|
||||
-- WHERE role_id IN (SELECT id FROM auth.roles WHERE code IN ('coach', 'staff', 'site_admin', 'tenant_admin'))
|
||||
-- AND permission_id IN (SELECT id FROM auth.permissions WHERE code IN ('view_tasks', 'view_board', 'view_board_finance', 'view_board_customer', 'view_board_coach'));
|
||||
--
|
||||
-- DELETE FROM auth.roles WHERE code IN ('coach', 'staff', 'site_admin', 'tenant_admin');
|
||||
--
|
||||
-- DELETE FROM auth.permissions WHERE code IN ('view_tasks', 'view_board', 'view_board_finance', 'view_board_customer', 'view_board_coach');
|
||||
Reference in New Issue
Block a user