refactor: rename 'hasil_cutting_diluar_sampel' to 'original_outside_sample' across models, requests, and UI components for consistency and clarity in cutting results management

This commit is contained in:
Yoga Pangestu 2026-06-29 08:36:24 +07:00
parent c3c25679be
commit b4e93fa329
20 changed files with 98 additions and 151 deletions

View File

@ -26,7 +26,7 @@ public function rules(): array
], ],
'cutting_result' => ['required', 'integer', 'min:1'], 'cutting_result' => ['required', 'integer', 'min:1'],
'sampel' => ['required', 'integer', 'min:0'], 'sampel' => ['required', 'integer', 'min:0'],
'hasil_cutting_diluar_sampel' => ['required', 'integer', 'min:0'], 'original_outside_sample' => ['required', 'integer', 'min:0'],
]; ];
} }
} }

View File

@ -50,7 +50,7 @@ public function rules(): array
]; ];
$rules['results.*.cutting_result'] = ['required', 'integer', 'min:1']; $rules['results.*.cutting_result'] = ['required', 'integer', 'min:1'];
$rules['results.*.sampel'] = ['required', 'integer', 'min:0']; $rules['results.*.sampel'] = ['required', 'integer', 'min:0'];
$rules['results.*.hasil_cutting_diluar_sampel'] = ['required', 'integer', 'min:0']; $rules['results.*.original_outside_sample'] = ['required', 'integer', 'min:0'];
} }
return $rules; return $rules;
@ -70,7 +70,7 @@ public function attributes(): array
'results.*.product_variant_id' => 'Varian Produk', 'results.*.product_variant_id' => 'Varian Produk',
'results.*.cutting_result' => 'Hasil', 'results.*.cutting_result' => 'Hasil',
'results.*.sampel' => 'Sampel', 'results.*.sampel' => 'Sampel',
'results.*.hasil_cutting_diluar_sampel' => 'Diluar Sampel', 'results.*.original_outside_sample' => 'Diluar Sampel',
'sewing_cost' => 'Jasa Jahit', 'sewing_cost' => 'Jasa Jahit',
'other_cost' => 'Biaya Lainnya', 'other_cost' => 'Biaya Lainnya',
]; ];

View File

