Merge branch 'dev/hotfix/restu' into 'development'

[FIX/FE] Adjustment Recording Logic

See merge request mbugroup/lti-web-client!226
This commit is contained in:
Rivaldi A N S
2026-01-21 07:42:39 +00:00
2 changed files with 100 additions and 56 deletions
@@ -156,39 +156,39 @@ const productionStandardColumns: ColumnDef<StandardDetails>[] = [
}, },
{ {
accessorKey: 'egg_production_standard_detail.target_hen_house_production', accessorKey: 'egg_production_standard_detail.target_hen_house_production',
header: 'Target Hen House (%)', header: 'Target Hen House (btr)',
cell: (props) => cell: (props) =>
`${ formatNumber(
(props.row.original.egg_production_standard_detail (props.row.original.egg_production_standard_detail
?.target_hen_house_production as number) || 0 ?.target_hen_house_production as number) || 0
}%`, ),
}, },
{ {
accessorKey: 'egg_production_standard_detail.target_egg_weight', accessorKey: 'egg_production_standard_detail.target_egg_weight',
header: 'Target Egg Weight (gram)', header: 'Target Egg Weight (g)',
cell: (props) => cell: (props) =>
formatNumber( `${
(props.row.original.egg_production_standard_detail (props.row.original.egg_production_standard_detail
?.target_egg_weight as number) || 0 ?.target_egg_weight as number) || 0
), } g`,
}, },
{ {
accessorKey: 'egg_production_standard_detail.target_egg_mass', accessorKey: 'egg_production_standard_detail.target_egg_mass',
header: 'Target Egg Mass (gram)', header: 'Target Egg Mass (kg)',
cell: (props) => cell: (props) =>
formatNumber( `${
(props.row.original.egg_production_standard_detail (props.row.original.egg_production_standard_detail
?.target_egg_mass as number) || 0 ?.target_egg_mass as number) || 0
), } kg`,
}, },
{ {
accessorKey: 'egg_production_standard_detail.standard_fcr', accessorKey: 'egg_production_standard_detail.standard_fcr',
header: 'Standard FCR', header: 'Standard FCR (g)',
cell: (props) => cell: (props) =>
formatNumber( `${
(props.row.original.egg_production_standard_detail (props.row.original.egg_production_standard_detail
?.standard_fcr as number) || 0 ?.standard_fcr as number) || 0
), } g`,
}, },
]; ];
@@ -552,23 +552,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
); );
const nextDayRecordingUrl = useMemo(() => { const nextDayRecordingUrl = useMemo(() => {
if (!selectedProjectFlock) return null; if (!projectFlockKandangLookup) return null;
const projectFlockId = const projectFlockKandangId = projectFlockKandangLookup.id;
typeof selectedProjectFlock.value === 'string' return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}`;
? parseInt(selectedProjectFlock.value, 10) }, [projectFlockKandangLookup]);
: selectedProjectFlock.value;
return `${RecordingApi.basePath}/next-day?project_flock_id=${projectFlockId}`;
}, [selectedProjectFlock]);
const { data: nextDayRecordingData } = useSWR( const { data: nextDayRecordingData } = useSWR(
nextDayRecordingUrl, nextDayRecordingUrl,
nextDayRecordingUrl nextDayRecordingUrl
? () => { ? () => {
const projectFlockId = const projectFlockKandangId = projectFlockKandangLookup!.id;
typeof selectedProjectFlock!.value === 'string' return RecordingApi.nextDayRecording(projectFlockKandangId);
? parseInt(selectedProjectFlock!.value, 10)
: selectedProjectFlock!.value;
return RecordingApi.nextDayRecording(projectFlockId);
} }
: null : null
); );
@@ -1180,6 +1174,47 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
[stockProducts] [stockProducts]
); );
const getProductUomSuffix = useCallback(
(productWarehouseId: number, dataSource: 'stock' | 'depletion' | 'egg') => {
if (type !== 'add' && initialValues) {
let items;
if (dataSource === 'stock') {
items = initialValues.stocks;
} else if (dataSource === 'depletion') {
items = initialValues.depletions;
} else if (dataSource === 'egg') {
items = initialValues.eggs;
}
if (items) {
const item = items.find(
(i) => i.product_warehouse_id === productWarehouseId
);
if (item?.product_warehouse?.product?.uom?.name) {
return item.product_warehouse.product.uom.name;
}
}
}
let rawData;
if (dataSource === 'stock') {
rawData = stockProducts;
} else if (dataSource === 'depletion') {
rawData = depletionProductsData;
} else if (dataSource === 'egg') {
rawData = eggProductsData;
}
if (!isResponseSuccess(rawData)) return null;
const data = rawData.data as unknown as ProductWarehouse[];
const productWarehouse = data.find((pw) => pw.id === productWarehouseId);
return productWarehouse?.product.uom.name || null;
},
[stockProducts, depletionProductsData, eggProductsData, initialValues, type]
);
const hasExceededStock = useMemo(() => { const hasExceededStock = useMemo(() => {
if ((type as 'add' | 'edit' | 'detail') === 'detail') return false; if ((type as 'add' | 'edit' | 'detail') === 'detail') return false;
return ( return (
@@ -2113,38 +2148,33 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td className='py-3 font-medium'>FCR</td> <td className='py-3 font-medium'>FCR (g)</td>
<td className='text-center py-3'> <td className='text-center py-3'>
<span className='font-semibold'> <span className='font-semibold'>
{initialValues.fcr_value != null {initialValues.fcr_value != null
? formatNumber(initialValues.fcr_value) ? `${formatNumber(initialValues.fcr_value)} g`
: '-'} : '-'}
</span> </span>
</td> </td>
<td className='text-center py-3 text-gray-600'> <td className='text-center py-3 text-gray-600'>
{initialValues.project_flock?.fcr?.fcr_std != null {initialValues.project_flock?.fcr?.fcr_std != null
? formatNumber( ? `${formatNumber(initialValues.project_flock?.fcr?.fcr_std)} g`
initialValues.project_flock?.fcr?.fcr_std
)
: '-'} : '-'}
</td> </td>
</tr> </tr>
<tr> <tr>
<td className='py-3 font-medium'>Feed Intake (KG)</td> <td className='py-3 font-medium'>Feed Intake (g)</td>
<td className='text-center py-3'> <td className='text-center py-3'>
<span className='font-semibold'> <span className='font-semibold'>
{initialValues.feed_intake != null {initialValues.feed_intake != null
? formatNumber(initialValues.feed_intake) ? `${formatNumber(initialValues.feed_intake)} g`
: '-'} : '-'}
</span> </span>
</td> </td>
<td className='text-center py-3 text-gray-600'> <td className='text-center py-3 text-gray-600'>
{initialValues.project_flock?.production_standart {initialValues.project_flock?.production_standart
?.feed_intake_std != null ?.feed_intake_std != null
? formatNumber( ? `${formatNumber(initialValues.project_flock?.production_standart?.feed_intake_std)} g`
initialValues.project_flock?.production_standart
?.feed_intake_std
)
: '-'} : '-'}
</td> </td>
</tr> </tr>
@@ -2224,51 +2254,43 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td className='py-3 font-medium'>Egg Mass</td> <td className='py-3 font-medium'>Egg Mass (kg)</td>
<td className='text-center py-3'> <td className='text-center py-3'>
<span className='font-semibold'> <span className='font-semibold'>
{initialValues.egg_mass != null {initialValues.egg_mass != null
? formatNumber(initialValues.egg_mass) ? `${formatNumber(initialValues.egg_mass)} kg`
: '-'} : '-'}
</span> </span>
</td> </td>
<td className='text-center py-3 text-gray-600'> <td className='text-center py-3 text-gray-600'>
{initialValues.project_flock?.production_standart {initialValues.project_flock?.production_standart
?.egg_mass_std != null ?.egg_mass_std != null
? formatNumber( ? `${formatNumber(initialValues.project_flock?.production_standart?.egg_mass_std)} kg`
initialValues.project_flock
?.production_standart?.egg_mass_std
)
: '-'} : '-'}
</td> </td>
</tr> </tr>
<tr> <tr>
<td className='py-3 font-medium'> <td className='py-3 font-medium'>Egg Weight (g)</td>
Egg Weight (KG)
</td>
<td className='text-center py-3'> <td className='text-center py-3'>
<span className='font-semibold'> <span className='font-semibold'>
{initialValues.egg_weight != null {initialValues.egg_weight != null
? formatNumber(initialValues.egg_weight) ? `${formatNumber(initialValues.egg_weight)} g`
: '-'} : '-'}
</span> </span>
</td> </td>
<td className='text-center py-3 text-gray-600'> <td className='text-center py-3 text-gray-600'>
{initialValues.project_flock?.production_standart {initialValues.project_flock?.production_standart
?.egg_weight_std != null ?.egg_weight_std != null
? formatNumber( ? `${formatNumber(initialValues.project_flock?.production_standart?.egg_weight_std)} g`
initialValues.project_flock
?.production_standart?.egg_weight_std
)
: '-'} : '-'}
</td> </td>
</tr> </tr>
<tr> <tr>
<td className='py-3 font-medium'>Hen Day</td> <td className='py-3 font-medium'>Hen Day (%)</td>
<td className='text-center py-3'> <td className='text-center py-3'>
<span className='font-semibold'> <span className='font-semibold'>
{initialValues.hen_day != null {initialValues.hen_day != null
? formatNumber(initialValues.hen_day) ? `${formatNumber(initialValues.hen_day)}%`
: '-'} : '-'}
</span> </span>
</td> </td>
@@ -2280,18 +2302,20 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</td> </td>
</tr> </tr>
<tr> <tr>
<td className='py-3 font-medium'>Hen House</td> <td className='py-3 font-medium'>
Hen House (btr)
</td>
<td className='text-center py-3'> <td className='text-center py-3'>
<span className='font-semibold'> <span className='font-semibold'>
{initialValues.hen_house != null {initialValues.hen_house != null
? formatNumber(initialValues.hen_house) ? `${formatNumber(initialValues.hen_house)} btr`
: '-'} : '-'}
</span> </span>
</td> </td>
<td className='text-center py-3 text-gray-600'> <td className='text-center py-3 text-gray-600'>
{initialValues.project_flock?.production_standart {initialValues.project_flock?.production_standart
?.hen_house_std != null ?.hen_house_std != null
? `${initialValues.project_flock?.production_standart?.hen_house_std}%` ? `${formatNumber(initialValues.project_flock?.production_standart?.hen_house_std)} btr`
: '-'} : '-'}
</td> </td>
</tr> </tr>
@@ -2468,6 +2492,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
wrapper: 'w-full min-w-24', wrapper: 'w-full min-w-24',
}} }}
placeholder='Masukkan jumlah pakai' placeholder='Masukkan jumlah pakai'
inputSuffix={
stock.product_warehouse_id
? getProductUomSuffix(
stock.product_warehouse_id,
'stock'
)
: null
}
/> />
{(type as 'add' | 'edit' | 'detail') !== 'detail' && {(type as 'add' | 'edit' | 'detail') !== 'detail' &&
getStockUsageAdornment(idx)} getStockUsageAdornment(idx)}
@@ -2663,6 +2695,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
wrapper: 'w-full min-w-24', wrapper: 'w-full min-w-24',
}} }}
placeholder='Masukkan jumlah deplesi' placeholder='Masukkan jumlah deplesi'
inputSuffix={
depletion.product_warehouse_id
? getProductUomSuffix(
depletion.product_warehouse_id,
'depletion'
)
: null
}
/> />
</td> </td>
{(type as 'add' | 'edit' | 'detail') !== 'detail' && ( {(type as 'add' | 'edit' | 'detail') !== 'detail' && (
@@ -2759,7 +2799,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
)} )}
<th>Kondisi Telur</th> <th>Kondisi Telur</th>
<th>Jumlah</th> <th>Jumlah</th>
<th>Berat (gram)</th> <th>Total Berat (Kilogram)</th>
{(type as 'add' | 'edit' | 'detail') !== 'detail' && ( {(type as 'add' | 'edit' | 'detail') !== 'detail' && (
<th>Action</th> <th>Action</th>
)} )}
@@ -2856,6 +2896,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
wrapper: 'w-full min-w-24', wrapper: 'w-full min-w-24',
}} }}
placeholder='Masukkan jumlah telur' placeholder='Masukkan jumlah telur'
inputSuffix={'Butir'}
/> />
</td> </td>
<td> <td>
@@ -2880,7 +2921,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
className={{ className={{
wrapper: 'w-full min-w-24', wrapper: 'w-full min-w-24',
}} }}
placeholder='Masukkan berat telur (gram)...' placeholder='Masukkan total berat telur (Kilogram)...'
inputSuffix='Kilogram'
/> />
</td> </td>
{(type as 'add' | 'edit' | 'detail') !== 'detail' && ( {(type as 'add' | 'edit' | 'detail') !== 'detail' && (
+2
View File
@@ -1,11 +1,13 @@
import { BaseMetadata } from '@/types/api/api-general'; import { BaseMetadata } from '@/types/api/api-general';
import { Warehouse } from '@/types/api/master-data/warehouse'; import { Warehouse } from '@/types/api/master-data/warehouse';
import { Product } from '@/types/api/master-data/product'; import { Product } from '@/types/api/master-data/product';
import { Uom } from '@/types/api/master-data/uom';
export type BaseProductWarehouse = { export type BaseProductWarehouse = {
id: number; id: number;
product_id: number; product_id: number;
warehouse_id: number; warehouse_id: number;
uom: Uom;
quantity: number; quantity: number;
product: Product; product: Product;
warehouse: Warehouse; warehouse: Warehouse;