forked from erp-dev/erp
83 lines
3.2 KiB
Markdown
83 lines
3.2 KiB
Markdown
# Business 模块采购单 API
|
||
|
||
## 创建采购单并触发入库
|
||
|
||
- **URL**: `POST /api/v1/purchase-orders/`
|
||
- **权限**: 需要登录且具备员工身份
|
||
- **描述**: 创建业务模块的 `PurchaseOrder`,并异步触发库存入库任务(通过 `stock.services.StockFlowService.stock_in` 实现)。
|
||
|
||
### 请求体
|
||
|
||
```json
|
||
{
|
||
"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] 需要提供 …”。
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"id": 35,
|
||
"message": "采购单创建成功,入库任务已排队"
|
||
}
|
||
```
|
||
|
||
创建成功即刻返回,实际入库明细由后台 Celery 任务生成,可在日志或 `stock_change` 记录中查看。
|
||
|
||
### 错误示例
|
||
|
||
| 状态码 | 示例 | 说明 |
|
||
|--------|------|------|
|
||
| 400 | `{"error": "缺少仓库 ID"}` | 请求缺失关键字段 |
|
||
| 400 | `{"error": "仓库为严进模式,items[0] 需要提供 numbers 数组"}` | 参数与仓库模式不匹配 |
|
||
| 400 | `{"error": "供应商 99 不存在"}` | 供应商不属于当前商户 |
|
||
| 403 | `{"error": "无权限访问"}` | 当前用户无员工信息 |
|
||
|
||
### 关联任务(business/tasks.py)
|
||
|
||
`create_purchase_order_stock_entries` 任务会接收 `purchase_order_id`、`warehouse_id`、已转换好的 `items` 信息,并通过 `StockFlowService.stock_in` 创建入库记录。
|
||
|
||
- 任务日志示例:`采购单 35 入库任务完成`
|
||
- 返回 payload 包含 `stock_change_record_id`、`created_details_count`
|
||
|
||
### 测试
|
||
|
||
`api_v1/tests.py` 中的 `PurchaseOrderAPITestCase` 覆盖宽进/严进模式、模式不匹配和未登录场景;
|
||
`business/tests.py` 中的 `PurchaseOrderServiceTestCase`、`PurchaseOrderStockTaskTestCase` 验证 service 层逻辑与 Celery 任务(通过 mock `StockFlowService`)。
|
||
|