项目骨架搭建实施报告v2
This commit is contained in:
398
Project/fonrey/实施报告/项目骨架搭建实施报告_v2.md
Normal file
398
Project/fonrey/实施报告/项目骨架搭建实施报告_v2.md
Normal file
@@ -0,0 +1,398 @@
|
||||
# Fonrey 项目骨架搭建实施报告 — v2
|
||||
|
||||
**版本**:v2.0
|
||||
**报告日期**:2026-04-30
|
||||
**实施范围**:Phase 1 配置 → Phase 2 数据模型 → Phase 3 前端/Docker 脚手架 → **Phase 4.0 模型 verbose_name** → **Phase 4.1 字段 verbose_name/help_text** → **Phase 5 PermissionDef 拆分 + 154 条 seed + 7 内置角色 + 矩阵 + Lookup 默认值 + 租户自动 seed**
|
||||
**实施依据**:`prompt/提示词模板/创建项目骨架提示词_v2.3.md`、`PRD/权限管理/PERMISSION_SEED_MVP_BATCH1.md`、`PRD/权限管理/权限管理模块PRD.md §5.5.2`、`PRD/权限管理/角色权限矩阵.md`、`DATA_MODEL/DATA_MODEL_SETTING.md §2.3`
|
||||
**项目根目录**:`/mnt/c/project/fonrey/`
|
||||
**Git HEAD**:`aaf3981`(main 分支,已 push 到 origin/main)
|
||||
**v1 → v2 增量**:14 个 commit(`79c3cf2` … `aaf3981`),覆盖 Phase 4.0、4.1、5
|
||||
|
||||
---
|
||||
|
||||
## 一、自 v1 以来的执行摘要
|
||||
|
||||
v1 报告(2026-04-29)覆盖 Phase 1–3 骨架。v2 在不改动 v1 的前提下追加 Phase 4.0、4.1、5 的实施记录与最终交付状态。
|
||||
|
||||
### 1.1 Phase 4.0 — 模型级 verbose_name(commit `79c3cf2`)
|
||||
|
||||
为全部 74 个具体 ORM 模型(不含抽象基类)补齐 `Meta.verbose_name` / `verbose_name_plural` 中文显示名,对齐 `DATA_MODEL_*.md`。
|
||||
|
||||
### 1.2 Phase 4.1 — 字段级 verbose_name + help_text(commits `3638fc0` … `8faa68b`,9 commit)
|
||||
|
||||
为全部 781 个字段补齐中文 `verbose_name` 与 `help_text`,按 9 个业务模块串行落盘:
|
||||
|
||||
| 顺序 | 模块 | commit |
|
||||
|---:|---|---|
|
||||
| 1 | property | `3638fc0` |
|
||||
| 2 | client | `e67b07a` |
|
||||
| 3 | complex | `a3800bf` |
|
||||
| 4 | org | `f185127` |
|
||||
| 5 | account | `b57070f` |
|
||||
| 6 | permission | `9ef6eb6` |
|
||||
| 7 | setting | `289ec43` |
|
||||
| 8 | region | `e3b26ce` |
|
||||
| 9 | tenant | `8faa68b` |
|
||||
|
||||
随后单独一个 commit `d00ff12` 生成对应的 9 份 verbose_name/help_text Alter migration(共 3880 行)。
|
||||
|
||||
### 1.3 Phase 5 — 权限种子与租户自动初始化
|
||||
|
||||
| 子任务 | commit | 说明 |
|
||||
|---|---|---|
|
||||
| 拆 PermissionDef 到 SHARED app | `b9245cd` | 新建 `apps.permission_def`(label `fonrey_permission_def`),保留表名 `permission_defs`;`fonrey_permission.PermissionDef` FK 字符串改为 `fonrey_permission_def.PermissionDef` |
|
||||
| 154 条 PermissionDef seed + 7 内置角色 + 154×7 矩阵 + Lookup 默认值 + 租户 post_save 自动 seed | `aaf3981` | data migration + 三个 service + 一个 signal |
|
||||
|
||||
### 1.4 最终验证
|
||||
|
||||
- `python manage.py check` ✅ 0 issues
|
||||
- `python manage.py makemigrations --dry-run` ✅ No changes detected
|
||||
- 154 条 PermissionDef 全部就位(migration 文件 grep `"code":` 计数 = 154)
|
||||
- 154 条 RolePermission 矩阵全部就位(service 文件 matrix dict 键数 = 154)
|
||||
- main 已 push 到 origin/main
|
||||
|
||||
---
|
||||
|
||||
## 二、v1 → v2 顶层变化
|
||||
|
||||
| 维度 | v1 (2026-04-29) | v2 (2026-04-30) |
|
||||
|---|---|---|
|
||||
| App 数 | 10 | **11**(新增 `apps.permission_def`) |
|
||||
| ORM 模型数 | 77 | 77(PermissionDef 从 `permission` 迁移到 `permission_def`) |
|
||||
| Migration 文件数 | 12 | **33** |
|
||||
| 业务代码 LoC(不含 migrations) | ~7332 | ~8095 |
|
||||
| Phase 4 verbose_name/help_text | 未做 | ✅ 全部 781 字段 + 74 模型 |
|
||||
| PermissionDef seed | 未做(v1 列入"未交付") | ✅ 154 条 |
|
||||
| 内置角色 + 矩阵 | 未做(v1 列入"未交付") | ✅ 7 角色 + 154×7 |
|
||||
| LookupItem 默认值 | 未做(v1 列入"未交付") | ✅ |
|
||||
| 租户自动 seed | 未做 | ✅ `apps.tenant.signals` post_save |
|
||||
|
||||
---
|
||||
|
||||
## 三、Phase 4.0/4.1 实施细节
|
||||
|
||||
### 3.1 verbose_name 与 help_text 来源
|
||||
|
||||
权威源为 `/mnt/d/Workspace/nexus/Project/fonrey/DATA_MODEL/DATA_MODEL_*.md`(9 个模块文件 + ENUMS.md v2.2)。补齐策略:
|
||||
|
||||
- 模型 `Meta.verbose_name` 取 PRD 中文表名(如 `verbose_name = "房源"`)
|
||||
- 字段 `verbose_name` 取 PRD 字段中文标题
|
||||
- 字段 `help_text` 取 PRD 字段 "说明" 列;ENUM 字段统一采用 `code=中文` 对照格式(如 `"public=公立 / private=私立"`)
|
||||
- BinaryField 加密手机号字段统一标注"AES-256-GCM 密文"
|
||||
|
||||
### 3.2 verbose_name migration 策略
|
||||
|
||||
由于 verbose_name/help_text 不影响 schema,全部归并为 9 个 `AlterField` migration(每模块一份),不与原有 schema migration 混用。`d00ff12` 一次性生成全部 9 份,dry-run 后 `manage.py check` 与 `makemigrations --dry-run` 双双干净。
|
||||
|
||||
### 3.3 受影响模型
|
||||
|
||||
74 个具体模型全部覆盖(不含抽象基类 `UUIDPrimaryKeyModel` / `TimeStampedModel` / `SoftDeleteModel` / `AuditedModel`)。
|
||||
|
||||
---
|
||||
|
||||
## 四、Phase 5 实施细节
|
||||
|
||||
### 4.1 PermissionDef 拆 SHARED 的动机与实现
|
||||
|
||||
**问题**:v1 阶段 PermissionDef 在 `apps.permission`(TENANT_APPS)。这意味着每个新租户都要复制全部 154 条权限定义;权限矩阵升级时需要在每个 schema 重复 migrate;管理员视角无法对全局权限做统一编辑。
|
||||
|
||||
**方案**:拆出独立 SHARED app `apps.permission_def`(label `fonrey_permission_def`),保留物理表名 `permission_defs`(避免 RENAME)。所有租户的 `Role.permission_def` / `StaffPermissionOverride.permission_def` FK 跨 schema 指向 `public.permission_defs`(django-tenants 默认 `search_path` 包含 `public`,FK 自然解析)。
|
||||
|
||||
**FK 字符串改写**:
|
||||
|
||||
| 文件 | 行 | 原 | 新 |
|
||||
|---|---|---|---|
|
||||
| `apps/permission/models/role.py` | 94 | `"fonrey_permission.PermissionDef"` | `"fonrey_permission_def.PermissionDef"` |
|
||||
| `apps/permission/models/staff_perm.py` | 89 | `"fonrey_permission.PermissionDef"` | `"fonrey_permission_def.PermissionDef"` |
|
||||
|
||||
**Migration 顺序**(fresh DB,无历史数据):
|
||||
|
||||
1. `permission_def/0001_initial`:在 public schema `CREATE TABLE permission_defs`
|
||||
2. `permission/0004_alter_..._delete_permissiondef`:依赖 `permission_def/0001`,对每个 tenant schema 既 `AlterField`(FK 字符串切换,Django state 一致性)也 `DeleteModel(PermissionDef)`(清理 tenant schema 中本不应存在的孤儿表)
|
||||
3. `permission_def/0002_seed_permission_defs`:在 public schema bulk_create 154 条
|
||||
|
||||
**SHARED_APPS 顺序**(`config/settings/base.py`):
|
||||
|
||||
```python
|
||||
SHARED_APPS = [
|
||||
"django_tenants",
|
||||
"apps.tenant",
|
||||
"apps.release",
|
||||
"apps.permission_def", # 新增
|
||||
"shared",
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
### 4.2 154 条 PermissionDef seed
|
||||
|
||||
文件:[`apps/permission_def/migrations/0002_seed_permission_defs.py`](file:///mnt/c/project/fonrey/apps/permission_def/migrations/0002_seed_permission_defs.py)(2358 行)
|
||||
|
||||
实现:
|
||||
|
||||
```python
|
||||
def seed(apps, schema_editor):
|
||||
PermissionDef = apps.get_model("fonrey_permission_def", "PermissionDef")
|
||||
PermissionDef.objects.bulk_create([PermissionDef(**d) for d in PERMISSION_DEFS])
|
||||
|
||||
def unseed(apps, schema_editor):
|
||||
PermissionDef = apps.get_model("fonrey_permission_def", "PermissionDef")
|
||||
PermissionDef.objects.filter(code__in=[d["code"] for d in PERMISSION_DEFS]).delete()
|
||||
```
|
||||
|
||||
公共元数据(每条都含):`is_active=True, is_deprecated=False, is_system=True, version=1`。
|
||||
|
||||
按权威源 `PERMISSION_SEED_MVP_BATCH1.md` 共 3 批:
|
||||
|
||||
| 批 | 模块 | 条数 | 主代码前缀 |
|
||||
|---:|---|---:|---|
|
||||
| 1 | property | 66 | `property.listing.*`、`property.contact.*`、`property.address.*`、`property.key.*`、`property.commission.*`、`property.image.*` |
|
||||
| 2 | client | 36 | `client.list.*`、`client.contact.*`、`client.viewing.*`、`client.match.*`、`client.transaction.*` |
|
||||
| 3 | home + complex + org | 52 | `home.*`、`complex.*`、`org.*` |
|
||||
| **合计** | | **154** | |
|
||||
|
||||
`module` 字段使用 `PermissionModule` enum:`org.*` 代码 → `module="hr"`(PRD 组织人事即 HR 模块);`complex.*` 代码 → `module="property"`(小区是房源子集)。
|
||||
|
||||
### 4.3 7 个内置角色 + 154×7 矩阵 service
|
||||
|
||||
文件:[`apps/permission/services/seed_default_roles.py`](file:///mnt/c/project/fonrey/apps/permission/services/seed_default_roles.py)(218 行)
|
||||
|
||||
7 角色映射到 `PermissionRoleCategory` 枚举(仅 `agent / store_manager / director / operator / custom` 5 选项):
|
||||
|
||||
| 角色名 | category |
|
||||
|---|---|
|
||||
| 置业顾问 | `agent` |
|
||||
| 店管 | `store_manager` |
|
||||
| 区管 | `custom` |
|
||||
| 区总 | `custom` |
|
||||
| 副总 | `custom` |
|
||||
| 总经 | `director` |
|
||||
| 其他职能 | `operator` |
|
||||
|
||||
矩阵符号转写:
|
||||
|
||||
| PRD 符号 | 落库 `value` |
|
||||
|---|---|
|
||||
| `✓` | `{"v": True}` |
|
||||
| `✗` | `{"v": False}` |
|
||||
| `本人` / `本部` / `全部` / `—` | `{"v": "self"}` / `{"v": "dept"}` / `{"v": "all"}` / `{"v": "none"}` |
|
||||
| 整型 N | `{"v": N}` |
|
||||
| `∞` | `{"v": -1}` |
|
||||
|
||||
入口:`def seed_default_roles(schema_name: str) -> None`。调用方在 `schema_context` 内调用即可(参数 `schema_name` 仅作日志 hint)。
|
||||
|
||||
实现:`Role.objects.get_or_create(name=..., defaults={...})` 7 次 → 遍历 154 个 code,按 `{code: PermissionDef}` 建表,组装 7×154 个 `RolePermission` → `bulk_create(ignore_conflicts=True)`。
|
||||
|
||||
**幂等保证**:`get_or_create` + `bulk_create(ignore_conflicts=True)`;对缺失 code 仅 `logger.warning` 跳过、不抛错。
|
||||
|
||||
### 4.4 LookupItem 默认值 service
|
||||
|
||||
文件:[`apps/setting/services/seed_default_lookups.py`](file:///mnt/c/project/fonrey/apps/setting/services/seed_default_lookups.py)(113 行)
|
||||
|
||||
依据 `DATA_MODEL_SETTING.md §2.3`,注入:
|
||||
|
||||
- 3 个 `LookupGroup`(按模块)
|
||||
- 各组的 `LookupItem` 默认枚举值
|
||||
- 1 个 `TenantSetting` 兜底默认行
|
||||
- `FieldRequirementRule` 默认规则
|
||||
|
||||
入口:`def seed_default_lookups(schema_name: str) -> None`。同样依赖调用方提供 schema 上下文。
|
||||
|
||||
### 4.5 租户自动 seed signal
|
||||
|
||||
文件:[`apps/tenant/signals.py`](file:///mnt/c/project/fonrey/apps/tenant/signals.py)(36 行)
|
||||
|
||||
```python
|
||||
def _register():
|
||||
Tenant = apps.get_model("tenant", "Tenant")
|
||||
|
||||
@receiver(post_save, sender=Tenant)
|
||||
def on_tenant_created(sender, instance, created, **kwargs):
|
||||
if not created or instance.schema_name == "public":
|
||||
return
|
||||
try:
|
||||
with schema_context(instance.schema_name):
|
||||
seed_default_roles(instance.schema_name)
|
||||
seed_default_lookups(instance.schema_name)
|
||||
except Exception:
|
||||
logger.exception("Failed to seed defaults for tenant %s", instance.schema_name)
|
||||
```
|
||||
|
||||
注册:`apps/tenant/apps.py` `ready()` 调用 `signals._register()`(lazy 注册避开 Django app loading 早期 model 引用)。
|
||||
|
||||
**容错**:try/except 包裹 seed 调用,失败仅记录日志,不阻断租户创建本身。
|
||||
|
||||
### 4.6 Phase 5 关键决策
|
||||
|
||||
| 决策 | 原因 |
|
||||
|---|---|
|
||||
| PermissionDef 拆出 SHARED 而非 RENAME 表 | 避免破坏式迁移,保持表名 `permission_defs` |
|
||||
| seed 用 RunPython data migration 而非 fixtures | 项目偏好,便于 `--reverse` 与 `apps.get_model` 历史模型 |
|
||||
| 角色 + 矩阵 + Lookup 用 service 函数而非 data migration | 三者写入 tenant schema,需 `schema_context`;migration 只走 default 连接 |
|
||||
| tenant post_save 自动调用 service | 用户明确选择"新建租户时自动 seed",避免 ops 手动跑命令 |
|
||||
| 不 seed `staff_data_scopes` 表 | 用户明确指示;scope 类 PermissionDef 的 `default_value` 已承担兜底 |
|
||||
| Platform admin 角色不在本批 | 用户明确指示,归 `apps.admin_console`(待建) |
|
||||
| signal 用 lazy `_register()` 而非模块级 `@receiver` | 避免 ready() 早期 `apps.get_model` 不可用 |
|
||||
|
||||
---
|
||||
|
||||
## 五、最新目录结构(v2 增量标注)
|
||||
|
||||
```
|
||||
apps/
|
||||
├── __init__.py
|
||||
├── account/ (4 模型)
|
||||
├── client/ (11 模型)
|
||||
├── complex/ (10 模型)
|
||||
├── org/ (11 模型)
|
||||
├── permission/ (6 模型 + services/seed_default_roles.py) ← v2: 6 模型(PermissionDef 已迁出)
|
||||
├── permission_def/ (1 模型) ← v2 新增 SHARED app
|
||||
├── property/ (23 模型)
|
||||
├── region/ (5 模型)
|
||||
├── release/ (0 模型)
|
||||
├── setting/ (4 模型 + services/seed_default_lookups.py) ← v2: 新增 service
|
||||
└── tenant/ (2 模型 + signals.py) ← v2: 新增 signal
|
||||
```
|
||||
|
||||
模型计数:77(与 v1 一致;PermissionDef 从 permission 迁到 permission_def)。
|
||||
|
||||
---
|
||||
|
||||
## 六、Migration 总览(33 份)
|
||||
|
||||
| App | Migration | 用途 |
|
||||
|---|---|---|
|
||||
| account | 0001 / 0002 | 初始 + AUTH_USER_MODEL 切换 |
|
||||
| account | 0003 / 0004 | Phase 4.0 / 4.1 verbose_name + help_text |
|
||||
| client | 0001 | 初始 |
|
||||
| client | 0002 | 分区表 + 触发器 |
|
||||
| client | 0003 / 0004 | Phase 4.0 / 4.1 |
|
||||
| complex | 0001 | 初始 |
|
||||
| complex | 0002 | pg_trgm + search_vector |
|
||||
| complex | 0003 / 0004 | Phase 4.0 / 4.1 |
|
||||
| org | 0001 | 初始 |
|
||||
| org | 0002 / 0003 | Phase 4.0 / 4.1 |
|
||||
| permission | 0001 / 0002 / 0003 | 初始 + Phase 4.0/4.1 |
|
||||
| permission | **0004** | **v2 新增**:FK 切换到 fonrey_permission_def + DeleteModel(PermissionDef) |
|
||||
| permission_def | **0001** | **v2 新增**:CREATE TABLE permission_defs(public schema) |
|
||||
| permission_def | **0002** | **v2 新增**:154 条 PermissionDef bulk_create |
|
||||
| property | 0001 | 初始 |
|
||||
| property | 0002 | 分区表 + 触发器 |
|
||||
| property | 0003 / 0004 | Phase 4.0 / 4.1 |
|
||||
| region | 0001 / 0002 / 0003 | 初始 + Phase 4.0/4.1 |
|
||||
| setting | 0001 / 0002 / 0003 | 初始 + Phase 4.0/4.1 |
|
||||
| tenant | 0001 / 0002 | 初始 + Phase 4.0/4.1 |
|
||||
|
||||
合计 33 个 migration。`makemigrations --dry-run` 干净。
|
||||
|
||||
---
|
||||
|
||||
## 七、Git 提交历史(v1 → v2 增量)
|
||||
|
||||
```
|
||||
aaf3981 feat(permission): seed 154 PermissionDefs + 7 builtin roles + matrix + lookups + tenant auto-seed
|
||||
b9245cd feat(permission): extract PermissionDef into shared apps.permission_def
|
||||
5dedd19 docker file & docker compose change
|
||||
d00ff12 feat(migrations): add Phase 4.0+4.1 verbose_name/help_text migrations
|
||||
8faa68b feat(tenant): add Chinese verbose_name/help_text to tenant models (Phase 4.1 part 9/9)
|
||||
e3b26ce feat(region): add Chinese verbose_name/help_text to region models (Phase 4.1 part 8/9)
|
||||
289ec43 feat(setting): add Chinese verbose_name/help_text to setting models (Phase 4.1 part 7/9)
|
||||
9ef6eb6 feat(permission): add Chinese verbose_name/help_text to permission models (Phase 4.1 part 6/9)
|
||||
b57070f feat(account): add Chinese verbose_name and help_text to all account fields (Phase 4.1 part 5/9)
|
||||
f185127 feat(org): add Chinese verbose_name and help_text to all org fields (Phase 4.1 part 4/9)
|
||||
a3800bf feat(complex): add Chinese verbose_name and help_text to all complex fields (Phase 4.1 part 3/9)
|
||||
e67b07a feat(client): add Chinese verbose_name and help_text to all client fields (Phase 4.1 part 2/9)
|
||||
3638fc0 feat(property): add Chinese verbose_name and help_text to all property fields (Phase 4.1)
|
||||
79c3cf2 feat(models): add Chinese verbose_name to all 74 models (Phase 4.0)
|
||||
```
|
||||
|
||||
每次 commit 后 `manage.py check` 0 issues。所有 commit 已 push 到 origin/main(`5dedd19..aaf3981`)。
|
||||
|
||||
---
|
||||
|
||||
## 八、未交付清单(v2 视角)
|
||||
|
||||
v1 列出的"未交付项"在 v2 的状态:
|
||||
|
||||
| v1 列项 | v2 状态 |
|
||||
| ----------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| ~300 条 PermissionDef 种子 | ✅ 已交付 154 条(MVP Batch 1);Batch 2/3 待补 |
|
||||
| 内置角色 + 默认 DataScope 种子 | 🟡 7 内置角色 + 矩阵已交付;DataScope **不 seed**(用户明确指示,scope 类 PermissionDef `default_value` 承担兜底) |
|
||||
| Setting LookupItem 默认值 | ✅ 已交付 |
|
||||
| Celery `partition_maintenance_task` | ⏸ 仍未做,建议上线前 1 周落地 |
|
||||
| API_CONTRACT 第 1–4 项 | ⏸ Phase 6+ 业务端点开发时同步推进 |
|
||||
| OpenAPI 实际生成 + schemathesis 实际运行 | ⏸ 同上 |
|
||||
| Heroicons SVG 资源文件 | ⏸ Phase 6+ UI 开发时落地 |
|
||||
| static/vendor/ JS(htmx/alpine) | ⏸ 同上 |
|
||||
|
||||
v2 新增/识别的待办:
|
||||
|
||||
| 项 | 优先级 | 说明 |
|
||||
|---|:---:|---|
|
||||
| Platform admin 角色 + 路由 + 视图 | 中 | 独立任务,归未来 `apps.admin_console`(SHARED) |
|
||||
| PermissionDef MVP Batch 2/3(合同/交易/数据/营销/移动端等模块) | 中 | 沿用 `0002_seed_permission_defs` 同模式追加 data migration |
|
||||
| `seed_default_roles` 中未使用的 `schema_context` import | 低 | 微清理,不阻断 |
|
||||
| signal 失败重试或离线补偿命令 | 中 | 当前 try/except + log;建议补 `manage.py reseed_tenant <schema>` 命令 |
|
||||
|
||||
---
|
||||
|
||||
## 九、关键约束遵守审计(v2 增量)
|
||||
|
||||
v1 §11 全部约束在 v2 仍然遵守。v2 新增约束:
|
||||
|
||||
| 约束 | 遵守状态 | 证据 |
|
||||
|---|:---:|---|
|
||||
| 不引入 docstring/无谓注释(hook 强制) | ✅ | Phase 4.1 + 5 全部新文件 grep `^\s*#` 与 docstring 极少,仅保留必要的 BDD/regex 注释 |
|
||||
| 不修改 Dockerfile / docker-compose.yml | ✅ | Phase 5 期间未触动;用户独立 commit `5dedd19` 覆盖 docker 改动 |
|
||||
| 不 commit 未明确授权的 untracked 文件 | ✅ | 仅 commit 计划内文件,每次 commit 列表精确 |
|
||||
| `manage.py check` 每次 commit 后 0 issues | ✅ | 14 个 commit 全部验证 |
|
||||
| `makemigrations --dry-run` 收尾时 No changes detected | ✅ | `aaf3981` 后实际跑过 |
|
||||
| PermissionDef 公共元数据完整(is_system / version=1 等) | ✅ | seed migration 154 条全部含 |
|
||||
| 不 seed staff_data_scopes | ✅ | 仅 PermissionDef + Role + RolePermission + Lookup |
|
||||
| Platform admin 不混入本批 | ✅ | 7 角色不含 platform_admin |
|
||||
| FK 跨 SHARED/TENANT 字符串引用正确 | ✅ | `manage.py check` 通过即证 |
|
||||
|
||||
---
|
||||
|
||||
## 十、下一步建议(v2 视角)
|
||||
|
||||
### 10.1 Phase 6 启动前必做
|
||||
|
||||
1. 决定 vendor JS 加载方式(npm install 还是直接放置静态文件)
|
||||
2. 准备 Heroicons SVG 库
|
||||
3. 实现 `apps.admin_console`(SHARED) + Platform admin 内置角色
|
||||
|
||||
### 10.2 Phase 6 业务模块开发与契约闭环
|
||||
|
||||
- 第一个真实业务端点(建议从 `release/client_update` 起步)落地后立即跑 `spectacular` + `schemathesis`,闭环 API_CONTRACT 7 项
|
||||
- 在每个业务视图 PR 中强制 `@extend_schema`
|
||||
- 每新增 PermissionDef 需要同步追加 `permission_def/000N_seed_*.py`,且新建 RolePermission 时使用 `seed_default_roles` 增量化
|
||||
- 撰写 `manage.py reseed_tenant <schema>` 命令用于 signal 失败补偿
|
||||
|
||||
### 10.3 上线前 1 周
|
||||
|
||||
- 实现 Celery `partition_maintenance_task`(property_follow_logs / property_photos / client_follow_logs 月度滚动)
|
||||
- 用真实 32 字节随机值替换 `.env` 占位的 `PHONE_ENCRYPTION_KEY`,托管至 Vault/Secret Manager
|
||||
- 验证租户创建 → signal 自动 seed 全链路(含异常路径:seed 失败时的补偿命令)
|
||||
|
||||
### 10.4 可选
|
||||
|
||||
- pre-commit 钩子(ruff + black + isort + django-check)
|
||||
- GitHub Actions CI(lint + test + spectacular dry-run + makemigrations --dry-run 必须 No changes)
|
||||
|
||||
---
|
||||
|
||||
## 十一、附录:v2 时点验证命令
|
||||
|
||||
```bash
|
||||
cd /mnt/c/project/fonrey
|
||||
.venv/bin/python manage.py check # System check identified no issues (0 silenced)
|
||||
.venv/bin/python manage.py makemigrations --dry-run # No changes detected
|
||||
grep -c '"code":' apps/permission_def/migrations/0002_seed_permission_defs.py # 154
|
||||
grep -c '^\s*"[a-z_]*\.[a-z_.]*":' apps/permission/services/seed_default_roles.py # 154
|
||||
git log --oneline 94d1602..HEAD | wc -l # 14
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**报告完**(v2.0 — 2026-04-30)
|
||||
Reference in New Issue
Block a user