refactor: enhance stock verification logic and error handling in StockVerifyDialog
This commit is contained in:
parent
2209f4901c
commit
39c8bd01a8
@ -2,7 +2,7 @@
|
|||||||
import { useForm } from '@inertiajs/vue3';
|
import { useForm } from '@inertiajs/vue3';
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import NumberInput from '@/components/form/number-input/NumberInput.vue';
|
import { NumberInput } from '@/components/form/number-input';
|
||||||
import { RupiahInput } from '@/components/form/rupiah-input';
|
import { RupiahInput } from '@/components/form/rupiah-input';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
@ -51,10 +51,14 @@ const verifyForm = useForm({
|
|||||||
cutting_result: res.cutting_result,
|
cutting_result: res.cutting_result,
|
||||||
original_sample: res.sample,
|
original_sample: res.sample,
|
||||||
original_outside_sample: res.original_outside_sample,
|
original_outside_sample: res.original_outside_sample,
|
||||||
good: res.original_outside_sample,
|
good: res.cutting_result,
|
||||||
reject: 0,
|
reject: 0,
|
||||||
})),
|
})),
|
||||||
variant_prices: [] as VariantPriceRow[],
|
variant_prices: props.cutting.results.map(res => ({
|
||||||
|
product_variant_id: res.product_variant?.id || 0,
|
||||||
|
name: `${res.product_variant?.product?.name || ''} (${res.product_variant?.name || ''})`,
|
||||||
|
prices: buildEmptyPrices(),
|
||||||
|
})),
|
||||||
shared_prices: buildEmptyPrices(),
|
shared_prices: buildEmptyPrices(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -67,7 +71,7 @@ watch(open, (isOpen) => {
|
|||||||
cutting_result: res.cutting_result,
|
cutting_result: res.cutting_result,
|
||||||
original_sample: res.sample,
|
original_sample: res.sample,
|
||||||
original_outside_sample: res.original_outside_sample,
|
original_outside_sample: res.original_outside_sample,
|
||||||
good: res.original_outside_sample,
|
good: res.cutting_result,
|
||||||
reject: 0,
|
reject: 0,
|
||||||
}));
|
}));
|
||||||
verifyForm.variant_prices = props.cutting.results.map(res => ({
|
verifyForm.variant_prices = props.cutting.results.map(res => ({
|
||||||
@ -80,6 +84,18 @@ watch(open, (isOpen) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onGoodChange(result: any, value: string | number) {
|
||||||
|
const val = Number(value) || 0;
|
||||||
|
result.good = val;
|
||||||
|
result.reject = Math.max(0, result.cutting_result - val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRejectChange(result: any, value: string | number) {
|
||||||
|
const val = Number(value) || 0;
|
||||||
|
result.reject = val;
|
||||||
|
result.good = Math.max(0, result.cutting_result - val);
|
||||||
|
}
|
||||||
|
|
||||||
function setSharedPrice(type: string, value: string) {
|
function setSharedPrice(type: string, value: string) {
|
||||||
verifyForm.shared_prices[type] = value;
|
verifyForm.shared_prices[type] = value;
|
||||||
verifyForm.variant_prices = verifyForm.variant_prices.map((row) => ({
|
verifyForm.variant_prices = verifyForm.variant_prices.map((row) => ({
|
||||||
@ -89,13 +105,13 @@ function setSharedPrice(type: string, value: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const resultPricesErrors = computed(() => {
|
const resultPricesErrors = computed(() => {
|
||||||
const message = (verifyForm.errors as Record<string, string | undefined>).result_prices;
|
return Object.entries(verifyForm.errors)
|
||||||
|
.filter(([key]) => key === 'result_prices' || key.startsWith('result_prices.'))
|
||||||
return message ? [message] : [];
|
.map(([_, message]) => message) as string[];
|
||||||
});
|
});
|
||||||
|
|
||||||
function buildResultPricesPayload() {
|
function buildResultPricesPayload(variantPrices: VariantPriceRow[]) {
|
||||||
return verifyForm.variant_prices.map((row) => ({
|
return variantPrices.map((row) => ({
|
||||||
product_variant_id: row.product_variant_id,
|
product_variant_id: row.product_variant_id,
|
||||||
prices: PRICE_TYPES.map((type) => ({
|
prices: PRICE_TYPES.map((type) => ({
|
||||||
type,
|
type,
|
||||||
@ -113,7 +129,7 @@ function submitVerify() {
|
|||||||
good,
|
good,
|
||||||
reject,
|
reject,
|
||||||
})),
|
})),
|
||||||
result_prices: buildResultPricesPayload(),
|
result_prices: buildResultPricesPayload(data.variant_prices),
|
||||||
}))
|
}))
|
||||||
.post(verify.url(props.cutting.id), {
|
.post(verify.url(props.cutting.id), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
@ -121,8 +137,22 @@ function submitVerify() {
|
|||||||
open.value = false;
|
open.value = false;
|
||||||
},
|
},
|
||||||
onError: (errors: Record<string, string>) => {
|
onError: (errors: Record<string, string>) => {
|
||||||
if (errors.system) {
|
const shown = new Set<string>();
|
||||||
toast.error(errors.system);
|
|
||||||
|
for (const [key, message] of Object.entries(errors)) {
|
||||||
|
if (
|
||||||
|
key === 'result_prices' ||
|
||||||
|
key.startsWith('result_prices.') ||
|
||||||
|
key.startsWith('results.') ||
|
||||||
|
key === 'verification_note'
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shown.has(message)) {
|
||||||
|
shown.add(message);
|
||||||
|
toast.error(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -145,31 +175,38 @@ function submitVerify() {
|
|||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<div v-for="(result, index) in verifyForm.results" :key="result.product_variant_id"
|
<div v-for="(result, index) in verifyForm.results" :key="result.product_variant_id"
|
||||||
class="flex items-center gap-3 rounded-lg border p-3">
|
class="flex flex-col gap-1 rounded-lg border p-3">
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex items-center gap-3">
|
||||||
<p class="font-medium text-sm truncate">{{ result.name }}</p>
|
<div class="flex-1 min-w-0">
|
||||||
<p class="text-xs text-muted-foreground">
|
<p class="font-medium text-sm truncate">{{ result.name }}</p>
|
||||||
{{ result.cutting_result }} pcs
|
<p class="text-xs text-muted-foreground">
|
||||||
<span class="text-[10px]">({{ result.original_sample }} Sample, {{
|
{{ result.cutting_result }} pcs
|
||||||
result.original_outside_sample }} Diluar Sample)</span>
|
<span class="text-[10px]">({{ result.original_sample }} Sample, {{
|
||||||
</p>
|
result.original_outside_sample }} Diluar Sample)</span>
|
||||||
</div>
|
</p>
|
||||||
<div class="flex items-center gap-2 shrink-0">
|
|
||||||
<div class="text-center">
|
|
||||||
<label :for="`stock-good-${index}`"
|
|
||||||
class="text-[10px] text-muted-foreground block">Bagus</label>
|
|
||||||
<NumberInput :id="`stock-good-${index}`" v-model="result.good"
|
|
||||||
class="h-7 w-20 px-1.5 text-xs text-center"
|
|
||||||
@input="result.reject = result.cutting_result - result.good" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center">
|
<div class="flex items-center gap-2 shrink-0">
|
||||||
<label :for="`stock-reject-${index}`"
|
<div class="text-center">
|
||||||
class="text-[10px] text-muted-foreground block">Reject</label>
|
<label :for="`stock-good-${index}`"
|
||||||
<NumberInput :id="`stock-reject-${index}`" v-model="result.reject"
|
class="text-[10px] text-muted-foreground block">Bagus</label>
|
||||||
class="h-7 w-20 px-1.5 text-xs text-center"
|
<NumberInput :id="`stock-good-${index}`" :model-value="result.good"
|
||||||
@input="result.good = result.cutting_result - result.reject" />
|
class="h-7 w-20 px-1.5 text-xs text-center"
|
||||||
|
@update:model-value="val => onGoodChange(result, val)" />
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<label :for="`stock-reject-${index}`"
|
||||||
|
class="text-[10px] text-muted-foreground block">Reject</label>
|
||||||
|
<NumberInput :id="`stock-reject-${index}`" :model-value="result.reject"
|
||||||
|
class="h-7 w-20 px-1.5 text-xs text-center"
|
||||||
|
@update:model-value="val => onRejectChange(result, val)" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<FieldError :errors="[
|
||||||
|
verifyForm.errors[`results.${index}.good`],
|
||||||
|
verifyForm.errors[`results.${index}.reject`],
|
||||||
|
verifyForm.errors[`results.${index}.product_variant_id`]
|
||||||
|
].filter(Boolean) as string[]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user