forked from erp-dev/erp
feat: added plate order clone
This commit is contained in:
138
docs/api_v2_stateflow_business_object_clone.md
Normal file
138
docs/api_v2_stateflow_business_object_clone.md
Normal file
@@ -0,0 +1,138 @@
|
||||
### 文档说明
|
||||
本文档描述 `api_v2` 的 **BusinessObject 克隆**接口与约束,用于在不影响原对象的情况下,克隆一个“流程实例数据完全一致”的新对象(包含日志与工艺参数历史),同时要求绑定到新的业务对象(`content_type + object_id`)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与目的
|
||||
`stateflow.BusinessObject` 通过:
|
||||
- `process` 指定流程模板;
|
||||
- `state_logs (StateFlowRecord)` 记录每一步完成情况;
|
||||
- `StateLogParameterRecord` 记录每次提交的工艺参数 JSON;
|
||||
- `content_type + object_id`(GenericForeignKey)可选关联到“订单/工单/任务”等业务对象。
|
||||
|
||||
克隆的目的:
|
||||
- **完整复制流程实例的历史数据**(含已撤销记录、含参数记录)用于“另起一份流程实例继续/重跑/复盘”;
|
||||
- **不影响原对象**;
|
||||
- **必须绑定新的业务对象 ID**,否则克隆出的对象与原对象在业务关联上无差异,容易造成误用。
|
||||
|
||||
---
|
||||
|
||||
## 2. API 概览
|
||||
### 2.1 Endpoint
|
||||
- **POST** `/api/v2/stateflow/business-objects/clone/`
|
||||
|
||||
### 2.2 权限
|
||||
- 需要登录:`IsAuthenticated`
|
||||
- 鉴权方式:项目统一 JWT(同其他 api_v2 端点)
|
||||
|
||||
### 2.3 请求参数(必须)
|
||||
请求体 JSON:
|
||||
- `business_object_id`:源 BusinessObject 的 ID
|
||||
- `content_type`:源对象的 `content_type_id`(仅用于一致性校验)
|
||||
- `object_id`:克隆后新对象要绑定的业务对象 ID(必须是新的)
|
||||
|
||||
> 说明:
|
||||
> - **content_type 仅做 “与源对象是否一致” 校验**,不做额外业务校验。
|
||||
> - **object_id 必须与源对象不同**;否则克隆没有业务意义,后端会拒绝。
|
||||
|
||||
### 2.4 响应
|
||||
成功:
|
||||
- 返回 `business_object_id`(克隆后新对象 ID)
|
||||
|
||||
---
|
||||
|
||||
## 3. 请求/响应示例
|
||||
### 3.1 成功克隆
|
||||
请求:
|
||||
```json
|
||||
{
|
||||
"business_object_id": 123,
|
||||
"content_type": 9,
|
||||
"object_id": 456
|
||||
}
|
||||
```
|
||||
|
||||
响应(200):
|
||||
```json
|
||||
{
|
||||
"business_object_id": 789
|
||||
}
|
||||
```
|
||||
|
||||
含义:
|
||||
- `123` 是源流程实例
|
||||
- `789` 是新的流程实例(日志与参数完整复制)
|
||||
- 新实例会绑定到新的业务对象:`content_type_id=9, object_id=456`
|
||||
|
||||
---
|
||||
|
||||
## 4. 重要校验规则与错误码
|
||||
### 4.1 404:源对象不存在
|
||||
当 `business_object_id` 不存在时:
|
||||
- 返回 **404**
|
||||
```json
|
||||
{ "detail": "business_object 不存在" }
|
||||
```
|
||||
|
||||
### 4.2 400:content_type 不一致
|
||||
当请求体 `content_type` 与源对象的 `content_type_id` 不一致:
|
||||
- 返回 **400**
|
||||
```json
|
||||
{ "detail": "content_type 与源对象不一致,拒绝克隆" }
|
||||
```
|
||||
|
||||
### 4.3 400:object_id 相关校验失败
|
||||
当源对象存在 `content_type_id`(即已绑定业务对象)时:
|
||||
- **必须提供** `object_id`;
|
||||
- 且 `object_id` **必须与源对象不同**。
|
||||
|
||||
可能返回的 400:
|
||||
```json
|
||||
{ "detail": "必须提供新的 object_id" }
|
||||
```
|
||||
或
|
||||
```json
|
||||
{ "detail": "object_id 必须与源对象不同" }
|
||||
```
|
||||
|
||||
### 4.4 400:源对象未绑定业务对象但传了 object_id
|
||||
当源对象 `content_type_id` 为 `null` 时,要求 `object_id` 也为 `null`:
|
||||
```json
|
||||
{ "detail": "源对象未绑定 content_type,object_id 必须为空" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 克隆范围与语义(后端实现约定)
|
||||
后端通过 `stateflow.services.clone_business_object(...)` 实现克隆,核心语义:
|
||||
- **克隆 BusinessObject 的基础字段**:`name / process / description / content_type`;
|
||||
- **克隆后的 object_id 使用请求体传入的 `object_id`**;
|
||||
- **复制所有 StateFlowRecord(state_logs)**:
|
||||
- 包含已撤销记录(`is_cancelled=True`)
|
||||
- 保持 `completed_at / cancelled_at` 等关键字段一致
|
||||
- **复制每条 StateFlowRecord 的 StateLogParameterRecord(parameter_records)**:
|
||||
- 复制 `parameters`(深拷贝 JSON)
|
||||
- 复制 `remark`
|
||||
- 保持 `created_at/updated_at` 一致
|
||||
- **时间戳一致性(严格)**:
|
||||
- `BusinessObject.created_at/updated_at` 也会被同步为源对象值(通过 update 绕过 auto_now/auto_now_add)
|
||||
- **互不影响**:
|
||||
- 修改克隆对象的参数记录/日志不会影响源对象(复制的是新记录)
|
||||
|
||||
---
|
||||
|
||||
## 6. 与测试的对应关系
|
||||
强校验与数据一致性主要由 **service 层严格测试**保证:
|
||||
- `stateflow/tests/test_clone_business_object.py`
|
||||
|
||||
API 层仅做轻量测试:
|
||||
- `api_v2/tests.py`(成功/404/401/ct不一致)
|
||||
|
||||
---
|
||||
|
||||
## 7. 变更提示(给前端/调用方)
|
||||
如果你之前使用旧版接口仅传 `business_object_id`:
|
||||
- 现在必须补齐 `content_type` 与新的 `object_id`;
|
||||
- 并且 `object_id` 必须是“新业务对象”的 id(例如新订单、复制出来的订单等)。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user