状态机 (State Machine)¶
概览¶
PO 工作流由数据库驱动的状态机控制。所有转换在执行前都会根据 Ref_PO_Transitions 表进行验证。
状态表 (Ref_PO_Status)¶
| 状态 ID | 状态名称 | 标签 (EN) | 标签 (ZH) | 颜色 | 终态? |
|---|---|---|---|---|---|
| 100 | NEW | New | 新建 | #0078d4 | 否 |
| 150 | REQUIRES_REVISION | Requires Revision | 需修改 | #c50f1f | 否 |
| 200 | PENDING_APPROVAL | Pending Approval | 待审批 | #ca5010 | 否 |
| 300 | CONFIRMED | Confirmed | 已确认 | #107c10 | 否 |
| 400 | IN_PRODUCTION | In Production | 生产中 | #0e7a0d | 否 |
| 500 | SHIPPED | Shipped | 已发货 | #8764b8 | 否 |
| 600 | DELIVERED | Delivered | 已交付 | #038387 | 是 |
| 900 | CANCELLED | Cancelled | 已取消 | #797775 | 是 |
转换表 (Ref_PO_Transitions)¶
stateDiagram-v2
[*] --> 100: Cin7 同步
100 --> 200: SUBMIT (供应商)
200 --> 300: APPROVE (经理)
200 --> 150: REJECT (经理)
200 --> 100: RECALL (供应商)
150 --> 200: SUBMIT (供应商)
300 --> 400: MOVE_TO_PRODUCTION (经理)
400 --> 500: MARK_SHIPPED (供应商)
500 --> 600: CONFIRM_DELIVERY (经理)
100 --> 900: CANCEL (经理)
150 --> 900: CANCEL (经理)
| 操作 | 从 (From) | 到 (To) | 允许的角色 | 守门员 (Gatekeeper) |
|---|---|---|---|---|
| SUBMIT | 100 (新建) | 200 (待审批) | Vendor | SUBMIT_READY |
| SUBMIT | 150 (需修改) | 200 (待审批) | Vendor | SUBMIT_READY |
| APPROVE | 200 (待审批) | 300 (已确认) | Manager, Admin | — |
| REJECT | 200 (待审批) | 150 (需修改) | Manager, Admin | — |
| RECALL | 200 (待审批) | 100 (新建) | Vendor | — |
| MOVE_TO_PRODUCTION | 300 (已确认) | 400 (生产中) | Manager, Admin | — |
| MARK_SHIPPED | 400 (生产中) | 500 (已发货) | Vendor, Manager | SHIPPING_READY |
| CONFIRM_DELIVERY | 500 (已发货) | 600 (已交付) | Manager, Admin | — |
| CANCEL | 100 (新建) | 900 (已取消) | Manager, Admin | — |
| CANCEL | 150 (需修改) | 900 (已取消) | Manager, Admin | — |
守门员检查 (Gatekeeper Checks)¶
SUBMIT_READY¶
在供应商提交之前,系统会验证:
has_pending_changes = 1或者这是一个全新的提交- 已上传并关联了形式发票 (Proforma Invoice)
SHIPPING_READY¶
在标记为已发货之前:
- 必须提供
container_number(集装箱号,不能为空)
转换引擎 (Transition Engine)¶
所有转换都通过单个接口进行:
POST /api/purchase-orders/{poRef}/transition
Body: { "action": "SUBMIT", "comment": "Ready for review" }
引擎流程:
- 查找 PO 当前的
app_po_status_id - 在
Ref_PO_Transitions中查询匹配的 (from_status, action, allowed_role) 行 - 如果未找到有效转换 → 返回 403 错误
- 如果适用,运行守门员检查
- 将
app_po_status_id更新为新状态 - 在
Log_PO_History中记录转换日志 - 返回新状态详情
历史日志 (Log_PO_History)¶
每次转换都会记录以下信息:
- PO 编号
- 旧状态和新状态 ID
- 操作名称
- 执行更改的用户
- 时间戳
- 可选备注 (例如:拒绝原因)
Cin7 初始状态映射 (Initial Status Mapping)¶
当 Airflow 将 PO 从 Cin7 同步到应用时,会根据 Cin7 的 stage 字段自动设置初始 app_po_status_id。
Cin7 status |
Cin7 stage |
app_po_status_id |
标签 |
|---|---|---|---|
| VOID | (任意) | — | 从应用中排除,不显示 |
| APPROVED | Delivered / Received |
600 | Delivered |
| APPROVED | In Transit |
500 | Shipped |
| APPROVED | New / NULL |
100 | New (默认) |
注意: Cin7 中状态为
VOID的 PO 不会出现在应用的任何页面或 KPI 统计中。 历史数据迁移脚本用于修复同步前已存在的数据。