Merge branch 'fix/adjustment-recording-and-uniformity' into 'development'

[FIX/FE] Adjustment Recording, Uniformity and Transfer Stock

See merge request mbugroup/lti-web-client!256
This commit is contained in:
Rivaldi A N S
2026-01-26 04:09:42 +00:00
6 changed files with 90 additions and 38 deletions
@@ -1369,9 +1369,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
}
readOnly
disabled
className={{
input: 'bg-base-200',
}}
/>
<TextInput
label='Lokasi'
@@ -1382,9 +1379,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
}
readOnly
disabled
className={{
input: 'bg-base-200',
}}
/>
</div>
</Card>
@@ -1433,9 +1427,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
}
readOnly
disabled
className={{
input: 'bg-base-200',
}}
/>
<TextInput
label='Lokasi'
@@ -1446,9 +1437,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
}
readOnly
disabled
className={{
input: 'bg-base-200',
}}
/>
</div>
</Card>
@@ -164,6 +164,9 @@ export const RecordingLayingFormSchema: Yup.ObjectSchema<RecordingLayingFormSche
export const UpdateRecordingGrowingFormSchema =
RecordingGrowingFormSchema.shape({
location_id: Yup.number().nullable().optional(),
project_flock_id: Yup.number().nullable().optional(),
kandang_id: Yup.number().nullable().optional(),
project_flock_kandang_id: Yup.number()
.default(0)
.typeError('Project Flock Kandang wajib diisi!')
@@ -176,6 +179,9 @@ export const UpdateRecordingGrowingFormSchema =
});
export const UpdateRecordingLayingFormSchema = RecordingLayingFormSchema.shape({
location_id: Yup.number().nullable().optional(),
project_flock_id: Yup.number().nullable().optional(),
kandang_id: Yup.number().nullable().optional(),
project_flock_kandang_id: Yup.number()
.default(0)
.typeError('Project Flock Kandang wajib diisi!')
@@ -217,13 +223,25 @@ export const getRecordingGrowingFormInitialValues = (
project_flock_id: 0,
kandang: null,
kandang_id: 0,
project_flock_kandang: initialValues?.project_flock_kandang_id
? {
value: initialValues.project_flock_kandang_id,
label: `Project Flock #${initialValues.project_flock_kandang_id}`,
}
: null,
project_flock_kandang_id: initialValues?.project_flock_kandang_id ?? 0,
project_flock_kandang:
(initialValues?.project_flock_kandang_id ??
initialValues?.project_flock?.project_flock_kandang_id)
? {
value:
initialValues?.project_flock_kandang_id ??
initialValues?.project_flock?.project_flock_kandang_id ??
0,
label: `Project Flock #${
initialValues?.project_flock_kandang_id ??
initialValues?.project_flock?.project_flock_kandang_id ??
0
}`,
}
: null,
project_flock_kandang_id:
initialValues?.project_flock_kandang_id ??
initialValues?.project_flock?.project_flock_kandang_id ??
0,
stocks: initialValues?.stocks?.map((stock) => ({
product_warehouse_id: stock.product_warehouse_id,
qty:
@@ -554,15 +554,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const nextDayRecordingUrl = useMemo(() => {
if (!projectFlockKandangLookup) return null;
const projectFlockKandangId = projectFlockKandangLookup.id;
return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}`;
}, [projectFlockKandangLookup]);
return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}&record_date=${selectedRecordDate}`;
}, [projectFlockKandangLookup, selectedRecordDate]);
const { data: nextDayRecordingData } = useSWR(
nextDayRecordingUrl,
nextDayRecordingUrl
? () => {
const projectFlockKandangId = projectFlockKandangLookup!.id;
return RecordingApi.nextDayRecording(projectFlockKandangId);
return RecordingApi.nextDayRecording(
projectFlockKandangId,
selectedRecordDate
);
}
: null
);
@@ -1075,14 +1078,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
if ((type as 'add' | 'edit' | 'detail') === 'detail') return null;
const stock = formik.values.stocks?.[stockIdx];
if (!stock || !stock.product_warehouse_id) return null;
const availableStock = getAvailableStock(stock.product_warehouse_id);
const requestedUsage = Number(stock.qty) || 0;
if (requestedUsage > availableStock) {
return `Jumlah pakai melebihi stok tersedia! Maksimal: ${formatNumber(availableStock)}`;
}
return null;
},
[formik.values.stocks, getAvailableStock, type]
[formik.values.stocks, type]
);
const getStockUsageAdornment = useCallback(
@@ -1096,7 +1094,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
if (requestedUsage > 0) {
return (
<span className='text-sm text-gray-600 whitespace-nowrap'>
(sisa: {formatNumber(remainingStock)})
(tersedia: {formatNumber(availableStock)} | pakai:{' '}
{formatNumber(requestedUsage)} | sisa:{' '}
{formatNumber(Math.max(remainingStock, 0))} | dipinjam:{' '}
{formatNumber(Math.max(-remainingStock, 0))})
</span>
);
}
@@ -2443,7 +2444,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
);
}}
options={unifiedStockProducts}
placeholder='Pilih Produk'
placeholder={
!formik.values.project_flock_kandang_id
? 'Pilih kandang terlebih dahulu'
: 'Pilih Produk'
}
isLoading={isLoadingStockProducts}
onMenuScrollToBottom={loadMoreStockProducts}
isError={
@@ -2464,7 +2469,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
wrapper: 'w-full min-w-48',
}}
isSearchable
isDisabled={type === 'detail'}
isDisabled={
type === 'detail' ||
!formik.values.project_flock_kandang_id
}
isClearable={type !== 'detail'}
startAdornment={
stock.product_warehouse_id
@@ -399,23 +399,58 @@ const UniformityForm = ({
// ===== SIDE EFFECTS =====
useEffect(() => {
if (
projectFlockKandangLookup?.chick_in_date &&
projectFlockKandangLookup?.project_flock_kandang_id &&
isResponseSuccess(recordingsData) &&
recordingsData.data
) {
const matchingRecording = recordingsData.data.find(
const matchingRecordings = recordingsData.data.filter(
(recording: Recording) =>
recording.project_flock?.project_flock_kandang_id ===
projectFlockKandangLookup.project_flock_kandang_id
);
if (matchingRecording?.project_flock?.production_standart?.week) {
const weekValue =
matchingRecording.project_flock.production_standart.week;
formik.setFieldValue('week', weekValue);
matchingRecordings.sort(
(a: Recording, b: Recording) =>
new Date(a.record_datetime).getTime() -
new Date(b.record_datetime).getTime()
);
const earliestRecording = matchingRecordings[0];
if (earliestRecording) {
const chickInDate = new Date(projectFlockKandangLookup.chick_in_date);
chickInDate.setHours(0, 0, 0, 0);
const earliestRecordDate = new Date(earliestRecording.record_datetime);
earliestRecordDate.setHours(0, 0, 0, 0);
const initialWeek =
earliestRecording.project_flock?.production_standart?.week || 18;
if (formik.values.date) {
const selectedDate = new Date(formik.values.date);
selectedDate.setHours(0, 0, 0, 0);
const daysDiff = Math.floor(
(selectedDate.getTime() - chickInDate.getTime()) /
(1000 * 60 * 60 * 24)
);
const weeksDiff = Math.floor(daysDiff / 7);
formik.setFieldValue('week', initialWeek + weeksDiff);
} else {
formik.setFieldValue('week', initialWeek);
}
}
}
}, [projectFlockKandangLookup?.project_flock_kandang_id, recordingsData]);
}, [
projectFlockKandangLookup?.chick_in_date,
projectFlockKandangLookup?.project_flock_kandang_id,
recordingsData,
formik.values.date,
]);
useEffect(() => {
const unsub = subscribeValidate(() => {
+3 -1
View File
@@ -74,7 +74,8 @@ export class RecordingService extends BaseApiService<
}
async nextDayRecording(
projectFlockId: number
projectFlockId: number,
recordDate?: string
): Promise<BaseApiResponse<NextDayRecording> | undefined> {
return await this.customRequest<BaseApiResponse<NextDayRecording>>(
`next-day`,
@@ -82,6 +83,7 @@ export class RecordingService extends BaseApiService<
method: 'GET',
params: {
project_flock_kandang_id: projectFlockId,
record_date: recordDate,
},
}
);
+1
View File
@@ -76,6 +76,7 @@ export type ProjectFlockKandangLookup = {
quantity: number;
available_quantity?: number;
population: number;
chick_in_date: string;
};
export type ProjectFlockAvailableQuantity = {