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 readOnly
disabled disabled
className={{
input: 'bg-base-200',
}}
/> />
<TextInput <TextInput
label='Lokasi' label='Lokasi'
@@ -1382,9 +1379,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
} }
readOnly readOnly
disabled disabled
className={{
input: 'bg-base-200',
}}
/> />
</div> </div>
</Card> </Card>
@@ -1433,9 +1427,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
} }
readOnly readOnly
disabled disabled
className={{
input: 'bg-base-200',
}}
/> />
<TextInput <TextInput
label='Lokasi' label='Lokasi'
@@ -1446,9 +1437,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
} }
readOnly readOnly
disabled disabled
className={{
input: 'bg-base-200',
}}
/> />
</div> </div>
</Card> </Card>
@@ -164,6 +164,9 @@ export const RecordingLayingFormSchema: Yup.ObjectSchema<RecordingLayingFormSche
export const UpdateRecordingGrowingFormSchema = export const UpdateRecordingGrowingFormSchema =
RecordingGrowingFormSchema.shape({ 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() project_flock_kandang_id: Yup.number()
.default(0) .default(0)
.typeError('Project Flock Kandang wajib diisi!') .typeError('Project Flock Kandang wajib diisi!')
@@ -176,6 +179,9 @@ export const UpdateRecordingGrowingFormSchema =
}); });
export const UpdateRecordingLayingFormSchema = RecordingLayingFormSchema.shape({ 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() project_flock_kandang_id: Yup.number()
.default(0) .default(0)
.typeError('Project Flock Kandang wajib diisi!') .typeError('Project Flock Kandang wajib diisi!')
@@ -217,13 +223,25 @@ export const getRecordingGrowingFormInitialValues = (
project_flock_id: 0, project_flock_id: 0,
kandang: null, kandang: null,
kandang_id: 0, kandang_id: 0,
project_flock_kandang: initialValues?.project_flock_kandang_id project_flock_kandang:
? { (initialValues?.project_flock_kandang_id ??
value: initialValues.project_flock_kandang_id, initialValues?.project_flock?.project_flock_kandang_id)
label: `Project Flock #${initialValues.project_flock_kandang_id}`, ? {
} value:
: null, initialValues?.project_flock_kandang_id ??
project_flock_kandang_id: initialValues?.project_flock_kandang_id ?? 0, 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) => ({ stocks: initialValues?.stocks?.map((stock) => ({
product_warehouse_id: stock.product_warehouse_id, product_warehouse_id: stock.product_warehouse_id,
qty: qty:
@@ -554,15 +554,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
const nextDayRecordingUrl = useMemo(() => { const nextDayRecordingUrl = useMemo(() => {
if (!projectFlockKandangLookup) return null; if (!projectFlockKandangLookup) return null;
const projectFlockKandangId = projectFlockKandangLookup.id; const projectFlockKandangId = projectFlockKandangLookup.id;
return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}`; return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}&record_date=${selectedRecordDate}`;
}, [projectFlockKandangLookup]); }, [projectFlockKandangLookup, selectedRecordDate]);
const { data: nextDayRecordingData } = useSWR( const { data: nextDayRecordingData } = useSWR(
nextDayRecordingUrl, nextDayRecordingUrl,
nextDayRecordingUrl nextDayRecordingUrl
? () => { ? () => {
const projectFlockKandangId = projectFlockKandangLookup!.id; const projectFlockKandangId = projectFlockKandangLookup!.id;
return RecordingApi.nextDayRecording(projectFlockKandangId); return RecordingApi.nextDayRecording(
projectFlockKandangId,
selectedRecordDate
);
} }
: null : null
); );
@@ -1075,14 +1078,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
if ((type as 'add' | 'edit' | 'detail') === 'detail') return null; if ((type as 'add' | 'edit' | 'detail') === 'detail') return null;
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 requestedUsage = Number(stock.qty) || 0;
if (requestedUsage > availableStock) {
return `Jumlah pakai melebihi stok tersedia! Maksimal: ${formatNumber(availableStock)}`;
}
return null; return null;
}, },
[formik.values.stocks, getAvailableStock, type] [formik.values.stocks, type]
); );
const getStockUsageAdornment = useCallback( const getStockUsageAdornment = useCallback(
@@ -1096,7 +1094,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
if (requestedUsage > 0) { if (requestedUsage > 0) {
return ( return (
<span className='text-sm text-gray-600 whitespace-nowrap'> <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> </span>
); );
} }
@@ -2443,7 +2444,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
); );
}} }}
options={unifiedStockProducts} options={unifiedStockProducts}
placeholder='Pilih Produk' placeholder={
!formik.values.project_flock_kandang_id
? 'Pilih kandang terlebih dahulu'
: 'Pilih Produk'
}
isLoading={isLoadingStockProducts} isLoading={isLoadingStockProducts}
onMenuScrollToBottom={loadMoreStockProducts} onMenuScrollToBottom={loadMoreStockProducts}
isError={ isError={
@@ -2464,7 +2469,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
wrapper: 'w-full min-w-48', wrapper: 'w-full min-w-48',
}} }}
isSearchable isSearchable
isDisabled={type === 'detail'} isDisabled={
type === 'detail' ||
!formik.values.project_flock_kandang_id
}
isClearable={type !== 'detail'} isClearable={type !== 'detail'}
startAdornment={ startAdornment={
stock.product_warehouse_id stock.product_warehouse_id
@@ -399,23 +399,58 @@ const UniformityForm = ({
// ===== SIDE EFFECTS ===== // ===== SIDE EFFECTS =====
useEffect(() => { useEffect(() => {
if ( if (
projectFlockKandangLookup?.chick_in_date &&
projectFlockKandangLookup?.project_flock_kandang_id && projectFlockKandangLookup?.project_flock_kandang_id &&
isResponseSuccess(recordingsData) && isResponseSuccess(recordingsData) &&
recordingsData.data recordingsData.data
) { ) {
const matchingRecording = recordingsData.data.find( const matchingRecordings = recordingsData.data.filter(
(recording: Recording) => (recording: Recording) =>
recording.project_flock?.project_flock_kandang_id === recording.project_flock?.project_flock_kandang_id ===
projectFlockKandangLookup.project_flock_kandang_id projectFlockKandangLookup.project_flock_kandang_id
); );
if (matchingRecording?.project_flock?.production_standart?.week) { matchingRecordings.sort(
const weekValue = (a: Recording, b: Recording) =>
matchingRecording.project_flock.production_standart.week; new Date(a.record_datetime).getTime() -
formik.setFieldValue('week', weekValue); 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(() => { useEffect(() => {
const unsub = subscribeValidate(() => { const unsub = subscribeValidate(() => {
+3 -1
View File
@@ -74,7 +74,8 @@ export class RecordingService extends BaseApiService<
} }
async nextDayRecording( async nextDayRecording(
projectFlockId: number projectFlockId: number,
recordDate?: string
): Promise<BaseApiResponse<NextDayRecording> | undefined> { ): Promise<BaseApiResponse<NextDayRecording> | undefined> {
return await this.customRequest<BaseApiResponse<NextDayRecording>>( return await this.customRequest<BaseApiResponse<NextDayRecording>>(
`next-day`, `next-day`,
@@ -82,6 +83,7 @@ export class RecordingService extends BaseApiService<
method: 'GET', method: 'GET',
params: { params: {
project_flock_kandang_id: projectFlockId, project_flock_kandang_id: projectFlockId,
record_date: recordDate,
}, },
} }
); );
+1
View File
@@ -76,6 +76,7 @@ export type ProjectFlockKandangLookup = {
quantity: number; quantity: number;
available_quantity?: number; available_quantity?: number;
population: number; population: number;
chick_in_date: string;
}; };
export type ProjectFlockAvailableQuantity = { export type ProjectFlockAvailableQuantity = {