forked from erp-dev/erp
421 lines
10 KiB
Markdown
421 lines
10 KiB
Markdown
# Shipment API 文档
|
||
|
||
出货管理模块 API 文档,包含出货单和销售品相关接口。
|
||
|
||
## 目录
|
||
|
||
- [查询出货单](#查询出货单)
|
||
- [创建出货单](#创建出货单)
|
||
- [通过生产订单查询销售品](#通过生产订单查询销售品)
|
||
|
||
---
|
||
|
||
## 查询出货单
|
||
|
||
### 出货单列表
|
||
|
||
- **URL**: `/api/v1/shipment/shipments/`
|
||
- **Method**: `GET`
|
||
- **认证**: 需要登录(JWT Token)
|
||
|
||
#### 查询参数(可选)
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| limit | int | 分页大小(LimitOffsetPagination) |
|
||
| offset | int | 偏移量 |
|
||
| customer | int | 客户ID |
|
||
| status | int | 状态(1=待送货, 2=已交付, 3=已取消) |
|
||
| external_id | string | 外部订单号(精确匹配) |
|
||
| shipment_date_from | string | 出货日期起始(YYYY-MM-DD) |
|
||
| shipment_date_to | string | 出货日期结束(YYYY-MM-DD) |
|
||
|
||
#### 响应格式
|
||
|
||
使用 LimitOffsetPagination:
|
||
|
||
```json
|
||
{
|
||
"count": 2,
|
||
"next": null,
|
||
"previous": null,
|
||
"results": [
|
||
{
|
||
"id": 1,
|
||
"merchant_id": 1,
|
||
"merchant_name": "测试印花厂",
|
||
"customer": 1,
|
||
"customer_name": "客户A",
|
||
"shipment_date": "2026-01-14",
|
||
"remark": "备注信息",
|
||
"items_count": 3,
|
||
"sales_items": [],
|
||
"external_finished_products": [],
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三",
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"updated_at": "2026-01-14T10:00:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 出货单详情
|
||
|
||
- **URL**: `/api/v1/shipment/shipments/<id>/`
|
||
- **Method**: `GET`
|
||
- **认证**: 需要登录(JWT Token)
|
||
|
||
---
|
||
|
||
## 创建出货单
|
||
|
||
创建出货单并关联销售品。
|
||
|
||
### 接口信息
|
||
|
||
- **URL**: `/api/v1/shipment/shipments/`
|
||
- **Method**: `POST`
|
||
- **认证**: 需要登录(JWT Token)
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| customer | int | 是 | 客户ID |
|
||
| shipment_date | string | 是 | 出货日期(YYYY-MM-DD) |
|
||
| area | string | 否 | 出货地区(可空字符串,长度<=30) |
|
||
| remark | string | 否 | 备注 |
|
||
| sales_items | array[int] | 否 | 要关联的销售品ID列表 |
|
||
|
||
### 请求示例
|
||
|
||
```json
|
||
{
|
||
"customer": 1,
|
||
"shipment_date": "2026-01-14",
|
||
"area": "华东",
|
||
"remark": "备注信息",
|
||
"sales_items": [1, 2, 3]
|
||
}
|
||
```
|
||
|
||
### 响应格式
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"merchant_id": 1,
|
||
"merchant_name": "测试印花厂",
|
||
"customer": 1,
|
||
"customer_name": "客户A",
|
||
"shipment_date": "2026-01-14",
|
||
"area": "华东",
|
||
"remark": "备注信息",
|
||
"items_count": 3,
|
||
"sales_items": [],
|
||
"external_finished_products": [],
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三",
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"updated_at": "2026-01-14T10:00:00Z"
|
||
}
|
||
```
|
||
|
||
### 响应字段说明
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | int | 出货单ID |
|
||
| merchant_id | int | 所属商户ID(从当前登录用户推导) |
|
||
| merchant_name | string | 所属商户名称(从当前登录用户推导) |
|
||
| customer | int | 客户ID |
|
||
| customer_name | string | 客户名称 |
|
||
| shipment_date | string | 出货日期 |
|
||
| area | string | 出货地区 |
|
||
| remark | string | 备注 |
|
||
| items_count | int | 关联的销售品数量 |
|
||
| created_by_id | int | 创建人ID |
|
||
| created_by_name | string | 创建人名称 |
|
||
| created_at | string | 创建时间 |
|
||
| updated_at | string | 更新时间 |
|
||
|
||
### 错误响应
|
||
|
||
#### 400 Bad Request - 客户不存在
|
||
|
||
```json
|
||
{
|
||
"detail": "客户 999 不存在"
|
||
}
|
||
```
|
||
|
||
#### 400 Bad Request - 销售品不存在
|
||
|
||
```json
|
||
{
|
||
"detail": "以下销售品不存在: [999]"
|
||
}
|
||
```
|
||
|
||
#### 400 Bad Request - 销售品已关联其他出货单
|
||
|
||
```json
|
||
{
|
||
"detail": "以下销售品已关联到其他出货单: [1, 2]"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 创建出货单(external 版)
|
||
|
||
创建出货单但**不绑定任何销售品**,同时写入并关联“外部成品表”(用于兼容外部遗留系统)。
|
||
|
||
### 接口信息
|
||
|
||
- **URL**: `/api/v1/shipment/shipments/external/`
|
||
- **Method**: `POST`
|
||
- **认证**: 需要登录(JWT Token)
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| customer | int | 是 | 客户ID |
|
||
| shipment_date | string | 是 | 出货日期(YYYY-MM-DD) |
|
||
| area | string | 否 | 出货地区(可空字符串,长度<=30) |
|
||
| remark | string | 否 | 备注 |
|
||
| external_id | string | 是 | 外部订单号(长度<=120) |
|
||
| external_finished_products | array[object] | 是 | 外部成品表结构数组(至少 1 条) |
|
||
|
||
`external_finished_products` 每项结构:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| style_name | string | 是 | 款式名称 |
|
||
| num_of_rolls | int | 是 | 卷数 |
|
||
| remark | string | 否 | 备注(可空) |
|
||
|
||
### 请求示例
|
||
|
||
```json
|
||
{
|
||
"customer": 1,
|
||
"shipment_date": "2026-01-14",
|
||
"area": "华南",
|
||
"remark": "external 备注(可选)",
|
||
"external_id": "EXT-ORDER-001",
|
||
"external_finished_products": [
|
||
{"style_name": "款式A", "num_of_rolls": 2, "remark": "A备注"},
|
||
{"style_name": "款式B", "num_of_rolls": 5}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 响应示例
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"merchant_id": 1,
|
||
"merchant_name": "测试印花厂",
|
||
"customer": 1,
|
||
"customer_name": "客户A",
|
||
"shipment_date": "2026-01-14",
|
||
"area": "华南",
|
||
"remark": "external 备注(可选)",
|
||
"status": 1,
|
||
"status_display": "待送货",
|
||
"external_id": "EXT-ORDER-001",
|
||
"cancelled_at": null,
|
||
"cancelled_by_id": null,
|
||
"cancelled_by_name": null,
|
||
"items_count": 0,
|
||
"external_finished_products_count": 2,
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三",
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"updated_at": "2026-01-14T10:00:00Z"
|
||
}
|
||
```
|
||
|
||
### 错误响应
|
||
|
||
#### 400 Bad Request - external_id 为空
|
||
|
||
```json
|
||
{
|
||
"external_id": ["external_id 不能为空"]
|
||
}
|
||
```
|
||
|
||
#### 400 Bad Request - external_finished_products 为空
|
||
|
||
```json
|
||
{
|
||
"external_finished_products": ["external_finished_products 不能为空"]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 通过生产订单查询销售品
|
||
|
||
查询与指定生产订单(PrintingOrder)关联的所有销售品(SalesItem)。
|
||
|
||
### 接口信息
|
||
|
||
- **URL**: `/api/v1/shipment/sales-items/by-printing-order/<printing_order_id>/`
|
||
- **Method**: `GET`
|
||
- **认证**: 需要登录(JWT Token)
|
||
|
||
### 路径参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| printing_order_id | int | 是 | 生产订单ID |
|
||
|
||
### 查询参数
|
||
|
||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
||
|------|------|------|--------|------|
|
||
| include_already_has_shipment | bool | 否 | false | 是否包含已关联出货单的销售品 |
|
||
|
||
### 业务逻辑
|
||
|
||
1. 根据 `printing_order_id` 获取该生产订单下所有 `PrintingJob` 的 ID
|
||
2. 查询 `SalesItem`,过滤 `printing_job_id` 在这些 job ID 中的记录
|
||
3. 根据 `include_already_has_shipment` 参数决定是否过滤已关联出货单的销售品:
|
||
- `false`(默认):只返回 `shipment` 为空的销售品(待出货)
|
||
- `true`:返回所有销售品(包含已出货的)
|
||
|
||
### 响应格式
|
||
|
||
```json
|
||
{
|
||
"count": 2,
|
||
"results": [
|
||
{
|
||
"id": 1,
|
||
"name": "产品A - 红色",
|
||
"quantity": "100.00",
|
||
"unit": 1,
|
||
"unit_display": "米",
|
||
"position": "A1-01",
|
||
"remark": "加急处理",
|
||
"printing_job_id": 123,
|
||
"customer_id": null,
|
||
"shipment_id": null,
|
||
"shipment_date": null,
|
||
"created_at": "2026-01-14T10:00:00Z",
|
||
"created_by_id": 1,
|
||
"created_by_name": "张三"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"name": "产品B - 蓝色",
|
||
"quantity": "50.50",
|
||
"unit": 1,
|
||
"unit_display": "米",
|
||
"position": "",
|
||
"remark": "",
|
||
"printing_job_id": 124,
|
||
"customer_id": 10,
|
||
"shipment_id": 5,
|
||
"shipment_date": "2026-01-13",
|
||
"created_at": "2026-01-13T15:30:00Z",
|
||
"created_by_id": 2,
|
||
"created_by_name": "李四"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 响应字段说明
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| count | int | 结果总数 |
|
||
| results | array | 销售品列表 |
|
||
| results[].id | int | 销售品ID |
|
||
| results[].name | string | 销售品名称 |
|
||
| results[].quantity | string | 数量(Decimal,保留2位小数) |
|
||
| results[].unit | int | 单位编码(1=米, 2=件, 3=码, 4=个) |
|
||
| results[].unit_display | string | 单位显示名称 |
|
||
| results[].position | string | 货位(可能为空) |
|
||
| results[].remark | string | 备注(可能为空) |
|
||
| results[].printing_job_id | int/null | 关联的生产任务ID |
|
||
| results[].customer_id | int/null | 销售品级别的客户ID |
|
||
| results[].shipment_id | int/null | 关联的出货单ID,null 表示未出货 |
|
||
| results[].shipment_date | string/null | 出货日期(YYYY-MM-DD),null 表示未出货 |
|
||
| results[].created_at | string | 创建时间(ISO 8601) |
|
||
| results[].created_by_id | int/null | 创建人ID |
|
||
| results[].created_by_name | string/null | 创建人名称 |
|
||
|
||
### 错误响应
|
||
|
||
#### 404 Not Found - 生产订单不存在
|
||
|
||
```json
|
||
{
|
||
"detail": "生产订单 999 不存在"
|
||
}
|
||
```
|
||
|
||
#### 401 Unauthorized - 未登录
|
||
|
||
```json
|
||
{
|
||
"detail": "Authentication credentials were not provided."
|
||
}
|
||
```
|
||
|
||
### 使用示例
|
||
|
||
#### 查询待出货的销售品(默认)
|
||
|
||
```bash
|
||
curl -X GET \
|
||
'https://api.example.com/api/v1/shipment/sales-items/by-printing-order/123/' \
|
||
-H 'Authorization: Bearer <token>'
|
||
```
|
||
|
||
#### 查询所有销售品(包含已出货)
|
||
|
||
```bash
|
||
curl -X GET \
|
||
'https://api.example.com/api/v1/shipment/sales-items/by-printing-order/123/?include_already_has_shipment=true' \
|
||
-H 'Authorization: Bearer <token>'
|
||
```
|
||
|
||
---
|
||
|
||
## 单位编码对照表
|
||
|
||
| 编码 | 名称 |
|
||
|------|------|
|
||
| 1 | 米 |
|
||
| 2 | 件 |
|
||
| 3 | 码 |
|
||
| 4 | 个 |
|
||
|
||
---
|
||
|
||
## 相关模块
|
||
|
||
- `shipment/services.py`: 业务逻辑层
|
||
- `api_v1/views/shipment/`: API 视图层
|
||
- `shipment/models.py`: 数据模型(SalesItem, Shipment)
|
||
|
||
---
|
||
|
||
## 外部系统兼容(数据模型说明)
|
||
|
||
为兼容外部遗留系统,Shipment 模块新增了“外部成品表”模型:
|
||
|
||
- **关系**:`Shipment` 1 → N `ExternalFinishedProduct`
|
||
- 外键在 `ExternalFinishedProduct.shipment`(可空)
|
||
- **Shipment 外部字段**:
|
||
- `external_id`:外部订单号(可空)
|