Files
nexus/Project/fonrey/DATA_MODEL/STATE_MACHINE.md
2026-06-04 14:34:32 +08:00

11 KiB
Raw Blame History

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_logaudit_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 -> resigned
  • active <-> frozen

8.4 审批流 (Approval)

实体: number_holder_approvals | 字段: status

  • pending -> approved / rejected

X. 状态机一致性校验清单

  1. 枚举同步: 状态字段值是否在 ENUMS.md 中定义且拼写一致?
  2. 日志完备: 每次 status 变更是否伴随对应的 status_log 插入动作?
  3. 并发控制: 状态变更是否包含 version 乐观锁检查?
  4. 终态拦截: 业务逻辑是否显式禁止从终态(如 sold, deleted, rolled_back)向外迁移?
  5. 副作用触发: 状态变更相关的异步任务(如转公客通知、缓存清理)是否已在 Service 层注册?

待澄清问题

  1. Client Invalid 恢复路径: DATA_MODEL_CLIENT.md §4 提到“需经理审批后可恢复”,但未定义恢复后的目标状态(是恢复到 suspended 还是之前的活跃态?)。
    • 涉及文件: DATA_MODEL_CLIENT.md
  2. Property Unlisted 属性: 房源在 unlisted 状态下,其 attribute (公/私盘) 是否有意义?若从 private 挂牌变为 unlisted,再次挂牌时是否应默认保留 private 属性?
    • 涉及文件: DATA_MODEL_PROPERTY.md
  3. Tenant Deleted 物理性: DATA_MODEL_PUBLIC.md §4.1 提到“硬删除直接到 deleted”但在 §2.1 又说“硬删除直接物理删除行”。需要明确 deleted 状态是代表软删除的终点还是物理删除前的标记。
    • 涉及文件: DATA_MODEL_PUBLIC.md
  4. Staff Resigned 恢复: 离职员工复职(rejoin)后,其 status 是回到 probation 还是 active
    • 涉及文件: DATA_MODEL_ORG.md