# API v1 印染订单接口说明（printing-orders）

版本日期：2026-06-26

本文档仅汇总 `/api/v1/printing-orders/` 相关接口，按当前代码实现整理，用于前端核对和更新字段。

## 基本信息

- 基础路径：`/api/v1/printing-orders/`
- 认证：需要登录认证。
- 权限：使用 `DjangoModelPermissions`，且用户必须关联印染工厂类型商户。
- 数据范围：默认按客户可见性过滤；拥有 `printing.view_all_printingorders` 权限可查看全部客户订单。
- 分页：列表接口使用 `limit` / `offset`，响应为 DRF LimitOffset 格式：`count`、`next`、`previous`、`results`。
- 列表缓存：列表接口有 20 秒缓存。
- 删除：不支持物理删除，请使用作废接口。

## 本版重点字段变更

以下字段是当前接口已返回/支持、前端需要重点核对的字段：

- `merchant_id`：列表和详情返回，当前订单所属商户 ID，可能为 `null`。
- `external_order_id`：外部订单编号；列表、详情返回；创建/更新也允许传入；支持过滤。
- `external_customer_id`：外部客户 ID；列表、详情返回。
- `external_customer_name`：外部客户名称；列表、详情返回。
- `external_employee_name`：外部员工名称；列表、详情返回。
- `created_by`：列表返回，创建人用户 ID。
- `created_by_name`：列表、详情返回，创建人关联员工姓名，可能为 `null`。
- `order_number`：新增查询参数，支持同时按 `external_order_id` 和内部订单号逻辑检索。
- `jobs_status_summary`：仅列表返回，订单下任务当前状态汇总。
- `jobs_last_status_summary`：仅列表返回，订单下任务最后完成状态汇总。

## 接口清单

| 方法 | 路径 | 说明 |
| --- | --- | --- |
| `GET` | `/api/v1/printing-orders/` | 印染订单列表 |
| `POST` | `/api/v1/printing-orders/` | 创建印染订单 |
| `GET` | `/api/v1/printing-orders/{id}/` | 印染订单详情 |
| `PUT` | `/api/v1/printing-orders/{id}/` | 全量更新印染订单 |
| `PATCH` | `/api/v1/printing-orders/{id}/` | 部分更新印染订单 |
| `DELETE` | `/api/v1/printing-orders/{id}/` | 已禁用，返回 405 |
| `POST` | `/api/v1/printing-orders/{id}/invalidate/` | 作废订单 |
| `POST` | `/api/v1/printing-orders/{id}/activate/` | 恢复订单 |
| `POST` | `/api/v1/printing-orders/{id}/mark_fabric_received/` | 标记布料已收 |

## 列表接口

`GET /api/v1/printing-orders/`

### 查询参数

列表查询参数全部可选；不传任何过滤条件时，默认返回当前权限范围内的未作废订单。

| 参数 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `limit` | number | 否 | 每页条数，默认 800，最大 1000 |
| `offset` | number | 否 | 偏移量 |
| `customer` | number | 否 | 客户 ID |
| `external_order_id` | string | 否 | 外部订单编号，模糊匹配 |
| `order_number` | string | 否 | 订单号检索：模糊匹配 `external_order_id`，并尝试匹配内部 `id` / `human_id` 后 6 位 |
| `customer_name` | string | 否 | 客户名称，模糊匹配 |
| `customer_phone` | string | 否 | 客户电话，模糊匹配 |
| `fabric` | string | 否 | 面料，模糊匹配 |
| `is_urgent` | boolean | 否 | 是否紧急 |
| `is_fabric_received` | boolean | 否 | 布料是否已收 |
| `is_invalid` | boolean | 否 | 是否作废；未传时默认只返回未作废订单 |
| `area` | string | 否 | 地区，模糊匹配 |
| `outgoing_date_from` | date/datetime | 否 | 出货日期起始；支持 `YYYY-MM-DD` 或日期时间 |
| `outgoing_date_to` | date/datetime | 否 | 出货日期结束；传 `YYYY-MM-DD` 时包含整天 |
| `created_date_from` | date | 否 | 创建日期起始 |
| `created_date_to` | date | 否 | 创建日期结束；包含整天 |
| `search` | string | 否 | 搜索客户名称、面料、地区、工艺、描述 |
| `ordering` | string | 否 | 排序字段，支持 `id`、`created_at`、`updated_at`、`outgoing_date`、`is_urgent`、`is_fabric_received`、`is_invalid`，默认 `-created_at` |

