Files
Neo-ZQYY/docs/database/BD_Manual_auth_tables.md
Neo 70324d8542 chore: 文档与 IDE 配置整理
- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro)
- CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/
- 新增 /spec-close、/pre-change 两个工作流命令
- DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表)
- BD_Manual → BD_manual 命名统一(48 个文件)
- 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数)
- 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表)
- 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档)
- docs/database/README.md 索引更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:02:37 +08:00

13 KiB
Raw Permalink Blame History

BD_Manualauth Schema 认证业务表

目标库:test_zqyy_app(通过 APP_DB_DSN 连接) 迁移脚本:

  • db/zqyy_app/migrations/2026-02-25__p3_create_auth_tables.sql(建表)
  • db/zqyy_app/migrations/2026-02-25__p3_seed_roles_permissions.sql(种子数据)
  • db/zqyy_app/migrations/2026-03-23__add_head_coach_manager_roles.sql(新增 head_coach、manager 角色及权限映射)
  • db/zqyy_app/migrations/2026-03-23__add_rejection_count_and_cancelled_status.sql申请审核流程增强rejection_count + cancelled 状态) 关联 SPECminiapp-auth-systemP3 小程序用户认证系统)

1. 变更说明

新增表9 张)

# 表名 用途 主要字段
1 auth.users 微信用户主表 id(PK), wx_openid(UK), wx_union_id, wx_avatar_url, nickname, phone, avatar_url, status(默认 new), rejection_count(默认 0累计被拒次数), created_at, updated_at
2 auth.user_applications 用户入驻申请表 id(PK), user_id(FK→users), site_code, site_id, applied_role_text, employee_number, phone, status(默认 pending,可选值: pending/approved/rejected/cancelled), reviewer_id, review_note, created_at, reviewed_at
3 auth._archived_site_code_mapping [已废弃] 球房ID与门店映射表NS4.1 重命名,替代方案:biz.sites + biz.site_code_history id(PK), site_code(UK), site_id(UK), site_name, tenant_id, created_at
4 auth.roles 角色定义表 id(PK), code(UK), name, description, created_at
5 auth.permissions 权限定义表 id(PK), code(UK), name, description, created_at
6 auth.role_permissions 角色-权限关联表 role_id(FK→roles), permission_id(FK→permissions),联合主键
7 auth.user_site_roles 用户-门店-角色关联表 id(PK), user_id(FK→users), site_id, role_id(FK→roles), created_at(user_id, site_id, role_id) 唯一约束
8 auth.user_assistant_binding 用户-人员绑定表 id(PK), user_id(FK→users), site_id, assistant_id(可空), staff_id(可空), binding_type, created_at
9 auth.tenant_admins 租户管理员表(详见 BD_Manual_tenant_admin_tables.md id(PK), username(UK), password_hash, display_name, tenant_id, managed_site_ids, is_active, deleted_at, created_by, created_at, last_login_at

约束与索引

约束/索引名 类型 说明
users uq_users_wx_openid UNIQUE 微信 openid 唯一
users ix_users_wx_openid INDEX openid 查询加速
site_code_mapping uq_site_code_mapping_site_code UNIQUE 球房ID 唯一(已废弃,表已重命名为 _archived_site_code_mapping
site_code_mapping uq_site_code_mapping_site_id UNIQUE site_id 唯一映射(已废弃)
site_code_mapping ix_site_code_mapping_site_code INDEX site_code 查询加速(已废弃)
roles uq_roles_code UNIQUE 角色 code 唯一
permissions uq_permissions_code UNIQUE 权限 code 唯一
role_permissions PK (role_id, permission_id) PRIMARY KEY 联合主键
role_permissions fk_role_permissions_role_id FK auth.roles(id) CASCADE
role_permissions fk_role_permissions_permission_id FK auth.permissions(id) CASCADE
user_applications user_applications_status_check CHECK status IN ('pending', 'approved', 'rejected', 'cancelled')
user_applications fk_user_applications_user_id FK auth.users(id) CASCADE
user_applications ix_user_applications_user_id INDEX user_id 查询加速
user_applications ix_user_applications_status INDEX status 过滤加速
user_site_roles uq_user_site_roles_user_site_role UNIQUE 防止重复分配
user_site_roles fk_user_site_roles_user_id FK auth.users(id) CASCADE
user_site_roles fk_user_site_roles_role_id FK auth.roles(id) CASCADE
user_site_roles ix_user_site_roles_user_site INDEX (user_id, site_id) 查询加速
user_assistant_binding fk_user_assistant_binding_user_id FK auth.users(id) CASCADE

种子数据

权限5 条)

code name description
view_tasks 查看任务 允许查看任务列表和任务详情
view_board 查看看板 允许查看数据看板概览
view_board_finance 查看财务看板 允许查看财务相关的数据看板
view_board_customer 查看客户看板 允许查看客户相关的数据看板
view_board_coach 查看助教看板 允许查看助教相关的数据看板

角色4 条)

