quantity; switch ($item->purchasable_type) { case Perfume::class: $relation = 'perfumes'; break; case Product::class: $relation = 'products'; break; case Bottle::class: $relation = 'bottles'; break; default: return; } // Lock the row to prevent race conditions $existing = $warehouse->{$relation}() ->where("{$relation}.id", $item->purchasable_id) ->lockForUpdate() ->withPivot('stock') ->first(); if ($existing) { $previousStock = $existing->pivot->stock ?? 0; $warehouse->{$relation}()->updateExistingPivot($item->purchasable_id, [ 'stock' => $previousStock + $quantity, ]); } else { $previousStock = 0; $warehouse->{$relation}()->attach($item->purchasable_id, [ 'stock' => $quantity, ]); } $purchase = $item->purchase ?? \App\Models\Purchase::find($item->purchase_id); if ($purchase) { StockActivityLogService::purchase( purchase: $purchase, product: $item->purchasable, quantity: $quantity, previousStock: $previousStock, newStock: $previousStock + $quantity ); } else { StockActivityLogService::logWarehouse( logName: StockActivityLogService::LOG_PURCHASE, event: 'increase', description: 'Stok '.$item->purchasable->name.' di gudang '.$warehouse->name.' bertambah '.formatCurrencyNumber($quantity), performedOn: $item->purchasable, warehouse: $warehouse, quantityChange: $quantity, previousStock: $previousStock, newStock: $previousStock + $quantity, extraProperties: [ 'purchasable_id' => $item->purchasable_id, 'purchasable_type' => $item->purchasable_type, 'purchase_id' => $item->purchase_id ?? null, ] ); } } public function decreaseWarehouseStock($warehouse, $item): void { $quantity = $item->quantity; switch ($item->purchasable_type) { case Perfume::class: $relation = 'perfumes'; break; case Product::class: $relation = 'products'; break; case Bottle::class: $relation = 'bottles'; break; default: return; } $existing = $warehouse->{$relation}() ->where("{$relation}.id", $item->purchasable_id) ->lockForUpdate() ->withPivot('stock') ->first(); if ($existing) { $currentStock = $existing->pivot->stock ?? 0; $newStock = max(0, $currentStock - $quantity); $warehouse->{$relation}()->updateExistingPivot($item->purchasable_id, [ 'stock' => $newStock, ]); } else { $currentStock = 0; $newStock = 0; } StockActivityLogService::logWarehouse( logName: StockActivityLogService::LOG_PURCHASE, event: 'decrease', description: 'Stok '.$item->purchasable->name.' di gudang '.$warehouse->name.' berkurang '.$quantity, performedOn: $item->purchasable, warehouse: $warehouse, quantityChange: -1 * abs($quantity), previousStock: $currentStock, newStock: $newStock, extraProperties: [ 'purchasable_id' => $item->purchasable_id, 'purchasable_type' => $item->purchasable_type, 'purchase_id' => $item->purchase_id, ] ); } }