@ -48,7 +48,7 @@ public function rules(): array
'results' => ['nullable', 'array'], 'results' => ['nullable', 'array'],
'results.*.product_variant_id' => ['required_with:results', 'integer', 'exists:product_variants,id'], 'results.*.product_variant_id' => ['required_with:results', 'integer', 'exists:product_variants,id'],
'results.*.sampel' => ['required_with:results', 'integer', 'min:0'], 'results.*.sampel' => ['required_with:results', 'integer', 'min:0'],
'results.*.hasil_cutting_diluar_sampel' => ['required_with:results', 'integer', 'min:0'], 'results.*.original_outside_sample' => ['required_with:results', 'integer', 'min:0'],
'result_prices' => ['nullable', 'array'], 'result_prices' => ['nullable', 'array'],
'result_prices.*.product_variant_id' => ['required_with:result_prices', 'integer', 'exists:product_variants,id'], 'result_prices.*.product_variant_id' => ['required_with:result_prices', 'integer', 'exists:product_variants,id'],
'result_prices.*.prices' => ['required_with:result_prices', 'array', 'min:1'], 'result_prices.*.prices' => ['required_with:result_prices', 'array', 'min:1'],
@ -102,7 +102,7 @@ public function withValidator(Validator $validator): void
foreach ($this->input('results', []) as $index => $item) { foreach ($this->input('results', []) as $index => $item) {
$variantId = $item['product_variant_id'] ?? 0; $variantId = $item['product_variant_id'] ?? 0;
$sampel = (int) ($item['sampel'] ?? 0); $sampel = (int) ($item['sampel'] ?? 0);
$hasilCuttingDiluarSampel = (int) ($item['hasil_cutting_diluar_sampel'] ?? 0); $hasilCuttingDiluarSampel = (int) ($item['original_outside_sample'] ?? 0);
$originalResult = $cuttingResults->get($variantId); $originalResult = $cuttingResults->get($variantId);
if ($originalResult === null) { if ($originalResult === null) {

View File

@ -20,7 +20,7 @@ protected function casts(): array
{ {
return [ return [
'cutting_result' => 'integer', 'cutting_result' => 'integer',
'hasil_cutting_diluar_sampel' => 'integer', 'original_outside_sample' => 'integer',
'sampel' => 'integer', 'sampel' => 'integer',
]; ];
} }

View File

@ -286,7 +286,7 @@ public function syncDraftResult(array $validated, User $user): array
$cuttingResult = (int) $validated['cutting_result']; $cuttingResult = (int) $validated['cutting_result'];
$sampel = (int) $validated['sampel']; $sampel = (int) $validated['sampel'];
$hasilCuttingDiluarSampel = (int) ($validated['hasil_cutting_diluar_sampel'] ?? 0); $hasilCuttingDiluarSampel = (int) ($validated['original_outside_sample'] ?? 0);
if ($cuttingResult < 1) { if ($cuttingResult < 1) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
@ -302,7 +302,7 @@ public function syncDraftResult(array $validated, User $user): array
if ($hasilCuttingDiluarSampel < 0) { if ($hasilCuttingDiluarSampel < 0) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'hasil_cutting_diluar_sampel' => 'Hasil cutting diluar sampel tidak boleh negatif.', 'original_outside_sample' => 'Hasil cutting diluar sampel tidak boleh negatif.',
]); ]);
} }
@ -321,7 +321,7 @@ public function syncDraftResult(array $validated, User $user): array
[ [
'cutting_result' => $cuttingResult, 'cutting_result' => $cuttingResult,
'sampel' => $sampel, 'sampel' => $sampel,
'hasil_cutting_diluar_sampel' => $hasilCuttingDiluarSampel, 'original_outside_sample' => $hasilCuttingDiluarSampel,
], ],
); );
@ -574,7 +574,7 @@ public function transitionStatus(
->where('product_variant_id', $item['product_variant_id']) ->where('product_variant_id', $item['product_variant_id'])
->update([ ->update([
'sampel' => $item['sampel'], 'sampel' => $item['sampel'],
'hasil_cutting_diluar_sampel' => $item['hasil_cutting_diluar_sampel'], 'original_outside_sample' => $item['original_outside_sample'],
]); ]);
} }
$cutting->load('results'); $cutting->load('results');
@ -678,7 +678,7 @@ private function buildResults(array $results): array
$cuttingResult = (int) $itemData['cutting_result']; $cuttingResult = (int) $itemData['cutting_result'];
$sampel = (int) $itemData['sampel']; $sampel = (int) $itemData['sampel'];
$hasilCuttingDiluarSampel = (int) ($itemData['hasil_cutting_diluar_sampel'] ?? 0); $hasilCuttingDiluarSampel = (int) ($itemData['original_outside_sample'] ?? 0);
if ($cuttingResult < 1) { if ($cuttingResult < 1) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
@ -694,7 +694,7 @@ private function buildResults(array $results): array
if ($hasilCuttingDiluarSampel < 0) { if ($hasilCuttingDiluarSampel < 0) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
"results.{$index}.hasil_cutting_diluar_sampel" => 'Hasil cutting diluar sampel tidak boleh negatif.', "results.{$index}.original_outside_sample" => 'Hasil cutting diluar sampel tidak boleh negatif.',
]); ]);
} }
@ -708,7 +708,7 @@ private function buildResults(array $results): array
'product_variant_id' => $variant->id, 'product_variant_id' => $variant->id,
'cutting_result' => $cuttingResult, 'cutting_result' => $cuttingResult,
'sampel' => $sampel, 'sampel' => $sampel,
'hasil_cutting_diluar_sampel' => $hasilCuttingDiluarSampel, 'original_outside_sample' => $hasilCuttingDiluarSampel,
]; ];
}) })
->all(); ->all();
@ -763,10 +763,10 @@ private function applyProductStockOnVerify(Cutting $cutting): void
->increment('stock', $result->sampel); ->increment('stock', $result->sampel);
} }
if ($result->hasil_cutting_diluar_sampel > 0) { if ($result->original_outside_sample > 0) {
ProductVariant::query() ProductVariant::query()
->whereKey($result->product_variant_id) ->whereKey($result->product_variant_id)
->increment('reject_stock', $result->hasil_cutting_diluar_sampel); ->increment('reject_stock', $result->original_outside_sample);
} }
} }
} }
@ -780,10 +780,10 @@ private function reverseProductStock(Cutting $cutting): void
->decrement('stock', $result->sampel); ->decrement('stock', $result->sampel);
} }
if ($result->hasil_cutting_diluar_sampel > 0) { if ($result->original_outside_sample > 0) {
ProductVariant::query() ProductVariant::query()
->whereKey($result->product_variant_id) ->whereKey($result->product_variant_id)
->decrement('reject_stock', $result->hasil_cutting_diluar_sampel); ->decrement('reject_stock', $result->original_outside_sample);
} }
} }
} }
@ -881,7 +881,7 @@ private function presentDraftResult(CuttingResult $item): array
'stock' => $variant?->stock ?? 0, 'stock' => $variant?->stock ?? 0,
'cutting_result' => (string) $item->cutting_result, 'cutting_result' => (string) $item->cutting_result,
'sampel' => (string) $item->sampel, 'sampel' => (string) $item->sampel,
'hasil_cutting_diluar_sampel' => (string) $item->hasil_cutting_diluar_sampel, 'original_outside_sample' => (string) $item->original_outside_sample,
'images' => $variant ? MediaPresenter::collection($variant, 'images') : [], 'images' => $variant ? MediaPresenter::collection($variant, 'images') : [],
]; ];
} }

