feat: add checkVariantUsage endpoint and implement price usage validation in RawMaterial management

This commit is contained in:
Yoga Pangestu 2026-07-27 19:02:54 +07:00
parent fa52f177e2
commit 562c5721dd
4 changed files with 76 additions and 1 deletions

View File

@ -5,9 +5,11 @@
use App\Enums\RawMaterialUnit;
use App\Http\Controllers\Concerns\FlashesEntityMessage;
use App\Http\Controllers\Concerns\ParsesDataTableQuery;
use App\Enums\CuttingStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Master\RawMaterialRequest;
use App\Http\Requests\Admin\ToggleStatusRequest;
use App\Models\CuttingMaterial;
use App\Models\RawMaterial;
use App\Services\Master\RawMaterialService;
use App\Support\Media\MediaPresenter;
@ -84,6 +86,27 @@ public function destroy(Request $request, RawMaterial $rawMaterial): RedirectRes
return redirect()->route('admin.master.raw_materials.index');
}
public function checkVariantUsage(Request $request): JsonResponse
{
$priceIds = $request->query('price_ids', []);
if (! is_array($priceIds) || $priceIds === []) {
return response()->json(['in_use' => []]);
}
$priceIds = array_map('intval', $priceIds);
$inUse = CuttingMaterial::query()
->whereIn('raw_material_price_id', $priceIds)
->whereHas('cutting', fn ($q) => $q->where('status', '!=', CuttingStatus::COMPLETED))
->pluck('raw_material_price_id')
->unique()
->values()
->toArray();
return response()->json(['in_use' => $inUse]);
}
public function toggleStatus(ToggleStatusRequest $request, RawMaterial $rawMaterial): RedirectResponse
{
$this->rawMaterialService->toggleStatus($rawMaterial, $request->validated(), $request->user());

View File

@ -313,6 +313,27 @@ private function ensureNotUsedInActiveCutting(RawMaterial $rawMaterial): void
}
}
private function ensurePricesNotUsedInActiveCutting(array $priceIds): void
{
$usedPriceIds = CuttingMaterial::query()
->whereIn('raw_material_price_id', $priceIds)
->whereHas('cutting', fn ($q) => $q->where('status', '!=', CuttingStatus::COMPLETED))
->pluck('raw_material_price_id')
->unique()
->toArray();
if ($usedPriceIds !== []) {
$variantNames = RawMaterialPrice::whereIn('id', $usedPriceIds)
->pluck('variant')
->unique()
->implode(', ');
throw ValidationException::withMessages([
'prices' => "Variant '{$variantNames}' tidak dapat dihapus karena masih digunakan dalam proses cutting yang belum selesai.",
]);
}
}
public function applyToggleStatus(OwnerVerificationRequest $verificationRequest): void
{
$rawMaterial = $verificationRequest->subject;
@ -353,6 +374,15 @@ private function applyPayloadToRawMaterial(
->map(fn ($id) => (int) $id)
->all();
$deletingPriceIds = $rawMaterial->prices()
->whereNotIn('id', $submittedPriceIds)
->pluck('id')
->toArray();
if ($deletingPriceIds !== []) {
$this->ensurePricesNotUsedInActiveCutting($deletingPriceIds);
}
$rawMaterial->prices()
->whereNotIn('id', $submittedPriceIds)
->get()

View File

@ -94,7 +94,23 @@ const useSamePrice = ref(prices.value.length <= 1 || allPricesHaveSameValue());
const showDeleteConfirm = ref(false);
const priceToDelete = ref<string | null>(null);
function confirmRemovePrice(clientId: string) {
async function confirmRemovePrice(clientId: string) {
const price = prices.value.find((p) => p.client_id === clientId);
if (price?.id) {
try {
const res = await fetch(`/admin/master/raw-materials/check-variant-usage?price_ids[]=${price.id}`);
const data: { in_use: number[] } = await res.json();
if (data.in_use?.includes(price.id)) {
toast.error(`Varian "${price.variant}" tidak dapat dihapus karena masih digunakan dalam proses cutting yang belum selesai.`);
return;
}
} catch {
// proceed to confirm dialog if check fails
}
}
priceToDelete.value = clientId;
showDeleteConfirm.value = true;
}
@ -223,6 +239,9 @@ function submit() {
if (errors.system) {
toast.error(errors.system);
}
if (errors.prices) {
toast.error(errors.prices);
}
},
});
}

View File

@ -146,6 +146,9 @@
Route::prefix('raw-materials')->name('raw_materials.')
->middleware('permission:'.Permission::RAW_MATERIALS_VIEW->value)
->group(function () {
Route::get('check-variant-usage', [RawMaterialController::class, 'checkVariantUsage'])
->name('check_variant_usage');
Route::get('create', [RawMaterialController::class, 'create'])
->middleware('permission:'.Permission::RAW_MATERIALS_CREATE->value)
->name('create');