130 lines
4.2 KiB
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,
|
|
]
|
|
);
|
|
}
|
|
}
|