fix: adjust stock, depletion, and egg select input

This commit is contained in:
ValdiANS
2026-05-02 17:04:59 +07:00
parent ff92073d19
commit 28a1852de8
3 changed files with 107 additions and 69 deletions
@@ -5,6 +5,7 @@ import {
CreateLayingRecordingPayload,
CreateEggPayload,
} from '@/types/api/production/recording';
import { getProductWarehouseOptionLabel } from '@/lib/product-warehouse';
type RecordingGrowingFormSchemaType = {
record_date: string;
@@ -29,11 +30,19 @@ type RecordingGrowingFormSchemaType = {
} | null;
project_flock_kandang_id: number;
stocks: {
product_warehouse_id: number;
product_warehouse_id:
| {
value: number;
label: string;
}
| undefined;
qty: number | string;
}[];
depletions: {
product_warehouse_id?: number;
product_warehouse_id?: {
value: number;
label: string;
};
source_product_warehouse_id?: number;
qty?: number | string;
}[];
@@ -41,34 +50,48 @@ type RecordingGrowingFormSchemaType = {
type RecordingLayingFormSchemaType = RecordingGrowingFormSchemaType & {
eggs: {
product_warehouse_id?: number;
product_warehouse_id?: {
value: number;
label: string;
};
qty?: number | string;
weight?: number | string;
}[];
};
export type StockSchema = {
product_warehouse_id: number;
product_warehouse_id: {
value: number;
label: string;
};
qty: number | string;
};
export type DepletionSchema = {
product_warehouse_id?: number;
product_warehouse_id?: {
value: number;
label: string;
};
source_product_warehouse_id?: number;
qty?: number | string;
};
export type EggSchema = {
product_warehouse_id?: number;
product_warehouse_id?: {
value: number;
label: string;
};
qty?: number | string;
weight?: number | string;
};
const StockObjectSchema: Yup.ObjectSchema<StockSchema> = Yup.object({
product_warehouse_id: Yup.number()
product_warehouse_id: Yup.object({
value: Yup.number().min(1).required(),
label: Yup.string().required(),
})
.required('Produk wajib diisi!')
.min(1, 'Produk wajib diisi!')
.typeError('Produk harus berupa angka!'),
.typeError('Produk wajib diisi!'),
qty: Yup.number()
.required('Jumlah penggunaan wajib diisi!')
.moreThan(0, 'Jumlah penggunaan harus lebih dari 0!')
@@ -76,7 +99,10 @@ const StockObjectSchema: Yup.ObjectSchema<StockSchema> = Yup.object({
});
const DepletionObjectSchema: Yup.ObjectSchema<DepletionSchema> = Yup.object({
product_warehouse_id: Yup.number()
product_warehouse_id: Yup.object({
value: Yup.number().min(1).required(),
label: Yup.string().required(),
})
.optional()
.typeError('Depletions harus berupa angka!'),
source_product_warehouse_id: Yup.number()
@@ -88,7 +114,10 @@ const DepletionObjectSchema: Yup.ObjectSchema<DepletionSchema> = Yup.object({
});
const EggObjectSchema: Yup.ObjectSchema<EggSchema> = Yup.object({
product_warehouse_id: Yup.number()
product_warehouse_id: Yup.object({
value: Yup.number().min(1).required(),
label: Yup.string().required(),
})
.optional()
.typeError('Kondisi telur harus berupa angka!'),
qty: Yup.number().optional().typeError('Jumlah telur harus berupa angka!'),
@@ -248,14 +277,17 @@ export const getRecordingGrowingFormInitialValues = (
initialValues?.project_flock?.project_flock_kandang_id ??
0,
stocks: initialValues?.stocks?.map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
product_warehouse_id: {
value: stock.product_warehouse_id,
label: getProductWarehouseOptionLabel(stock.product_warehouse),
},
qty:
(stock as { qty?: number; usage_amount?: number }).qty ||
(stock as { qty?: number; usage_amount?: number }).usage_amount ||
'',
})) ?? [
{
product_warehouse_id: 0,
product_warehouse_id: undefined,
qty: '',
},
],
@@ -263,13 +295,16 @@ export const getRecordingGrowingFormInitialValues = (
(
depletion: NonNullable<CreateGrowingRecordingPayload['depletions']>[0]
) => ({
product_warehouse_id: depletion.product_warehouse_id,
product_warehouse_id: {
value: Number(depletion.product_warehouse_id ?? 0),
label: getProductWarehouseOptionLabel(depletion.product_warehouse),
},
source_product_warehouse_id: depletion.source_product_warehouse_id,
qty: depletion.qty,
})
) ?? [
{
product_warehouse_id: 0,
product_warehouse_id: undefined,
qty: '',
},
],
@@ -281,12 +316,15 @@ export const getRecordingLayingFormInitialValues = (
...getRecordingGrowingFormInitialValues(initialValues),
eggs: initialValues?.eggs?.map((egg: CreateEggPayload) => ({
product_warehouse_id: egg.product_warehouse_id,
product_warehouse_id: {
value: Number(egg.product_warehouse_id ?? 0),
label: getProductWarehouseOptionLabel(egg.product_warehouse),
},
qty: egg.qty,
weight: egg.weight,
})) ?? [
{
product_warehouse_id: 0,
product_warehouse_id: undefined,
qty: '',
weight: '',
},
@@ -522,7 +522,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
? values.depletions
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
product_warehouse_id: depletion.product_warehouse_id?.value ?? 0,
...(depletion.source_product_warehouse_id && {
source_product_warehouse_id:
depletion.source_product_warehouse_id,
@@ -533,13 +533,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const stocks = recordingRestriction.canEditStock
? (values.stocks ?? [])
.filter((s) => s.product_warehouse_id && s.qty)
.filter((s) => s.product_warehouse_id?.value && s.qty)
.map((stock) => ({
// In migration mode, product_warehouse_id field holds product.id;
// send it as product_id so the backend auto-creates the warehouse entry.
...(isMigrationMode
? { product_id: stock.product_warehouse_id }
: { product_warehouse_id: stock.product_warehouse_id }),
? { product_id: stock.product_warehouse_id?.value }
: { product_warehouse_id: stock.product_warehouse_id?.value }),
qty: Number(stock.qty) || 0,
}))
: [];
@@ -561,9 +561,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const createLayingPayload = useCallback(
(values: RecordingLayingFormValues) => {
const depletions = values.depletions
?.filter((d) => d.product_warehouse_id && d.qty)
?.filter((d) => d.product_warehouse_id?.value && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
product_warehouse_id: depletion.product_warehouse_id?.value ?? 0,
...(depletion.source_product_warehouse_id && {
source_product_warehouse_id: depletion.source_product_warehouse_id,
}),
@@ -573,7 +573,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const eggs = values.eggs
?.filter((e) => e.product_warehouse_id && e.qty && e.weight)
.map((egg) => ({
product_warehouse_id: egg.product_warehouse_id!,
product_warehouse_id: egg.product_warehouse_id?.value ?? 0,
qty: Number(egg.qty) || 0,
weight:
typeof egg.weight === 'number'
@@ -583,11 +583,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const stocks = recordingRestriction.canEditStock
? values.stocks
.filter((s) => s.product_warehouse_id && s.qty)
.filter((s) => s.product_warehouse_id?.value && s.qty)
.map((stock) => ({
...(isMigrationMode
? { product_id: stock.product_warehouse_id }
: { product_warehouse_id: stock.product_warehouse_id }),
? { product_id: stock.product_warehouse_id?.value }
: { product_warehouse_id: stock.product_warehouse_id?.value }),
qty: Number(stock.qty) || 0,
}))
: [];
@@ -1283,8 +1283,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
// product_warehouse object returned by the API.
if (isMigrationMode && type === 'edit' && initialValues?.stocks?.length) {
baseValues.stocks = initialValues.stocks.map((stock) => ({
product_warehouse_id:
stock.product_warehouse?.product_id ?? stock.product_warehouse_id,
product_warehouse_id: {
value: Number(
stock.product_warehouse?.product_id ?? stock.product_warehouse_id
),
label: getProductWarehouseOptionLabel(stock.product_warehouse),
},
qty: stock.usage_amount ?? '',
}));
}
@@ -1438,8 +1442,12 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
formik.setFieldValue(
'stocks',
initialValues.stocks.map((stock) => ({
product_warehouse_id:
stock.product_warehouse?.product_id ?? stock.product_warehouse_id,
product_warehouse_id: {
value: Number(
stock.product_warehouse?.product_id ?? stock.product_warehouse_id
),
label: getProductWarehouseOptionLabel(stock.product_warehouse),
},
qty: stock.usage_amount ?? '',
}))
);
@@ -1462,7 +1470,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
(stockIdx: number) => {
if ((type as 'add' | 'edit' | 'detail') === 'detail') return null;
const stock = formik.values.stocks?.[stockIdx];
if (!stock || !stock.product_warehouse_id) return null;
if (!stock || !stock.product_warehouse_id?.value) return null;
return null;
},
[formik.values.stocks, type]
@@ -1492,13 +1500,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const getStockUsageAdornment = useCallback(
(stockIdx: number) => {
const stock = formik.values.stocks?.[stockIdx];
if (!stock || !stock.product_warehouse_id) return null;
if (!stock || !stock.product_warehouse_id?.value) return null;
const isDetail = (type as 'add' | 'edit' | 'detail') === 'detail';
const availableStock = getAvailableStock(stock.product_warehouse_id);
const availableStock = getAvailableStock(
stock.product_warehouse_id.value
);
const requestedUsage = Number(stock.qty) || 0;
const remainingStock = availableStock - requestedUsage;
const { pendingQty } = getStockPendingInfo(stock.product_warehouse_id);
const { pendingQty } = getStockPendingInfo(
stock.product_warehouse_id.value
);
if (isDetail) {
if (pendingQty > 0) {
@@ -1605,10 +1617,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
return (
idx !== currentIdx &&
s.product_warehouse_id &&
s.product_warehouse_id !== 0
s.product_warehouse_id.value !== 0
);
})
.map((s) => s.product_warehouse_id) || [];
.map((s) => s.product_warehouse_id?.value) || [];
return unifiedStockProducts.filter(
(opt) => !selectedProductIds.includes(Number(opt.value))
@@ -1625,10 +1637,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
return (
idx !== currentIdx &&
d.product_warehouse_id &&
d.product_warehouse_id !== 0
d.product_warehouse_id.value !== 0
);
})
.map((d) => d.product_warehouse_id) || [];
.map((d) => d.product_warehouse_id?.value) || [];
return depletionProducts.filter(
(opt) => !selectedProductIds.includes(Number(opt.value))
@@ -1645,10 +1657,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
return (
idx !== currentIdx &&
e.product_warehouse_id &&
e.product_warehouse_id !== 0
e.product_warehouse_id.value !== 0
);
})
.map((e) => e.product_warehouse_id) || [];
.map((e) => e.product_warehouse_id?.value) || [];
return eggProducts.filter(
(opt) => !selectedProductIds.includes(Number(opt.value))
@@ -1694,7 +1706,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
isError: touchedField && Boolean(errorField?.[column]),
errorMessage:
touchedField && errorField?.[column]
? (errorField[column] as string)
? errorField[column] instanceof Object
? (errorField[column] as OptionType)?.label
: (errorField[column] as string)
: '',
};
};
@@ -2901,20 +2915,15 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
<td>
<SelectInput
required
key={`stock-product-${idx}-${stock.product_warehouse_id}`}
value={
unifiedStockProducts.find(
(product) =>
product.value === stock.product_warehouse_id
) || null
}
key={`stock-product-${idx}-${stock.product_warehouse_id?.value}`}
value={stock.product_warehouse_id}
onInputChange={setStockInputValue}
onChange={(selectedOption) => {
const option =
selectedOption as OptionType | null;
formik.setFieldValue(
`stocks.${idx}.product_warehouse_id`,
option?.value || 0
option
);
}}
options={getAvailableStockProductOptions(idx)}
@@ -2950,9 +2959,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
}
isClearable={type !== 'detail'}
inputPrefix={
stock.product_warehouse_id
stock.product_warehouse_id?.value
? getProductFlagBadgeAdornment(
stock.product_warehouse_id
stock.product_warehouse_id.value
)
: undefined
}
@@ -2988,7 +2997,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
inputSuffix={
stock.product_warehouse_id
? getProductUomSuffix(
stock.product_warehouse_id,
stock.product_warehouse_id.value,
'stock'
)
: null
@@ -3181,19 +3190,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
)}
<td>
<SelectInput
value={
depletionProducts.find(
(product) =>
product.value ===
depletion.product_warehouse_id
) || null
}
value={depletion.product_warehouse_id}
onChange={(selectedOption) => {
const option =
selectedOption as OptionType | null;
formik.setFieldValue(
`depletions.${idx}.product_warehouse_id`,
option?.value || 0
option
);
}}
options={getAvailableDepletionProductOptions(idx)}
@@ -3256,7 +3259,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
inputSuffix={
depletion.product_warehouse_id
? getProductUomSuffix(
depletion.product_warehouse_id,
depletion.product_warehouse_id.value,
'depletion'
)
: null
@@ -3434,18 +3437,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
)}
<td>
<SelectInput
value={
eggProducts.find(
(product) =>
product.value === egg.product_warehouse_id
) || null
}
value={egg.product_warehouse_id}
onChange={(selectedOption) => {
const option =
selectedOption as OptionType | null;
formik.setFieldValue(
`eggs.${idx}.product_warehouse_id`,
option?.value || 0
option
);
}}
options={getAvailableEggProductOptions(idx)}
+2
View File
@@ -117,6 +117,7 @@ export type CreateGrowingRecordingPayload = {
product_warehouse_id?: number;
source_product_warehouse_id?: number;
qty?: number;
product_warehouse?: ProductWarehouse;
}[];
};
@@ -124,6 +125,7 @@ export type CreateEggPayload = {
product_warehouse_id?: number;
qty?: number;
weight?: number;
product_warehouse?: ProductWarehouse;
};
export type CreateLayingRecordingPayload = CreateGrowingRecordingPayload & {