store/app/Services/Manage/RetailStockService.php

91 lines
3.0 KiB
PHP

<?php
namespace App\Services\Manage;
use App\Models\ProductVariant;
use App\Models\RetailStockHistory;
use App\Models\User;
use App\Services\System\PushNotificationService;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
class RetailStockService
{
public function __construct(
private readonly PushNotificationService $pushNotificationService,
) {}
public function transfer(int $variantId, int $quantity, User $user, ?string $notes = null): void
{
if ($quantity <= 0) {
throw ValidationException::withMessages([
'quantity' => 'Jumlah harus lebih dari 0.',
]);
}
$variant = ProductVariant::query()->with('product')->findOrFail($variantId);
if ($variant->stock < $quantity) {
throw ValidationException::withMessages([
'quantity' => "Stok bagus tidak mencukupi. Stok saat ini: {$variant->stock} pcs.",
]);
}
$this->executeTransfer($variant, $quantity, $user, $notes);
$this->pushNotificationService->sendToRoles(
'📦 Perubahan Stok Ecer',
"Perubahan {$quantity} pcs stok ecer untuk varian '{$variant->name}' telah diterapkan.",
['owner', 'developer', 'direktur'],
route('admin.master.products.index', ['search_id' => $variant->product_id]),
);
}
public function applyRetailStockTransfer(OwnerVerificationRequest $request): void
{
$payload = $request->payload ?? [];
$newData = $payload['new'] ?? [];
$quantity = (int) ($newData['quantity'] ?? 0);
if ($quantity <= 0) {
return;
}
$variant = ProductVariant::query()->find($request->subject_id);
if (! $variant) {
return;
}
$this->executeTransfer($variant, $quantity, $request->submittedBy, $newData['notes'] ?? null);
}
private function executeTransfer(ProductVariant $variant, int $quantity, User $user, ?string $notes = null): void
{
DB::transaction(function () use ($variant, $quantity, $user, $notes): void {
$variant = ProductVariant::query()
->whereKey($variant->id)
->lockForUpdate()
->firstOrFail();
$stockBefore = $variant->stock;
$retailStockBefore = $variant->retail_stock;
$variant->decrement('stock', $quantity);
$variant->increment('retail_stock', $quantity);
RetailStockHistory::create([
'product_variant_id' => $variant->id,
'user_id' => $user->id,
'quantity' => $quantity,
'stock_before' => $stockBefore,
'retail_stock_before' => $retailStockBefore,
'stock_after' => $stockBefore - $quantity,
'retail_stock_after' => $retailStockBefore + $quantity,
'notes' => $notes,
'created_at' => now(),
]);
});
}
}