1
0
forked from erp-dev/erp
Files
erpnew/stateflow/CHANGELOG.md
2025-11-11 18:05:10 +08:00

5.5 KiB
Raw Permalink Blame History

Stateflow 修正记录

2025-11-11: 重要架构调整

修正1: 日志不可删除,仅能标记为已撤销

问题: 之前重置进度时会删除所有完成记录,导致操作历史丢失。

解决方案:

  • 添加 OrderStateLog.is_cancelled 字段(是否已撤销)
  • 添加 OrderStateLog.cancelled_at 字段(撤销时间)
  • 修改 reset_order_progress() 函数,不再删除记录,而是:
    order.state_logs.filter(is_cancelled=False).update(
        is_cancelled=True,
        cancelled_at=timezone.now()
    )
    

影响:

  • 保留完整的操作历史
  • 可以审计谁在什么时候撤销了进度
  • 支持未来可能的"恢复"功能

修正2: 初始状态改为 None未开始

问题: 之前订单创建后,初始状态就是第一个节点,无法区分"未开始"和"进行中"。

解决方案:

  • 修改 get_order_current_state() 函数:
    • 没有任何有效完成记录时返回 None(而不是第一个节点)
    • 所有状态都完成后也返回 None
  • 新增 get_overall_status() 函数:
    • 用于区分 'not_started'(未开始)和 'completed'(已完成)
  • 修改 advance_to_next_state() 函数:
    • 当当前状态为 None 且没有完成记录时,自动推进到第一个节点

状态转换流程:

创建订单 → None (not_started)
   ↓ 第一次推进
状态1 完成 → 状态2 (in_progress)
   ↓ 第二次推进
状态2 完成 → 状态3 (in_progress)
   ↓ 第三次推进
状态3 完成 → None (completed)

影响:

  • 可以区分"未开始处理"和"正在处理"
  • 可以区分"正在处理"和"已完成"
  • API 可以根据状态显示不同的操作按钮

修正3: 撤销记录保存撤销时间

问题: 重置进度时,无法知道具体在什么时候撤销的。

解决方案:

  • OrderStateLog 模型中添加 cancelled_at 字段
  • 重置进度时,自动记录撤销时间:
    order.state_logs.filter(is_cancelled=False).update(
        is_cancelled=True,
        cancelled_at=timezone.now()
    )
    

影响:

  • 完整的审计追踪
  • 可以分析订单被重置的频率和原因
  • 便于问题排查和数据分析

数据库迁移

# 生成迁移文件
python manage.py makemigrations stateflow

# 应用迁移
python manage.py migrate

迁移文件: 0010_remove_orderstatelog_notes_and_more.py

变更内容:

  • 添加 cancelled_at 字段DateTimeField, nullable
  • 添加 is_cancelled 字段BooleanField, default=False

测试验证

所有测试通过 (6 tests in 0.598s)

新增测试:

  • test_reset_progress: 验证重置进度不删除记录
  • test_timeline_with_cancelled: 验证时间线包含撤销记录
  • test_initial_state: 验证初始状态为 None

API 变更

返回值变更

advance_to_next_state(order, user):

  • 之前: bool
  • 现在: Tuple[bool, str] (是否成功, 消息)

can_advance_to_next_state(order):

  • 之前: Tuple[bool, str]
  • 现在: Tuple[bool, str] (是否可以推进, 原因)

新增函数

get_overall_status(order) -> str:

  • 返回: 'not_started' | 'in_progress' | 'completed'
  • 用途: 区分未开始和已完成(两者的 current_state 都是 None

行为变更

reset_order_progress(order):

  • 之前: 删除所有完成记录
  • 现在: 标记所有记录为已撤销,记录撤销时间

get_order_current_state(order):

  • 之前: 无记录时返回第一个节点
  • 现在: 无记录时返回 None

Admin 界面更新

OrderStateLog 内联

新增字段显示:

  • is_cancelled: 是否已撤销
  • cancelled_at: 撤销时间

OrderAdmin

显示逻辑更新:

  • current_state_display: 显示"未开始"、"已完成"或具体状态名
  • 重置进度操作提示: "已标记为撤销"而非"已删除"

升级指南

如果你已经在使用旧版本的 stateflow

  1. 备份数据库(重要!)

  2. 应用迁移:

    python manage.py migrate stateflow
    
  3. 更新代码:

    • advance_to_next_state() 的返回值解包为 (success, message)
    • 使用 get_overall_status() 替代直接判断 current_state is None
  4. 测试验证:

    python manage.py test stateflow
    

向后兼容性

⚠️ 破坏性变更:

  • get_order_current_state() 的返回值变化
  • advance_to_next_state() 的返回值从 bool 变为 Tuple[bool, str]

兼容性保持:

  • 数据库表结构只增不减
  • 现有的 OrderStateLog 记录自动设置 is_cancelled=False
  • API 端点可以平滑升级

最佳实践

  1. 永远不要删除 OrderStateLog

    • 使用 Admin 界面时,设置 can_delete=False
    • 在 API 中禁用 DELETE 端点
  2. 记录所有操作人

    • advance_to_next_state() 必须传入 completed_by
    • 可以在中间件中自动获取当前用户
  3. 定期清理撤销记录

    • 建议保留至少 1 年的撤销记录
    • 可以归档到历史表而不是直接删除
  4. 监控重置频率

    • 高频率的重置可能表明流程设计有问题
    • 可以添加告警机制

疑问解答

Q: ProcessNode 和 OrderStateLog 有什么区别?

A:

  • ProcessNode: 流程模板(定义流程有哪些步骤)
  • OrderStateLog: 订单实例的执行记录(记录实际完成了什么)

类比:

  • ProcessNode = 菜谱(定义做菜步骤)
  • OrderStateLog = 做菜记录(记录实际操作)

详细说明请参考 README.md 的"ProcessNode vs OrderStateLog"章节。