parfum/app/Traits/StockTransfer/WithStockTransferStock.php

170 lines
5.9 KiB
PHP

<?php
namespace App\Traits\StockTransfer;
use App\Models\Bottle;
use App\Models\Perfume;
use App\Models\Product;
use App\Models\StockTransfer;
use App\Services\StockActivityLogService;
trait WithStockTransferStock
{
public function transferStockBetweenOutlets($sourceOutlet, $destinationOutlet, $item): void
{
$quantity = $item->quantity;
switch ($item->transferable_type) {
case Perfume::class:
$relation = 'perfumes';
break;
case Product::class:
$relation = 'products';
break;
case Bottle::class:
$relation = 'bottles';
break;
default:
return;
}
// Decrease source outlet stock
$sourceItem = $sourceOutlet->{$relation}()
->where("{$relation}.id", $item->transferable_id)
->lockForUpdate()
->withPivot('stock')
->first();
$sourcePreviousStock = 0;
if ($sourceItem) {
$sourcePreviousStock = $sourceItem->pivot->stock ?? 0;
}
if ($sourcePreviousStock < $quantity) {
throw new \Exception("Stok {$item->transferable->name} di outlet asal tidak mencukupi. Tersisa {$sourcePreviousStock}, diminta {$quantity}.");
}
$sourceNewStock = $sourcePreviousStock - $quantity;
$sourceOutlet->{$relation}()->updateExistingPivot($item->transferable_id, [
'stock' => $sourceNewStock,
]);
// Increase destination outlet stock
$destinationItem = $destinationOutlet->{$relation}()
->where("{$relation}.id", $item->transferable_id)
->lockForUpdate()
->withPivot('stock')
->first();
if ($destinationItem) {
$destinationPreviousStock = $destinationItem->pivot->stock ?? 0;
$destinationOutlet->{$relation}()->updateExistingPivot($item->transferable_id, [
'stock' => $destinationPreviousStock + $quantity,
]);
} else {
$destinationPreviousStock = 0;
$destinationOutlet->{$relation}()->attach($item->transferable_id, [
'stock' => $quantity,
]);
}
$destinationNewStock = $destinationPreviousStock + $quantity;
$stockTransfer = $item->stockTransfer ?? StockTransfer::find($item->stock_transfer_id);
if ($stockTransfer) {
StockActivityLogService::transfer(
stockTransfer: $stockTransfer,
product: $item->transferable,
quantity: $quantity,
sourcePreviousStock: $sourcePreviousStock,
sourceNewStock: $sourceNewStock,
destinationPreviousStock: $destinationPreviousStock,
destinationNewStock: $destinationNewStock
);
}
}
public function reverseStockTransferBetweenOutlets($sourceOutlet, $destinationOutlet, $item): void
{
$quantity = $item->quantity;
switch ($item->transferable_type) {
case Perfume::class:
$relation = 'perfumes';
break;
case Product::class:
$relation = 'products';
break;
case Bottle::class:
$relation = 'bottles';
break;
default:
return;
}
// Return items to source outlet
$sourcePivot = $sourceOutlet->{$relation}()
->where("{$relation}.id", $item->transferable_id)
->first();
$currentSourceStock = $sourcePivot?->pivot?->stock ?? 0;
$newSourceStock = $currentSourceStock + $quantity;
if ($sourcePivot) {
$sourceOutlet->{$relation}()->updateExistingPivot($item->transferable_id, [
'stock' => $newSourceStock,
]);
} else {
$sourceOutlet->{$relation}()->attach($item->transferable_id, [
'stock' => $quantity,
]);
}
$stockTransfer = $item->stockTransfer ?? StockTransfer::find($item->stock_transfer_id);
if ($stockTransfer) {
StockActivityLogService::logOutlet(
logName: StockActivityLogService::LOG_TRANSFER,
event: 'increase',
description: "Transfer Stok #{$stockTransfer->hash_id} Dihapus: Mengembalikan {$quantity} stok ke outlet asal.",
performedOn: $item->transferable,
outlet: $sourceOutlet,
quantityChange: $quantity,
previousStock: $currentSourceStock,
newStock: $newSourceStock,
extraProperties: ['stock_transfer_id' => $stockTransfer->id]
);
}
// Remove items from destination outlet
$destinationPivot = $destinationOutlet->{$relation}()
->where("{$relation}.id", $item->transferable_id)
->first();
$currentDestinationStock = $destinationPivot?->pivot?->stock ?? 0;
$newDestinationStock = max(0, $currentDestinationStock - $quantity);
if ($destinationPivot) {
$destinationOutlet->{$relation}()->updateExistingPivot($item->transferable_id, [
'stock' => $newDestinationStock,
]);
}
if ($stockTransfer) {
StockActivityLogService::logOutlet(
logName: StockActivityLogService::LOG_TRANSFER,
event: 'decrease',
description: "Transfer Stok #{$stockTransfer->hash_id} Dihapus: Menghapus {$quantity} stok dari outlet tujuan.",
performedOn: $item->transferable,
outlet: $destinationOutlet,
quantityChange: -1 * abs($quantity),
previousStock: $currentDestinationStock,
newStock: $newDestinationStock,
extraProperties: ['stock_transfer_id' => $stockTransfer->id]
);
}
}
}