find($poId); if (!$po || in_array($po->status, [PurchaseOrder::STATUS_CANCELED, PurchaseOrder::STATUS_RECEIVED], true)) { throw new RuntimeException('PO not receivable.'); } if (empty($received)) { throw new RuntimeException('No items to receive.'); } return DB::transaction(function () use ($po, $received, $issuedBy) { $completed = true; foreach ($received as $item) { $itemId = (int) ($item['id'] ?? 0); $qty = (int) ($item['quantity'] ?? 0); if ($itemId <= 0 || $qty <= 0) { continue; } $poItem = PurchaseOrderItem::query() ->where('purchase_order_id', $po->id) ->where('id', $itemId) ->first(); if (!$poItem) { $completed = false; continue; } $remaining = (int) $poItem->quantity - (int) $poItem->received_qty; $toReceive = min($remaining, $qty); if ($toReceive <= 0) { continue; } $poItem->received_qty = (int) $poItem->received_qty + $toReceive; $poItem->save(); $supply = Supply::query()->find($poItem->supply_id); if (!$supply) { $completed = false; continue; } $supply->qty_on_hand = (int) $supply->qty_on_hand + $toReceive; $supply->save(); SupplyTransaction::query()->create([ 'supply_id' => $supply->id, 'type' => 'in', 'quantity' => $toReceive, 'ref' => 'PO ' . ($po->po_number ?? $po->id), 'issued_to' => 'Inventory', 'issued_by' => $issuedBy, 'notes' => 'Received against PO', ]); if ($poItem->received_qty < $poItem->quantity) { $completed = false; } } $po->status = $completed ? PurchaseOrder::STATUS_RECEIVED : PurchaseOrder::STATUS_ORDERED; $po->save(); return [ 'status' => $po->status, 'completed' => $completed, ]; }); } }