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>
This commit is contained in:
Neo
2026-04-06 00:02:37 +08:00
parent 8228b3fa37
commit 70324d8542
185 changed files with 13595 additions and 1219 deletions

View File

@@ -0,0 +1,254 @@
# BD 手册biz 注册体系表NS4.1 registry
## 概述
NS4.1 注册体系新增 4 张表,全部位于 `biz` Schema建立「连接器 → 租户 → 店铺」三级注册体系。合并原 `auth.site_code_mapping`,统一管理上游 SaaS 系统、租户和店铺的关系并为简写ID 提供归属和变更历史。
所有表位于 `zqyy_app` / `test_zqyy_app` 数据库。
## 变更原因
- NS4.1 注册体系设计,建立项目级「连接器 → 租户 → 店铺」三级结构
- 合并原 `auth.site_code_mapping``biz.sites`增加租户关联和简写ID 变更历史管理
- 数据来源:种子数据从 `auth.site_code_mapping` 迁移ETL 增量同步从 `dwd.dim_site`
## 变更说明
| 库 | Schema | 表 | 变更类型 | 说明 |
|----|--------|---|---------|------|
| zqyy_app | biz | connectors | 新建 | 连接器注册表 |
| zqyy_app | biz | tenants | 新建 | 租户注册表 |
| zqyy_app | biz | sites | 新建 | 店铺注册表(合并原 auth.site_code_mapping |
| zqyy_app | biz | site_code_history | 新建 | 简写ID 变更历史表 |
| zqyy_app | auth | site_code_mapping | 废弃重命名 | → `auth._archived_site_code_mapping` |
---
## 1. biz.connectors — 连接器注册表
记录本项目接入的上游 SaaS 系统。当前仅有飞球feiqiu一个连接器预留多连接器扩展能力。
### 表结构
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | SERIAL | PRIMARY KEY | 自增主键 |
| connector_key | VARCHAR(50) | UNIQUE NOT NULL | 连接器标识(如 `'feiqiu'` |
| display_name | VARCHAR(100) | NOT NULL | 显示名称 |
| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 |
| created_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
### 约束与索引
| 名称 | 类型 | 列 | 说明 |
|------|------|---|------|
| connectors_pkey | PRIMARY KEY | id | 主键 |
| connectors_connector_key_key | UNIQUE | connector_key | 连接器标识唯一 |
### 种子数据
```sql
INSERT INTO biz.connectors (connector_key, display_name) VALUES ('feiqiu', '飞球');
```
---
## 2. biz.tenants — 租户注册表
连接器下的租户,`tenant_id` 来自上游系统。同一连接器下 `tenant_id` 唯一。
### 表结构
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | SERIAL | PRIMARY KEY | 自增主键 |
| connector_id | INTEGER | NOT NULL FK → biz.connectors(id) | 所属连接器 |
| tenant_id | BIGINT | NOT NULL | 上游系统租户 ID |
| tenant_name | VARCHAR(200) | — | 租户名称 |
| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 |
| created_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 更新时间 |
### 约束与索引
| 名称 | 类型 | 列 | 说明 |
|------|------|---|------|
| tenants_pkey | PRIMARY KEY | id | 主键 |
| tenants_connector_id_tenant_id_key | UNIQUE | (connector_id, tenant_id) | 同一连接器下租户唯一 |
| tenants_connector_id_fkey | FOREIGN KEY | connector_id → biz.connectors(id) | 外键关联连接器 |
### 种子数据
```sql
INSERT INTO biz.tenants (connector_id, tenant_id, tenant_name)
VALUES (1, 2790683160709957, '朗朗桌球');
```
---
## 3. biz.sites — 店铺注册表
合并原 `auth.site_code_mapping`增加租户关联和简写ID 管理。`site_id` 来自上游系统,全局唯一。`site_code` 为当前生效的简写ID6 位字符3+3 格式),全局唯一。
### 表结构
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | SERIAL | PRIMARY KEY | 自增主键 |
| tenant_id | INTEGER | NOT NULL FK → biz.tenants(id) | 所属租户 |
| site_id | BIGINT | NOT NULL UNIQUE | 上游系统门店 ID |
| site_name | VARCHAR(200) | — | 门店名称 |
| site_code | VARCHAR(6) | UNIQUE | 当前生效的简写ID3+3 格式,如 `LLQ001` |
| site_label | VARCHAR(50) | — | 门店标签 |
| is_active | BOOLEAN | NOT NULL DEFAULT true | 是否启用 |
| created_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 更新时间 |
### 约束与索引
| 名称 | 类型 | 列 | 说明 |
|------|------|---|------|
| sites_pkey | PRIMARY KEY | id | 主键 |
| sites_site_id_key | UNIQUE | site_id | 上游门店 ID 唯一 |
| sites_site_code_key | UNIQUE | site_code | 简写ID 全局唯一 |
| sites_tenant_id_fkey | FOREIGN KEY | tenant_id → biz.tenants(id) | 外键关联租户 |
### 数据迁移
```sql
-- 从 auth.site_code_mapping 迁移真实数据
INSERT INTO biz.sites (tenant_id, site_id, site_name, site_code)
SELECT t.id, scm.site_id, scm.site_name, scm.site_code
FROM auth.site_code_mapping scm
JOIN biz.tenants t ON t.tenant_id = scm.tenant_id
WHERE scm.tenant_id IS NOT NULL;
-- ETL 增量同步补充:通过 FDW 读取 dwd.dim_sitescd2_is_current=1
-- 补充 auth.site_code_mapping 中没有但 dwd.dim_site 中有的店铺
```
---
## 4. biz.site_code_history — 简写ID 变更历史表
增量记录所有使用过的简写ID。`site_code` 全局唯一(含历史),确保已退役的 code 不会被重新分配。每个 `site_id` 最多一条 `is_current=true` 记录。
### 表结构
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | SERIAL | PRIMARY KEY | 自增主键 |
| site_id | BIGINT | NOT NULL | 关联 biz.sites.site_id |
| site_code | VARCHAR(6) | NOT NULL UNIQUE | 简写ID全局唯一含历史 |
| is_current | BOOLEAN | NOT NULL DEFAULT false | true=当前生效,每个 site_id 最多一条 |
| created_at | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
| retired_at | TIMESTAMPTZ | — | 退役时间is_current=false 时设置) |
### 约束与索引
| 名称 | 类型 | 列 | 说明 |
|------|------|---|------|
| site_code_history_pkey | PRIMARY KEY | id | 主键 |
| site_code_history_site_code_key | UNIQUE | site_code | 简写ID 全局唯一(含历史) |
### 初始数据
```sql
-- 为已有 site_code 的店铺创建历史记录
INSERT INTO biz.site_code_history (site_id, site_code, is_current)
SELECT site_id, site_code, true
FROM biz.sites
WHERE site_code IS NOT NULL;
```
---
## 兼容性
| 组件 | 影响 |
|------|------|
| 后端 API | 全部切换到 `biz.sites` + `biz.site_code_history`。新增 `admin_registry` 路由模块租户列表、店铺列表、简写ID 管理)。`admin_tenant_admins` 路由中 `tenant_id``biz.tenants` 选择。`tenant_users` 路由中 site_code 查询从 `auth.site_code_mapping` 切换到 `biz.sites` |
| ETL | 无直接影响。店铺同步通过 FDW 只读访问 ETL 库 `dwd.dim_site`,写入 `biz.sites`。ETL 流程本身不变 |
| 小程序 | 无需改动。用户申请时的 site_code 验证由后端 API 透明切换到 `biz.sites` + `biz.site_code_history` |
| 管理后台admin-web | 新增注册体系 API 调用(`src/api/registry.ts`),租户管理员创建流程从 `biz.tenants`/`biz.sites` 选择 |
| 原 auth.site_code_mapping | 迁移完成后重命名为 `auth._archived_site_code_mapping`,保留供回滚 |
## 回滚策略
### 完整回滚(逆序 DROP + 恢复原表)
```sql
BEGIN;
-- 1. 逆序删除注册体系表
DROP TABLE IF EXISTS biz.site_code_history CASCADE;
DROP TABLE IF EXISTS biz.sites CASCADE;
DROP TABLE IF EXISTS biz.tenants CASCADE;
DROP TABLE IF EXISTS biz.connectors CASCADE;
-- 2. 恢复原表(如已重命名)
ALTER TABLE IF EXISTS auth._archived_site_code_mapping
RENAME TO site_code_mapping;
COMMENT ON TABLE auth.site_code_mapping IS '店铺简写ID 映射表(已恢复)';
COMMIT;
```
注意:
- 回滚前需确认后端代码已切换回 `auth.site_code_mapping` 查询
- `CASCADE` 会级联删除依赖对象
- 如果 `biz.sites` 中已有新增店铺ETL 同步补充的),回滚后这些数据将丢失
## 验证 SQL
```sql
-- 1. 验证 biz.sites 中已有 site_code 的店铺数量
SELECT COUNT(*) FROM biz.sites WHERE site_code IS NOT NULL;
-- 预期:与原 auth.site_code_mapping 中有 site_code 的行数一致
-- 2. 验证 sites 与 site_code_history 的一致性
SELECT s.site_id, s.site_code, h.is_current
FROM biz.sites s
LEFT JOIN biz.site_code_history h
ON h.site_id = s.site_id AND h.site_code = s.site_code
WHERE s.site_code IS NOT NULL;
-- 预期:所有行的 h.is_current = true每个有 code 的店铺在历史表中有对应的当前记录)
-- 3. 验证三级注册体系关联完整性
SELECT c.connector_key, t.tenant_name, COUNT(s.id) AS site_count
FROM biz.connectors c
JOIN biz.tenants t ON t.connector_id = c.id
LEFT JOIN biz.sites s ON s.tenant_id = t.id
GROUP BY c.connector_key, t.tenant_name;
-- 预期:至少 1 行feiqiu / 朗朗桌球 / Nsite_count > 0
-- 4. 验证 4 张注册体系表全部存在
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'biz'
AND table_name IN ('connectors', 'tenants', 'sites', 'site_code_history')
ORDER BY table_name;
-- 预期:返回 4 行
-- 5. 验证 site_code 全局唯一性sites + history 无冲突)
SELECT site_code, COUNT(*) AS cnt
FROM biz.site_code_history
GROUP BY site_code
HAVING COUNT(*) > 1;
-- 预期:返回 0 行(每个 site_code 在历史表中最多出现一次)
-- 6. 验证种子数据
SELECT connector_key, display_name FROM biz.connectors WHERE connector_key = 'feiqiu';
-- 预期1 行feiqiu / 飞球)
SELECT tenant_id, tenant_name FROM biz.tenants WHERE tenant_id = 2790683160709957;
-- 预期1 行2790683160709957 / 朗朗桌球)
```
## 关联文件
- DDL 基线biz`docs/database/ddl/zqyy_app__biz.sql`
- 迁移脚本:`db/zqyy_app/migrations/2026-03-22__ns41_registry_tables.sql`
- 后端路由:`apps/backend/app/routers/admin_registry.py`
- 后端 Schema`apps/backend/app/schemas/admin_registry.py`
- 管理员路由:`apps/backend/app/routers/admin_tenant_admins.py`
- 前端 API`apps/admin-web/src/api/registry.ts`
- Spec`.kiro/specs/admin-web-enhancement/`
- PRD`docs/prd/Neo_Specs/NS4.1-tenant-admin-redesign.md`