code name description
coach 助教 球房助教,可查看任务和助教看板
staff 员工 球房员工,可查看任务和数据看板
head_coach 教练 主教练,负责训练助教,可查看任务和全部看板
manager 管理员 球房管理员,可查看任务和全部看板,未来将与 staff 进一步区分权限

注:site_admintenant_admin 已于 2026-03-23 从小程序 RBAC 体系中清理。租户/店铺管理员的区分通过 auth.tenant_admins.admin_type 列实现,不依赖 auth.roles 表。

角色-权限映射11 条)

角色 权限列表 权限数
coach view_tasks, view_board_coach 2
staff view_tasks, view_board 2
head_coach view_tasks, view_board 2
manager view_tasks, view_board, view_board_finance, view_board_customer, view_board_coach 5

注:site_admin5 条)和 tenant_admin5 条)的权限映射已于 2026-03-23 删除,角色体系隔离后总映射从 24 条减为 11 条head_coach 仅分配 view_tasks + view_board非全部 5 个权限)。详见迁移脚本 2026-03-23__cleanup_roles_add_admin_type.sql


2. 兼容性影响

组件 影响
ETL 任务 无影响。本次变更仅操作业务库 auth Schema不涉及 ETL 库
后端 API 直接依赖。FastAPI 后端将基于这些表实现微信登录、用户申请、审核、权限中间件等认证功能
小程序 间接依赖。小程序通过后端 API 间接使用这些表(登录、申请、状态查询)
管理后台 间接依赖。管理端通过后端 API 进行申请审核操作
FDW 配置 无影响。fdw_etl Schema 独立于 auth,但人员匹配服务会通过 FDW 查询 ETL 库的助教/员工表
public Schema 无影响。脚本不包含任何对 public 的操作
现有 auth Schema 兼容。auth Schema 已由 P1 迁移脚本创建,本次仅在其中新增表,不修改已有对象

3. 回滚策略

按逆序 DROP TABLE IF EXISTS CASCADE(迁移脚本末尾已包含注释形式的回滚语句):

-- 先删除种子数据(如需保留表结构)
DELETE FROM auth.role_permissions
WHERE role_id IN (SELECT id FROM auth.roles WHERE code IN ('coach', 'staff', 'head_coach', 'manager'))
  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', 'head_coach', 'manager');
DELETE FROM auth.permissions WHERE code IN ('view_tasks', 'view_board', 'view_board_finance', 'view_board_customer', 'view_board_coach');

-- 删除表按逆序CASCADE 处理外键依赖)
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._archived_site_code_mapping CASCADE;
DROP TABLE IF EXISTS auth.users CASCADE;

注意:CASCADE 会级联删除依赖对象。如果表中已有业务数据,需先备份再执行回滚。


4. 验证 SQL

-- 1. 验证 auth Schema 下 9 张认证表全部存在
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'auth'
  AND table_name IN (
    'users', 'user_applications', '_archived_site_code_mapping',
    'roles', 'permissions', 'role_permissions',
    'user_site_roles', 'user_assistant_binding', 'tenant_admins'
  )
ORDER BY table_name;
-- 预期:返回 9 行

-- 2. 验证种子数据5 条权限
SELECT COUNT(*) AS perm_count
FROM auth.permissions
WHERE code IN ('view_tasks', 'view_board', 'view_board_finance', 'view_board_customer', 'view_board_coach');
-- 预期5