### 列表响应字段

`results[]` 每项字段：

列表响应字段均会返回；“可为空”表示字段值可能为 `null`、空字符串或空数组。

| 字段 | 类型 | 是否返回 | 可为空 | 说明 |
| --- | --- | --- | --- | --- |
| `id` | number | 是 | 否 | 内部订单 ID |
| `human_id` | string | 是 | 否 | 人类可读订单号，格式为 `YYYYMMDD + 6 位 ID` |
| `merchant_id` | number/null | 是 | 是 | 所属商户 ID |
| `customer` | number | 是 | 否 | 客户 ID |
| `customer_name` | string | 是 | 否 | 客户名称 |
| `customer_phone` | string/null | 是 | 是 | 客户手机号 |
| `fabric` | string | 是 | 否 | 面料 |
| `width` | string | 是 | 否 | 幅宽 |
| `is_urgent` | boolean | 是 | 否 | 是否紧急 |
| `area` | string/null | 是 | 是 | 地区 |
| `address` | string/null | 是 | 是 | 地址 |
| `curve` | string/null | 是 | 是 | 曲线 |
| `is_fabric_received` | boolean | 是 | 否 | 布料是否已收 |
| `outgoing_date` | datetime/null | 是 | 是 | 出货日期时间 |
| `is_invalid` | boolean | 是 | 否 | 是否作废 |
| `new_curve` | string/null | 是 | 是 | 新加曲线 |
| `process` | number/null | 是 | 是 | 印染流程 ID |
| `process_name` | string/null | 是 | 是 | 印染流程名称 |
| `progress` | number | 是 | 否 | 订单进度百分比；无任务时为 0 |
| `position` | string/null | 是 | 是 | 位置 |
| `print_count` | number | 是 | 否 | 打印次数 |
| `jobs_status_summary` | array | 是 | 是 | 订单下任务按当前状态汇总；无任务时为空数组 |
| `jobs_last_status_summary` | array | 是 | 是 | 订单下任务按最后完成状态汇总；无已完成状态时为空数组 |
| `external_order_id` | string/null | 是 | 是 | 外部订单编号 |
| `external_customer_id` | string/null | 是 | 是 | 外部客户 ID |
| `external_customer_name` | string/null | 是 | 是 | 外部客户名称 |
| `external_employee_name` | string/null | 是 | 是 | 外部员工名称 |
| `created_by` | number/null | 是 | 是 | 创建人用户 ID |
| `created_by_name` | string/null | 是 | 是 | 创建人关联员工姓名 |
| `created_at` | datetime | 是 | 否 | 创建时间 |
| `updated_at` | datetime | 是 | 否 | 更新时间 |

`jobs_status_summary` 格式：

```json
[
  {
    "state_name": "待印染",
    "state_id": 1,
    "count": 3
  }
]
```

`jobs_last_status_summary` 格式：

```json
[
  {
    "state_name": "印染中",
    "count": 2
  }
]
```

## 详情接口

`GET /api/v1/printing-orders/{id}/`

### 详情响应字段

详情响应字段均会返回；“可为空”表示字段值可能为 `null` 或空字符串。

