forked from erp-dev/erp
161 lines
5.6 KiB
Markdown
161 lines
5.6 KiB
Markdown
### 文档说明
|
||
本文档描述 `api_v2` 中 **PrintingJob 批量推进流程状态**的两个接口(preview + submit),用于前端生成批量表单与提交批量推进。
|
||
|
||
### 背景与术语
|
||
- **PrintingJob**:概念上等同于“订单明细对象”,归属一个 `PrintingOrder`。
|
||
- **Stateflow**:PrintingJob 通过 `business_object`(`stateflow.BusinessObject`)承载流程实例;推进逻辑复用 `stateflow.services.advance_to_next_state(...)`。
|
||
- **批量推进**:对多个 PrintingJob(要求同一订单、同一待执行节点)使用同一份工艺参数推进一个节点。
|
||
|
||
### 权限与鉴权
|
||
- **鉴权**:需要登录(`IsAuthenticated`),使用系统统一 JWT 认证。
|
||
- **业务权限**:需要印染工厂身份(`IsPrintingFactory`),即 `request.user.employee.merchant.type == FACTORY`。
|
||
|
||
### 路由与代码位置
|
||
- **Base**:`/api/v2/`
|
||
- **实现文件**:`api_v2/views/printing.py`
|
||
- **路由定义**:`api_v2/urls.py`
|
||
|
||
### 统一校验规则(preview 与 submit 共用)
|
||
批量推进(或预览)必须同时满足:
|
||
- **ID 存在**:`printing_job_ids` 全部存在,否则 400。
|
||
- **同一订单**:所有 job 必须属于同一个 `printing_order`,否则 400。
|
||
- **必须绑定流程实例**:每个 job 必须有 `business_object`,否则 400。
|
||
- **同一待执行节点**:所有 job 的 `next_pending_state` 必须一致,否则 400。
|
||
- **可推进**:任一 job 的 `next_pending_state` 为 `None`(流程已完成或无节点)则 400。
|
||
|
||
> 备注:当前 **不做 preview→submit 竞态处理**(例如 preview 通过后,期间有人推进了其中部分 job)。submit 会重新校验;如需更好的用户体验,后续可引入 snapshot token / 幂等键。
|
||
|
||
---
|
||
|
||
## 批量推进预览(用于生成批量表单)
|
||
### Endpoint
|
||
- **POST** `api/v2/printing-jobs/batch-advance/preview/`
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"printing_job_ids": [101, 102, 103]
|
||
}
|
||
```
|
||
|
||
### Response(200)
|
||
返回下一待执行节点(统一)及其工艺参数定义:
|
||
```json
|
||
{
|
||
"printing_order_id": 55,
|
||
"printing_job_ids": [101, 102, 103],
|
||
"next_state": {
|
||
"id": 7,
|
||
"name": "染色",
|
||
"description": "染色工序",
|
||
"order": 0,
|
||
"parameters": [
|
||
{
|
||
"id": 12,
|
||
"key": "temperature",
|
||
"value": "",
|
||
"attachment": null,
|
||
"attachment_url": null,
|
||
"description": "温度(必填)",
|
||
"is_required": true,
|
||
"is_image_path": false
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 典型错误(400)
|
||
返回 `{"detail": "<原因>"}` 或字段级错误,例如:
|
||
- 不同订单:`所选明细不属于同一个 printing_order,无法批量推进`
|
||
- 缺 business_object:`以下 printing_job 未关联流程实例(business_object),无法推进: ...`
|
||
- next_state 不一致:`所选明细当前待执行节点不一致,无法批量推进...`
|
||
- 已完成/无节点:`没有待执行节点(流程已完成或无节点)`
|
||
|
||
---
|
||
|
||
## 批量推进提交(全成功/全失败)
|
||
### Endpoint
|
||
- **POST** `api/v2/printing-jobs/batch-advance/`
|
||
|
||
### 语义(重要)
|
||
- **事务全成功/全失败**:接口使用数据库事务包裹:
|
||
- 创建批量推进记录(审计表)
|
||
- 逐个调用 `stateflow.services.advance_to_next_state(...)` 推进每个 job 的 `business_object`
|
||
- 任意一个 job 推进失败:**整体回滚**(不会产生任何 stateflow 日志,也不会产生批量记录)
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"printing_job_ids": [101, 102, 103],
|
||
"parameters": {
|
||
"temperature": "25.5",
|
||
"operator": "张三"
|
||
}
|
||
}
|
||
```
|
||
说明:
|
||
- `parameters` 会作为 `**kwargs` 传入 `stateflow.services.advance_to_next_state(...)`。
|
||
- 若下一节点存在必填参数(`is_required=true`),则必须提供对应 key,否则返回 400(错误信息形如 `缺失必填参数: temperature`)。
|
||
|
||
### Response(200)
|
||
```json
|
||
{
|
||
"detail": "已完成状态: 染色",
|
||
"batch_id": 9,
|
||
"printing_order_id": 55,
|
||
"printing_job_ids": [101, 102, 103],
|
||
"jobs": [
|
||
{
|
||
"id": 101,
|
||
"printing_order": 55,
|
||
"product": { "id": 1, "...": "..." },
|
||
"work_state": 0,
|
||
"quantity": 10,
|
||
"width": "150cm",
|
||
"fabric": "棉",
|
||
"unit": "米",
|
||
"size": null,
|
||
"pieces": null,
|
||
"description": null,
|
||
"business_object_id": 888,
|
||
"created_at": "2025-12-12T10:00:00+08:00",
|
||
"updated_at": "2025-12-12T10:01:00+08:00",
|
||
"billed_quantity": "0.00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
说明:
|
||
- `jobs` 使用 `PrintingJobV2Serializer`:其中 `product` 为嵌套对象(不是纯 ID)。
|
||
|
||
### 典型错误(400)
|
||
- 参数缺失:`{"detail": "缺失必填参数: temperature"}`
|
||
- 不满足一致性校验:同 preview 的错误列表。
|
||
|
||
---
|
||
|
||
## 批量推进审计表:PrintingJobBatchAdvanceRecord
|
||
### 模型
|
||
`printing.models.PrintingJobBatchAdvanceRecord`
|
||
|
||
### 字段(核心)
|
||
- `created_at` / `updated_at`:来自 `ModelBase`
|
||
- `created_by`:操作人(可空,删除用户后保留记录)
|
||
- `printing_order`:所属主订单
|
||
- `state`:本次被“完成”的流程节点(推进时的 next_pending_state)
|
||
- `parameters`:本次批量推进提交的参数(JSON)
|
||
- `printing_jobs`:本次批量推进涉及的明细集合(ManyToMany)
|
||
|
||
### 迁移
|
||
- `printing/migrations/0024_printingjobbatchadvancerecord.py`
|
||
|
||
---
|
||
|
||
## 前端联调建议
|
||
- 先调用 preview 获取 `next_state.parameters` 生成批量表单(必填项根据 `is_required`)。
|
||
- 表单提交调用 submit;如返回 400,提示 `detail` 并建议用户刷新列表后重试。
|
||
- 当前未实现竞态 token/幂等键;如需要防重复提交,建议后续加 `Idempotency-Key`(前端生成 UUID,后端在批量记录表上做去重)。
|
||
|
||
|