4.7 KiB
Business 模块采购单 API
创建采购单(默认待审批)
- URL:
POST /api/v1/purchase-orders/ - 权限: 需要登录且具备员工身份
- 描述: 创建业务模块的
PurchaseOrder,默认状态为PENDING(审批中)。此时不会立即生成入库记录,需在审批通过后才会触发库存入库任务。
请求体
{
"supplier": 1,
"warehouse_id": 2,
"order_date": "2025-11-26",
"remarks": "测试采购单",
"items": [
{
"product_id": 10,
"quantity": 120,
"num_of_rolls": 3,
"price": "12.50",
"unit": "米",
"empty_diff_percent": "0"
}
]
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| supplier | integer | ✅ | 供应商 ID,必须隶属于当前商户 |
| warehouse / warehouse_id | integer | ✅ | 入库仓库 ID(两字段二选一,推荐 warehouse_id) |
| order_date | string (date) | ✅ | 订单日期(YYYY-MM-DD) |
| remarks | string | 否 | 备注 |
| items | array | ✅ | 入库明细,根据仓库模式提供不同字段 |
items 结构说明
-
宽进仓(UNRESTRICTED)
- 必填:
product_id、quantity、num_of_rolls quantity_of_rolls会自动置空,并以{value, num_of_rolls}的形式传递给StockFlowService.stock_in的宽松模式。
- 必填:
-
严进仓(RESTRICT_IN / RESTRICT_IN_OUT)
- 必填:
product_id、numbers(数组) - 后端会以数组长度设置
num_of_rolls,把所有数值拼为quantity_of_rolls="10,5,8",同时求和得到quantity,并生成{'quantities': ['10','5','8']}传递给严谨模式。
- 必填:
公共可选字段:price、unit、color、empty_diff_percent、batch_number、remarks。缺省时默认使用 0 或产品单位。
⚠️ 当仓库模式与 items 字段不匹配(例如严进仓缺少 numbers、宽进仓提供 numbers)时将返回 400,提示“仓库为 ×× 模式,items[n] 需要提供 …”。
响应
{
"id": 35,
"status": 1,
"message": "采购单创建成功,等待审批"
}
创建成功即刻返回,状态为 审批中。只有在审批通过后才会调用库存入库任务。
错误示例
| 状态码 | 示例 | 说明 |
|---|---|---|
| 400 | {"error": "缺少仓库 ID"} |
请求缺失关键字段 |
| 400 | {"error": "仓库为严进模式,items[0] 需要提供 numbers 数组"} |
参数与仓库模式不匹配 |
| 400 | {"error": "供应商 99 不存在"} |
供应商不属于当前商户 |
| 403 | {"error": "无权限访问"} |
当前用户无员工信息 |
审批 / 作废采购单(API & Service)
- URL:
POST /api/v1/purchase-orders/<id>/review/ - 权限: 登录 + 员工身份
- 请求体:
{
"action": "approve" // 可选: approve / cancel
}
当 action=approve 时,会调用 business.services.review_purchase_order 将采购单状态更新为 APPROVED,并在商户设置 auto_create_stock_change_tasks=True 时自动触发 create_purchase_order_stock_entries Celery 任务(根据采购单明细重建 StockFlowService.stock_in 所需 payload)。
当 action=cancel 时,会尝试将采购单状态改为 CANCELLED。如果该采购单已经生成过出入库记录(source_type=PURCHASE、source_id=采购单ID),接口会返回 400,提示“采购单已生成出入库记录,无法作废”。
响应示例
{
"id": 12,
"status": 2,
"supplier_name": "供应商A",
"warehouse_name": "严进仓",
"total_amount": "1500.00",
"diff_quantity": "0.00",
"total_quantity": "120.00",
"items": [
{
"id": 33,
"product": 10,
"quantity": "120.00",
"unit": "米",
"spec": "50D",
"num_of_rolls": 3
}
]
}
错误示例
| 状态码 | 示例 | 说明 |
|---|---|---|
| 400 | {"action": ["This field is required."]} |
缺少 action |
| 400 | {"error": "采购单已生成出入库记录,无法作废"} |
尝试作废但已生成出入库单 |
| 404 | {"error": "采购单不存在"} |
ID 不在当前商户下 |
关联任务(business/tasks.py)
create_purchase_order_stock_entries 任务会接收 purchase_order_id、warehouse_id、已转换好的 items 信息,并通过 StockFlowService.stock_in 创建入库记录。只有当采购单审批通过且商户开启自动入库设置时才会派发该任务。
测试
business/tests.PurchaseOrderServiceTestCase:覆盖创建采购单、审批触发任务、作废校验以及宽/严模式的 payload 生成逻辑。business/tests.PurchaseOrderStockServiceTestCase与PurchaseOrderStockTaskTestCase:继续验证 service 层生成入库单及 Celery 任务封装逻辑。