refactor(FE): Refactor payload creation to respect recording

restrictions
This commit is contained in:
rstubryan
2026-03-11 09:56:14 +07:00
parent 1621f2ab7d
commit 11eeac3289
2 changed files with 135 additions and 83 deletions
@@ -290,63 +290,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
return recording?.approval?.action === 'REJECTED';
}, []);
// ===== PAYLOAD CREATION HELPERS =====
const createGrowingPayload = useCallback(
(values: RecordingGrowingFormValues) => {
const depletions = values.depletions
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
qty: Number(depletion.qty) || 0,
}));
return {
project_flock_kandang_id: values.project_flock_kandang_id,
record_date: values.record_date,
stocks: (values.stocks ?? []).map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
})),
...(depletions && depletions.length > 0 && { depletions }),
};
},
[]
);
const createLayingPayload = useCallback(
(values: RecordingLayingFormValues) => {
const depletions = values.depletions
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
qty: Number(depletion.qty) || 0,
}));
const eggs = values.eggs
?.filter((e) => e.product_warehouse_id && e.qty && e.weight)
.map((egg) => ({
product_warehouse_id: egg.product_warehouse_id!,
qty: Number(egg.qty) || 0,
weight:
typeof egg.weight === 'number'
? egg.weight
: parseFloat(String(egg.weight)) || 0,
}));
return {
project_flock_kandang_id: values.project_flock_kandang_id,
record_date: values.record_date,
stocks: values.stocks.map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
})),
...(depletions && depletions.length > 0 && { depletions }),
...(eggs && eggs.length > 0 && { eggs }),
};
},
[]
);
// ===== FORM HANDLERS =====
const createRecordingHandler = useCallback(
async (
@@ -513,7 +456,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
}, [initialValues, projectFlockKandangLookup]);
const recordingRestriction = useMemo(() => {
// Determine isLaying primarily from transition flags.
let isLaying: boolean;
if (initialValues?.is_laying !== undefined) {
isLaying = initialValues.is_laying;
@@ -531,13 +473,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
false;
const currentIsLaying =
projectFlockKandangDetail?.project_flock?.category === 'LAYING';
type === 'edit'
? projectFlockKandangDetail?.project_flock?.category === 'LAYING'
: projectFlockKandangLookup?.project_flock?.category === 'LAYING';
return getRecordingRestriction(
isLaying,
isTransition,
type === 'edit' ? currentIsLaying : undefined
);
return getRecordingRestriction(isLaying, isTransition, currentIsLaying);
}, [
initialValues,
projectFlockKandangLookup,
@@ -545,6 +485,77 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
type,
]);
// ===== PAYLOAD CREATION HELPERS =====
const createGrowingPayload = useCallback(
(values: RecordingGrowingFormValues) => {
const depletions = recordingRestriction.canEditDepletion
? values.depletions
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
qty: Number(depletion.qty) || 0,
}))
: [];
const stocks = recordingRestriction.canEditStock
? (values.stocks ?? [])
.filter((s) => s.product_warehouse_id && s.qty)
.map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
}))
: [];
return {
project_flock_kandang_id: values.project_flock_kandang_id,
record_date: values.record_date,
...(stocks.length > 0 && { stocks }),
...(depletions.length > 0 && { depletions }),
};
},
[recordingRestriction.canEditStock, recordingRestriction.canEditDepletion]
);
const createLayingPayload = useCallback(
(values: RecordingLayingFormValues) => {
const depletions = values.depletions
?.filter((d) => d.product_warehouse_id && d.qty)
.map((depletion) => ({
product_warehouse_id: depletion.product_warehouse_id!,
qty: Number(depletion.qty) || 0,
}));
const eggs = values.eggs
?.filter((e) => e.product_warehouse_id && e.qty && e.weight)
.map((egg) => ({
product_warehouse_id: egg.product_warehouse_id!,
qty: Number(egg.qty) || 0,
weight:
typeof egg.weight === 'number'
? egg.weight
: parseFloat(String(egg.weight)) || 0,
}));
const stocks = recordingRestriction.canEditStock
? values.stocks
.filter((s) => s.product_warehouse_id && s.qty)
.map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty: Number(stock.qty) || 0,
}))
: [];
return {
project_flock_kandang_id: values.project_flock_kandang_id,
record_date: values.record_date,
...(stocks.length > 0 && { stocks }),
...(depletions && depletions.length > 0 && { depletions }),
...(eggs && eggs.length > 0 && { eggs }),
};
},
[recordingRestriction.canEditStock]
);
const isRecordingEditable = useCallback((recording?: Recording) => {
if (!recording) return true;
@@ -677,14 +688,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
}, [approvedProjectFlockKandangsData]);
const isLayingCategory = useMemo(() => {
// Priority 1: initialValues (for edit/detail mode)
if (initialValues?.is_laying !== undefined) {
return initialValues.is_laying;
// Priority 1: initialValues category (for edit/detail mode)
if (initialValues?.project_flock?.project_flock_category !== undefined) {
return initialValues.project_flock.project_flock_category === 'LAYING';
}
// Priority 2: projectFlockKandangLookup flag (for add mode)
if (projectFlockKandangLookup?.is_laying !== undefined) {
return projectFlockKandangLookup.is_laying;
// Priority 2: projectFlockKandangLookup category (for add mode)
if (projectFlockKandangLookup?.project_flock?.category !== undefined) {
return projectFlockKandangLookup.project_flock.category === 'LAYING';
}
// Priority 3: projectFlockKandangDetail (fallback for edit/detail mode)
@@ -692,7 +703,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
projectFlockKandangDetail?.project_flock?.category === 'LAYING' || false
);
}, [
initialValues?.is_laying,
initialValues?.project_flock?.project_flock_category,
projectFlockKandangLookup,
projectFlockKandangDetail,
]);
@@ -1062,7 +1073,36 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
? UpdateRecordingGrowingFormSchema
: RecordingGrowingFormSchema;
}
return schema.clone().concat(
if (!recordingRestriction.canEditStock) {
schema = schema.shape({
stocks: Yup.array()
.of(
Yup.object({
product_warehouse_id: Yup.number().optional(),
qty: Yup.number().optional(),
})
)
.optional()
.default([]) as unknown as Yup.Schema<unknown>,
});
}
if (!recordingRestriction.canEditDepletion) {
schema = schema.shape({
depletions: Yup.array()
.of(
Yup.object({
product_warehouse_id: Yup.number().optional(),
qty: Yup.number().optional(),
})
)
.optional()
.default([]) as unknown as Yup.Schema<unknown>,
});
}
return schema.concat(
Yup.object().shape({
project_flock_kandang_id: Yup.number().test(
'not-already-recorded',
@@ -11,7 +11,29 @@ export const getRecordingRestriction = (
isTransition: boolean,
currentIsLaying?: boolean
): RecordingRestriction => {
if (currentIsLaying && !isLaying) {
if (isTransition && !isLaying) {
const isLayingKandangInTransition = currentIsLaying === true;
if (isLayingKandangInTransition) {
return {
canEditStock: false,
canEditDepletion: true,
canEditEgg: true,
isLocked: false,
lockReason: undefined,
};
} else {
return {
canEditStock: true,
canEditDepletion: false,
canEditEgg: false,
isLocked: false,
lockReason: undefined,
};
}
}
if (!isLaying && !isTransition && currentIsLaying) {
return {
canEditStock: false,
canEditDepletion: false,
@@ -22,16 +44,6 @@ export const getRecordingRestriction = (
};
}
if (isTransition && !isLaying) {
return {
canEditStock: true,
canEditDepletion: false,
canEditEgg: false,
isLocked: false,
lockReason: undefined,
};
}
if (!isLaying && !isTransition) {
return {
canEditStock: true,