forked from erp-dev/erp
fix: process id change when plate_order and printing_order update
This commit is contained in:
@@ -93,7 +93,7 @@ python manage.py backfill_merchant <merchant_id>
|
||||
|
||||
在 `settings.py` 中添加 `AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER` 配置项:
|
||||
|
||||
- **默认值**: `True`(保持现有行为)
|
||||
- **默认值**: `False`(默认关闭,避免未确认流程就自动落库)
|
||||
- **环境变量**: `AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER`
|
||||
- **作用**: 当设为 `False` 时,`printing/handlers.py` 中的流程完成信号处理器将不再自动创建销售品
|
||||
|
||||
@@ -103,6 +103,15 @@ python manage.py backfill_merchant <merchant_id>
|
||||
|
||||
---
|
||||
|
||||
### 6.1. 强制从 .env 读取 PRINTING_SALES_ITEM_SOURCE_STATE_ID(无默认值)
|
||||
|
||||
为避免遗漏配置导致“取错工序参数”,将 `PRINTING_SALES_ITEM_SOURCE_STATE_ID` 改为必须在 `.env` 中显式配置(不提供默认值)。
|
||||
|
||||
#### 修改文件
|
||||
- `flower/settings.py`: `PRINTING_SALES_ITEM_SOURCE_STATE_ID = env.int('PRINTING_SALES_ITEM_SOURCE_STATE_ID')`
|
||||
|
||||
---
|
||||
|
||||
### 7. Printing 模块客户可见性过滤
|
||||
|
||||
实现了基于客户可见性的订单查询过滤功能,确保员工只能看到自己负责的客户的订单。
|
||||
@@ -152,7 +161,15 @@ python manage.py backfill_merchant <merchant_id>
|
||||
- `shipment/migrations/0005_fix_shipment_external_finished_product_relation.py`(修正关系方向:Shipment 1→N ExternalFinishedProduct)
|
||||
|
||||
#### 测试
|
||||
- 运行 `api_v1.views.shipment.test_api`:13 个测试通过
|
||||
- 运行 `api_v1.views.shipment.test_api`:17 个测试通过
|
||||
|
||||
---
|
||||
|
||||
### 8.1. Admin 支持(Shipment)
|
||||
|
||||
补齐 Shipment 模块在 Django Admin 中的可用性,便于测试/排查数据:
|
||||
|
||||
- `shipment/admin.py`: 注册 `Shipment`、`SalesItem` 并提供基础展示/筛选字段
|
||||
|
||||
---
|
||||
|
||||
@@ -182,7 +199,15 @@ python manage.py backfill_merchant <merchant_id>
|
||||
#### merchant 强制归属(非空)
|
||||
- 为 `Shipment` 与 `SalesItem` 增加 `merchant` 外键且不允许为空
|
||||
- 创建时从 `request.user.employee.merchant` 自动绑定,并校验 customer 同商户
|
||||
- 普通版在关联销售品时校验销售品同商户,避免跨商户关联
|
||||
- 普通版在关联销售品时校验销售品同商户,避免跨商户关联(不一致则报错并回滚)
|
||||
- printing 流程完成自动创建 `SalesItem` 时增加 merchant 推导兜底(job → order → operator),避免 merchant 为空导致创建失败
|
||||
|
||||
#### Migration
|
||||
- `shipment/migrations/0006_add_merchant_to_shipment_and_salesitem.py`
|
||||
- 先以可空字段落库 → RunPython 补齐 → 再改为 `null=False`(避免 makemigrations 交互式默认值)
|
||||
|
||||
#### 响应字段补充
|
||||
- Shipment 响应增加 `merchant_id` / `merchant_name`(便于前端展示/二次校验)
|
||||
|
||||
#### 文档
|
||||
- `docs/shipment_api.md`: 补充 external create API 文档
|
||||
@@ -197,4 +222,4 @@ python manage.py backfill_merchant <merchant_id>
|
||||
|
||||
- API 独立于 printing 模块,避免影响现有功能
|
||||
- 完整的测试覆盖:正常查询、包含已出货、数据格式、404 错误、空结果、未认证
|
||||
- printing 和 shipment 模块全部测试通过(共 13 个测试用例)
|
||||
- printing 和 shipment 模块相关测试通过(`api_v1.views.shipment.test_api` 共 17 个用例)
|
||||
|
||||
35
docs/2026-01-15_summary.md
Normal file
35
docs/2026-01-15_summary.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# 2026-01-15 工作日志
|
||||
|
||||
## 背景
|
||||
|
||||
发现 `PlateOrder`(以及同类的 `PrintingOrder/PrintingJob`)在 PUT/PATCH 更新时允许修改流程相关字段,可能导致:
|
||||
- 业务对象的 `process` 已变更
|
||||
- 但已绑定的 `BusinessObject.process` 仍指向旧流程
|
||||
|
||||
从而出现“流程推进/状态展示与当前流程不一致”的严重数据一致性漏洞。
|
||||
|
||||
---
|
||||
|
||||
## 今日完成
|
||||
|
||||
- 修复流程变更导致的 `BusinessObject` 不匹配漏洞(统一收敛到 `stateflow` 层处理)
|
||||
- 约束更新行为:
|
||||
- `PrintingJob` 不再允许修改 `printing_order` 绑定关系(返回 400)
|
||||
- `PrintingOrder` 修改 `process` 时:
|
||||
- `process=None` 视为非法(返回 400)
|
||||
- 只要任意 job 存在“未撤销进度”(`has_started=True`),整笔订单不允许改流程(返回 400)
|
||||
- 若所有 jobs 均未开始,则修改订单流程时会同步为其下所有 jobs 重建并重新绑定新的 `BusinessObject`
|
||||
- `PlateOrder` 修改 `process` 时:
|
||||
- 若存在“未撤销进度”(`has_started=True`),不允许改流程(返回 400)
|
||||
- 否则重建并重新绑定新的 `BusinessObject`(旧 BO 保留不删除)
|
||||
- 测试补齐/修正:
|
||||
- PlateOrder:修改流程会重建 BO;存在有效进度时拒绝
|
||||
- PrintingOrder:有 job 且未开始时改流程会 relink jobs
|
||||
- PrintingJob:禁止变更 printing_order
|
||||
|
||||
---
|
||||
|
||||
## 文档
|
||||
|
||||
- 新增独立说明文档:`docs/business_object_relink_fix.md`(背景、风险、修正案与规则)
|
||||
|
||||
68
docs/business_object_relink_fix.md
Normal file
68
docs/business_object_relink_fix.md
Normal file
@@ -0,0 +1,68 @@
|
||||
## 背景与问题
|
||||
|
||||
系统中 `PlateOrder` / `PrintingJob` 都通过 `business_object`(`stateflow.BusinessObject`)承载流程推进数据:
|
||||
- `BusinessObject.process` 决定了流程节点序列
|
||||
- `BusinessObject.state_logs` 记录了推进轨迹(`StateFlowRecord`,支持撤销)
|
||||
|
||||
但在现有 API 中(PUT/PATCH 更新):
|
||||
- `PlateOrder.process`(整型流程 ID)允许被更新
|
||||
- `PrintingOrder.process`(外键流程)允许在“所有 jobs 未开始”时被更新
|
||||
- `PrintingJob` 允许修改 `printing_order`(从而间接改变其应当使用的流程)
|
||||
|
||||
这些更新行为会导致一个严重一致性漏洞:
|
||||
> 业务对象的“当前流程字段”发生变化,但其已绑定的 `BusinessObject.process` 仍指向旧流程,导致后续状态推进与展示出现错乱。
|
||||
|
||||
---
|
||||
|
||||
## 修正案(最小改动原则)
|
||||
|
||||
目标:
|
||||
- 只在必要处拦截/修复更新行为
|
||||
- 将核心逻辑集中到 `stateflow/services.py`(跨模块统一)
|
||||
- 不删除旧的 BusinessObject(后续可通过“无反向引用”识别悬空 BO)
|
||||
|
||||
核心做法:
|
||||
- 新增 `stateflow.services.relink_business_object_for_instance(...)`
|
||||
- 当流程发生变化时,创建并绑定一个新的 BusinessObject(新流程)
|
||||
- 若旧 BO 存在“未撤销进度”,则拒绝(返回 None,由调用方转 400)
|
||||
- 内部新增 `_can_relink_business_object(...)`
|
||||
- 判定口径与 `has_started` 保持一致:只要存在 `is_cancelled=False` 的记录即视为已开始
|
||||
|
||||
---
|
||||
|
||||
## 规则(对外行为)
|
||||
|
||||
### PlateOrder(更新 process)
|
||||
|
||||
- **process 未变化**:不触发 relink
|
||||
- **process 变化**:
|
||||
- 若已存在“未撤销进度”(has_started=True):返回 400
|
||||
- 否则:创建新 BO 并绑定;旧 BO 保留
|
||||
|
||||
### PrintingOrder(更新 process)
|
||||
|
||||
- **process=None**:非法,返回 400
|
||||
- **任意 job 已存在未撤销进度**:整笔订单不允许改流程,返回 400
|
||||
- **所有 jobs 均未开始**:允许改流程,并对订单下所有 jobs 进行 relink(创建新 BO 并绑定)
|
||||
|
||||
### PrintingJob(更新 printing_order)
|
||||
|
||||
- 不允许通过更新接口修改 `printing_order` 绑定关系:返回 400
|
||||
- 避免绕过 `PrintingOrder` 的流程一致性约束
|
||||
|
||||
---
|
||||
|
||||
## 影响与收益
|
||||
|
||||
- **收益**:保证 `process` 与 `BusinessObject.process` 的一致性,避免状态推进/展示错乱
|
||||
- **可追溯性**:旧 BO 不删除,未来可实现“悬空 BO 查看/排查”
|
||||
- **风险控制**:仅在“无有效进度”时允许换流程,避免对已开始流程造成破坏
|
||||
|
||||
## 涉及代码文件
|
||||
|
||||
- stateflow/services.py
|
||||
- api_v1/views/printing/serializers.py
|
||||
- api_v1/views/printing/services.py
|
||||
- api_v1/views/printing/test_plate_order_api.py
|
||||
- api_v1/views/printing/test_api.py
|
||||
- api_v1/views/printing/test_printing_job_api.py
|
||||
Reference in New Issue
Block a user