View File

@ -85,7 +85,7 @@ public function submitVerification(
->where('product_variant_id', $item['product_variant_id']) ->where('product_variant_id', $item['product_variant_id'])
->update([ ->update([
'sampel' => $item['good'], 'sampel' => $item['good'],
'hasil_cutting_diluar_sampel' => $item['reject'], 'original_outside_sample' => $item['reject'],
]); ]);
} }
$cutting->load('results'); $cutting->load('results');
@ -255,10 +255,10 @@ private function applyProductStockOnVerify(Cutting $cutting): void
->increment('stock', $result->sampel); ->increment('stock', $result->sampel);
} }
if ($result->hasil_cutting_diluar_sampel > 0) { if ($result->original_outside_sample > 0) {
ProductVariant::query() ProductVariant::query()
->whereKey($result->product_variant_id) ->whereKey($result->product_variant_id)
->increment('reject_stock', $result->hasil_cutting_diluar_sampel); ->increment('reject_stock', $result->original_outside_sample);
} }
} }
} }

View File

@ -22,7 +22,7 @@ public function definition(): array
'product_variant_id' => ProductVariant::factory(), 'product_variant_id' => ProductVariant::factory(),
'cutting_result' => $cuttingResult, 'cutting_result' => $cuttingResult,
'sampel' => $cuttingResult - $hasilCuttingDiluarSampel, 'sampel' => $cuttingResult - $hasilCuttingDiluarSampel,
'hasil_cutting_diluar_sampel' => $hasilCuttingDiluarSampel, 'original_outside_sample' => $hasilCuttingDiluarSampel,
]; ];
} }
} }

View File

@ -17,7 +17,7 @@ public function up(): void
$table->unsignedInteger('cutting_result'); $table->unsignedInteger('cutting_result');
$table->unsignedInteger('sampel'); $table->unsignedInteger('sampel');
$table->unsignedInteger('hasil_cutting_diluar_sampel')->default(0); $table->unsignedInteger('original_outside_sample')->default(0);
$table->timestamp('created_at')->useCurrent(); $table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate(); $table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();

View File

