feat: B-001 驳回库存释放 + B-002 缺失路由 + B-003 delivery路径统一

- StockService: 添加unlockStock()方法
- OrderController: 驳回时自动解锁库存
- routes/api.php: 添加warehouse/bindings、operation-logs、delivery统一路由
This commit is contained in:
Yatu 2026-04-01 19:05:21 +08:00
parent 32685b3b01
commit e80e57cdcf
3 changed files with 78 additions and 1 deletions

View File

@ -229,6 +229,19 @@ public function batchAudit(Request $request)
continue;
}
// 驳回时解锁库存
if ($request->action === 'reject') {
$stockService = app(\App\Services\StockService::class);
foreach ($order->items as $item) {
$stockService->unlockStock(
$item->sku_code ?? $item->erp_sku_id,
$order->warehouse_id,
$item->quantity,
$order->id
);
}
}
$order->update([
'audit_status' => $request->action === 'approve' ? 'approved' : 'rejected',
'audit_comment' => $request->comment,
@ -284,6 +297,19 @@ public function auditOrder(Request $request, string $id)
], 400);
}
// 驳回时解锁库存
if ($request->action === 'reject') {
$stockService = app(\App\Services\StockService::class);
foreach ($order->items as $item) {
$stockService->unlockStock(
$item->sku_code ?? $item->erp_sku_id,
$order->warehouse_id,
$item->quantity,
$order->id
);
}
}
$order->update([
'audit_status' => $request->action === 'approve' ? 'approved' : 'rejected',
'audit_comment' => $request->comment,

View File

@ -38,6 +38,37 @@ public function lock($skuCode, $warehouseId, $quantity, $orderId)
});
}
/**
* 解锁库存(驳回订单时调用)
*/
public function unlockStock($skuCode, $warehouseId, $quantity, $orderId)
{
if ($quantity <= 0) {
throw new \InvalidArgumentException('解锁数量必须为正数');
}
return DB::transaction(function () use ($skuCode, $warehouseId, $quantity, $orderId) {
$stock = $this->getStock($skuCode, $warehouseId);
if ($stock->locked_quantity < $quantity) {
throw new \Exception("商品 {$skuCode} 锁定库存不足,当前锁定{$stock->locked_quantity},需解锁{$quantity}");
}
$stock->decrement('locked_quantity', $quantity);
StockLog::create([
'sku_code' => $skuCode,
'warehouse_id' => $warehouseId,
'change_quantity' => -$quantity,
'type' => 'unlock',
'order_id' => $orderId,
'remark' => "解锁库存订单ID {$orderId}",
]);
return $stock;
});
}
/**
* 获取指定SKU在仓库的可用库存
*/

View File

@ -95,5 +95,25 @@
Route::delete('/{id}', [GoodsController::class, 'destroy']);
});
// 商品模块ERP SKU
// 仓库模板绑定
Route::middleware('auth:sanctum')->prefix('warehouse')->group(function () {
Route::get('/bindings', [WarehouseTemplateBindingController::class, 'index']);
Route::post('/bindings', [WarehouseTemplateBindingController::class, 'store']);
Route::put('/bindings/{id}', [WarehouseTemplateBindingController::class, 'update']);
Route::delete('/bindings/{id}', [WarehouseTemplateBindingController::class, 'destroy']);
});
// 操作日志
Route::middleware('auth:sanctum')->prefix('operation-logs')->group(function () {
Route::get('/', [OperationLogController::class, 'index']);
Route::get('/export', [OperationLogController::class, 'export']);
});
// 发货管理 - 统一路径
Route::middleware('auth:sanctum')->prefix('delivery')->group(function () {
Route::get('/pending', [DeliveryController::class, 'pending']);
Route::get('/pending-delivery', [DeliveryController::class, 'pending']); // 兼容旧路径
Route::get('/reprint/{id}', [DeliveryController::class, 'reprint']);
Route::post('/reprint', [DeliveryController::class, 'reprintBatch']); // 批量重打
});