-- 3. 验证种子数据4 条角色site_admin/tenant_admin 已于 2026-03-23 删除)
SELECT COUNT(*) AS role_count
FROM auth.roles
WHERE code IN ('coach', 'staff', 'head_coach', 'manager');
-- 预期4

-- 4. 验证角色-权限映射数量11 条)
SELECT r.code AS role_code, COUNT(rp.permission_id) AS perm_count
FROM auth.roles r
JOIN auth.role_permissions rp ON r.id = rp.role_id
GROUP BY r.code
ORDER BY r.code;
-- 预期coach=2, head_coach=2, manager=5, staff=2共 11 条映射,无 site_admin/tenant_admin

-- 5. 验证关键约束存在
SELECT conname, contype
FROM pg_constraint
WHERE conrelid IN (
    'auth.users'::regclass,
    'auth._archived_site_code_mapping'::regclass,
    'auth.user_site_roles'::regclass
)
ORDER BY conrelid::regclass::text, conname;
-- 预期:包含 uq_users_wx_openid、uq_site_code_mapping_site_code已废弃表 _archived_site_code_mapping、uq_site_code_mapping_site_id、uq_user_site_roles_user_site_role 等


5. 变更记录2026-03-23 申请审核流程增强

5.1 变更说明

对象 变更类型 说明
auth.users.rejection_count 新增字段 integer NOT NULL DEFAULT 0,累计被管理员拒绝的申请次数,达到 3 次自动将 status 设为 disabled
auth.user_applications.status CHECK 约束 修改 新增 'cancelled' 可选值(用户主动取消申请),约束名 user_applications_status_check

5.2 业务规则

  • 管理员拒绝申请时:rejection_count += 1,第 3 次自动将 users.status 设为 disabled
  • 用户主动取消(cancelled)不计入 rejection_count
  • cancelled 状态的申请不在管理端申请列表中显示
  • disabled 用户不允许重新申请,需管理员手动解除(功能待开发)

5.3 兼容性影响

组件 影响
ETL 无影响,不涉及 ETL 库
后端 API 直接依赖。reject_application 增加 rejection_count 累加逻辑;新增 cancel_application 服务和 /api/xcx/cancel-application 端点;/api/xcx/me 返回 latestApplication 详情
小程序 间接依赖。reviewing 页展示申请详情+重新申请按钮no-permission 页区分 rejected/disabled 状态
管理后台 间接依赖。拒绝端点自动累加 rejection_count 并触发禁用;申请列表排除 cancelled

5.4 回滚策略

-- 回滚 rejection_count 字段
ALTER TABLE auth.users DROP COLUMN IF EXISTS rejection_count;

-- 回滚 status CHECK 约束(恢复为不含 cancelled
ALTER TABLE auth.user_applications DROP CONSTRAINT IF EXISTS user_applications_status_check;
ALTER TABLE auth.user_applications
  ADD CONSTRAINT user_applications_status_check
  CHECK (status IN ('pending', 'approved', 'rejected'));

-- 注意:回滚前需确认无 status='cancelled' 的记录,否则约束添加会失败
-- UPDATE auth.user_applications SET status = 'pending' WHERE status = 'cancelled';

5.5 验证 SQL

-- 1. 验证 rejection_count 字段存在且默认值正确
SELECT column_name, data_type, column_default, is_nullable
FROM information_schema.columns
WHERE table_schema = 'auth' AND table_name = 'users' AND column_name = 'rejection_count';
-- 预期integer, 0, NO

-- 2. 验证 CHECK 约束包含 cancelled
SELECT conname, pg_get_constraintdef(oid) AS constraint_def
FROM pg_constraint
WHERE conrelid = 'auth.user_applications'::regclass
  AND conname = 'user_applications_status_check';
-- 预期:包含 'cancelled'

-- 3. 验证现有数据 rejection_count 默认值
SELECT COUNT(*) AS users_with_zero_rejection
FROM auth.users
WHERE rejection_count = 0;
-- 预期:等于 users 表总行数(所有现有用户默认 0

-- 4. 验证 cancelled 状态可正常写入dry-run 验证)
-- INSERT INTO auth.user_applications (user_id, site_code, site_id, applied_role_text, phone, status)
-- VALUES (1, 'TEST', 1, '测试', '13800000000', 'cancelled');
-- 预期:不报 CHECK 约束错误