1
0
forked from erp-dev/erp

feat: transfer api for stock module

This commit is contained in:
2025-12-02 14:14:17 +08:00
parent 9dbb2f9c9b
commit 0b8146d972
9 changed files with 616 additions and 0 deletions

View File

@@ -302,6 +302,89 @@ Warehouses can operate in different modes:
}
```
### 4. Stock Transfer (调拨)
**URL**: `POST /api/v1/stock-change/transfer/`
**Description**: Performs an in-transaction transfer between two warehouses that share the same warehouse **mode** (可以跨类型,例如整件仓 → 散件仓)。一次调用会同步创建调出与调入的 `StockChangeRecord` 并立即完成库存扣加,确保库存一致性。
**Business Constraints**:
- `from_warehouse``to_warehouse` 必须属于当前商户,且不可相同。
- 两个仓库的 `mode` 必须一致RESTRICT_IN、UNRESTRICTED 均可)。目前不支持 `RESTRICT_IN_OUT`(严进严出)的调拨。
- 请求在数据库事务内完成,不能依赖异步任务;支持 `request_id` 幂等重试。
- `products` 列表沿用原出入库的 payload 结构,允许:
- `quantities`: 严谨/严进模式的显式数量数组;
- `value + unit_count/num_of_rolls`: 宽松模式的拆分定义;
- `consume_detail_ids`: 若未来开放严进严出调拨,可在此补充(当前会拒绝)。
**Request Parameters**:
```json
{
"from_warehouse": 3,
"to_warehouse": 5,
"transfer_date": "2025-12-02", // 可选,默认当天
"remarks": "整件仓调拨到散件仓", // 可选
"request_id": "transfer-20251202-001", // 可选幂等键
"products": [
{ "product_id": 12, "quantities": ["10.50", "5.25"] },
{ "product_id": 27, "value": "120.0", "unit_count": "30" }
]
}
```
**Response**:
```json
{
"id": 88,
"merchant": 6,
"from_warehouse": 3,
"from_warehouse_name": "整件一号仓",
"to_warehouse": 5,
"to_warehouse_name": "散件贵宾仓",
"mode": 1,
"mode_display": "严进宽出",
"operator": 24,
"transfer_date": "2025-12-02",
"status": 2,
"status_display": "已完成",
"remarks": "整件仓调拨到散件仓",
"request_id": "transfer-20251202-001",
"outgoing_record_id": 512,
"incoming_record_id": 513,
"items": [
{
"id": 143,
"product": 12,
"product_name": "贡缎白坯布",
"total_quantity": "15.75",
"unit": 1,
"unit_display": "米",
"num_of_rolls": 2
},
{
"id": 144,
"product": 27,
"product_name": "彩纱混纺",
"total_quantity": "120.00",
"unit": 1,
"unit_display": "米",
"num_of_rolls": 4
}
]
}
```
**Error Cases**:
| HTTP | Payload 示例 | 说明 |
|------|--------------|------|
| 400 | `{ "error": "调拨要求调出仓与调入仓的出入库模式一致" }` | 两仓 mode 不同 |
| 400 | `{ "error": "调入仓与调出仓不能相同" }` | 相同仓库 |
| 400 | `{ "error": "调出仓不存在或不属于当前商户" }` | 仓库不属于当前商户 |
| 400 | `{ "error": "调拨产品明细不能为空" }` | products 为空 |
| 409 | `{ "error": "请求重复" }` *(未来可扩展)* | 同一 `request_id` 重复提交(当前直接返回已存在记录) |
> **提示**:响应中附带 `outgoing_record_id` 与 `incoming_record_id`,可继续使用既有的 `GET /api/v1/stock-change/<id>/` 接口查看具体的明细与快照。
### Other Related Endpoints
#### List Stock Changes