76 lines
2.7 KiB
PHP
76 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Concerns;
|
|
|
|
use App\Enums\ProductStockQuality;
|
|
use App\Models\ProductVariant;
|
|
use App\Services\StockMutationService;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
trait HasStockAdjustment
|
|
{
|
|
private const QUALITY_STOCK_MAP = [
|
|
ProductStockQuality::GOOD->value => 'stock',
|
|
ProductStockQuality::REJECT->value => 'reject_stock',
|
|
ProductStockQuality::RETAIL->value => 'retail_stock',
|
|
];
|
|
|
|
private function adjustStock(Model $model, string $field, int $quantity, int $sign, ?Model $source = null, ?string $description = null): void
|
|
{
|
|
$before = (int) $model->{$field};
|
|
|
|
if ($sign > 0) {
|
|
$model->increment($field, $quantity);
|
|
} else {
|
|
if ($before < $quantity) {
|
|
$label = match ($field) {
|
|
'stock' => 'stok bagus',
|
|
'reject_stock' => 'stok reject',
|
|
'retail_stock' => 'stok ecer',
|
|
default => $field,
|
|
};
|
|
throw ValidationException::withMessages([
|
|
'stock' => "Stok {$label} tidak mencukupi. Tersedia: {$model->{$field}}, dibutuhkan: {$quantity}.",
|
|
]);
|
|
}
|
|
$model->decrement($field, $quantity);
|
|
}
|
|
|
|
app(StockMutationService::class)->record(
|
|
model: $model,
|
|
type: $sign > 0 ? 'in' : 'out',
|
|
quantity: $sign * $quantity,
|
|
stockBefore: $before,
|
|
stockAfter: $before + ($sign * $quantity),
|
|
stockQuality: StockMutationService::qualityFromField($field),
|
|
description: $description ?? 'Perubahan stok',
|
|
source: $source,
|
|
);
|
|
}
|
|
|
|
private function adjustVariantStock(int $variantId, int $quantity, int $sign, string $stockType, ?Model $source = null, ?string $description = null): void
|
|
{
|
|
$field = self::QUALITY_STOCK_MAP[$stockType] ?? 'stock';
|
|
|
|
$this->adjustStock(
|
|
model: app(ProductVariant::class)->newQuery()->findOrFail($variantId),
|
|
field: $field,
|
|
quantity: $quantity,
|
|
sign: $sign,
|
|
source: $source,
|
|
description: $description,
|
|
);
|
|
}
|
|
|
|
private function applyStock(array $items, string $stockType, int $sign, ?Model $source = null, ?string $description = null): void
|
|
{
|
|
DB::transaction(function () use ($items, $stockType, $sign, $source, $description) {
|
|
foreach ($items as $item) {
|
|
$this->adjustVariantStock($item['product_variant_id'], $item['quantity'], $sign, $stockType, $source, $description);
|
|
}
|
|
});
|
|
}
|
|
}
|