refactor(FE-170,174): update schema and validation for stocks and depletions; rename usage_qty to qty for consistency

This commit is contained in:
rstubryan
2025-11-02 23:14:07 +07:00
parent e116311dc2
commit aac7215be7
3 changed files with 24 additions and 25 deletions
@@ -20,7 +20,7 @@ type RecordingGrowingFormSchemaType = {
}[]; }[];
stocks: { stocks: {
product_warehouse_id: number; product_warehouse_id: number;
usage_qty: number | string; qty: number | string;
}[]; }[];
depletions: { depletions: {
product_warehouse_id: number; product_warehouse_id: number;
@@ -51,7 +51,7 @@ export type BodyWeightSchema = {
export type StockSchema = { export type StockSchema = {
product_warehouse_id: number; product_warehouse_id: number;
usage_qty: number | string; qty: number | string;
}; };
export type DepletionSchema = { export type DepletionSchema = {
@@ -84,7 +84,7 @@ const StockObjectSchema: Yup.ObjectSchema<StockSchema> = Yup.object({
.required('Produk wajib diisi!') .required('Produk wajib diisi!')
.min(1, 'Produk wajib diisi!') .min(1, 'Produk wajib diisi!')
.typeError('Produk harus berupa angka!'), .typeError('Produk harus berupa angka!'),
usage_qty: Yup.number() qty: Yup.number()
.required('Jumlah penggunaan wajib diisi!') .required('Jumlah penggunaan wajib diisi!')
.min(1, 'Jumlah penggunaan tidak boleh 0!') .min(1, 'Jumlah penggunaan tidak boleh 0!')
.typeError('Jumlah penggunaan harus berupa angka!'), .typeError('Jumlah penggunaan harus berupa angka!'),
@@ -266,12 +266,12 @@ export const getRecordingGrowingFormInitialValues = (
stocks: initialValues?.stocks?.map( stocks: initialValues?.stocks?.map(
(stock: NonNullable<CreateGrowingRecordingPayload['stocks']>[0]) => ({ (stock: NonNullable<CreateGrowingRecordingPayload['stocks']>[0]) => ({
product_warehouse_id: stock.product_warehouse_id, product_warehouse_id: stock.product_warehouse_id,
usage_qty: stock.usage_qty, qty: stock.qty,
}) })
) ?? [ ) ?? [
{ {
product_warehouse_id: 0, product_warehouse_id: 0,
usage_qty: '', qty: '',
}, },
], ],
depletions: initialValues?.depletions?.map( depletions: initialValues?.depletions?.map(
@@ -380,25 +380,25 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const layingValues = values as RecordingLayingFormValues; const layingValues = values as RecordingLayingFormValues;
const layingPayload = { const layingPayload = {
project_flock_kandangs_id: layingValues.project_flock_kandangs_id, project_flock_kandang_id: layingValues.project_flock_kandangs_id,
body_weights: (layingValues.body_weights ?? []).map((bw) => ({ body_weights: (layingValues.body_weights ?? []).map((bw) => ({
avg_weight: avg_weight:
typeof bw.avg_weight === 'number' typeof bw.avg_weight === 'number'
? bw.avg_weight ? bw.avg_weight
: parseFloat(String(bw.avg_weight)) || 0, : parseFloat(String(bw.avg_weight)) || 0,
qty: bw.qty || 0, qty: Number(bw.qty) || 0,
})), })),
stocks: (layingValues.stocks ?? []).map((stock) => ({ stocks: (layingValues.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id, product_warehouse_id: stock.product_warehouse_id,
usage_qty: stock.usage_qty || 0, qty: Number(stock.qty) || 0,
})), })),
depletions: (layingValues.depletions ?? []).map((depletion) => ({ depletions: (layingValues.depletions ?? []).map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id, product_warehouse_id: depletion.product_warehouse_id,
qty: depletion.qty || 0, qty: Number(depletion.qty) || 0,
})), })),
eggs: (layingValues.eggs ?? []).map((egg) => ({ eggs: (layingValues.eggs ?? []).map((egg) => ({
product_warehouse_id: egg.product_warehouse_id, product_warehouse_id: egg.product_warehouse_id,
qty: egg.qty || 0, qty: Number(egg.qty) || 0,
})), })),
}; };
@@ -419,21 +419,21 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const growingValues = values as RecordingGrowingFormValues; const growingValues = values as RecordingGrowingFormValues;
const growingPayload = { const growingPayload = {
project_flock_kandangs_id: growingValues.project_flock_kandangs_id, project_flock_kandang_id: growingValues.project_flock_kandangs_id,
body_weights: (growingValues.body_weights ?? []).map((bw) => ({ body_weights: (growingValues.body_weights ?? []).map((bw) => ({
avg_weight: avg_weight:
typeof bw.avg_weight === 'number' typeof bw.avg_weight === 'number'
? bw.avg_weight ? bw.avg_weight
: parseFloat(String(bw.avg_weight)) || 0, : parseFloat(String(bw.avg_weight)) || 0,
qty: bw.qty || 0, qty: Number(bw.qty) || 0,
})), })),
stocks: (growingValues.stocks ?? []).map((stock) => ({ stocks: (growingValues.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id, product_warehouse_id: stock.product_warehouse_id,
usage_qty: stock.usage_qty || 0, qty: Number(stock.qty) || 0,
})), })),
depletions: (growingValues.depletions ?? []).map((depletion) => ({ depletions: (growingValues.depletions ?? []).map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id, product_warehouse_id: depletion.product_warehouse_id,
qty: depletion.qty || 0, qty: Number(depletion.qty) || 0,
})), })),
}; };
@@ -493,7 +493,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const stock = formik.values.stocks?.[stockIdx]; const stock = formik.values.stocks?.[stockIdx];
if (!stock || !stock.product_warehouse_id) return null; if (!stock || !stock.product_warehouse_id) return null;
const availableStock = getAvailableStock(stock.product_warehouse_id); const availableStock = getAvailableStock(stock.product_warehouse_id);
const requestedUsage = Number(stock.usage_qty) || 0; const requestedUsage = Number(stock.qty) || 0;
if (requestedUsage > availableStock) { if (requestedUsage > availableStock) {
return `Jumlah pakai melebihi stok tersedia! Maksimal: ${availableStock.toLocaleString('en-US')}`; return `Jumlah pakai melebihi stok tersedia! Maksimal: ${availableStock.toLocaleString('en-US')}`;
} }
@@ -508,7 +508,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const stock = formik.values.stocks?.[stockIdx]; const stock = formik.values.stocks?.[stockIdx];
if (!stock || !stock.product_warehouse_id) return null; if (!stock || !stock.product_warehouse_id) return null;
const availableStock = getAvailableStock(stock.product_warehouse_id); const availableStock = getAvailableStock(stock.product_warehouse_id);
const requestedUsage = Number(stock.usage_qty) || 0; const requestedUsage = Number(stock.qty) || 0;
const remainingStock = availableStock - requestedUsage; const remainingStock = availableStock - requestedUsage;
if (requestedUsage > 0) { if (requestedUsage > 0) {
return ( return (
@@ -864,7 +864,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
...(formik.values.stocks || []), ...(formik.values.stocks || []),
{ {
product_warehouse_id: 0, product_warehouse_id: 0,
usage_qty: '', qty: '',
}, },
]; ];
formik.setFieldValue('stocks', newStocks); formik.setFieldValue('stocks', newStocks);
@@ -873,7 +873,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const handleStockUsageQtyChangeWrapper = useCallback( const handleStockUsageQtyChangeWrapper = useCallback(
(idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => { (idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
const value = parseFloat(e.target.value) || 0; const value = parseFloat(e.target.value) || 0;
formik.setFieldValue(`stocks.${idx}.usage_qty`, value); formik.setFieldValue(`stocks.${idx}.qty`, value);
}, },
[formik] [formik]
); );
@@ -1578,8 +1578,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
<div className='flex flex-col gap-1'> <div className='flex flex-col gap-1'>
<NumberInput <NumberInput
required required
name={`stocks.${idx}.usage_qty`} name={`stocks.${idx}.qty`}
value={stock.usage_qty ?? ''} value={stock.qty ?? ''}
onChange={handleStockUsageQtyChangeWrapper(idx)} onChange={handleStockUsageQtyChangeWrapper(idx)}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
decimalScale={0} decimalScale={0}
@@ -1587,11 +1587,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
thousandSeparator=',' thousandSeparator=','
decimalSeparator='.' decimalSeparator='.'
isError={ isError={
isRepeaterInputError('stocks', 'usage_qty', idx) isRepeaterInputError('stocks', 'qty', idx)
.isError || Boolean(getStockUsageError(idx)) .isError || Boolean(getStockUsageError(idx))
} }
errorMessage={ errorMessage={
isRepeaterInputError('stocks', 'usage_qty', idx) isRepeaterInputError('stocks', 'qty', idx)
.errorMessage || .errorMessage ||
getStockUsageError(idx) || getStockUsageError(idx) ||
undefined undefined
+2 -3
View File
@@ -69,15 +69,14 @@ export type Recording = BaseMetadata &
}; };
export type CreateGrowingRecordingPayload = { export type CreateGrowingRecordingPayload = {
project_flock_kandangs_id: number; project_flock_kandang_id: number;
body_weights: { body_weights: {
avg_weight: number; avg_weight: number;
qty: number; qty: number;
}[]; }[];
stocks?: { stocks?: {
product_warehouse_id: number; product_warehouse_id: number;
usage_qty: number; qty: number;
pending_qty?: number;
}[]; }[];
depletions?: { depletions?: {
product_warehouse_id: number; product_warehouse_id: number;