From 8c73a8f61af18ffe2c0dc0bcf06a118df9e032b6 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sat, 24 Jan 2026 11:17:13 +0700 Subject: [PATCH 01/21] refactor(FE): Include selected record date in next-day API --- .../pages/production/recording/form/RecordingForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 63d78397..f3d175a1 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -554,8 +554,8 @@ 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, From 52213fc8c4f03437902aabb699b790a7a5e096ce Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sat, 24 Jan 2026 12:51:01 +0700 Subject: [PATCH 02/21] refactor(FE): Add optional location and flock ids --- .../recording/form/RecordingForm.schema.ts | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.schema.ts b/src/components/pages/production/recording/form/RecordingForm.schema.ts index 063c2cc0..b39f94ca 100644 --- a/src/components/pages/production/recording/form/RecordingForm.schema.ts +++ b/src/components/pages/production/recording/form/RecordingForm.schema.ts @@ -164,6 +164,9 @@ export const RecordingLayingFormSchema: Yup.ObjectSchema ({ product_warehouse_id: stock.product_warehouse_id, qty: From 6307cdc0dc199217ae3e44247a784e63834132fe Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sat, 24 Jan 2026 12:53:54 +0700 Subject: [PATCH 03/21] refactor(FE): Send selected record date to next-day API --- .../pages/production/recording/form/RecordingForm.tsx | 5 ++++- src/services/api/production.ts | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index f3d175a1..6ea77373 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -562,7 +562,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { nextDayRecordingUrl ? () => { const projectFlockKandangId = projectFlockKandangLookup!.id; - return RecordingApi.nextDayRecording(projectFlockKandangId); + return RecordingApi.nextDayRecording( + projectFlockKandangId, + selectedRecordDate + ); } : null ); diff --git a/src/services/api/production.ts b/src/services/api/production.ts index 8e66d57e..d481081d 100644 --- a/src/services/api/production.ts +++ b/src/services/api/production.ts @@ -74,7 +74,8 @@ export class RecordingService extends BaseApiService< } async nextDayRecording( - projectFlockId: number + projectFlockId: number, + recordDate?: string ): Promise | undefined> { return await this.customRequest>( `next-day`, @@ -82,6 +83,7 @@ export class RecordingService extends BaseApiService< method: 'GET', params: { project_flock_kandang_id: projectFlockId, + record_date: recordDate, }, } ); From 2d6e8480f5407f24336226d9e5f870b5b8432851 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sat, 24 Jan 2026 13:27:17 +0700 Subject: [PATCH 04/21] refactor(FE): Show detailed stock usage and remove limit check --- .../production/recording/form/RecordingForm.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 6ea77373..24f862d7 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -1078,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( @@ -1099,7 +1094,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { if (requestedUsage > 0) { return ( - (sisa: {formatNumber(remainingStock)}) + (tersedia: {formatNumber(availableStock)} | pakai:{' '} + {formatNumber(requestedUsage)} | sisa:{' '} + {formatNumber(Math.max(remainingStock, 0))} | dipinjam:{' '} + {formatNumber(Math.max(-remainingStock, 0))}) ); } From 1d06c6f02af976460e0b545d6e5e6505efd01a8c Mon Sep 17 00:00:00 2001 From: randy-ar Date: Sat, 24 Jan 2026 14:52:54 +0700 Subject: [PATCH 05/21] fix(FE): fixing injection payload negative not send properly --- .../pages/finance/add/injection/FormFinanceInjection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pages/finance/add/injection/FormFinanceInjection.tsx b/src/components/pages/finance/add/injection/FormFinanceInjection.tsx index ff49005c..07c8e61e 100644 --- a/src/components/pages/finance/add/injection/FormFinanceInjection.tsx +++ b/src/components/pages/finance/add/injection/FormFinanceInjection.tsx @@ -94,7 +94,7 @@ const FormFinanceInjection = ({ return { bank_id: Number(values.bank_id_option?.value) || 0, adjustment_date: formatDate(values.adjustment_date, 'YYYY-MM-DD'), - nominal: Number(values.nominal.replace(/\D/g, '')) || 0, + nominal: isNaN(Number(values.nominal)) ? 0 : Number(values.nominal), notes: values.note, }; }; From caba77d87107d2af840e6ca856010dc8f83a622b Mon Sep 17 00:00:00 2001 From: randy-ar Date: Sun, 25 Jan 2026 14:11:47 +0700 Subject: [PATCH 06/21] fix(FE): fixing bank undefined in detail page --- src/components/pages/finance/FinanceDetail.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/pages/finance/FinanceDetail.tsx b/src/components/pages/finance/FinanceDetail.tsx index 3ee9a7df..12d513d7 100644 --- a/src/components/pages/finance/FinanceDetail.tsx +++ b/src/components/pages/finance/FinanceDetail.tsx @@ -30,7 +30,7 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => { }, { label: 'Jenis Transaksi', - value: finance.transaction_type, + value: formatTitleCase(finance.transaction_type.split('_').join(' ')), }, { label: 'Pihak', @@ -56,7 +56,9 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => { }, { label: 'Nomor Rekening', - value: `${finance.bank?.alias} - ${finance.bank?.account_number} - ${finance.bank?.owner}`, + value: finance.bank?.alias + ? `${finance.bank?.alias} - ${finance.bank?.account_number} - ${finance.bank?.owner}` + : '-', }, { label: `Rekening ${formatTitleCase(finance.party?.type)}`, From 8b1e43cdb95539c839c1ae9d0cb7c1a079811e4f Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sun, 25 Jan 2026 18:00:53 +0700 Subject: [PATCH 07/21] refactor(FE): Set week using chick_in_date and earliest record --- .../uniformity/form/UniformityForm.tsx | 47 ++++++++++++++++--- src/types/api/production/project-flock.d.ts | 1 + 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/components/pages/production/uniformity/form/UniformityForm.tsx b/src/components/pages/production/uniformity/form/UniformityForm.tsx index d7013520..e6b0657d 100644 --- a/src/components/pages/production/uniformity/form/UniformityForm.tsx +++ b/src/components/pages/production/uniformity/form/UniformityForm.tsx @@ -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(() => { diff --git a/src/types/api/production/project-flock.d.ts b/src/types/api/production/project-flock.d.ts index dcc1a348..d3a862d9 100644 --- a/src/types/api/production/project-flock.d.ts +++ b/src/types/api/production/project-flock.d.ts @@ -76,6 +76,7 @@ export type ProjectFlockKandangLookup = { quantity: number; available_quantity?: number; population: number; + chick_in_date: string; }; export type ProjectFlockAvailableQuantity = { From 56326cc8d242b121eecf195dd4370224780dac97 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 26 Jan 2026 09:41:50 +0700 Subject: [PATCH 08/21] refactor(FE): Disable product select until kandang chosen --- .../pages/production/recording/form/RecordingForm.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 24f862d7..4603832c 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -2444,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={ @@ -2465,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 From 47e51e01056c87e0c04501a61c672206b100046f Mon Sep 17 00:00:00 2001 From: rstubryan Date: Mon, 26 Jan 2026 09:51:37 +0700 Subject: [PATCH 09/21] refactor(FE): Remove redundant input bg class from TextInputs --- .../pages/inventory/movement/form/MovementForm.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/components/pages/inventory/movement/form/MovementForm.tsx b/src/components/pages/inventory/movement/form/MovementForm.tsx index bdf37487..d4d175e2 100644 --- a/src/components/pages/inventory/movement/form/MovementForm.tsx +++ b/src/components/pages/inventory/movement/form/MovementForm.tsx @@ -1369,9 +1369,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { } readOnly disabled - className={{ - input: 'bg-base-200', - }} /> { } readOnly disabled - className={{ - input: 'bg-base-200', - }} /> @@ -1433,9 +1427,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { } readOnly disabled - className={{ - input: 'bg-base-200', - }} /> { } readOnly disabled - className={{ - input: 'bg-base-200', - }} /> From 85f4a5deaac7c7b251da4a309f48bd8659133943 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Mon, 26 Jan 2026 16:08:23 +0700 Subject: [PATCH 10/21] fix(FE): adding select injection type for positive and negative value --- .../pages/finance/FinanceDetail.tsx | 6 ++- .../injection/FormFinanceInjection.schema.ts | 2 + .../add/injection/FormFinanceInjection.tsx | 43 ++++++++++++++++++- src/config/constant.ts | 5 +++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/components/pages/finance/FinanceDetail.tsx b/src/components/pages/finance/FinanceDetail.tsx index 12d513d7..622fff6f 100644 --- a/src/components/pages/finance/FinanceDetail.tsx +++ b/src/components/pages/finance/FinanceDetail.tsx @@ -66,7 +66,11 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => { }, { label: 'Nominal', - value: formatCurrency(Math.abs(finance.nominal)), + value: formatCurrency( + finance.transaction_type === 'INJECTION' + ? finance.nominal + : Math.abs(finance.nominal) + ), }, ].filter((item) => { // Hide party account number row if transaction type is INJECTION diff --git a/src/components/pages/finance/add/injection/FormFinanceInjection.schema.ts b/src/components/pages/finance/add/injection/FormFinanceInjection.schema.ts index c6118af6..304bac18 100644 --- a/src/components/pages/finance/add/injection/FormFinanceInjection.schema.ts +++ b/src/components/pages/finance/add/injection/FormFinanceInjection.schema.ts @@ -5,6 +5,7 @@ import * as Yup from 'yup'; export type InjectionFormValues = { bank_id_option: OptionType | null; adjustment_date: string; + injection_type?: OptionType | null | undefined; nominal: string; note: string; }; @@ -18,6 +19,7 @@ export const InjectionFormSchema = Yup.object({ (value) => value !== null && value !== undefined ), adjustment_date: Yup.string().required('Tanggal penyesuaian wajib diisi'), + injection_type: Yup.mixed().nullable().required('Tipe injeksi wajib diisi'), nominal: Yup.string().required('Nominal wajib diisi'), note: Yup.string().required('Catatan wajib diisi'), }); diff --git a/src/components/pages/finance/add/injection/FormFinanceInjection.tsx b/src/components/pages/finance/add/injection/FormFinanceInjection.tsx index 07c8e61e..a4b77baf 100644 --- a/src/components/pages/finance/add/injection/FormFinanceInjection.tsx +++ b/src/components/pages/finance/add/injection/FormFinanceInjection.tsx @@ -28,6 +28,10 @@ import { useCallback, useMemo, useState } from 'react'; import toast from 'react-hot-toast'; import Alert from '@/components/Alert'; import { Icon } from '@iconify/react'; +import { + FINANCE_INJECTION_STATUS, + FINANCE_INJECTION_TYPE_OPTIONS, +} from '@/config/constant'; interface FormFinanceInjectionProps { type?: 'add' | 'edit'; @@ -51,6 +55,11 @@ const FormFinanceInjection = ({ } : null, adjustment_date: initialValues?.payment_date || '', + injection_type: initialValues?.nominal + ? initialValues.nominal < 0 + ? FINANCE_INJECTION_TYPE_OPTIONS[1] + : FINANCE_INJECTION_TYPE_OPTIONS[0] + : FINANCE_INJECTION_TYPE_OPTIONS[0], nominal: initialValues?.nominal?.toString() || '', note: initialValues?.notes || '', }; @@ -94,7 +103,10 @@ const FormFinanceInjection = ({ return { bank_id: Number(values.bank_id_option?.value) || 0, adjustment_date: formatDate(values.adjustment_date, 'YYYY-MM-DD'), - nominal: isNaN(Number(values.nominal)) ? 0 : Number(values.nominal), + nominal: + values.injection_type?.value == 'POSITIVE' + ? Math.abs(Number(values.nominal)) + : -Math.abs(Number(values.nominal)), notes: values.note, }; }; @@ -203,6 +215,24 @@ const FormFinanceInjection = ({ } required /> + { + formik.setFieldValue('injection_type', value); + }} + isError={Boolean( + formik.touched.injection_type && formik.errors.injection_type + )} + errorMessage={ + formik.touched.injection_type && formik.errors.injection_type + ? formik.errors.injection_type + : '' + } + required + /> + ) : formik.values.injection_type?.value === 'NEGATIVE' ? ( + + ) : ( + '' + ) + } />