forked from erp-dev/erp
6.1 KiB
6.1 KiB
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 | 个 | - |
请求示例
{
"printing_job_id": 123,
"name": "产品A-2026-03",
"quantity": "150.50",
"unit": 1,
"customer_id": 456,
"remark": "加急订单",
"position": "A1-01"
}
响应示例
成功响应(201 Created)
{
"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 - 缺少必填字段
{
"printing_job_id": ["此字段为必填项。"],
"name": ["此字段为必填项。"],
"quantity": ["此字段为必填项。"],
"unit": ["此字段为必填项。"]
}
400 Bad Request - 生产任务不存在
{
"detail": "生产任务 123 不存在或不属于当前商户"
}
400 Bad Request - 单位值无效
{
"unit": ["单位值无效。可选值:{1: '米', 2: '件', 3: '码', 4: '个'}"]
}
400 Bad Request - 数量格式无效
{
"detail": "数量 abc 格式无效: invalid literal for int() with base 10: 'abc'"
}
403 Forbidden - 用户未关联商户
{
"detail": "用户未关联商户,无法创建销售品"
}
401 Unauthorized - 未认证
{
"detail": "身份认证信息未提供。"
}
权限说明
- 认证要求:需要登录用户(
IsAuthenticated) - 商户隔离:自动从当前用户的
employee.merchant获取商户信息 - Django权限:需要
shipment.add_salesitem权限(遵循Django表级权限) - 生产任务验证:必须验证生产任务属于当前商户
业务逻辑
创建流程
- 验证用户商户:从
request.user.employee.merchant获取当前商户 - 验证生产任务:确认生产任务存在且属于当前商户
- 数据转换:将数量字符串转换为 Decimal
- 获取客户ID:如果未提供,自动从生产订单获取
- 创建销售品:
shipment = null(待分配状态)printing_job_id关联生产任务merchant设置为当前商户
状态说明
销售品没有独立的状态字段,通过 shipment 字段判断:
- 待分配:
shipment = null - 已关联出货单:
shipment != null
创建后的销售品处于"待分配"状态,可通过出货单 API 关联到出货单。
使用场景
场景1:自动转化开关关闭时
当 AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER = False 时,系统不会自动创建销售品。此时需要通过此 API 手动创建:
# 生产任务完成后,手动创建销售品
POST /api/v1/shipment/sales-items/
{
"printing_job_id": 123,
"name": "产品A",
"quantity": "100",
"unit": 1
}
场景2:补充创建销售品
即使自动转化开关开启,也可以通过此 API 手动创建额外的销售品(用于特殊情况)。
场景3:修正销售品
如果自动创建的销售品信息有误,可以:
- 删除自动创建的销售品
- 使用此 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]
}
注意事项
- 商户隔离:只能为当前用户所属商户创建销售品
- 生产任务验证:必须提供有效的生产任务ID,且该任务必须属于当前商户
- 数量格式:支持小数,使用字符串传递避免精度丢失
- 单位验证:必须提供有效的单位值(1/2/3/4)
- 重复创建:同一个生产任务可以创建多个销售品(如果业务需要)
测试示例
curl 命令
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 示例
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 首次创建,支持手动创建销售品