parfum/app/Traits/Restock/WithRestockStock.php
2026-01-02 13:13:23 +07:00

170 lines
5.6 KiB
PHP

<?php
namespace App\Traits\Restock;
use App\Models\Bottle;
use App\Models\Perfume;
use App\Models\Product;
use App\Models\Restock;
use App\Services\StockActivityLogService;
trait WithRestockStock
{
public function transferStockFromWarehouseToOutlet($warehouse, $outlet, $item): void
{
$quantity = $item->quantity;
switch ($item->restockable_type) {
case Perfume::class:
$relation = 'perfumes';
break;
case Product::class:
$relation = 'products';
break;
case Bottle::class:
$relation = 'bottles';
break;
default:
return;
}
// Decrease warehouse stock
$warehouseItem = $warehouse->{$relation}()
->where("{$relation}.id", $item->restockable_id)
->lockForUpdate()
->withPivot('stock')
->first();
$warehousePreviousStock = 0;
if ($warehouseItem) {
$warehousePreviousStock = $warehouseItem->pivot->stock ?? 0;
}
if ($warehousePreviousStock < $quantity) {
throw new \Exception("Stok {$item->restockable->name} di gudang tidak mencukupi. Tersisa {$warehousePreviousStock}, diminta {$quantity}.");
}
$warehouseNewStock = $warehousePreviousStock - $quantity;
$warehouse->{$relation}()->updateExistingPivot($item->restockable_id, [
'stock' => $warehouseNewStock,
]);
// Increase outlet stock
$outletItem = $outlet->{$relation}()
->where("{$relation}.id", $item->restockable_id)
->lockForUpdate()
->withPivot('stock')
->first();
if ($outletItem) {
$outletPreviousStock = $outletItem->pivot->stock ?? 0;
$outlet->{$relation}()->updateExistingPivot($item->restockable_id, [
'stock' => $outletPreviousStock + $quantity,
]);
} else {
$outletPreviousStock = 0;
$outlet->{$relation}()->attach($item->restockable_id, [
'stock' => $quantity,
]);
}
$outletNewStock = $outletPreviousStock + $quantity;
$restock = $item->restock ?? Restock::find($item->restock_id);
if ($restock) {
StockActivityLogService::distribution(
restock: $restock,
product: $item->restockable,
quantity: $quantity,
warehousePreviousStock: $warehousePreviousStock,
warehouseNewStock: $warehouseNewStock,
outletPreviousStock: $outletPreviousStock,
outletNewStock: $outletNewStock
);
}
}
public function reverseStockTransfer($warehouse, $outlet, $item): void
{
$quantity = $item->quantity;
switch ($item->restockable_type) {
case Perfume::class:
$relation = 'perfumes';
break;
case Product::class:
$relation = 'products';
break;
case Bottle::class:
$relation = 'bottles';
break;
default:
return;
}
// Return items to Warehouse
$warehousePivot = $warehouse->{$relation}()
->where("{$relation}.id", $item->restockable_id)
->first();
$currentWarehouseStock = $warehousePivot?->pivot?->stock ?? 0;
$newWarehouseStock = $currentWarehouseStock + $quantity;
if ($warehousePivot) {
$warehouse->{$relation}()->updateExistingPivot($item->restockable_id, [
'stock' => $newWarehouseStock,
]);
} else {
$warehouse->{$relation}()->attach($item->restockable_id, [
'stock' => $quantity,
]);
}
$restock = $item->restock ?? Restock::find($item->restock_id);
if ($restock) {
StockActivityLogService::logWarehouse(
logName: StockActivityLogService::LOG_DISTRIBUTION,
event: 'increase',
description: "Restock #{$restock->hash_id} Deleted: Returned {$quantity} stock to Warehouse.",
performedOn: $item->restockable,
warehouse: $warehouse,
quantityChange: $quantity,
previousStock: $currentWarehouseStock,
newStock: $newWarehouseStock,
extraProperties: ['restock_id' => $restock->id]
);
}
// Remove items from Outlet
$outletPivot = $outlet->{$relation}()
->where("{$relation}.id", $item->restockable_id)
->first();
$currentOutletStock = $outletPivot?->pivot?->stock ?? 0;
$newOutletStock = max(0, $currentOutletStock - $quantity);
if ($outletPivot) {
$outlet->{$relation}()->updateExistingPivot($item->restockable_id, [
'stock' => $newOutletStock,
]);
}
if ($restock) {
StockActivityLogService::logOutlet(
logName: StockActivityLogService::LOG_DISTRIBUTION,
event: 'decrease',
description: "Restock #{$restock->hash_id} Deleted: Removed {$quantity} stock from Outlet.",
performedOn: $item->restockable,
outlet: $outlet,
quantityChange: -1 * abs($quantity),
previousStock: $currentOutletStock,
newStock: $newOutletStock,
extraProperties: ['restock_id' => $restock->id]
);
}
}
}