1
0
forked from erp-dev/erp

feat: salesitem create api

This commit is contained in:
2026-03-10 19:30:48 +08:00
parent e2b91f977b
commit f0b017de52
6 changed files with 1469 additions and 583 deletions

View File

@@ -0,0 +1,263 @@
# SalesItem 创建 API 文档
## 概述
当自动转化销售品开关(`AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER`)关闭时,通过此 API 手动创建销售品。
## API 端点
```
POST /api/v1/shipment/sales-items/
```
## 请求头
```
Authorization: Bearer <token>
Content-Type: application/json
```
## 请求参数
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| printing_job_id | integer | 是 | 生产任务ID |
| name | string | 是 | 销售品名称最大200字符 |
| quantity | string | 是 | 数量(支持小数,如:"100.50" |
| unit | integer | 是 | 单位(见下方单位可选值) |
| customer_id | integer | 否 | 客户ID默认从生产订单获取 |
| remark | string | 否 | 备注最大200字符 |
| position | string | 否 | 货位最大200字符 |
## 单位可选值
| 值 | 单位 | 说明 |
|----|------|------|
| 1 | 米 | 默认单位 |
| 2 | 件 | - |
| 3 | 码 | - |
| 4 | 个 | - |
## 请求示例
```json
{
"printing_job_id": 123,
"name": "产品A-2026-03",
"quantity": "150.50",
"unit": 1,
"customer_id": 456,
"remark": "加急订单",
"position": "A1-01"
}
```
## 响应示例
### 成功响应201 Created
```json
{
"id": 1,
"name": "产品A-2026-03",
"quantity": "150.50",
"unit": 1,
"unit_display": "米",
"position": "A1-01",
"remark": "加急订单",
"printing_job_id": 123,
"customer_id": 456,
"shipment_id": null,
"shipment_date": null,
"created_at": "2026-03-05T10:30:00Z",
"created_by_id": 1,
"created_by_name": "张三"
}
```
**注意**`shipment_id``null` 表示该销售品处于"待分配"状态,尚未关联出货单。
### 错误响应
#### 400 Bad Request - 缺少必填字段
```json
{
"printing_job_id": ["此字段为必填项。"],
"name": ["此字段为必填项。"],
"quantity": ["此字段为必填项。"],
"unit": ["此字段为必填项。"]
}
```
#### 400 Bad Request - 生产任务不存在
```json
{
"detail": "生产任务 123 不存在或不属于当前商户"
}
```
#### 400 Bad Request - 单位值无效
```json
{
"unit": ["单位值无效。可选值:{1: '米', 2: '件', 3: '码', 4: '个'}"]
}
```
#### 400 Bad Request - 数量格式无效
```json
{
"detail": "数量 abc 格式无效: invalid literal for int() with base 10: 'abc'"
}
```
#### 403 Forbidden - 用户未关联商户
```json
{
"detail": "用户未关联商户,无法创建销售品"
}
```
#### 401 Unauthorized - 未认证
```json
{
"detail": "身份认证信息未提供。"
}
```
## 权限说明
- **认证要求**:需要登录用户(`IsAuthenticated`
- **商户隔离**:自动从当前用户的 `employee.merchant` 获取商户信息
- **Django权限**:需要 `shipment.add_salesitem` 权限遵循Django表级权限
- **生产任务验证**:必须验证生产任务属于当前商户
## 业务逻辑
### 创建流程
1. **验证用户商户**:从 `request.user.employee.merchant` 获取当前商户
2. **验证生产任务**:确认生产任务存在且属于当前商户
3. **数据转换**:将数量字符串转换为 Decimal
4. **获取客户ID**:如果未提供,自动从生产订单获取
5. **创建销售品**
- `shipment = null`(待分配状态)
- `printing_job_id` 关联生产任务
- `merchant` 设置为当前商户
### 状态说明
销售品没有独立的状态字段,通过 `shipment` 字段判断:
- **待分配**`shipment = null`
- **已关联出货单**`shipment != null`
创建后的销售品处于"待分配"状态,可通过出货单 API 关联到出货单。
## 使用场景
### 场景1自动转化开关关闭时
`AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER = False` 时,系统不会自动创建销售品。此时需要通过此 API 手动创建:
```python
# 生产任务完成后,手动创建销售品
POST /api/v1/shipment/sales-items/
{
"printing_job_id": 123,
"name": "产品A",
"quantity": "100",
"unit": 1
}
```
### 场景2补充创建销售品
即使自动转化开关开启,也可以通过此 API 手动创建额外的销售品(用于特殊情况)。
### 场景3修正销售品
如果自动创建的销售品信息有误,可以:
1. 删除自动创建的销售品
2. 使用此 API 手动创建正确的销售品
## 相关 API
### 查询销售品
```
GET /api/v1/shipment/sales-items/by-printing-order/<printing_order_id>/?include_already_has_shipment=false
```
### 创建出货单并关联销售品
```
POST /api/v1/shipment/shipments/
{
"customer": 1,
"shipment_date": "2026-03-05",
"sales_items": [1, 2, 3]
}
```
## 注意事项
1. **商户隔离**:只能为当前用户所属商户创建销售品
2. **生产任务验证**必须提供有效的生产任务ID且该任务必须属于当前商户
3. **数量格式**:支持小数,使用字符串传递避免精度丢失
4. **单位验证**必须提供有效的单位值1/2/3/4
5. **重复创建**:同一个生产任务可以创建多个销售品(如果业务需要)
## 测试示例
### curl 命令
```bash
curl -X POST http://localhost:8000/api/v1/shipment/sales-items/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"printing_job_id": 123,
"name": "测试产品",
"quantity": "100.50",
"unit": 1,
"remark": "测试备注"
}'
```
### Python 示例
```python
import requests
data = {
"printing_job_id": 123,
"name": "产品A-2026-03",
"quantity": "150.50",
"unit": 1, # 米
"customer_id": 456,
"remark": "加急订单",
"position": "A1-01"
}
response = requests.post(
"http://localhost:8000/api/v1/shipment/sales-items/",
json=data,
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
if response.status_code == 201:
sales_item = response.json()
print(f"创建成功:{sales_item['name']} x {sales_item['quantity']} {sales_item['unit_display']}")
else:
print(f"错误:{response.json()}")
```
## 更新日志
- **2026-03-05**: API 首次创建,支持手动创建销售品