| 字段 | 类型 | 是否返回 | 可为空 | 说明 |
| --- | --- | --- | --- | --- |
| `id` | number | 是 | 否 | 内部订单 ID |
| `human_id` | string | 是 | 否 | 人类可读订单号 |
| `merchant_id` | number/null | 是 | 是 | 所属商户 ID |
| `customer` | number | 是 | 否 | 客户 ID |
| `customer_name` | string | 是 | 否 | 客户名称 |
| `customer_phone` | string/null | 是 | 是 | 客户手机号 |
| `customer_area` | string/null | 是 | 是 | 客户区域 |
| `fabric` | string | 是 | 否 | 面料 |
| `width` | string | 是 | 否 | 幅宽 |
| `is_urgent` | boolean | 是 | 否 | 是否紧急 |
| `area` | string/null | 是 | 是 | 地区 |
| `address` | string/null | 是 | 是 | 地址 |
| `fabric_source` | string/null | 是 | 是 | 布料来源 |
| `is_fabric_received` | boolean | 是 | 否 | 布料是否已收 |
| `craft` | string/null | 是 | 是 | 工艺 |
| `description` | string/null | 是 | 是 | 订单描述 |
| `outgoing_date` | datetime/null | 是 | 是 | 出货日期时间 |
| `curve` | string/null | 是 | 是 | 曲线 |
| `new_curve` | string/null | 是 | 是 | 新加曲线 |
| `position` | string/null | 是 | 是 | 位置 |
| `created_by_name` | string/null | 是 | 是 | 创建人关联员工姓名 |
| `printing_warn` | string/null | 是 | 是 | 打印注意事项 |
| `rolling_warn` | string/null | 是 | 是 | 滚筒注意事项 |
| `production_warn` | string/null | 是 | 是 | 生产注意事项 |
| `external_order_id` | string/null | 是 | 是 | 外部订单编号 |
| `external_customer_id` | string/null | 是 | 是 | 外部客户 ID |
| `external_customer_name` | string/null | 是 | 是 | 外部客户名称 |
| `external_employee_name` | string/null | 是 | 是 | 外部员工名称 |
| `is_invalid` | boolean | 是 | 否 | 是否作废 |
| `process` | number/null | 是 | 是 | 印染流程 ID |
| `process_name` | string/null | 是 | 是 | 印染流程名称 |
| `progress` | number | 是 | 否 | 订单进度百分比 |
| `print_count` | number | 是 | 否 | 打印次数 |
| `created_at` | datetime | 是 | 否 | 创建时间 |
| `updated_at` | datetime | 是 | 否 | 更新时间 |

注意：详情接口不返回 `jobs_status_summary` 和 `jobs_last_status_summary`，这两个字段是列表专用字段。

## 创建接口

`POST /api/v1/printing-orders/`

### 请求字段

| 字段 | 类型 | 必填 | 可传空 | 默认/说明 |
| --- | --- | --- | --- | --- |
| `customer` | number | 是 | 否 | 客户 ID |
| `fabric` | string | 是 | 否 | 面料 |
| `width` | string | 是 | 否 | 幅宽 |
| `is_urgent` | boolean | 否 | 否 | 默认 `false`，是否紧急 |
| `area` | string/null | 否 | 是 | 地区 |
| `address` | string/null | 否 | 是 | 地址 |
| `fabric_source` | string/null | 否 | 是 | 布料来源 |
| `is_fabric_received` | boolean | 否 | 否 | 默认 `false`，布料是否已收 |
| `craft` | string/null | 否 | 是 | 工艺 |
| `description` | string/null | 否 | 是 | 订单描述 |
| `outgoing_date` | date/datetime/null | 否 | 是 | 出货日期时间；支持 `YYYY-MM-DD`、`YYYY-MM-DD HH:mm`、`YYYY-MM-DD HH:mm:ss`、ISO8601；仅传日期时按当天 `00:00:00` 处理 |
| `curve` | string/null | 否 | 是 | 曲线 |
| `new_curve` | string/null | 否 | 是 | 新加曲线 |
| `position` | string/null | 否 | 是 | 位置 |
| `printing_warn` | string/null | 否 | 是 | 打印注意事项 |
| `rolling_warn` | string/null | 否 | 是 | 滚筒注意事项 |
| `production_warn` | string/null | 否 | 是 | 生产注意事项 |
| `is_invalid` | boolean | 否 | 否 | 默认 `false`，是否作废 |
| `process` | number/null | 否 | 创建可空，更新不可改为空 | 印染流程 ID；创建不传或传空时使用系统默认流程；更新时不能改为空 |
| `external_order_id` | string/null | 否 | 是 | 外部订单编号 |

创建时后端会自动写入：

- `merchant`：从当前用户关联员工的商户取得。
- `created_by`：当前登录用户。
- `process`：未传时尝试使用系统默认印染流程。

### 创建请求示例

```json
{
  "customer": 12,
  "fabric": "纯棉布料",
  "width": "150cm",
  "is_urgent": true,
  "area": "白云区",
  "address": "白云区xxx",
  "fabric_source": "客户提供",
  "is_fabric_received": false,
  "craft": "活性印花",
  "description": "测试订单描述",
  "outgoing_date": "2026-06-26",
  "printing_warn": "注意颜色",
  "rolling_warn": "注意温度",
  "production_warn": "质量检查",
  "external_order_id": "KD20410611"
}
```

成功响应使用创建/更新序列化器字段，通常包含请求字段及 `id`。

## 更新接口

`PUT /api/v1/printing-orders/{id}/`

`PATCH /api/v1/printing-orders/{id}/`

更新请求字段与创建接口一致。

必填规则：

- `PUT` 是全量更新，建议至少传 `customer`、`fabric`、`width`；未传的可写字段可能按 DRF 全量更新规则校验。
- `PATCH` 是部分更新，只需要传要修改的字段。
- `id`、`human_id`、`merchant_id`、`created_by`、`created_by_name`、`external_customer_id`、`external_customer_name`、`external_employee_name`、`created_at`、`updated_at` 等不作为请求字段提交。

### 流程修改限制

- 当订单下没有任务，或所有任务都未开始时，可以修改 `process`。
- 修改 `process` 时，后端会重建/重新绑定订单下未开始任务的流程实例。
- 如果存在任何已开始的 `PrintingJob`，修改 `process` 会返回 `400`。
- `process` 不能更新为空，否则返回错误。

错误示例：

```json
{
  "process": ["存在已开始的印染任务，无法修改流程"]
}
```

或：

```json
"存在已开始的印染任务，无法修改流程"
```

## 作废订单

`POST /api/v1/printing-orders/{id}/invalidate/`

权限：需要 `printing.can_invalidate_printingorder`。

成功响应：

```json
{
  "detail": "订单已作废",
  "data": {
    "id": 1
  }
}
```

失败情况：

- 无权限：`403`，`{"detail": "您没有权限作废订单"}`
- 已作废：`400`，`{"detail": "该订单已经作废"}`

## 恢复订单

`POST /api/v1/printing-orders/{id}/activate/`

权限：需要 `printing.can_activate_printingorder`。

成功响应：

```json
{
  "detail": "订单已恢复",
  "data": {
    "id": 1
  }
}
```

失败情况：

- 无权限：`403`，`{"detail": "您没有权限恢复订单"}`
- 未作废：`400`，`{"detail": "该订单未作废，无需恢复"}`

## 标记布料已收

`POST /api/v1/printing-orders/{id}/mark_fabric_received/`

成功后将 `is_fabric_received` 置为 `true`。

成功响应：

```json
{
  "detail": "已标记布料已收",
  "data": {
    "id": 1,
    "is_fabric_received": true
  }
}
```

失败情况：

- 已经标记为已收：`400`，`{"detail": "布料已经标记为已收"}`

## 删除接口

`DELETE /api/v1/printing-orders/{id}/`

该接口已禁用，固定返回 `405`：

```json
{
  "detail": "印染订单不支持删除操作，请使用作废功能"
}
```

## 前端核对建议

- 列表页应优先使用 `human_id` 展示内部订单号，外部来源订单可同时展示 `external_order_id`。
- 默认列表不包含作废订单；作废订单列表需要显式传 `is_invalid=true`。
- 若前端有“订单号搜索”输入框，建议接入 `order_number`，不用同时拼多个参数。
- `outgoing_date_to=YYYY-MM-DD` 会包含当天整天，前端无需手动补 `23:59:59`。
- 外部字段 `external_customer_id`、`external_customer_name`、`external_employee_name` 当前只读返回，创建/更新接口只暴露 `external_order_id`。
