forked from erp-dev/erp
908 lines
24 KiB
Markdown
908 lines
24 KiB
Markdown
# Shipment 模块 API v1 文档
|
||
|
||
面向前端对接,基于当前代码生成。接口统一前缀为 `/api/v1/`。
|
||
|
||
## 通用说明
|
||
|
||
- 认证:所有接口均要求登录认证。
|
||
- 商户隔离:普通用户只能访问自己员工所属商户的数据;超级管理员部分接口可跨商户,具体见接口说明。
|
||
- 分页:列表接口使用 `limit`、`offset`,分页响应一般为 `{ "count": 0, "next": null, "previous": null, "results": [] }`。
|
||
- 错误:业务校验失败通常返回 `400 { "detail": "错误原因" }`;不存在通常返回 `404`。
|
||
|
||
## 枚举
|
||
|
||
### 出货单状态 `ShipmentStatus`
|
||
|
||
| 值 | 含义 |
|
||
| --- | --- |
|
||
| `1` | 草稿(未发布) |
|
||
| `2` | 已发布 |
|
||
| `3` | 已取消 |
|
||
| `4` | 已驳回 |
|
||
| `5` | 已审核 |
|
||
|
||
### 送货单状态 `ShipmentDeliveryStatus`
|
||
|
||
| 值 | 含义 |
|
||
| --- | --- |
|
||
| `1` | 待送货 |
|
||
| `2` | 送货中 |
|
||
| `3` | 已送达 |
|
||
|
||
### 销售品单位 `UnitChoices`
|
||
|
||
| 值 | 含义 |
|
||
| --- | --- |
|
||
| `1` | 米 |
|
||
| `2` | 件 |
|
||
| `3` | 码 |
|
||
| `4` | 个 |
|
||
|
||
## 公共响应结构
|
||
|
||
### Shipment
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"merchant_id": 1,
|
||
"merchant_name": "测试印花厂",
|
||
"customer": 10,
|
||
"customer_name": "客户A",
|
||
"address_id": 5,
|
||
"fabric": "面料信息",
|
||
"order_description": "订单描述",
|
||
"shipment_date": "2026-01-14",
|
||
"address": "杭州市测试路 1 号",
|
||
"contact_name": "张三",
|
||
"contact_phone": "13800138000",
|
||
"area": "华东",
|
||
"coordinates": "120.1551,30.2741",
|
||
"remark": "备注",
|
||
"status": 1,
|
||
"status_display": "草稿(未发布)",
|
||
"external_id": null,
|
||
"geo_coordinates": null,
|
||
"extra": {"source": "customer_address"},
|
||
"delivery_id": null,
|
||
"status_modified_at": null,
|
||
"cancelled_by_id": null,
|
||
"cancelled_by_name": null,
|
||
"approved_by_id": null,
|
||
"approved_by_name": null,
|
||
"items_count": 2,
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三",
|
||
"external_finished_products_count": 0,
|
||
"sales_items": [],
|
||
"external_finished_products": [],
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"updated_at": "2026-01-14T10:00:00Z"
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `address_id` | integer/null | 关联客户地址 ID,只表示关联关系 |
|
||
| `address` | string | 出货单地址快照,由请求体写入 |
|
||
| `contact_name` | string | 联系人快照,由请求体写入 |
|
||
| `contact_phone` | string | 联系电话快照,由请求体写入 |
|
||
| `area` | string | 地区快照,最大 100 字符 |
|
||
| `coordinates` | string/null | 经纬度字符串,最大 100 字符 |
|
||
| `geo_coordinates` | object/array/null | 历史 Geo 字段,保留兼容老数据 |
|
||
| `extra` | object/array/null | 扩展 JSON |
|
||
|
||
重要行为:传 `address_id` 时,后端只校验并保存关联,不会用 `CustomerAddress` 自动覆盖 `address/contact_name/contact_phone/area/coordinates/extra`。这些快照字段仍以请求体为准。
|
||
|
||
### SalesItem
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"name": "销售品A",
|
||
"quantity": "100.00",
|
||
"unit": 1,
|
||
"unit_display": "米",
|
||
"position": "A1-01",
|
||
"remark": "备注",
|
||
"printing_job_id": 123,
|
||
"printing_order_id": 456,
|
||
"external_order_id": "KD20441758",
|
||
"customer_id": 10,
|
||
"customer_name": "客户A",
|
||
"shipment_id": null,
|
||
"shipment_date": null,
|
||
"merge_remark": null,
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三"
|
||
}
|
||
```
|
||
|
||
详情接口额外包含:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `product_image_url` | string/null | 关联生产任务产品主图 URL |
|
||
|
||
### ShipmentDelivery
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"merchant_id": 1,
|
||
"merchant_name": "测试印花厂",
|
||
"driver_name": "司机A",
|
||
"vehicle_trip": "浙A12345",
|
||
"contact_phone": "13800138000",
|
||
"vehicle_capacity": "4.2米",
|
||
"remark": "备注",
|
||
"internal_remark": "内部备注",
|
||
"shipment_order_ids": [1, 2, 3],
|
||
"status": 1,
|
||
"status_display": "待送货",
|
||
"started_at": null,
|
||
"delivered_at": null,
|
||
"cancelled_at": null,
|
||
"shipments_count": 2,
|
||
"shipments": [],
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三",
|
||
"operator_id": null,
|
||
"operator_name": null,
|
||
"cancelled_by_id": null,
|
||
"cancelled_by_name": null,
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"updated_at": "2026-01-14T10:00:00Z"
|
||
}
|
||
```
|
||
|
||
### ShipmentPrintingJobSummary
|
||
|
||
出货单/送货单关联生产任务的精简 DTO,仅用于快速跳转生产任务详情。
|
||
|
||
```json
|
||
{
|
||
"id": 123,
|
||
"printing_order_id": 456,
|
||
"external_order_id": "KD20453713",
|
||
"customer_name": "客户A"
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `id` | integer | `PrintingJob.id` |
|
||
| `printing_order_id` | integer | 关联的 `PrintingOrder.id` |
|
||
| `external_order_id` | string/null | 关联生产订单的外部订单编号 |
|
||
| `customer_name` | string/null | 关联生产订单客户名称 |
|
||
|
||
`shipments` 内元素为送货单内出货单摘要:
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"customer": 10,
|
||
"customer_name": "客户A",
|
||
"address_id": 5,
|
||
"address": "杭州市测试路 1 号",
|
||
"contact_name": "张三",
|
||
"contact_phone": "13800138000",
|
||
"area": "华东",
|
||
"coordinates": "120.1551,30.2741",
|
||
"geo_coordinates": null,
|
||
"extra": {"dock": "A"},
|
||
"fabric": "面料信息",
|
||
"order_description": "订单描述",
|
||
"shipment_date": "2026-01-14",
|
||
"status": 5,
|
||
"status_display": "已审核",
|
||
"external_id": null,
|
||
"delivery_id": 1
|
||
}
|
||
```
|
||
|
||
地址说明:送货单本身不保存地址;一个送货单可包含多个出货单,每个出货单可能有不同地址。送货单返回的 `shipments[]` 中地址字段均来自对应 `Shipment` 的地址快照字段,`address_id` 仅表示关联的客户地址 ID。
|
||
|
||
## 出货单接口
|
||
|
||
### 查询出货单列表
|
||
|
||
`GET /api/v1/shipment/shipments/`
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `customer` | integer | 否 | 客户 ID |
|
||
| `status` | integer | 否 | 出货单状态 |
|
||
| `delivery_id` | integer | 否 | 送货单 ID;空字符串、`null`、`none` 不触发过滤 |
|
||
| `delivery_isnull` | boolean | 否 | `true/1/yes` 查未绑定送货单,`false/0/no` 查已绑定送货单 |
|
||
| `external_id` | string | 否 | 外部订单号精确匹配 |
|
||
| `shipment_date_from` | date | 否 | 出货日期起始,`YYYY-MM-DD` |
|
||
| `shipment_date_to` | date | 否 | 出货日期结束,`YYYY-MM-DD` |
|
||
| `only_address_null` | boolean | 否 | `true` 查地址为空字符串,`false` 查地址非空 |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:分页 `Shipment[]`。
|
||
|
||
### 创建出货单
|
||
|
||
`POST /api/v1/shipment/shipments/`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"customer": 10,
|
||
"address_id": 5,
|
||
"shipment_date": "2026-01-14",
|
||
"address": "杭州市测试路 1 号",
|
||
"contact_name": "张三",
|
||
"contact_phone": "13800138000",
|
||
"area": "华东",
|
||
"coordinates": "120.1551,30.2741",
|
||
"extra": {"source": "customer_address"},
|
||
"remark": "备注",
|
||
"sales_items": [1, 2, 3]
|
||
}
|
||
```
|
||
|
||
请求字段:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `customer` | integer | 是 | 客户 ID |
|
||
| `address_id` | integer/null | 否 | 客户地址 ID;仅校验和关联 |
|
||
| `shipment_date` | date | 是 | 出货日期 |
|
||
| `address` | string | 否 | 地址快照,默认 `""`,最大 255 |
|
||
| `contact_name` | string | 否 | 联系人快照,默认 `""`,最大 100 |
|
||
| `contact_phone` | string | 否 | 联系电话快照,默认 `""`,最大 50 |
|
||
| `area` | string | 否 | 地区快照,默认 `""`,最大 100 |
|
||
| `coordinates` | string/null | 否 | 经纬度字符串,最大 100 |
|
||
| `extra` | JSON/null | 否 | 扩展信息 |
|
||
| `remark` | string | 否 | 出货单备注,默认 `""` |
|
||
| `sales_items` | integer[] | 否 | 要关联的销售品 ID 列表,默认 `[]`,后端会去重 |
|
||
|
||
业务规则:
|
||
|
||
- 用户必须关联商户。
|
||
- 客户必须属于当前商户。
|
||
- `address_id` 存在时,客户地址必须存在、未软删除、属于当前商户、属于请求中的 `customer`。
|
||
- `sales_items` 非空时,销售品必须存在、未删除、未绑定其他出货单、属于当前商户,并且都来自同一个生产订单。
|
||
|
||
响应:`201 Shipment`。
|
||
|
||
### 创建外部出货单
|
||
|
||
`POST /api/v1/shipment/shipments/external/`
|
||
|
||
用于没有内部销售品、但需要记录外部成品表的出货单。
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"customer": 10,
|
||
"shipment_date": "2026-01-14",
|
||
"address": "杭州市测试路 1 号",
|
||
"contact_name": "张三",
|
||
"contact_phone": "13800138000",
|
||
"area": "华东",
|
||
"coordinates": "120.1551,30.2741",
|
||
"extra": {"source": "external"},
|
||
"remark": "备注",
|
||
"external_id": "EXT-001",
|
||
"external_finished_products": [
|
||
{
|
||
"style_name": "款式A",
|
||
"num_of_rolls": 10,
|
||
"remark": "成品备注"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
请求字段:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `customer` | integer | 是 | 客户 ID |
|
||
| `shipment_date` | date | 是 | 出货日期 |
|
||
| `address` | string | 否 | 地址,最大 255 |
|
||
| `contact_name` | string | 否 | 联系人,最大 100 |
|
||
| `contact_phone` | string | 否 | 联系电话,最大 50 |
|
||
| `area` | string | 否 | 地区,最大 100 |
|
||
| `coordinates` | string/null | 否 | 经纬度字符串,最大 100 |
|
||
| `extra` | JSON/null | 否 | 扩展信息 |
|
||
| `remark` | string | 否 | 备注 |
|
||
| `external_id` | string | 是 | 外部订单号,不能为空,最大 120 |
|
||
| `external_finished_products` | array | 是 | 外部成品表,不能为空 |
|
||
|
||
`external_finished_products` 元素:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `style_name` | string | 是 | 款式名,最大 200 |
|
||
| `num_of_rolls` | integer | 是 | 卷数,最小 0 |
|
||
| `remark` | string/null | 否 | 备注,最大 200 |
|
||
|
||
响应:`201 Shipment`。
|
||
|
||
### 获取出货单详情
|
||
|
||
`GET /api/v1/shipment/shipments/{id}/`
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `status` | integer | 否 | 可选状态过滤;不匹配则返回 404 |
|
||
|
||
响应:`200 Shipment`。
|
||
|
||
### 查询出货单关联生产任务
|
||
|
||
`GET /api/v1/shipment/shipments/{id}/printing-jobs/`
|
||
|
||
用于快速获取该出货单关联的生产任务列表,不返回销售品明细。
|
||
|
||
关联路径:`Shipment -> SalesItem.printing_job_id -> PrintingJob`。
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:分页 `ShipmentPrintingJobSummary[]`。
|
||
|
||
说明:
|
||
|
||
- 仅统计未软删除销售品:`SalesItem.delete_at IS NULL`。
|
||
- 相同 `printing_job_id` 会去重。
|
||
- 默认按 `PrintingJob.id` 升序。
|
||
- 如需销售品明细,调用 `GET /api/v1/shipment/shipments/{id}/`。
|
||
|
||
### 更新出货单
|
||
|
||
`PATCH /api/v1/shipment/shipments/{id}/`
|
||
|
||
`PUT /api/v1/shipment/shipments/{id}/`
|
||
|
||
当前 `PUT` 行为等同 `PATCH`,允许只传部分字段。
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"customer": 10,
|
||
"shipment_date": "2026-01-15",
|
||
"address": "新地址",
|
||
"contact_name": "李四",
|
||
"contact_phone": "13900139000",
|
||
"area": "华南",
|
||
"coordinates": null,
|
||
"extra": null,
|
||
"remark": "新备注",
|
||
"external_id": "EXT-002",
|
||
"geo_coordinates": {"lng": 120.1, "lat": 30.2}
|
||
}
|
||
```
|
||
|
||
可更新字段:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `customer` | integer | 客户 ID |
|
||
| `shipment_date` | date | 出货日期 |
|
||
| `address` | string | 地址,最大 255 |
|
||
| `contact_name` | string | 联系人,最大 100 |
|
||
| `contact_phone` | string | 联系电话,最大 50 |
|
||
| `area` | string | 地区,最大 100 |
|
||
| `coordinates` | string/null | 经纬度字符串;传 `null` 可清空 |
|
||
| `extra` | JSON/null | 扩展信息;传 `null` 可清空 |
|
||
| `remark` | string | 备注 |
|
||
| `external_id` | string/null | 外部订单号;空字符串或 `null` 会清空 |
|
||
| `geo_coordinates` | JSON/null | 当前 serializer 接收该字段,但业务更新服务未保存它,前端不建议使用 |
|
||
|
||
业务规则:
|
||
|
||
- 已关联送货单的出货单不允许修改业务数据。
|
||
- 修改客户时,新客户必须存在且属于同一商户。
|
||
|
||
响应:`200 Shipment`。
|
||
|
||
### 修改出货单状态
|
||
|
||
`PATCH /api/v1/shipment/shipments/{id}/status/`
|
||
|
||
`PUT /api/v1/shipment/shipments/{id}/status/`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"status": 5
|
||
}
|
||
```
|
||
|
||
响应:`200 Shipment`。
|
||
|
||
## 送货单接口
|
||
|
||
### 查询送货单列表
|
||
|
||
`GET /api/v1/shipment/deliveries/`
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `status` | integer | 否 | 送货单状态 |
|
||
| `driver_name` | string | 否 | 司机名模糊匹配 |
|
||
| `vehicle_trip` | string | 否 | 车次模糊匹配 |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:分页 `ShipmentDelivery[]`。
|
||
|
||
### 创建送货单
|
||
|
||
`POST /api/v1/shipment/deliveries/`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"driver_name": "司机A",
|
||
"vehicle_trip": "浙A12345",
|
||
"contact_phone": "13800138000",
|
||
"vehicle_capacity": "4.2米",
|
||
"remark": "备注",
|
||
"internal_remark": "内部备注",
|
||
"shipment_order_ids": [3, 2, 1],
|
||
"shipments": [1, 2, 3]
|
||
}
|
||
```
|
||
|
||
请求字段:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `driver_name` | string | 是 | 司机名,最大 100 |
|
||
| `vehicle_trip` | string | 是 | 车次,最大 100 |
|
||
| `contact_phone` | string | 否 | 联系电话,默认 `""`,最大 50 |
|
||
| `vehicle_capacity` | string | 否 | 车辆容量,默认 `""`,最大 100 |
|
||
| `remark` | string | 否 | 备注,默认 `""`,最大 200 |
|
||
| `internal_remark` | string | 否 | 内部备注,默认 `""`,最大 200 |
|
||
| `shipment_order_ids` | array/null | 否 | 前端自管出货单排序 ID 数组,可为 `null` |
|
||
| `shipments` | integer[] | 否 | 要关联的出货单 ID 列表,默认 `[]`,后端会去重 |
|
||
|
||
响应:`201 ShipmentDelivery`。
|
||
|
||
### 按生产订单查询送货单
|
||
|
||
`GET /api/v1/shipment/deliveries/by-printing-order/{printing_order_id}/`
|
||
|
||
路径参数:
|
||
|
||
- `printing_order_id` 支持内部 `PrintingOrder.id` 或 `external_order_id`。
|
||
- 如果 `external_order_id` 匹配多个生产订单,返回 `500 { "message": "...请改用内部ID查询" }`。
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `status` | integer | 否 | 送货单状态 |
|
||
| `driver_name` | string | 否 | 模糊匹配 |
|
||
| `vehicle_trip` | string | 否 | 模糊匹配 |
|
||
| `contact_phone` | string | 否 | 模糊匹配 |
|
||
| `vehicle_capacity` | string | 否 | 模糊匹配 |
|
||
| `remark` | string | 否 | 模糊匹配 |
|
||
| `internal_remark` | string | 否 | 模糊匹配 |
|
||
| `started_at_from` | date/datetime | 否 | 开始送货时间起 |
|
||
| `started_at_to` | date/datetime | 否 | 开始送货时间止 |
|
||
| `delivered_at_from` | date/datetime | 否 | 送达时间起 |
|
||
| `delivered_at_to` | date/datetime | 否 | 送达时间止 |
|
||
| `cancelled_at_from` | date/datetime | 否 | 取消时间起 |
|
||
| `cancelled_at_to` | date/datetime | 否 | 取消时间止 |
|
||
| `created_at_from` | date/datetime | 否 | 创建时间起 |
|
||
| `created_at_to` | date/datetime | 否 | 创建时间止 |
|
||
| `shipment_date_from` | date | 否 | 关联出货日期起 |
|
||
| `shipment_date_to` | date | 否 | 关联出货日期止 |
|
||
| `ordering` | string | 否 | 可选 `id/created_at/updated_at/started_at/delivered_at/cancelled_at/status`,支持前缀 `-` |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:分页 `ShipmentDelivery[]`,字段使用专用 DTO,不包含 `cancelled_by_id/cancelled_by_name`。
|
||
|
||
### 获取送货单详情
|
||
|
||
`GET /api/v1/shipment/deliveries/{id}/`
|
||
|
||
响应:`200 ShipmentDelivery`。
|
||
|
||
### 查询送货单关联生产任务
|
||
|
||
`GET /api/v1/shipment/deliveries/{id}/printing-jobs/`
|
||
|
||
用于快速获取该送货单下所有出货单关联的生产任务列表,不返回销售品明细。
|
||
|
||
关联路径:`ShipmentDelivery -> Shipments -> SalesItem.printing_job_id -> PrintingJob`。
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:分页 `ShipmentPrintingJobSummary[]`。
|
||
|
||
说明:
|
||
|
||
- 仅统计未软删除销售品:`SalesItem.delete_at IS NULL`。
|
||
- 同一个生产任务通过多个销售品或多个出货单关联时只返回一次。
|
||
- 默认按 `PrintingJob.id` 升序。
|
||
- 如需送货单内出货单摘要,调用 `GET /api/v1/shipment/deliveries/{id}/`。
|
||
- 如需某个出货单的销售品明细,调用 `GET /api/v1/shipment/shipments/{shipment_id}/`。
|
||
|
||
### 更新送货单
|
||
|
||
`PATCH /api/v1/shipment/deliveries/{id}/`
|
||
|
||
`PUT /api/v1/shipment/deliveries/{id}/`
|
||
|
||
当前 `PUT` 行为等同 `PATCH`。
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"driver_name": "司机B",
|
||
"vehicle_trip": "浙B12345",
|
||
"contact_phone": "13900139000",
|
||
"vehicle_capacity": "9.6米",
|
||
"remark": "新备注",
|
||
"internal_remark": "新内部备注",
|
||
"shipment_order_ids": [2, 1],
|
||
"shipments": [1, 2]
|
||
}
|
||
```
|
||
|
||
可更新字段:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `driver_name` | string | 司机名,最大 100,不允许空字符串 |
|
||
| `vehicle_trip` | string | 车次,最大 100,不允许空字符串 |
|
||
| `contact_phone` | string | 联系电话,最大 50 |
|
||
| `vehicle_capacity` | string | 车辆容量,最大 100 |
|
||
| `remark` | string | 备注,最大 200 |
|
||
| `internal_remark` | string | 内部备注,最大 200 |
|
||
| `shipment_order_ids` | array/null | 前端自管排序 ID 数组,传入即更新 |
|
||
| `shipments` | integer[] | 传入即替换当前绑定出货单 |
|
||
|
||
响应:`200 ShipmentDelivery`。
|
||
|
||
### 删除送货单
|
||
|
||
`DELETE /api/v1/shipment/deliveries/{id}/`
|
||
|
||
响应:`204 No Content`。
|
||
|
||
### 修改送货单状态
|
||
|
||
`POST /api/v1/shipment/deliveries/{id}/status/`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"status": 2
|
||
}
|
||
```
|
||
|
||
允许状态:`1`、`2`、`3`。
|
||
|
||
响应:`200 ShipmentDelivery`。
|
||
|
||
### 取消送货单
|
||
|
||
`POST /api/v1/shipment/deliveries/{id}/cancel/`
|
||
|
||
权限:需要 `shipment.cancel_shipmentdelivery`。
|
||
|
||
响应:`200 ShipmentDelivery`。
|
||
|
||
### 追加绑定出货单到送货单
|
||
|
||
`POST /api/v1/shipment/deliveries/{id}/bind-shipments/`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"shipments": [4, 5]
|
||
}
|
||
```
|
||
|
||
请求字段:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `shipments` | integer[] | 是 | 要追加绑定的出货单 ID,不能为空,后端会去重 |
|
||
|
||
响应:`200 ShipmentDelivery`。
|
||
|
||
## 销售品接口
|
||
|
||
### 查询当前可出货客户
|
||
|
||
`GET /api/v1/shipment/sales-items/customers/`
|
||
|
||
从未出货销售品反推出客户列表。
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `merchant` | integer | 超级管理员必填 | 超级管理员必须传商户 ID;普通用户忽略 |
|
||
| `customer_name` | string | 否 | 客户名称模糊匹配 |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:
|
||
|
||
```json
|
||
{
|
||
"count": 1,
|
||
"next": null,
|
||
"previous": null,
|
||
"results": [
|
||
{
|
||
"customer_id": 10,
|
||
"customer_name": "客户A",
|
||
"mobile": "13900139000",
|
||
"area": "杭州",
|
||
"unshipped_sales_items_count": 3
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 按客户查询销售品
|
||
|
||
`GET /api/v1/shipment/sales-items/by-customer/{customer_id}/`
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `include_already_has_shipment` | boolean | 否 | 是否包含已关联出货单销售品,默认 `false`;只有字符串 `true` 会视为真 |
|
||
| `external_order_id` | string | 否 | 按生产订单外部订单号过滤 |
|
||
| `limit` | integer | 否 | 分页大小 |
|
||
| `offset` | integer | 否 | 分页偏移 |
|
||
|
||
响应:分页 `SalesItem[]`。
|
||
|
||
### 按客户查询销售品分组
|
||
|
||
`GET /api/v1/shipment/sales-items/by-customer/{customer_id}/group/`
|
||
|
||
第一层按 `external_order_id` 分组并分页,第二层按 `name` 分组。
|
||
|
||
查询参数同“按客户查询销售品”。
|
||
|
||
响应:
|
||
|
||
```json
|
||
{
|
||
"count": 1,
|
||
"next": null,
|
||
"previous": null,
|
||
"results": [
|
||
{
|
||
"external_order_id": "KD20441758",
|
||
"count": 2,
|
||
"name_groups": [
|
||
{
|
||
"name": "销售品A",
|
||
"count": 2,
|
||
"items": []
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
排序:`external_order_id = null` 排最后。
|
||
|
||
### 按生产订单查询销售品
|
||
|
||
`GET /api/v1/shipment/sales-items/by-printing-order/{printing_order_id}/`
|
||
|
||
路径参数:
|
||
|
||
- `printing_order_id` 支持内部 `PrintingOrder.id` 或 `external_order_id`。
|
||
- 如果 `external_order_id` 匹配多个生产订单,此接口返回 `400 { "detail": "...请改用内部ID查询" }`。
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `include_already_has_shipment` | boolean | 否 | 是否包含已关联出货单销售品,默认 `false`;只有字符串 `true` 会视为真 |
|
||
|
||
响应:
|
||
|
||
```json
|
||
{
|
||
"count": 2,
|
||
"results": []
|
||
}
|
||
```
|
||
|
||
`results` 为 `SalesItem[]`,该接口不使用标准分页。
|
||
|
||
### 按生产订单查询销售品分组
|
||
|
||
`GET /api/v1/shipment/sales-items/by-printing-order/{printing_order_id}/group/`
|
||
|
||
按 `printing_job_id` 分组并分页。
|
||
|
||
查询参数:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `include_already_has_shipment` | boolean | 否 | 是否包含已关联出货单销售品,默认 `false` |
|
||
| `limit` | integer | 否 | 分页大小,作用于分组数量 |
|
||
| `offset` | integer | 否 | 分页偏移,作用于分组数量 |
|
||
|
||
响应:
|
||
|
||
```json
|
||
{
|
||
"count": 1,
|
||
"next": null,
|
||
"previous": null,
|
||
"results": [
|
||
{
|
||
"printing_job_id": 123,
|
||
"count": 2,
|
||
"items": []
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 手动创建销售品
|
||
|
||
`POST /api/v1/shipment/sales-items/`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"printing_job_id": 123,
|
||
"name": "销售品A",
|
||
"quantity": "100.50",
|
||
"unit": 1,
|
||
"customer_id": 10,
|
||
"remark": "备注",
|
||
"position": "A1-01",
|
||
"merge_remark": {
|
||
"merge_type": "merge",
|
||
"jobs": [1, 2],
|
||
"main_job": 1,
|
||
"quantity": "100.50",
|
||
"unit": "米",
|
||
"job_count": 2
|
||
}
|
||
}
|
||
```
|
||
|
||
请求字段:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `printing_job_id` | integer | 是 | 生产任务 ID,最小 1 |
|
||
| `name` | string | 是 | 销售品名称,最大 200 |
|
||
| `quantity` | string | 是 | 数量,最大 20,支持小数 |
|
||
| `unit` | integer | 是 | 单位:`1/2/3/4` |
|
||
| `customer_id` | integer/null | 否 | 客户 ID;不传时默认从生产订单获取 |
|
||
| `remark` | string | 否 | 备注,最大 200 |
|
||
| `position` | string | 否 | 货位,最大 200 |
|
||
| `merge_remark` | object/null | 否 | 合卷备注 JSON,结构严格校验 |
|
||
|
||
`merge_remark` 必须只包含这些字段:`merge_type`、`jobs`、`main_job`、`quantity`、`unit`、`job_count`。
|
||
|
||
响应:`201 SalesItem`。
|
||
|
||
### 获取销售品详情
|
||
|
||
`GET /api/v1/shipment/sales-items/{id}/`
|
||
|
||
响应:`200 SalesItem`,包含 `product_image_url`。
|
||
|
||
### 更新销售品
|
||
|
||
`PATCH /api/v1/shipment/sales-items/{id}/`
|
||
|
||
请求体只能包含以下字段:
|
||
|
||
```json
|
||
{
|
||
"quantity": "80.00",
|
||
"remark": "新备注",
|
||
"position": "B2-01"
|
||
}
|
||
```
|
||
|
||
可更新字段:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `quantity` | string | 数量,支持小数 |
|
||
| `remark` | string | 备注,最大 200 |
|
||
| `position` | string | 货位,最大 200 |
|
||
|
||
如果请求包含其他字段,返回 `400`。
|
||
|
||
响应:`200 SalesItem`,包含 `product_image_url`。
|
||
|
||
### 删除销售品
|
||
|
||
`DELETE /api/v1/shipment/sales-items/{id}/`
|
||
|
||
权限:需要 `shipment.soft_delete_salesitem`。
|
||
|
||
响应:
|
||
|
||
```json
|
||
{
|
||
"detail": "销售品已标记为删除"
|
||
}
|
||
```
|
||
|
||
### 重建销售品
|
||
|
||
`POST /api/v1/shipment/sales-items/{id}/rebuild/`
|
||
|
||
仅销售品创建者可执行。
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"new_printing_job_id": 456,
|
||
"quantity": "50.00"
|
||
}
|
||
```
|
||
|
||
请求字段:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `new_printing_job_id` | integer | 是 | 新生产任务 ID,最小 1 |
|
||
| `quantity` | string | 否 | 新数量;不传则沿用原销售品数量 |
|
||
|
||
响应:`200 SalesItem`。
|
||
|
||
## 前端重点注意
|
||
|
||
- 创建出货单时,`address_id` 不会自动填充地址快照。前端若选择客户地址,需要同时把地址表中的 `address/contact_name/contact_phone/area/coordinates/extra` 放入创建请求。
|
||
- `coordinates` 是新的字符串字段,前端不要再把新数据写到 `geo_coordinates`。
|
||
- `geo_coordinates` 是历史兼容字段,读取时可能存在旧值,但更新接口目前不保存它。
|
||
- `area` 现在最大 100 字符,可以直接承载客户地址的 `area`。
|
||
- `extra` 可用于承载客户地址扩展信息,允许对象、数组或 `null`。
|
||
- 更新出货单时,传 `coordinates: null` 或 `extra: null` 可以清空对应字段;不传则不修改。
|
||
- 按生产订单查送货单的 `external_order_id` 多匹配错误返回 `500 + message`;按生产订单查销售品的同类错误返回 `400 + detail`。
|