@ -39,19 +39,18 @@ const initialData = computed(() => ({
stock: item.product_variant?.stock ?? 0, stock: item.product_variant?.stock ?? 0,
cutting_result: String(item.cutting_result), cutting_result: String(item.cutting_result),
sampel: String(item.sampel), sampel: String(item.sampel),
hasil_cutting_diluar_sampel: String(item.hasil_cutting_diluar_sampel), original_outside_sample: String(item.original_outside_sample),
images: item.product_variant?.images ?? [], images: item.product_variant?.images ?? [],
})), })),
})); }));
</script> </script>
<template> <template>
<Head title="Ubah Cutting" /> <Head title="Ubah Cutting" />
<AdminLayout> <AdminLayout>
<div <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"
>
<div class="space-y-1"> <div class="space-y-1">
<h2 class="text-2xl font-bold tracking-tight">Ubah Cutting</h2> <h2 class="text-2xl font-bold tracking-tight">Ubah Cutting</h2>
</div> </div>
@ -59,13 +58,8 @@ const initialData = computed(() => ({
<BackButton :href="index.url()" /> <BackButton :href="index.url()" />
</div> </div>
<CuttingPosForm <CuttingPosForm :raw-material-catalog="rawMaterialCatalog" :product-catalog="productCatalog"
:raw-material-catalog="rawMaterialCatalog" :initial-data="initialData" :submit-url="update.url(props.cutting.id)" method="put"
:product-catalog="productCatalog" submit-label="Perbarui" />
:initial-data="initialData"
:submit-url="update.url(props.cutting.id)"
method="put"
submit-label="Perbarui"
/>
</AdminLayout> </AdminLayout>
</template> </template>

View File

@ -28,11 +28,8 @@ const open = defineModel<boolean>('open', { required: true });
<div v-if="materialCart.length > 0"> <div v-if="materialCart.length > 0">
<p class="mb-2 text-xs font-medium text-muted-foreground">Bahan Baku</p> <p class="mb-2 text-xs font-medium text-muted-foreground">Bahan Baku</p>
<div class="space-y-2"> <div class="space-y-2">
<div <div v-for="item in materialCart" :key="`detail-mat-${item.raw_material_price_id}`"
v-for="item in materialCart" class="rounded-lg border p-3">
:key="`detail-mat-${item.raw_material_price_id}`"
class="rounded-lg border p-3"
>
<div class="flex items-start justify-between gap-2"> <div class="flex items-start justify-between gap-2">
<div class="min-w-0"> <div class="min-w-0">
<p class="truncate text-sm font-medium">{{ item.raw_material_name }}</p> <p class="truncate text-sm font-medium">{{ item.raw_material_name }}</p>
@ -45,7 +42,8 @@ const open = defineModel<boolean>('open', { required: true });
</span> </span>
</div> </div>
<div class="mt-1.5 flex items-center justify-between gap-2 text-xs text-muted-foreground"> <div class="mt-1.5 flex items-center justify-between gap-2 text-xs text-muted-foreground">
<span class="font-medium text-foreground">{{ formatRupiah(materialLineCost(item)) }}</span> <span class="font-medium text-foreground">{{ formatRupiah(materialLineCost(item))
}}</span>
</div> </div>
</div> </div>
</div> </div>
@ -53,11 +51,8 @@ const open = defineModel<boolean>('open', { required: true });
<div v-if="resultCart.length > 0"> <div v-if="resultCart.length > 0">
<p class="mb-2 text-xs font-medium text-muted-foreground">Hasil Produk</p> <p class="mb-2 text-xs font-medium text-muted-foreground">Hasil Produk</p>
<div class="space-y-2"> <div class="space-y-2">
<div <div v-for="item in resultCart" :key="`detail-res-${item.product_variant_id}`"
v-for="item in resultCart" class="rounded-lg border p-3">
:key="`detail-res-${item.product_variant_id}`"
class="rounded-lg border p-3"
>
<div class="flex items-start justify-between gap-2"> <div class="flex items-start justify-between gap-2">
<div class="min-w-0"> <div class="min-w-0">
<p class="truncate text-sm font-medium">{{ item.product_name }}</p> <p class="truncate text-sm font-medium">{{ item.product_name }}</p>
@ -71,7 +66,7 @@ const open = defineModel<boolean>('open', { required: true });
<span class="text-muted-foreground">·</span> <span class="text-muted-foreground">·</span>
<span>Sampel: <strong>{{ item.sampel }}</strong></span> <span>Sampel: <strong>{{ item.sampel }}</strong></span>
<span class="text-muted-foreground">·</span> <span class="text-muted-foreground">·</span>
<span>Diluar Sampel: <strong>{{ item.hasil_cutting_diluar_sampel }}</strong></span> <span>Diluar Sampel: <strong>{{ item.original_outside_sample }}</strong></span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -100,7 +100,7 @@ function buildPayload() {
product_variant_id: item.product_variant_id, product_variant_id: item.product_variant_id,
cutting_result: item.cutting_result, cutting_result: item.cutting_result,
sampel: item.sampel, sampel: item.sampel,
hasil_cutting_diluar_sampel: item.hasil_cutting_diluar_sampel, original_outside_sample: item.original_outside_sample,
})); }));
} }
@ -147,44 +147,22 @@ function submit() {
<template> <template>
<div class="grid gap-4 xl:grid-cols-[1fr_400px]"> <div class="grid gap-4 xl:grid-cols-[1fr_400px]">
<div class="space-y-4"> <div class="space-y-4">
<CuttingPosMaterialCatalogPanel <CuttingPosMaterialCatalogPanel v-model:material-search="materialSearch"
v-model:material-search="materialSearch" :filtered-raw-materials="filteredRawMaterials" :get-material-cart-item="getMaterialCartItem"
:filtered-raw-materials="filteredRawMaterials" @add-material="addMaterial" @decrease-material-qty="decreaseMaterialQty" />
:get-material-cart-item="getMaterialCartItem"
@add-material="addMaterial"
@decrease-material-qty="decreaseMaterialQty"
/>
<CuttingPosResultCatalogPanel <CuttingPosResultCatalogPanel v-model:product-search="productSearch" :filtered-products="filteredProducts"
v-model:product-search="productSearch" :get-result-cart-item="getResultCartItem" @add-result="addResult"
:filtered-products="filteredProducts" @decrease-result-qty="decreaseResultQty" />
:get-result-cart-item="getResultCartItem"
@add-result="addResult"
@decrease-result-qty="decreaseResultQty"
/>
</div> </div>
<CuttingPosSummaryPanel <CuttingPosSummaryPanel :form="form" :material-cart="materialCart" :result-cart="resultCart"
:form="form" :total-result-pieces="totalResultPieces" :submit-label="submitLabel" @submit="submit"
:material-cart="materialCart" @open-detail="cartDetailOpen = true" @remove-material="removeMaterial"
:result-cart="resultCart" @sync-material-field="syncMaterialField" @remove-result="removeResult"
:total-result-pieces="totalResultPieces" @sync-result-totals="syncResultTotals" @sync-result-field="syncResultField" />
:submit-label="submitLabel"
@submit="submit"
@open-detail="cartDetailOpen = true"
@remove-material="removeMaterial"
@sync-material-field="syncMaterialField"
@remove-result="removeResult"
@sync-result-totals="syncResultTotals"
@sync-result-field="syncResultField"
/>
</div> </div>
<CuttingPosCartDetailDialog <CuttingPosCartDetailDialog v-model:open="cartDetailOpen" :material-cart="materialCart" :result-cart="resultCart"
v-model:open="cartDetailOpen" :material-line-cost="materialLineCost" :total-material-cost="totalMaterialCost" />
:material-cart="materialCart"
:result-cart="resultCart"
:material-line-cost="materialLineCost"
:total-material-cost="totalMaterialCost"
/>
</template> </template>

View File

@ -30,19 +30,13 @@ const emit = defineEmits<{
</Badge> </Badge>
</div> </div>
<div <div v-if="resultCart.length === 0"
v-if="resultCart.length === 0" class="rounded-lg border border-dashed px-4 py-6 text-center text-sm text-muted-foreground">
class="rounded-lg border border-dashed px-4 py-6 text-center text-sm text-muted-foreground"
>
Belum ada produk hasil dipilih. Belum ada produk hasil dipilih.
</div> </div>
<div v-else class="scrollbar-thin max-h-80 space-y-3 overflow-y-auto overscroll-y-contain"> <div v-else class="scrollbar-thin max-h-80 space-y-3 overflow-y-auto overscroll-y-contain">
<div <div v-for="(item, index) in resultCart" :key="item.product_variant_id" class="rounded-lg border p-3">
v-for="(item, index) in resultCart"
:key="item.product_variant_id"
class="rounded-lg border p-3"
>
<div class="mb-2 flex items-start justify-between gap-2"> <div class="mb-2 flex items-start justify-between gap-2">
<div class="min-w-0"> <div class="min-w-0">
<p class="truncate text-sm font-medium"> <p class="truncate text-sm font-medium">
@ -52,13 +46,8 @@ const emit = defineEmits<{
{{ item.variant_name }} · Stok {{ item.stock }} pcs {{ item.variant_name }} · Stok {{ item.stock }} pcs
</p> </p>
</div> </div>
<Button <Button type="button" variant="ghost" size="icon"
type="button" class="size-7 shrink-0 text-destructive hover:text-destructive" @click="emit('remove', index)">
variant="ghost"
size="icon"
class="size-7 shrink-0 text-destructive hover:text-destructive"
@click="emit('remove', index)"
>
<Trash2 class="size-3.5" /> <Trash2 class="size-3.5" />
</Button> </Button>
</div> </div>
@ -66,23 +55,17 @@ const emit = defineEmits<{
<div class="grid grid-cols-3 gap-2"> <div class="grid grid-cols-3 gap-2">
<Field> <Field>
<FieldLabel class="text-xs">Hasil</FieldLabel> <FieldLabel class="text-xs">Hasil</FieldLabel>
<NumberInput <NumberInput v-model="item.cutting_result" class="h-8"
v-model="item.cutting_result" @change="emit('sync-totals', item); emit('sync-field', index)" />
class="h-8"
@change="emit('sync-totals', item); emit('sync-field', index)"
/>
</Field> </Field>
<Field> <Field>
<FieldLabel class="text-xs">Sampel</FieldLabel> <FieldLabel class="text-xs">Sampel</FieldLabel>
<NumberInput <NumberInput v-model="item.sampel" class="h-8"
v-model="item.sampel" @change="emit('sync-totals', item); emit('sync-field', index)" />
class="h-8"
@change="emit('sync-totals', item); emit('sync-field', index)"
/>
</Field> </Field>
<Field> <Field>
<FieldLabel class="text-xs">Diluar Sampel</FieldLabel> <FieldLabel class="text-xs">Diluar Sampel</FieldLabel>
<NumberInput v-model="item.hasil_cutting_diluar_sampel" class="h-8" /> <NumberInput v-model="item.original_outside_sample" class="h-8" />
</Field> </Field>
</div> </div>
</div> </div>

View File

@ -187,7 +187,7 @@ export function useCuttingPosCart(options: {
product_variant_id: variant.id, product_variant_id: variant.id,
cutting_result: cuttingResult, cutting_result: cuttingResult,
sampel, sampel,
hasil_cutting_diluar_sampel: hasilCuttingDiluarSampel, original_outside_sample: hasilCuttingDiluarSampel,
}), }),
}); });
@ -206,7 +206,7 @@ export function useCuttingPosCart(options: {
product_variant_id: variantId, product_variant_id: variantId,
cutting_result: cuttingResult, cutting_result: cuttingResult,
sampel, sampel,
hasil_cutting_diluar_sampel: hasilCuttingDiluarSampel, original_outside_sample: hasilCuttingDiluarSampel,
}), }),
}); });
@ -225,7 +225,7 @@ export function useCuttingPosCart(options: {
const total = Number(item.cutting_result) || 0; const total = Number(item.cutting_result) || 0;
const sampel = Number(item.sampel) || 0; const sampel = Number(item.sampel) || 0;
item.hasil_cutting_diluar_sampel = String(Math.max(total - sampel, 0)); item.original_outside_sample = String(Math.max(total - sampel, 0));
} }
async function removeMaterial(index: number) { async function removeMaterial(index: number) {
@ -414,7 +414,7 @@ export function useCuttingPosCart(options: {
stock: variant.stock, stock: variant.stock,
cutting_result: '1', cutting_result: '1',
sampel: '1', sampel: '1',
hasil_cutting_diluar_sampel: '0', original_outside_sample: '0',
images: variant.images ?? [], images: variant.images ?? [],
}); });
} }
@ -445,7 +445,7 @@ export function useCuttingPosCart(options: {
item.product_variant_id, item.product_variant_id,
item.cutting_result, item.cutting_result,
item.sampel, item.sampel,
item.hasil_cutting_diluar_sampel, item.original_outside_sample,
); );
} catch (error) { } catch (error) {
toast.error(error instanceof Error ? error.message : 'Gagal memperbarui item.'); toast.error(error instanceof Error ? error.message : 'Gagal memperbarui item.');

View File

@ -133,7 +133,9 @@ function getGroupedResults(results: any[]): GroupedCuttingResults[] {
<div class="flex flex-wrap gap-x-4 gap-y-1 text-sm"> <div class="flex flex-wrap gap-x-4 gap-y-1 text-sm">
<span>Total Hasil Cutting <strong class="text-primary">{{ cutting.total_result_pieces ?? <span>Total Hasil Cutting <strong class="text-primary">{{ cutting.total_result_pieces ??
0 }} pcs</strong></span> 0 }} pcs</strong></span>
<span v-if="cutting.total_material_usage_summary_formatted">Total Pemakaian Bahan <strong class="text-primary">{{ cutting.total_material_usage_summary_formatted }}</strong></span> <span v-if="cutting.total_material_usage_summary_formatted">Total Pemakaian Bahan
<strong class="text-primary">{{ cutting.total_material_usage_summary_formatted
}}</strong></span>
<span>Biaya Bahan <strong class="text-primary">{{ <span>Biaya Bahan <strong class="text-primary">{{
cutting.total_material_cost_formatted ?? 'Rp 0' }}</strong></span> cutting.total_material_cost_formatted ?? 'Rp 0' }}</strong></span>
</div> </div>
@ -223,7 +225,7 @@ function getGroupedResults(results: any[]): GroupedCuttingResults[] {
{{ result.sampel }} pcs {{ result.sampel }} pcs
</TableCell> </TableCell>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ result.hasil_cutting_diluar_sampel }} pcs {{ result.original_outside_sample }} pcs
</TableCell> </TableCell>
</TableRow> </TableRow>
</template> </template>
@ -237,10 +239,6 @@ function getGroupedResults(results: any[]): GroupedCuttingResults[] {
<DataTableEmpty v-else description="Silakan lakukan pencarian untuk menemukan data yang Anda cari." /> <DataTableEmpty v-else description="Silakan lakukan pencarian untuk menemukan data yang Anda cari." />
<GroupedTableFooter <GroupedTableFooter :summary="paginationSummary" :pagination="pagination" :pagination-links="paginationLinks" />
:summary="paginationSummary"
:pagination="pagination"
:pagination-links="paginationLinks"
/>
</div> </div>
</template> </template>

View File

@ -50,9 +50,9 @@ const verifyForm = useForm({
name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`, name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`,
cutting_result: res.cutting_result, cutting_result: res.cutting_result,
sampel: res.sampel, sampel: res.sampel,
hasil_cutting_diluar_sampel: res.hasil_cutting_diluar_sampel, original_outside_sample: res.original_outside_sample,
original_sampel: res.sampel, original_sampel: res.sampel,
original_hasil_cutting_diluar_sampel: res.hasil_cutting_diluar_sampel, original_original_outside_sample: res.original_outside_sample,
prices: buildEmptyPrices(), prices: buildEmptyPrices(),
})), })),
result_prices: [] as Array<{ result_prices: [] as Array<{
@ -70,9 +70,9 @@ watch(open, (isOpen) => {
name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`, name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`,
cutting_result: res.cutting_result, cutting_result: res.cutting_result,
sampel: res.sampel, sampel: res.sampel,
hasil_cutting_diluar_sampel: res.hasil_cutting_diluar_sampel, original_outside_sample: res.original_outside_sample,
original_sampel: res.sampel, original_sampel: res.sampel,
original_hasil_cutting_diluar_sampel: res.hasil_cutting_diluar_sampel, original_original_outside_sample: res.original_outside_sample,
prices: buildEmptyPrices(), prices: buildEmptyPrices(),
})); }));
verifyForm.result_prices = []; verifyForm.result_prices = [];
@ -88,7 +88,7 @@ watch(allMatches, (matches) => {
verifyForm.results = verifyForm.results.map((result) => ({ verifyForm.results = verifyForm.results.map((result) => ({
...result, ...result,
sampel: result.original_sampel, sampel: result.original_sampel,
hasil_cutting_diluar_sampel: result.original_hasil_cutting_diluar_sampel, original_outside_sample: result.original_original_outside_sample,
})); }));
}); });
@ -99,7 +99,7 @@ function setAllMatches(value: boolean) {
verifyForm.results = verifyForm.results.map((result) => ({ verifyForm.results = verifyForm.results.map((result) => ({
...result, ...result,
sampel: result.original_sampel, sampel: result.original_sampel,
hasil_cutting_diluar_sampel: result.original_hasil_cutting_diluar_sampel, original_outside_sample: result.original_original_outside_sample,
})); }));
} }
} }
@ -132,10 +132,10 @@ function submitVerify() {
.transform((data) => ({ .transform((data) => ({
status: data.status, status: data.status,
verification_note: data.verification_note, verification_note: data.verification_note,
results: data.results.map(({ product_variant_id, sampel, hasil_cutting_diluar_sampel }) => ({ results: data.results.map(({ product_variant_id, sampel, original_outside_sample }) => ({
product_variant_id, product_variant_id,
sampel, sampel,
hasil_cutting_diluar_sampel, original_outside_sample,
})), })),
result_prices: buildResultPricesPayload(), result_prices: buildResultPricesPayload(),
})) }))
@ -188,13 +188,13 @@ function submitVerify() {
<span class="text-muted-foreground block mb-0.5">Data cutting:</span> <span class="text-muted-foreground block mb-0.5">Data cutting:</span>
<span class="font-medium tabular-nums"> <span class="font-medium tabular-nums">
{{ result.original_sampel }} sampel · {{ result.original_sampel }} sampel ·
{{ result.original_hasil_cutting_diluar_sampel }} diluar sampel {{ result.original_original_outside_sample }} diluar sampel
</span> </span>
</div> </div>
<div> <div>
<span class="text-muted-foreground block">Diluar Sampel:</span> <span class="text-muted-foreground block">Diluar Sampel:</span>
<Badge variant="secondary" class="font-semibold"> <Badge variant="secondary" class="font-semibold">
{{ result.hasil_cutting_diluar_sampel }} pcs {{ result.original_outside_sample }} pcs
</Badge> </Badge>
</div> </div>
</div> </div>
@ -205,7 +205,7 @@ function submitVerify() {
<Input :id="`sampel-${index}`" type="number" v-model.number="result.sampel" min="0" <Input :id="`sampel-${index}`" type="number" v-model.number="result.sampel" min="0"
:max="result.cutting_result" class="h-8 w-full px-2 text-xs" :max="result.cutting_result" class="h-8 w-full px-2 text-xs"
:disabled="allMatches" :disabled="allMatches"
@input="result.hasil_cutting_diluar_sampel = result.cutting_result - result.sampel" /> @input="result.original_outside_sample = result.cutting_result - result.sampel" />
</div> </div>
<div> <div>
<label :for="`diluar-sampel-${index}`" <label :for="`diluar-sampel-${index}`"
@ -213,10 +213,10 @@ function submitVerify() {
Sampel Sampel
(diterima):</label> (diterima):</label>
<Input :id="`diluar-sampel-${index}`" type="number" <Input :id="`diluar-sampel-${index}`" type="number"
v-model.number="result.hasil_cutting_diluar_sampel" min="0" v-model.number="result.original_outside_sample" min="0"
:max="result.cutting_result" class="h-8 w-full px-2 text-xs" :max="result.cutting_result" class="h-8 w-full px-2 text-xs"
:disabled="allMatches" :disabled="allMatches"
@input="result.sampel = result.cutting_result - result.hasil_cutting_diluar_sampel" /> @input="result.sampel = result.cutting_result - result.original_outside_sample" />
</div> </div>
</div> </div>

View File

@ -75,7 +75,7 @@ defineProps<{
{{ result.sampel }} pcs {{ result.sampel }} pcs
</TableCell> </TableCell>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ result.hasil_cutting_diluar_sampel }} pcs {{ result.original_outside_sample }} pcs
</TableCell> </TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>

View File

@ -70,7 +70,7 @@ defineProps<{
{{ result.sampel }} pcs {{ result.sampel }} pcs
</TableCell> </TableCell>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ result.hasil_cutting_diluar_sampel }} pcs {{ result.original_outside_sample }} pcs
</TableCell> </TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>

View File

@ -128,7 +128,7 @@ const showingCount = computed(() => props.cuttings.length);
{{ result.sampel }} pcs {{ result.sampel }} pcs
</TableCell> </TableCell>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ result.hasil_cutting_diluar_sampel }} pcs {{ result.original_outside_sample }} pcs
</TableCell> </TableCell>
</TableRow> </TableRow>
</template> </template>

