11 KiB
For AI assistants: Read this entire file before writing any code. All decisions here are final.
Fonrey — 统一状态机规范 (STATE_MACHINE)
定位:本文档是 Fonrey 项目所有实体生命周期与状态流转的唯一权威定义。
变更历史:
| 日期 | 变更人 | 变更内容 |
|---|---|---|
| 2026-06-04 | Sisyphus | 初始版本:整合各模块状态机逻辑,对齐 ENUMS v2.2 |
1. 通用约定
- 状态值命名:统一采用
lower_snake_case,必须与DATA_MODEL/ENUMS.md完全一致。 - 触发动作:状态迁移必须由显式的动作(Action)或事件(Event)触发。
- 操作日志:所有关键状态迁移(除系统内部中间态外)必须记录对应的
status_log或audit_log表。 - 不可逆规则:标注为“终态”的状态禁止迁回初始态或中间态。
- 权限要求:状态迁移接口必须校验操作者的 DataScope 与 Function Permission。
2. 租户生命周期 (Public.Tenant)
实体: public.tenants | 字段: status
参考: DATA_MODEL_PUBLIC.md §2.1, §4.1
stateDiagram-v2
[*] --> creating
creating --> active: 初始化完成
creating --> failed: 初始化失败
active --> suspended: 逾期/违规/申请
suspended --> active: 恢复条件满足
active --> pending_delete: 申请注销
suspended --> pending_delete: 申请注销
pending_delete --> deleted: 30天后/人工确认
deleted --> [*]
状态枚举值
(domain: public.tenant.status)
creating: 创建中active: 正常suspended: 已挂起pending_delete: 待删除deleted: 已删除failed: 创建/初始化失败
状态迁移表
| 当前状态 | 下一状态 | 触发动作/事件 | 触发角色 | 副作用 | 是否可逆 |
|---|---|---|---|---|---|
creating |
active |
租户 Schema 初始化成功 | System | 写 tenant_status_logs |
否 |
creating |
failed |
初始化脚本执行失败 | System | 记录错误日志 | 否 |
active |
suspended |
欠费/违规/License过期 | System/SuperAdmin | 设置 suspended_until, 写日志 |
是 |
suspended |
active |
缴费成功/解封/到期恢复 | System/SuperAdmin | 清除挂起原因 | 是 |
active/suspended |
pending_delete |
提交注销申请 | TenantAdmin | 设置 deleted_at |
是 |
pending_delete |
deleted |
确认注销/静默期结束 | SuperAdmin/System | 物理删除或深度标记 | 否 |
来源章节: DATA_MODEL_PUBLIC.md §4.1
3. 客源状态机 (Client)
实体: client.clients | 字段: status
参考: DATA_MODEL_CLIENT.md §3.1, §4 | ENUMS.md §3.6
stateDiagram-v2
[*] --> buying
[*] --> renting
[*] --> buy_or_rent
state "活跃态" as Active {
buying
renting
buy_or_rent
}
Active --> suspended: 暂时无需求
suspended --> Active: 重新激活
Active --> public: 手动转公/超时自动
suspended --> public: 手动转公
Active --> bought: 转成交(我购)
Active --> rented_done: 转成交(我租)
Active --> invalid: 转无效
suspended --> invalid: 转无效
invalid --> Active: 经理审批恢复
bought --> [*]
rented_done --> [*]
public --> [*]
状态枚举值
(domain: client.status)
buying: 求购renting: 求租buy_or_rent: 租购suspended: 暂缓bought: 已购 (我购)rented_done: 已租 (我租)public: 公客invalid: 无效
状态迁移表
| 当前状态 | 下一状态 | 触发动作/事件 | 触发角色 | 副作用 | 是否可逆 |
|---|---|---|---|---|---|
buying/renting/buy_or_rent |
suspended |
修改状态为暂缓 | 经纪人 | 写 client_status_logs |
是 |
suspended |
buying/renting/buy_or_rent |
重新激活需求 | 经纪人 | 更新 last_active_at |
是 |
Active/suspended |
public |
手动转公/超时自动转公 | 经纪人/System | 修改 client_type='public' |
否 |
Active |
bought/rented_done |
录入成交合同 | 经纪人 | 修改 client_type='transacted' |
否 |
Active/suspended |
invalid |
标记无效 | 经纪人 | 记录 invalid_reason |
需审批 |
禁迁规则
transacted(bought/rented_done) 状态为绝对终态,禁止迁往任何其他状态。public状态客源禁止直接修改为private状态下的需求状态,必须走领用流程。
来源章节: DATA_MODEL_CLIENT.md §4, ENUMS.md §3.6
4. 房源状态机 (Property)
实体: property.properties | 字段: status
参考: DATA_MODEL_PROPERTY.md §3, §4.1
stateDiagram-v2
[*] --> unlisted
unlisted --> for_sale: 挂牌出售
unlisted --> for_rent: 挂牌出租
state "在盘态" as Listed {
for_sale
for_rent
for_sale_rent
}
Listed --> suspended: 业主暂缓
suspended --> Listed: 重新上架
Listed --> sold: 本司成交
Listed --> sold_elsewhere: 他售
Listed --> rented_elsewhere: 他租
Listed --> unlisted: 下架
sold --> [*]
sold_elsewhere --> [*]
状态枚举值
(domain: property.status)
for_sale: 出售for_rent: 出租for_sale_rent: 租售suspended: 暂缓sold_elsewhere: 他售rented_elsewhere: 他租sold: 成交unlisted: 未挂牌
状态迁移表
| 当前状态 | 下一状态 | 触发动作/事件 | 触发角色 | 副作用 | 是否可逆 |
|---|---|---|---|---|---|
unlisted |
for_sale/for_rent |
房源挂牌 | 经纪人 | 新增 listing_histories |
是 |
Listed |
suspended |
业主通知暂缓 | 经纪人 | 写跟进日志 | 是 |
Listed |
sold |
本司录入成交 | 经纪人 | 自动结束挂牌历史 | 否 |
Listed |
sold_elsewhere/rented_elsewhere |
核实他司已成交 | 经纪人 | 否 | |
Listed |
unlisted |
强制下架 | 管理员 | 是 |
来源章节: DATA_MODEL_PROPERTY.md §3
5. 客户/房源等级 (Grade)
实体: client.clients / property.properties | 字段: grade
参考: DATA_MODEL_CLIENT.md §3.1 | DATA_MODEL_PROPERTY.md §4.1
状态枚举值
(domain: client.grade / property.grade)
A: A (急迫)B: B (较强)C: C (一般)D: D (较弱)E: E (暂不关注) - 仅客源
状态迁移表
| 当前状态 | 下一状态 | 触发动作/事件 | 触发角色 | 副作用 | 是否可逆 |
|---|---|---|---|---|---|
| 任意状态 | A/B/C/D/E |
手动调整等级 | 经纪人 | 写 status_log / follow_log |
是 |
来源章节: DATA_MODEL_CLIENT.md §4, DATA_MODEL_PROPERTY.md §3
6. 账号状态机 (Account)
实体: login.user_accounts | 字段: status
参考: DATA_MODEL_LOGIN.md §5.1
stateDiagram-v2
[*] --> active: 创建(初始密码)
active --> locked: 密码错误≥5次
locked --> active: 30min到期/手动解锁
active --> disabled: 离职/手动停用
disabled --> active: 复职/手动恢复
状态枚举值
(domain: login.user_account.status)
active: 启用disabled: 停用locked: 锁定
状态迁移表
| 当前状态 | 下一状态 | 触发动作/事件 | 触发角色 | 副作用 | 是否可逆 |
|---|---|---|---|---|---|
active |
locked |
密码连续错误5次 | System | 设置 locked_until |
是 |
locked |
active |
时间到期/管理员解锁 | System/Admin | 是 | |
active |
disabled |
员工离职/手动停用 | Admin/System | 踢出所有 Session | 是 |
来源章节: DATA_MODEL_LOGIN.md §5.1
7. 升级事件状态机 (Upgrade Event)
实体: public.upgrade_events | 字段: status
参考: DATA_MODEL_PUBLIC.md §4.2
stateDiagram-v2
[*] --> draft
draft --> pre_check: 提交
pre_check --> pre_backup: 健康检查通过
pre_backup --> batch_running: 备份完成
batch_running --> batch_done: 批次租户成功
batch_done --> batch_running: 下一批次
batch_done --> succeeded: 全部完成
batch_running --> halted: 失败/门控拦截
halted --> batch_running: 人工继续
halted --> rollback_running: 人工回滚
rollback_running --> rolled_back: 回滚完成
batch_running --> failed: 严重故障
状态枚举值
(domain: public.upgrade_event.status)
draft: 草稿pre_check: 预检查pre_backup: 预备份batch_running: 批次执行中batch_done: 批次完成halted: 已暂停succeeded: 已成功failed: 失败rollback_running: 回滚中rolled_back: 已回滚
来源章节: DATA_MODEL_PUBLIC.md §4.2
8. 其他辅助状态
8.1 备份/导出任务 (Backup/Export)
字段: status | 参考: ENUMS.md §2.3
pending->in_progress->success/failed
8.2 客户端发布 (Client Release)
字段: status | 参考: ENUMS.md §2.4
draft->published->archived- 约束: 同平台架构下仅允许一个
published。
8.3 员工状态 (Staff)
字段: status | 参考: DATA_MODEL_ORG.md §4
probation->active->resignedactive<->frozen
8.4 审批流 (Approval)
实体: number_holder_approvals | 字段: status
pending->approved/rejected
X. 状态机一致性校验清单
- 枚举同步: 状态字段值是否在
ENUMS.md中定义且拼写一致? - 日志完备: 每次
status变更是否伴随对应的status_log插入动作? - 并发控制: 状态变更是否包含
version乐观锁检查? - 终态拦截: 业务逻辑是否显式禁止从终态(如
sold,deleted,rolled_back)向外迁移? - 副作用触发: 状态变更相关的异步任务(如转公客通知、缓存清理)是否已在 Service 层注册?
待澄清问题
- Client Invalid 恢复路径:
DATA_MODEL_CLIENT.md§4 提到“需经理审批后可恢复”,但未定义恢复后的目标状态(是恢复到suspended还是之前的活跃态?)。- 涉及文件:
DATA_MODEL_CLIENT.md
- 涉及文件:
- Property Unlisted 属性: 房源在
unlisted状态下,其attribute(公/私盘) 是否有意义?若从private挂牌变为unlisted,再次挂牌时是否应默认保留private属性?- 涉及文件:
DATA_MODEL_PROPERTY.md
- 涉及文件:
- Tenant Deleted 物理性:
DATA_MODEL_PUBLIC.md§4.1 提到“硬删除直接到 deleted”,但在 §2.1 又说“硬删除直接物理删除行”。需要明确deleted状态是代表软删除的终点还是物理删除前的标记。- 涉及文件:
DATA_MODEL_PUBLIC.md
- 涉及文件:
- Staff Resigned 恢复: 离职员工复职(
rejoin)后,其status是回到probation还是active?- 涉及文件:
DATA_MODEL_ORG.md
- 涉及文件: