mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE): adding 4 input scenario marketing type
This commit is contained in:
@@ -208,6 +208,7 @@ const SalesOrderFormModal = ({
|
|||||||
convertion_unit: normalizedConvertionUnit,
|
convertion_unit: normalizedConvertionUnit,
|
||||||
weight_per_convertion:
|
weight_per_convertion:
|
||||||
product.weight_per_convertion ?? undefined,
|
product.weight_per_convertion ?? undefined,
|
||||||
|
week: product.week?.value ?? undefined,
|
||||||
} as CreateSalesOrderProductPayload;
|
} as CreateSalesOrderProductPayload;
|
||||||
}),
|
}),
|
||||||
} as CreateSalesOrderPayload)
|
} as CreateSalesOrderPayload)
|
||||||
|
|||||||
@@ -115,14 +115,24 @@ export const SalesProductToFieldValues = (
|
|||||||
qty: product.qty,
|
qty: product.qty,
|
||||||
avg_weight: product.avg_weight,
|
avg_weight: product.avg_weight,
|
||||||
total_price: product.total_price,
|
total_price: product.total_price,
|
||||||
marketing_type: {
|
marketing_type: product.marketing_type
|
||||||
value: product.marketing_type,
|
? {
|
||||||
label: formatTitleCase(product.marketing_type),
|
value: product.marketing_type,
|
||||||
},
|
label: formatTitleCase(product.marketing_type),
|
||||||
convertion_unit: {
|
}
|
||||||
value: product.convertion_unit,
|
: null,
|
||||||
label: formatTitleCase(product.convertion_unit),
|
convertion_unit: product.convertion_unit
|
||||||
},
|
? {
|
||||||
|
value: product.convertion_unit,
|
||||||
|
label: formatTitleCase(product.convertion_unit),
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
week: product.week
|
||||||
|
? {
|
||||||
|
value: product.week,
|
||||||
|
label: `Week ${product.week}`,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
total_peti: product.total_peti,
|
total_peti: product.total_peti,
|
||||||
weight_per_convertion: product.weight_per_convertion,
|
weight_per_convertion: product.weight_per_convertion,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,14 @@ type SalesOrderProductSchemaType = {
|
|||||||
price_sisa_berat?: number | null | undefined;
|
price_sisa_berat?: number | null | undefined;
|
||||||
/** Harga per butir telur untuk TELUR + QTY */
|
/** Harga per butir telur untuk TELUR + QTY */
|
||||||
price_per_qty?: number | null | undefined;
|
price_per_qty?: number | null | undefined;
|
||||||
|
/** Week untuk ayam pullet */
|
||||||
|
week?:
|
||||||
|
| {
|
||||||
|
value?: number;
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
| null
|
||||||
|
| undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> =
|
export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> =
|
||||||
@@ -88,6 +96,28 @@ export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaTy
|
|||||||
sisa_berat: Yup.number().nullable().optional().notRequired(),
|
sisa_berat: Yup.number().nullable().optional().notRequired(),
|
||||||
price_sisa_berat: Yup.number().nullable().optional().notRequired(),
|
price_sisa_berat: Yup.number().nullable().optional().notRequired(),
|
||||||
price_per_qty: Yup.number().nullable().optional().notRequired(),
|
price_per_qty: Yup.number().nullable().optional().notRequired(),
|
||||||
|
week: Yup.object({
|
||||||
|
value: Yup.number(),
|
||||||
|
label: Yup.string(),
|
||||||
|
})
|
||||||
|
.nullable()
|
||||||
|
.default(null)
|
||||||
|
.when('marketing_type', {
|
||||||
|
is: (marketingType: { value: string } | null | undefined) =>
|
||||||
|
marketingType?.value?.toLowerCase() === 'ayam_pullet',
|
||||||
|
then: (schema) =>
|
||||||
|
schema
|
||||||
|
.shape({
|
||||||
|
value: Yup.number().required(
|
||||||
|
'Week wajib diisi untuk Ayam Pullet!'
|
||||||
|
),
|
||||||
|
label: Yup.string().required(
|
||||||
|
'Week wajib diisi untuk Ayam Pullet!'
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.required('Week wajib diisi untuk Ayam Pullet!'),
|
||||||
|
otherwise: (schema) => schema.optional().notRequired(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SalesOrderProductFormValues = Yup.InferType<
|
export type SalesOrderProductFormValues = Yup.InferType<
|
||||||
|
|||||||
+24
-12
@@ -70,8 +70,10 @@ const SalesOrderProductForm = ({
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const initialPriceSisaBerat =
|
const initialPriceSisaBerat =
|
||||||
Number(initialValues?.total_price) -
|
initialValues?.total_price && initialValues?.total_peti
|
||||||
initialPricePerConvertion * Number(initialValues?.total_peti);
|
? Number(initialValues.total_price) -
|
||||||
|
initialPricePerConvertion * Number(initialValues.total_peti)
|
||||||
|
: 0;
|
||||||
|
|
||||||
const [hasSisaBerat, setHasSisaBerat] = useState<boolean>(
|
const [hasSisaBerat, setHasSisaBerat] = useState<boolean>(
|
||||||
initialSisaBerat > 0
|
initialSisaBerat > 0
|
||||||
@@ -103,6 +105,7 @@ const SalesOrderProductForm = ({
|
|||||||
price_per_qty: initialValues?.price_per_qty ?? null,
|
price_per_qty: initialValues?.price_per_qty ?? null,
|
||||||
sisa_berat: initialSisaBerat,
|
sisa_berat: initialSisaBerat,
|
||||||
price_sisa_berat: initialPriceSisaBerat,
|
price_sisa_berat: initialPriceSisaBerat,
|
||||||
|
week: initialValues?.week ?? null,
|
||||||
},
|
},
|
||||||
validationSchema: SalesOrderProductSchema,
|
validationSchema: SalesOrderProductSchema,
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
@@ -122,11 +125,11 @@ const SalesOrderProductForm = ({
|
|||||||
loadMore: loadMoreKandang,
|
loadMore: loadMoreKandang,
|
||||||
} = useSelect<Kandang>(WarehouseApi.basePath, 'id', 'name');
|
} = useSelect<Kandang>(WarehouseApi.basePath, 'id', 'name');
|
||||||
|
|
||||||
// Options Weeks dari minggu 1 - 22
|
// Options Week dari minggu 1 - 22
|
||||||
const optionsWeeks = useMemo(() => {
|
const optionsWeek = useMemo(() => {
|
||||||
return Array.from({ length: 22 }, (_, i) => ({
|
return Array.from({ length: 22 }, (_, i) => ({
|
||||||
value: i + 1,
|
value: i + 1,
|
||||||
label: `Weeks ${i + 1}`,
|
label: `Week ${i + 1}`,
|
||||||
}));
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -205,6 +208,7 @@ const SalesOrderProductForm = ({
|
|||||||
weight_per_convertion: null,
|
weight_per_convertion: null,
|
||||||
price_per_convertion: null,
|
price_per_convertion: null,
|
||||||
uom: '',
|
uom: '',
|
||||||
|
week: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -256,6 +260,10 @@ const SalesOrderProductForm = ({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleBlurField('week');
|
||||||
|
}, [formik.values.week]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<form
|
<form
|
||||||
@@ -452,20 +460,24 @@ const SalesOrderProductForm = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Konversi Satuan Weeks Pullet */}
|
{/* Konversi Satuan Week Pullet */}
|
||||||
{/* {formik.values.marketing_type?.value.toLowerCase() ===
|
{formik.values.marketing_type?.value.toLowerCase() ===
|
||||||
'ayam_pullet' && (
|
'ayam_pullet' && (
|
||||||
<SelectInputRadio
|
<SelectInputRadio
|
||||||
required
|
required
|
||||||
label='Minggu'
|
label='Minggu'
|
||||||
options={optionsWeeks}
|
options={optionsWeek}
|
||||||
value={formik.values.weeks || undefined}
|
value={
|
||||||
|
formik.values.week?.value
|
||||||
|
? (formik.values.week as { value: number; label: string })
|
||||||
|
: null
|
||||||
|
}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue('weeks', val);
|
formik.setFieldValue('week', val);
|
||||||
}}
|
}}
|
||||||
placeholder='Pilih Weeks'
|
placeholder='Pilih Week'
|
||||||
/>
|
/>
|
||||||
)} */}
|
)}
|
||||||
|
|
||||||
{/* Total Peti */}
|
{/* Total Peti */}
|
||||||
{formik.values.convertion_unit?.value.toLowerCase() === 'peti' && (
|
{formik.values.convertion_unit?.value.toLowerCase() === 'peti' && (
|
||||||
|
|||||||
@@ -222,12 +222,21 @@ const SalesOrderProductTable = ({
|
|||||||
{item.product_warehouse?.label}
|
{item.product_warehouse?.label}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
{item.marketing_type?.value.toLowerCase() === 'telur' && (
|
||||||
<td className='text-sm px-4 py-3'>Tipe Konversi</td>
|
<tr>
|
||||||
<td className='text-sm px-4 py-3'>
|
<td className='text-sm px-4 py-3'>Tipe Konversi</td>
|
||||||
{item.convertion_unit?.label}
|
<td className='text-sm px-4 py-3'>
|
||||||
</td>
|
{item.convertion_unit?.label}
|
||||||
</tr>
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
{item.marketing_type?.value.toLowerCase() ===
|
||||||
|
'ayam_pullet' && (
|
||||||
|
<tr>
|
||||||
|
<td className='text-sm px-4 py-3'>Tipe Konversi</td>
|
||||||
|
<td className='text-sm px-4 py-3'>{item.week?.label}</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
{item.convertion_unit?.value.toLowerCase() === 'peti' && (
|
{item.convertion_unit?.value.toLowerCase() === 'peti' && (
|
||||||
<tr>
|
<tr>
|
||||||
<td className='text-sm px-4 py-3'>Total Peti</td>
|
<td className='text-sm px-4 py-3'>Total Peti</td>
|
||||||
@@ -236,25 +245,30 @@ const SalesOrderProductTable = ({
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
<tr>
|
{item.marketing_type?.value.toLowerCase() !== 'trading' && (
|
||||||
<td className='text-sm px-4 py-3'>Total Bobot</td>
|
<>
|
||||||
<td className='text-sm px-4 py-3'>
|
<tr>
|
||||||
{item.total_weight
|
<td className='text-sm px-4 py-3'>Total Bobot</td>
|
||||||
? formatNumber(
|
<td className='text-sm px-4 py-3'>
|
||||||
parseFloat(item.total_weight as string)
|
{item.total_weight
|
||||||
) + ' Kg'
|
? formatNumber(
|
||||||
: '-'}
|
parseFloat(item.total_weight as string)
|
||||||
</td>
|
) + ' Kg'
|
||||||
</tr>
|
: '0 Kg'}
|
||||||
<tr>
|
</td>
|
||||||
<td className='text-sm px-4 py-3'>Avg Bobot</td>
|
</tr>
|
||||||
<td className='text-sm px-4 py-3'>
|
<tr>
|
||||||
{item.avg_weight
|
<td className='text-sm px-4 py-3'>Avg Bobot</td>
|
||||||
? formatNumber(parseFloat(item.avg_weight as string)) +
|
<td className='text-sm px-4 py-3'>
|
||||||
' Kg'
|
{item.avg_weight
|
||||||
: '-'}
|
? formatNumber(
|
||||||
</td>
|
parseFloat(item.avg_weight as string)
|
||||||
</tr>
|
) + ' Kg'
|
||||||
|
: '0 Kg'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<tr>
|
<tr>
|
||||||
<td className='text-sm px-4 py-3'>
|
<td className='text-sm px-4 py-3'>
|
||||||
{item.marketing_type?.value === 'telur'
|
{item.marketing_type?.value === 'telur'
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export type MarketingFormValues = {
|
|||||||
total_price?: string | number;
|
total_price?: string | number;
|
||||||
marketing_type?: { value: string; label: string } | null;
|
marketing_type?: { value: string; label: string } | null;
|
||||||
convertion_unit?: { value: string; label: string } | null;
|
convertion_unit?: { value: string; label: string } | null;
|
||||||
weeks?: { value: number; label: string } | null;
|
week?: { value?: number; label?: string } | null;
|
||||||
weight_per_convertion?: number | null;
|
weight_per_convertion?: number | null;
|
||||||
price_per_convertion?: number | null;
|
price_per_convertion?: number | null;
|
||||||
total_peti?: number | null;
|
total_peti?: number | null;
|
||||||
@@ -100,7 +100,7 @@ export const calculateAyamPullet = (
|
|||||||
): void => {
|
): void => {
|
||||||
const { values, setFieldValue } = ctx;
|
const { values, setFieldValue } = ctx;
|
||||||
const unitPrice = Number(values.unit_price || 0);
|
const unitPrice = Number(values.unit_price || 0);
|
||||||
const weeks = Number(values.weeks?.value || 0);
|
const week = Number(values.week?.value || 0);
|
||||||
const qty = Number(values.qty || 0);
|
const qty = Number(values.qty || 0);
|
||||||
const avgWeight = Number(values.avg_weight || 0);
|
const avgWeight = Number(values.avg_weight || 0);
|
||||||
const totalWeight = Number(values.total_weight || 0);
|
const totalWeight = Number(values.total_weight || 0);
|
||||||
@@ -108,11 +108,11 @@ export const calculateAyamPullet = (
|
|||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'unit_price':
|
case 'unit_price':
|
||||||
case 'weeks':
|
case 'week':
|
||||||
case 'qty': {
|
case 'qty': {
|
||||||
// total_price = unit_price × weeks × qty
|
// total_price = unit_price × week × qty
|
||||||
if (unitPrice > 0 && weeks > 0 && qty > 0) {
|
if (unitPrice > 0 && week > 0 && qty > 0) {
|
||||||
setFieldValue('total_price', roundPrice(unitPrice * weeks * qty));
|
setFieldValue('total_price', roundPrice(unitPrice * week * qty));
|
||||||
}
|
}
|
||||||
// total_weight = avg_weight × qty
|
// total_weight = avg_weight × qty
|
||||||
if (avgWeight > 0 && qty > 0) {
|
if (avgWeight > 0 && qty > 0) {
|
||||||
@@ -133,9 +133,9 @@ export const calculateAyamPullet = (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'total_price': {
|
case 'total_price': {
|
||||||
// Reverse: unit_price = total_price / (weeks × qty)
|
// Reverse: unit_price = total_price / (week × qty)
|
||||||
if (totalPrice > 0 && weeks > 0 && qty > 0) {
|
if (totalPrice > 0 && week > 0 && qty > 0) {
|
||||||
setFieldValue('unit_price', roundPrice(totalPrice / (weeks * qty)));
|
setFieldValue('unit_price', roundPrice(totalPrice / (week * qty)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-11
@@ -40,6 +40,8 @@ export type BaseSalesOrder = {
|
|||||||
convertion_unit: string;
|
convertion_unit: string;
|
||||||
total_peti: number;
|
total_peti: number;
|
||||||
weight_per_convertion: number;
|
weight_per_convertion: number;
|
||||||
|
/** Umur minggu untuk AYAM_PULLET */
|
||||||
|
week?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BaseDeliveryOrder = {
|
export type BaseDeliveryOrder = {
|
||||||
@@ -115,17 +117,6 @@ export type BaseCreateMarketingProductPayload = {
|
|||||||
avg_weight: string | number | undefined;
|
avg_weight: string | number | undefined;
|
||||||
total_price: string | number | undefined;
|
total_price: string | number | undefined;
|
||||||
marketing_type: string;
|
marketing_type: string;
|
||||||
/**
|
|
||||||
* Tipe konversi untuk TELUR
|
|
||||||
* - "PETI": Penjualan telur dalam satuan peti
|
|
||||||
* - "KG": Penjualan telur dalam satuan kilogram
|
|
||||||
*
|
|
||||||
* Note: Untuk mode "QTY" di FE, tetap kirim "KG" ke BE dengan unit_price yang dinormalisasi
|
|
||||||
* karena BE tidak support convertion_unit "QTY". Workaround:
|
|
||||||
* - FE hitung: total_price = qty × price_per_qty
|
|
||||||
* - FE normalisasi: unit_price = total_price / total_weight
|
|
||||||
* - BE akan hitung: total_price = total_weight × unit_price (hasil sama)
|
|
||||||
*/
|
|
||||||
convertion_unit?: 'PETI' | 'KG';
|
convertion_unit?: 'PETI' | 'KG';
|
||||||
/** Berat per peti (kg), hanya untuk TELUR + PETI */
|
/** Berat per peti (kg), hanya untuk TELUR + PETI */
|
||||||
weight_per_convertion?: number;
|
weight_per_convertion?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user