feat(order): throw transaction jika stok produk tidak mencukupi

This commit is contained in:
Yoga Pangestu 2025-11-05 13:49:18 +07:00
parent 464ce3df39
commit c63245bf68
2 changed files with 98 additions and 77 deletions

View File

@ -115,6 +115,7 @@ public function store()
// Wrap the entire operation in a database transaction // Wrap the entire operation in a database transaction
// Ensures atomicity — if any step fails, all changes are rolled back // Ensures atomicity — if any step fails, all changes are rolled back
try {
DB::transaction(function () use ($invoiceNumber, $cogs, $subtotal, $discount, $total, $items, $pointsEarned) { DB::transaction(function () use ($invoiceNumber, $cogs, $subtotal, $discount, $total, $items, $pointsEarned) {
$member = User::whereHas('customer', fn ($q) => $q->where('id', $this->member_id)) $member = User::whereHas('customer', fn ($q) => $q->where('id', $this->member_id))
->with(['membership' => fn ($q) => $q->lockForUpdate()]) ->with(['membership' => fn ($q) => $q->lockForUpdate()])
@ -136,14 +137,18 @@ public function store()
'ordered_at' => now(), 'ordered_at' => now(),
]); ]);
foreach ($items as $item) {
// Deduct item stock from the outlet inventory
$result = $this->decreaseOutletStock($order->outlet, $item);
if ($result && ! $result['status']) {
throw new \Exception($result['message']);
}
// Attach all order items to the newly created order // Attach all order items to the newly created order
$items->each(function ($item) use ($order) {
$item->order_id = $order->id; $item->order_id = $order->id;
$item->save(); $item->save();
}
// Deduct item stock from the outlet inventory
$this->decreaseOutletStock($order->outlet, $item);
});
// Automatically record payment for the order // Automatically record payment for the order
Payment::create([ Payment::create([
@ -187,9 +192,13 @@ public function store()
]); ]);
} }
}); });
} catch (\Exception $e) {
return [ return [
'status' => true, 'status' => false,
'message' => $e->getMessage(),
]; ];
} }
return ['status' => true];
}
} }

View File

@ -73,15 +73,27 @@ public function decreaseOutletStock($outlet, $item)
return; return;
} }
$existing = $outlet->{$relation}()->withPivot('stock')->where("{$relation}.id", $item->orderable_id)->first(); $existing = $outlet->{$relation}()
->withPivot('stock')
->where("{$relation}.id", $item->orderable_id)
->lockForUpdate()
->first();
if (! $existing) {
return ['status' => false, 'message' => "Produk {$item->orderable->name} tidak ditemukan di {$outlet->name}."];
}
if ($existing) {
$currentStock = $existing->pivot->stock ?? 0; $currentStock = $existing->pivot->stock ?? 0;
$newStock = max(0, $currentStock - $quantity);
if ($currentStock < $quantity) {
return ['status' => false, 'message' => "Stok produk {$item->orderable->name} tidak mencukupi. Tersisa {$currentStock}, diminta {$quantity}. Silakan hubungi Administrator."];
}
$newStock = $currentStock - $quantity;
$outlet->{$relation}()->updateExistingPivot($item->orderable_id, [ $outlet->{$relation}()->updateExistingPivot($item->orderable_id, [
'stock' => $newStock, 'stock' => $newStock,
]); ]);
}
activity('Order') activity('Order')
->performedOn($item->orderable) ->performedOn($item->orderable)