diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 5ffa1344..a59952ec 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -31,12 +31,14 @@ import { RecordingApi, ProjectFlockApi, } from '@/services/api/production'; -import { ProductionStandardApi } from '@/services/api/master-data'; +import { ProductionStandardApi, ProductApi } from '@/services/api/master-data'; import { ProductionStandard, StandardDetails, } from '@/types/api/master-data/production-standard'; +import { Product } from '@/types/api/master-data/product'; import { LocationApi } from '@/services/api/master-data'; +import { SystemSettingsApi } from '@/services/api/system-settings'; import { ProductWarehouseApi } from '@/services/api/inventory'; import { ProductWarehouse } from '@/types/api/inventory/product-warehouse'; @@ -499,6 +501,20 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { type, ]); + // ===== MIGRATION MODE ===== + const { data: systemSettingsResponse } = useSWR( + SystemSettingsApi.basePath, + SystemSettingsApi.getAllFetcher + ); + + const isMigrationMode = useMemo(() => { + if (!isResponseSuccess(systemSettingsResponse)) return false; + const setting = systemSettingsResponse.data.find( + (s) => s.key === 'allow_negative_pakan_ovk' + ); + return setting?.value === 'true'; + }, [systemSettingsResponse]); + // ===== PAYLOAD CREATION HELPERS ===== const createGrowingPayload = useCallback( (values: RecordingGrowingFormValues) => { @@ -519,7 +535,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ? (values.stocks ?? []) .filter((s) => s.product_warehouse_id && s.qty) .map((stock) => ({ - product_warehouse_id: stock.product_warehouse_id, + // In migration mode, product_warehouse_id field holds product.id; + // send it as product_id so the backend auto-creates the warehouse entry. + ...(isMigrationMode + ? { product_id: stock.product_warehouse_id } + : { product_warehouse_id: stock.product_warehouse_id }), qty: Number(stock.qty) || 0, })) : []; @@ -531,7 +551,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ...(depletions.length > 0 && { depletions }), }; }, - [recordingRestriction.canEditStock, recordingRestriction.canEditDepletion] + [ + isMigrationMode, + recordingRestriction.canEditStock, + recordingRestriction.canEditDepletion, + ] ); const createLayingPayload = useCallback( @@ -561,7 +585,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ? values.stocks .filter((s) => s.product_warehouse_id && s.qty) .map((stock) => ({ - product_warehouse_id: stock.product_warehouse_id, + ...(isMigrationMode + ? { product_id: stock.product_warehouse_id } + : { product_warehouse_id: stock.product_warehouse_id }), qty: Number(stock.qty) || 0, })) : []; @@ -574,7 +600,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ...(eggs && eggs.length > 0 && { eggs }), }; }, - [recordingRestriction.canEditStock] + [isMigrationMode, recordingRestriction.canEditStock] ); const isRecordingEditable = useCallback((recording?: Recording) => { @@ -603,18 +629,51 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { return true; }, []); + // When migration mode ON: fetch all master PAKAN/OVK products (no warehouse entry needed). + // When migration mode OFF: fetch from product-warehouses as usual. const { setInputValue: setStockProductInputValue, - rawData: stockProducts, - isLoadingOptions: isLoadingStockProducts, - loadMore: loadMoreStockProducts, - } = useSelect(ProductWarehouseApi.basePath, 'id', 'product.name', 'search', { - flags: 'PAKAN,OVK', - limit: '100', - available_only: 'false', - location_id: stockProductsLocationId, - ...(selectedKandangId ? { kandang_id: selectedKandangId.toString() } : {}), - }); + rawData: stockProductsPW, + isLoadingOptions: isLoadingStockProductsPW, + loadMore: loadMoreStockProductsPW, + } = useSelect( + isMigrationMode ? null : ProductWarehouseApi.basePath, + 'id', + 'product.name', + 'search', + { + flags: 'PAKAN,OVK', + limit: '100', + available_only: 'false', + location_id: stockProductsLocationId, + ...(selectedKandangId + ? { kandang_id: selectedKandangId.toString() } + : {}), + } + ); + + const { + setInputValue: setStockMasterInputValue, + rawData: stockProductsMaster, + isLoadingOptions: isLoadingStockProductsMaster, + loadMore: loadMoreStockProductsMaster, + } = useSelect( + isMigrationMode ? ProductApi.basePath : null, + 'id', + 'name', + 'search', + { flags: 'PAKAN,OVK', limit: '100' } + ); + + const isLoadingStockProducts = isMigrationMode + ? isLoadingStockProductsMaster + : isLoadingStockProductsPW; + const loadMoreStockProducts = isMigrationMode + ? loadMoreStockProductsMaster + : loadMoreStockProductsPW; + const setStockInputValue = isMigrationMode + ? setStockMasterInputValue + : setStockProductInputValue; const { rawData: depletionProductsData, @@ -999,9 +1058,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { useEffect(() => { const items: Array = []; - if (isResponseSuccess(stockProducts)) { + if (!isMigrationMode && isResponseSuccess(stockProductsPW)) { items.push( - ...((stockProducts.data as unknown as ProductWarehouse[]) ?? []) + ...((stockProductsPW.data as unknown as ProductWarehouse[]) ?? []) ); } @@ -1035,7 +1094,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { mergeKnownProductWarehouses(items); }, [ - stockProducts, + isMigrationMode, + stockProductsPW, depletionProductsData, eggProductsData, initialValues, @@ -1066,9 +1126,20 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ); const unifiedStockProducts = useMemo(() => { - const options = isResponseSuccess(stockProducts) + if (isMigrationMode) { + // In migration mode, show all master PAKAN/OVK products (no warehouse context). + // value = product.id; submission will send product_id to the backend. + const options: OptionType[] = isResponseSuccess(stockProductsMaster) + ? (stockProductsMaster.data as unknown as Product[]) + .map((p) => ({ value: p.id, label: p.name })) + .sort((a, b) => a.label.localeCompare(b.label)) + : []; + return options; + } + + const options = isResponseSuccess(stockProductsPW) ? buildProductWarehouseOptions( - stockProducts.data as unknown as ProductWarehouse[] + stockProductsPW.data as unknown as ProductWarehouse[] ) : []; @@ -1085,7 +1156,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { return options; }, [ - stockProducts, + isMigrationMode, + stockProductsMaster, + stockProductsPW, buildProductWarehouseOptions, initialValues, type, @@ -2797,7 +2870,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { product.value === stock.product_warehouse_id ) || null } - onInputChange={setStockProductInputValue} + onInputChange={setStockInputValue} onChange={(selectedOption) => { const option = selectedOption as OptionType | null;