with(['fromWarehouse', 'toWarehouse', 'operator']) ->when($request->transfer_no, fn($q, $v) => $q->where('transfer_no', 'like', "%{$v}%")) ->when($request->has('status'), fn($q) => $q->where('status', $request->status)) ->when($request->from_warehouse_id, fn($q, $v) => $q->where('from_warehouse_id', $v)); return $this->paginate($query->latest()->paginate($request->input('per_page', 15))); } public function store(Request $request): JsonResponse { $v = $request->validate([ 'transfer_no' => 'required|string|max:50|unique:transfer_orders', 'from_warehouse_id' => 'required|exists:warehouses,id', 'to_warehouse_id' => 'required|exists:warehouses,id|different:from_warehouse_id', 'items' => 'nullable|array', 'remark' => 'nullable|string|max:500', ]); $v['status'] = 0; $v['operator_id'] = auth()->id(); return $this->success(TransferOrder::create($v)); } public function show(TransferOrder $transferOrder): JsonResponse { return $this->success($transferOrder->load(['fromWarehouse', 'toWarehouse', 'operator'])); } public function confirm(TransferOrder $transferOrder): JsonResponse { if ($transferOrder->status !== 0) { return $this->error('当前状态不可确认', 40001); } DB::transaction(function () use ($transferOrder) { $transferOrder->update(['status' => 1]); // 调拨:减源仓库、加目标仓库 foreach (($transferOrder->items ?? []) as $item) { $materialId = $item['material_id']; $qty = $item['quantity'] ?? 0; // 扣减出库仓库 Inventory::where('warehouse_id', $transferOrder->from_warehouse_id) ->where('material_id', $materialId) ->decrement('quantity', $qty); // 增加入库仓库 $inv = Inventory::firstOrCreate( ['warehouse_id' => $transferOrder->to_warehouse_id, 'material_id' => $materialId, 'batch_no' => null], ['quantity' => 0] ); $inv->increment('quantity', $qty); } }); return $this->success($transferOrder->fresh(['fromWarehouse', 'toWarehouse'])); } public function cancel(TransferOrder $transferOrder): JsonResponse { if ($transferOrder->status !== 0) { return $this->error('只有待确认状态可取消', 40001); } $transferOrder->update(['status' => 2]); return $this->success($transferOrder); } }