parfum/app/Traits/Purchase/WithWarehouseStock.php

130 lines
4.2 KiB
PHP

<?php
namespace App\Traits\Purchase;
use App\Models\Bottle;
use App\Models\Perfume;
use App\Models\Product;
use App\Services\StockActivityLogService;
trait WithWarehouseStock
{
public function increaseWarehouseStock($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;
}
// 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,
]
);
}
}