1
0
forked from erp-dev/erp
Files
erpnew/docs/shipment_api.md

414 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 |
| remark | string | 否 | 备注 |
| sales_items | array[int] | 否 | 要关联的销售品ID列表 |
### 请求示例
```json
{
"customer": 1,
"shipment_date": "2026-01-14",
"remark": "备注信息",
"sales_items": [1, 2, 3]
}
```
### 响应格式
```json
{
"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"
}
```
### 响应字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| id | int | 出货单ID |
| merchant_id | int | 所属商户ID从当前登录用户推导 |
| merchant_name | string | 所属商户名称(从当前登录用户推导) |
| customer | int | 客户ID |
| customer_name | string | 客户名称 |
| shipment_date | 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 |
| 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",
"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",
"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 | 关联的出货单IDnull 表示未出货 |
| results[].shipment_date | string/null | 出货日期YYYY-MM-DDnull 表示未出货 |
| 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`:外部订单号(可空)