View File

@ -54,7 +54,7 @@ const verifyForm = useForm({
name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`, name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`,
cutting_result: res.cutting_result, cutting_result: res.cutting_result,
original_sampel: res.sampel, original_sampel: res.sampel,
original_outside_sample: res.hasil_cutting_diluar_sampel, original_outside_sample: res.original_outside_sample,
good: res.cutting_result, good: res.cutting_result,
reject: 0, reject: 0,
})), })),
@ -71,7 +71,7 @@ watch(open, (isOpen) => {
name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`, name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`,
cutting_result: res.cutting_result, cutting_result: res.cutting_result,
original_sampel: res.sampel, original_sampel: res.sampel,
original_outside_sample: res.hasil_cutting_diluar_sampel, original_outside_sample: res.original_outside_sample,
good: res.cutting_result, good: res.cutting_result,
reject: 0, reject: 0,
})); }));
@ -194,17 +194,17 @@ function submitVerify() {
<div class="text-center"> <div class="text-center">
<label :for="`stock-good-${index}`" <label :for="`stock-good-${index}`"
class="text-[10px] text-muted-foreground block">Bagus</label> class="text-[10px] text-muted-foreground block">Bagus</label>
<Input :id="`stock-good-${index}`" type="number" <Input :id="`stock-good-${index}`" type="number" v-model.number="result.good"
v-model.number="result.good" min="0" :max="result.cutting_result" min="0" :max="result.cutting_result" class="h-7 w-16 px-1.5 text-xs text-center"
class="h-7 w-16 px-1.5 text-xs text-center" :disabled="allMatches" :disabled="allMatches"
@input="result.reject = result.cutting_result - result.good" /> @input="result.reject = result.cutting_result - result.good" />
</div> </div>
<div class="text-center"> <div class="text-center">
<label :for="`stock-reject-${index}`" <label :for="`stock-reject-${index}`"
class="text-[10px] text-muted-foreground block">Reject</label> class="text-[10px] text-muted-foreground block">Reject</label>
<Input :id="`stock-reject-${index}`" type="number" <Input :id="`stock-reject-${index}`" type="number" v-model.number="result.reject"
v-model.number="result.reject" min="0" :max="result.cutting_result" min="0" :max="result.cutting_result" class="h-7 w-16 px-1.5 text-xs text-center"
class="h-7 w-16 px-1.5 text-xs text-center" :disabled="allMatches" :disabled="allMatches"
@input="result.good = result.cutting_result - result.reject" /> @input="result.good = result.cutting_result - result.reject" />
</div> </div>
</div> </div>
@ -238,8 +238,7 @@ function submitVerify() {
</div> </div>
<DialogFooter class="mt-6"> <DialogFooter class="mt-6">
<Button type="button" variant="outline" :disabled="verifyForm.processing" <Button type="button" variant="outline" :disabled="verifyForm.processing" @click="open = false">
@click="open = false">
Batal Batal
</Button> </Button>
<Button type="submit" :disabled="verifyForm.processing"> <Button type="submit" :disabled="verifyForm.processing">

View File

@ -46,7 +46,7 @@ export type CuttingResultListItem = {
id: number; id: number;
cutting_result: number; cutting_result: number;
sampel: number; sampel: number;
hasil_cutting_diluar_sampel: number; original_outside_sample: number;
product_variant?: { product_variant?: {
id: number; id: number;
name: string; name: string;
@ -121,7 +121,7 @@ export type CuttingResultCartItem = {
stock: number; stock: number;
cutting_result: string; cutting_result: string;
sampel: string; sampel: string;
hasil_cutting_diluar_sampel: string; original_outside_sample: string;
images?: MediaItem[]; images?: MediaItem[];
}; };
@ -149,7 +149,7 @@ export type CuttingEditItem = {
product_variant_id: number; product_variant_id: number;
cutting_result: number; cutting_result: number;
sampel: number; sampel: number;
hasil_cutting_diluar_sampel: number; original_outside_sample: number;
product_variant?: { product_variant?: {
name: string; name: string;
stock: number; stock: number;