文档更新
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
# Fonrey — Public Schema 数据模型
|
||||
|
||||
> **作者**: Backend Architect
|
||||
> **版本**: v1.5
|
||||
> **日期**: 2026-04-30
|
||||
> **版本**: v1.6
|
||||
> **日期**: 2026-05-02
|
||||
> **权威源**: 本文件是 `public` schema 所有表的唯一权威定义
|
||||
> **设计依据**: 系统管理模块 PRD(`PRD/系统管理/系统管理模块PRD.md`);客户端发布管理模块 PRD(`PRD/发布管理/客户端发布管理模块PRD.md`)
|
||||
> **设计依据**: 平台管理后台 PRD(`PRD/平台管理后台/平台管理后台PRD.md`)
|
||||
> **索引文档**: [`DATA_MODEL.md §三`](./DATA_MODEL.md)(仅保留摘要索引,开发以本文件为准)
|
||||
|
||||
---
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
| 日期 | 变更人 | 变更内容 |
|
||||
|---|---|---|
|
||||
| 2026-05-02 | Atlas | 对齐平台管理后台 PRD v1.0:`tenants` 增加 License 授权用户数上限字段 `license_user_limit`(含约束、索引、查询示例);`suspended_reason` 增加 `license_expired`;审计动作补充 `UPDATE_LICENSE_USER_LIMIT` 与 `AUTO_SUSPEND_LICENSE_EXPIRED`;`domains` 标注为统一 `tenant=` 路由下的兼容保留;同步更新元信息与版本历史。 |
|
||||
| 2026-04-30 | Atlas | 补充“变更历史”章节(文档治理) |
|
||||
|
||||
## 一、概览
|
||||
@@ -53,7 +54,7 @@ PostgreSQL Instance
|
||||
| 表名 | 说明 | 节 |
|
||||
|------|------|----|
|
||||
| `public.tenants` | 租户主表(每家房产公司一条记录) | §2.1 |
|
||||
| `public.domains` | 域名↔租户映射(多域名支持) | §2.1 |
|
||||
| `public.domains` | 域名↔租户映射(兼容保留;主路径已切换统一 `tenant=` 参数路由) | §2.1 |
|
||||
| `public.tenant_status_logs` | 租户状态变更不可变审计日志 | §2.1 |
|
||||
| `public.platform_admins` | 平台管理员账号(3 种角色) | §2.2 |
|
||||
| `public.admin_mfa_devices` | 管理员 TOTP MFA 设备(强制启用) | §2.2 |
|
||||
@@ -81,7 +82,7 @@ PostgreSQL Instance
|
||||
-- ============================================================
|
||||
-- 文件: shared_schema.sql
|
||||
-- 用途: django-tenants 公共 Schema,存放平台运营层数据
|
||||
-- 设计依据: 系统管理模块 PRD v1.0
|
||||
-- 设计依据: 平台管理后台 PRD v1.0
|
||||
-- ============================================================
|
||||
|
||||
-- ────────────────────────────────────────────────────────────
|
||||
@@ -111,11 +112,13 @@ CREATE TABLE public.tenants (
|
||||
CHECK (status IN ('creating','active','suspended','pending_delete','deleted','failed')),
|
||||
suspended_until TIMESTAMPTZ, -- NULL = 永久挂起,非 NULL = Celery Beat 定时恢复
|
||||
suspended_reason VARCHAR(50)
|
||||
CHECK (suspended_reason IN ('overdue','violation','requested','other')),
|
||||
CHECK (suspended_reason IN ('overdue','violation','requested','other','license_expired')),
|
||||
deleted_at TIMESTAMPTZ, -- 软删除时间戳;硬删除直接物理删除行
|
||||
|
||||
-- 订阅
|
||||
paid_until DATE, -- 订阅到期日
|
||||
paid_until DATE, -- 订阅到期日(License 到期日期)
|
||||
license_user_limit INTEGER NOT NULL DEFAULT 50
|
||||
CHECK (license_user_limit > 0), -- License 授权用户数上限(含 Tenant Admin + Agent)
|
||||
on_trial BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
-- 灰度升级
|
||||
@@ -139,11 +142,14 @@ CREATE INDEX idx_tenants_suspended_until ON public.tenants(suspended_until)
|
||||
CREATE INDEX idx_tenants_canary ON public.tenants(is_canary) WHERE is_canary = TRUE;
|
||||
CREATE INDEX idx_tenants_pending_delete ON public.tenants(deleted_at)
|
||||
WHERE status = 'pending_delete';
|
||||
CREATE INDEX idx_tenants_license_user_limit ON public.tenants(license_user_limit);
|
||||
CREATE INDEX idx_tenants_paid_until_active ON public.tenants(paid_until)
|
||||
WHERE status = 'active';
|
||||
-- Feature Flag 租户级覆盖的 GIN 索引(详见 §2.7)
|
||||
-- 同时在 §2.7 中以 ALTER TABLE ADD COLUMN IF NOT EXISTS 兜底,便于按模块独立部署
|
||||
CREATE INDEX idx_tenants_feature_flags_gin ON public.tenants USING gin (feature_flags);
|
||||
|
||||
-- 域名映射表(支持多域名绑定一个租户,子域名创建后不可修改)
|
||||
-- 域名映射表(兼容保留:主路径已切换统一 `tenant=` 参数路由;子域名创建后不可修改)
|
||||
CREATE TABLE public.domains (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain VARCHAR(253) UNIQUE NOT NULL, -- 含子域名的完整域名(如 abc.platform.com)
|
||||
@@ -257,6 +263,7 @@ CREATE TABLE public.platform_audit_logs (
|
||||
operator_name VARCHAR(100), -- 快照(防止账号删除后失去溯源)
|
||||
action_type VARCHAR(50) NOT NULL,
|
||||
-- CREATE_TENANT | SUSPEND_TENANT | RESUME_TENANT | DELETE_TENANT | HARD_DELETE_TENANT
|
||||
-- UPDATE_LICENSE | UPDATE_LICENSE_USER_LIMIT | AUTO_SUSPEND_LICENSE_EXPIRED
|
||||
-- RESTORE_DATA | TRIGGER_BACKUP | SYSTEM_UPGRADE | ROLLBACK
|
||||
-- RESET_PASSWORD | CREATE_ADMIN | DEACTIVATE_ADMIN | FORCE_LOGOUT
|
||||
-- UPDATE_IP_WHITELIST | UPDATE_BACKUP_SCHEDULE | EXPORT_DATA | ...
|
||||
@@ -709,7 +716,7 @@ CREATE INDEX idx_ff_log_operator ON public.feature_flag_change_log(operator_id,
|
||||
| `tenant_status_logs` append-only | 禁止 UPDATE / DELETE;状态机变更只追加新行 |
|
||||
| `platform_audit_logs` append-only | 禁止 UPDATE / DELETE;建议按月 RANGE 分区 |
|
||||
| `public.tenants.schema_name` 不可修改 | 创建后禁止 UPDATE,PG schema 绑定 |
|
||||
| `public.domains.domain` 不可修改 | 子域名创建后禁止 UPDATE |
|
||||
| `public.domains.domain` 不可修改(兼容保留) | `tenant=` 统一路由方案下,`domains` 仅用于历史兼容与迁移窗口;子域名创建后禁止 UPDATE |
|
||||
| `system_versions` 唯一 current | `idx_system_versions_current` 部分唯一索引保证全局只有一个 `status='current'` |
|
||||
| `backup_schedules.tenant_id` UNIQUE | 每个租户最多一条独立计划;`NULL` 全局计划由应用层保证唯一 |
|
||||
| `platform_admins` 与 `staff` 完全独立 | 不共享表、不共享 auth 系统 |
|
||||
@@ -801,16 +808,25 @@ draft ──提交──► pre_check ──健康检查通过──► pre_back
|
||||
|
||||
```sql
|
||||
-- 查询所有活跃租户
|
||||
SELECT id, name, plan, paid_until
|
||||
SELECT id, name, plan, paid_until, license_user_limit
|
||||
FROM public.tenants
|
||||
WHERE status = 'active'
|
||||
ORDER BY created_at DESC;
|
||||
|
||||
-- 查询即将到期的租户(7 天内)
|
||||
SELECT id, name, contact_email, paid_until
|
||||
-- 查询即将到期的租户(15 天内,对齐平台管理后台 PRD)
|
||||
SELECT id, name, contact_email, paid_until, license_user_limit
|
||||
FROM public.tenants
|
||||
WHERE status = 'active'
|
||||
AND paid_until BETWEEN CURRENT_DATE AND CURRENT_DATE + 7;
|
||||
AND paid_until BETWEEN CURRENT_DATE AND CURRENT_DATE + 15;
|
||||
|
||||
-- 查询“用户数已满/超限”的租户(供运营筛选)
|
||||
-- current_user_count 由租户侧聚合任务回填至统计视图或物化视图,此处示例为联表查询形态
|
||||
SELECT t.id, t.name, t.tenant_code, t.license_user_limit, u.current_user_count
|
||||
FROM public.tenants t
|
||||
JOIN public.v_tenant_user_counts u ON u.tenant_id = t.id
|
||||
WHERE t.status = 'active'
|
||||
AND u.current_user_count >= t.license_user_limit
|
||||
ORDER BY u.current_user_count DESC, t.created_at DESC;
|
||||
|
||||
-- 查询灰度租户(canary 升级目标)
|
||||
SELECT id, schema_name, name
|
||||
@@ -1009,7 +1025,7 @@ ORDER BY created_at DESC;
|
||||
| `DELETE FROM public.platform_audit_logs` | append-only 审计表 |
|
||||
| `UPDATE public.tenants SET schema_name = ...` | schema 名绑定 PG 物理 schema |
|
||||
| `UPDATE public.tenants SET tenant_code = ...` | 12 位识别码一旦发放给用户不可更改,避免经纪人无法登录 |
|
||||
| `UPDATE public.domains SET domain = ...` | 域名路由不可变 |
|
||||
| `UPDATE public.domains SET domain = ...` | 域名路由不可变(`domains` 为兼容保留表,主路径使用 `tenant=` 参数) |
|
||||
| `UPDATE public.client_releases SET version = ...` | 版本号创建后不可修改,变更须新建记录 |
|
||||
| 在租户 schema 中创建 `client_releases` 副本 | 本表属于 public schema,多租户共享,禁止下沉到租户层 |
|
||||
| `UPDATE public.feature_flag_change_log` / `DELETE FROM ...` | append-only 审计表 |
|
||||
@@ -1030,3 +1046,4 @@ ORDER BY created_at DESC;
|
||||
| v1.3 | 2026-04-30 | 配合登录管理 PRD v2.0 / 系统管理 PRD:§2.1 `tenants` 新增 `tenant_code` (CHAR(12), 全局唯一对外识别码) 与 `contact_phone` (CHAR(11),Tenant Admin 账号创建数据来源),`contact_email` 改为可 NULL;同步更新约束、查询模式 |
|
||||
| v1.4 | 2026-04-30 | 配合客户端发布管理 PRD v1.1 §5.5 Story 5:§2.6 新增 `client_heartbeats` 表(启动时 Upsert by `tenant_id + device_id`,活跃定义为最近 24h 内心跳);同步更新表清单、§三 约束(Upsert 锚点 / 启动上报 / 不可下沉到租户 schema)、§5.1 查询模式(Upsert 模板 + 版本活跃分布 JOIN + 平台总活跃数 + 租户维度排查);MVP 不做升级趋势图(v2 规划) |
|
||||
| v1.5 | 2026-04-30 | 配合客户端发布管理 PRD v1.2 §5.5 Story 5 验收标准追加(按租户统计安装数):① §2.6 `client_heartbeats.tenant_id` 注释强化,明确为"按租户统计安装数 / 活跃数 / 版本分布"的核心维度字段;② §5.1 新增"租户维度安装/活跃统计"查询专区(4 个查询:某租户活跃安装数 / 历史装机总数 / 租户内版本分布 / 全平台租户活跃榜) |
|
||||
| v1.6 | 2026-05-02 | 对齐平台管理后台 PRD v1.0:① `tenants` 增加 `license_user_limit`(`INTEGER NOT NULL DEFAULT 50 CHECK (>0)`)并新增 `idx_tenants_license_user_limit`;② `suspended_reason` 增加 `license_expired` 枚举;③ 新增 `idx_tenants_paid_until_active` 并将“即将到期”查询窗口由 7 天调整为 15 天;④ 新增“用户数已满/超限”查询示例(`v_tenant_user_counts` 联表);⑤ 审计动作补充 `UPDATE_LICENSE_USER_LIMIT`、`AUTO_SUSPEND_LICENSE_EXPIRED`;⑥ `domains` 标记为统一 `tenant=` 路由下的兼容保留。 |
|
||||
|
||||
Reference in New Issue
Block a user