mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE): calculation penjualan telur + peti
This commit is contained in:
@@ -14,8 +14,6 @@ import {
|
|||||||
DeliveryProductToFieldValues,
|
DeliveryProductToFieldValues,
|
||||||
mergeSOwithDO,
|
mergeSOwithDO,
|
||||||
SalesProductToFieldValues,
|
SalesProductToFieldValues,
|
||||||
} from '@/components/pages/marketing/form/MarketingForm';
|
|
||||||
import {
|
|
||||||
DeliveryOrderFormValues,
|
DeliveryOrderFormValues,
|
||||||
DeliveryOrderSchema,
|
DeliveryOrderSchema,
|
||||||
getFilledMarketingFormInitialValues,
|
getFilledMarketingFormInitialValues,
|
||||||
@@ -210,7 +208,6 @@ 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.weeks?.value ?? undefined,
|
|
||||||
} as CreateSalesOrderProductPayload;
|
} as CreateSalesOrderProductPayload;
|
||||||
}),
|
}),
|
||||||
} as CreateSalesOrderPayload)
|
} as CreateSalesOrderPayload)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export type SalesOrderFormValues = Yup.InferType<typeof SalesOrderSchema>;
|
|||||||
export type DeliveryOrderFormValues = Yup.InferType<typeof DeliveryOrderSchema>;
|
export type DeliveryOrderFormValues = Yup.InferType<typeof DeliveryOrderSchema>;
|
||||||
|
|
||||||
// ================ Helper Function ================
|
// ================ Helper Function ================
|
||||||
const SalesProductToFieldValues = (
|
export const SalesProductToFieldValues = (
|
||||||
product: BaseSalesOrder
|
product: BaseSalesOrder
|
||||||
): SalesOrderProductFormValues => {
|
): SalesOrderProductFormValues => {
|
||||||
return {
|
return {
|
||||||
@@ -123,9 +123,11 @@ const SalesProductToFieldValues = (
|
|||||||
value: product.convertion_unit,
|
value: product.convertion_unit,
|
||||||
label: formatTitleCase(product.convertion_unit),
|
label: formatTitleCase(product.convertion_unit),
|
||||||
},
|
},
|
||||||
|
total_peti: product.total_peti,
|
||||||
|
weight_per_convertion: product.weight_per_convertion,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const DeliveryProductToFieldValues = (
|
export const DeliveryProductToFieldValues = (
|
||||||
salesOrders: BaseSalesOrder[],
|
salesOrders: BaseSalesOrder[],
|
||||||
delivery: BaseDeliveryOrder
|
delivery: BaseDeliveryOrder
|
||||||
): DeliveryOrderProductFormValues[] => {
|
): DeliveryOrderProductFormValues[] => {
|
||||||
@@ -221,3 +223,11 @@ export const getFilledMarketingFormInitialValues = (
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getPricePerConvertion = (
|
||||||
|
totalPrice: number,
|
||||||
|
weightPerConvertion: number,
|
||||||
|
totalPeti: number
|
||||||
|
) => {
|
||||||
|
return totalPrice / (weightPerConvertion * totalPeti);
|
||||||
|
};
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ 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;
|
||||||
weeks?: {
|
|
||||||
value: number;
|
|
||||||
label: string;
|
|
||||||
} | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> =
|
export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> =
|
||||||
@@ -92,13 +88,6 @@ 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(),
|
||||||
weeks: Yup.object({
|
|
||||||
value: Yup.number().required('Minggu wajib diisi!'),
|
|
||||||
label: Yup.string().required('Minggu wajib diisi!'),
|
|
||||||
})
|
|
||||||
.nullable()
|
|
||||||
.optional()
|
|
||||||
.notRequired(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SalesOrderProductFormValues = Yup.InferType<
|
export type SalesOrderProductFormValues = Yup.InferType<
|
||||||
|
|||||||
+72
-15
@@ -5,7 +5,7 @@ import {
|
|||||||
SalesOrderProductFormValues,
|
SalesOrderProductFormValues,
|
||||||
SalesOrderProductSchema,
|
SalesOrderProductSchema,
|
||||||
} from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema';
|
} from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema';
|
||||||
import { RefObject, useMemo, useState } from 'react';
|
import { RefObject, useEffect, useMemo, useState } from 'react';
|
||||||
import { OptionType, useSelect } from '@/components/input/SelectInput';
|
import { OptionType, useSelect } from '@/components/input/SelectInput';
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
import { WarehouseApi } from '@/services/api/master-data';
|
import { WarehouseApi } from '@/services/api/master-data';
|
||||||
@@ -49,7 +49,33 @@ const SalesOrderProductForm = ({
|
|||||||
const [currentInput, setCurrentInput] = useState<string>('');
|
const [currentInput, setCurrentInput] = useState<string>('');
|
||||||
const [selectedProductWarehouse, setSelectedProductWarehouse] =
|
const [selectedProductWarehouse, setSelectedProductWarehouse] =
|
||||||
useState<ProductWarehouse | null>(null);
|
useState<ProductWarehouse | null>(null);
|
||||||
const [hasSisaBerat, setHasSisaBerat] = useState<boolean>(false);
|
|
||||||
|
// Check jika ada sisa berat = total_weight - (weight_per_convertion * total_peti)
|
||||||
|
const initialSisaBerat =
|
||||||
|
initialValues?.total_weight &&
|
||||||
|
initialValues?.weight_per_convertion &&
|
||||||
|
initialValues?.total_peti
|
||||||
|
? Number(initialValues.total_weight) -
|
||||||
|
Number(initialValues.weight_per_convertion) *
|
||||||
|
Number(initialValues.total_peti)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
const initialPricePerConvertion =
|
||||||
|
initialValues?.total_price &&
|
||||||
|
initialValues?.total_peti &&
|
||||||
|
Number(initialValues.total_peti) !== 0
|
||||||
|
? (Number(initialValues.total_price) -
|
||||||
|
initialSisaBerat * Number(initialValues.unit_price || 0)) /
|
||||||
|
Number(initialValues.total_peti)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
const initialPriceSisaBerat =
|
||||||
|
Number(initialValues?.total_price) -
|
||||||
|
initialPricePerConvertion * Number(initialValues?.total_peti);
|
||||||
|
|
||||||
|
const [hasSisaBerat, setHasSisaBerat] = useState<boolean>(
|
||||||
|
initialSisaBerat > 0
|
||||||
|
);
|
||||||
|
|
||||||
// ============ Formik ============
|
// ============ Formik ============
|
||||||
const formik = useFormik<SalesOrderProductFormValues>({
|
const formik = useFormik<SalesOrderProductFormValues>({
|
||||||
@@ -70,11 +96,13 @@ const SalesOrderProductForm = ({
|
|||||||
initialValues?.weight_per_convertion != null
|
initialValues?.weight_per_convertion != null
|
||||||
? Number(initialValues.weight_per_convertion)
|
? Number(initialValues.weight_per_convertion)
|
||||||
: null,
|
: null,
|
||||||
|
price_per_convertion: initialPricePerConvertion,
|
||||||
convertion_unit: initialValues?.convertion_unit || null,
|
convertion_unit: initialValues?.convertion_unit || null,
|
||||||
marketing_type: initialValues?.marketing_type || null,
|
marketing_type: initialValues?.marketing_type || null,
|
||||||
total_peti: initialValues?.total_peti ?? null,
|
total_peti: initialValues?.total_peti ?? null,
|
||||||
weeks: initialValues?.weeks || null,
|
|
||||||
price_per_qty: initialValues?.price_per_qty ?? null,
|
price_per_qty: initialValues?.price_per_qty ?? null,
|
||||||
|
sisa_berat: initialSisaBerat,
|
||||||
|
price_sisa_berat: initialPriceSisaBerat,
|
||||||
},
|
},
|
||||||
validationSchema: SalesOrderProductSchema,
|
validationSchema: SalesOrderProductSchema,
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
@@ -168,6 +196,15 @@ const SalesOrderProductForm = ({
|
|||||||
qty: '',
|
qty: '',
|
||||||
avg_weight: '',
|
avg_weight: '',
|
||||||
total_price: '',
|
total_price: '',
|
||||||
|
total_peti: null,
|
||||||
|
price_per_qty: null,
|
||||||
|
price_sisa_berat: null,
|
||||||
|
sisa_berat: null,
|
||||||
|
convertion_unit: null,
|
||||||
|
marketing_type: null,
|
||||||
|
weight_per_convertion: null,
|
||||||
|
price_per_convertion: null,
|
||||||
|
uom: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -182,6 +219,28 @@ const SalesOrderProductForm = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handler khusus untuk toggle sisa berat - langsung pakai nilai baru
|
||||||
|
const handleSisaBeratToggle = (newHasSisaBerat: boolean) => {
|
||||||
|
setHasSisaBerat(newHasSisaBerat);
|
||||||
|
|
||||||
|
if (!newHasSisaBerat) {
|
||||||
|
// Ketika OFF - set nilai ke 0 dan recalculate tanpa sisa
|
||||||
|
formik.setFieldValue('sisa_berat', 0);
|
||||||
|
formik.setFieldValue('price_sisa_berat', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Langsung trigger recalculation dengan hasSisaBerat yang baru
|
||||||
|
handleMarketingCalculation('total_peti', {
|
||||||
|
values: {
|
||||||
|
...formik.values,
|
||||||
|
sisa_berat: newHasSisaBerat ? formik.values.sisa_berat : 0,
|
||||||
|
price_sisa_berat: newHasSisaBerat ? formik.values.price_sisa_berat : 0,
|
||||||
|
},
|
||||||
|
setFieldValue: formik.setFieldValue,
|
||||||
|
hasSisaBerat: newHasSisaBerat,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// ===== Formik Error List =====
|
// ===== Formik Error List =====
|
||||||
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(
|
const { formErrorList, close, handleFormSubmit } = useFormikErrorList(
|
||||||
formik,
|
formik,
|
||||||
@@ -314,7 +373,7 @@ const SalesOrderProductForm = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{formik.values.convertion_unit &&
|
{formik.values.convertion_unit &&
|
||||||
formik.values.convertion_unit.value === 'peti' && (
|
formik.values.convertion_unit.value.toLowerCase() === 'peti' && (
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
<label className='font-semibold text-xs py-2 leading-5'>
|
<label className='font-semibold text-xs py-2 leading-5'>
|
||||||
Tipe Konversi <span className='text-error'>*</span>
|
Tipe Konversi <span className='text-error'>*</span>
|
||||||
@@ -387,32 +446,33 @@ const SalesOrderProductForm = ({
|
|||||||
);
|
);
|
||||||
setCurrentInput(e.target.name);
|
setCurrentInput(e.target.name);
|
||||||
}}
|
}}
|
||||||
|
onBlur={() => handleBlurField('weight_per_convertion')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Konversi Satuan Weeks Pullet */}
|
{/* Konversi Satuan Weeks 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={optionsWeeks}
|
||||||
value={formik.values.weeks}
|
value={formik.values.weeks || undefined}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue('weeks', val);
|
formik.setFieldValue('weeks', val);
|
||||||
}}
|
}}
|
||||||
placeholder='Pilih Weeks'
|
placeholder='Pilih Weeks'
|
||||||
/>
|
/>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
{/* Total Peti */}
|
{/* Total Peti */}
|
||||||
{formik.values.convertion_unit?.value === 'peti' && (
|
{formik.values.convertion_unit?.value.toLowerCase() === 'peti' && (
|
||||||
<NumberInput
|
<NumberInput
|
||||||
required
|
required
|
||||||
label='Total Peti'
|
label='Total Peti'
|
||||||
name='total_pet'
|
name='total_peti'
|
||||||
value={formik.values.total_peti ?? undefined}
|
value={formik.values.total_peti ?? undefined}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
formik.handleChange(e);
|
formik.handleChange(e);
|
||||||
@@ -429,7 +489,7 @@ const SalesOrderProductForm = ({
|
|||||||
<span className='text-sm text-base-content/50'>Kg</span>
|
<span className='text-sm text-base-content/50'>Kg</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
bottomLabel={`1 ${formik.values.convertion_unit?.value} = ${formik.values.weight_per_convertion ?? 0} Kg`}
|
bottomLabel={`1 ${formik.values.convertion_unit?.value.toLowerCase()} = ${formik.values.weight_per_convertion ?? 0} Kg`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -586,12 +646,9 @@ const SalesOrderProductForm = ({
|
|||||||
<div className='py-2 gap-3 flex items-center'>
|
<div className='py-2 gap-3 flex items-center'>
|
||||||
<input
|
<input
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
name='sisa_berat'
|
name='sisa_berat_toggle'
|
||||||
checked={hasSisaBerat}
|
checked={hasSisaBerat}
|
||||||
onChange={() => {
|
onChange={() => handleSisaBeratToggle(!hasSisaBerat)}
|
||||||
setHasSisaBerat(!hasSisaBerat);
|
|
||||||
}}
|
|
||||||
onBlur={() => handleBlurField('sisa_berat')}
|
|
||||||
className='toggle toggle-primary rounded-full before:rounded-full before:bg-base-content/50 border-base-content/50 checked:border-primary checked:bg-primary checked:before:bg-base-100'
|
className='toggle toggle-primary rounded-full before:rounded-full before:bg-base-content/50 border-base-content/50 checked:border-primary checked:bg-primary checked:before:bg-base-100'
|
||||||
/>
|
/>
|
||||||
<label className='text-sm text-base-content/50'>
|
<label className='text-sm text-base-content/50'>
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ const SalesOrderProductTable = ({
|
|||||||
<tr>
|
<tr>
|
||||||
<td className='text-sm px-4 py-3'>Total Peti</td>
|
<td className='text-sm px-4 py-3'>Total Peti</td>
|
||||||
<td className='text-sm px-4 py-3'>
|
<td className='text-sm px-4 py-3'>
|
||||||
{item.convertion_unit?.label}
|
{item.total_peti} {item.convertion_unit?.label}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -199,9 +199,12 @@ export const calculateAyam = (field: string, ctx: CalculationContext): void => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TELUR + PETI: Penjualan telur dalam satuan peti
|
* TELUR + PETI: Penjualan telur dalam satuan peti
|
||||||
* - Formula: total_price = (price_per_convertion × total_peti) + price_sisa_berat
|
*
|
||||||
|
* Formulas:
|
||||||
* - total_weight = (weight_per_convertion × total_peti) + sisa_berat
|
* - total_weight = (weight_per_convertion × total_peti) + sisa_berat
|
||||||
* - Payload: unit_price = total_price / qty (normalisasi untuk BE)
|
* - total_price = (price_per_convertion × total_peti) + price_sisa_berat
|
||||||
|
* - unit_price = total_price / total_weight (untuk BE)
|
||||||
|
* - avg_weight = total_weight / qty
|
||||||
*/
|
*/
|
||||||
export const calculateTelurPeti = (
|
export const calculateTelurPeti = (
|
||||||
field: string,
|
field: string,
|
||||||
@@ -217,27 +220,83 @@ export const calculateTelurPeti = (
|
|||||||
: 0;
|
: 0;
|
||||||
const qty = Number(values.qty || 0);
|
const qty = Number(values.qty || 0);
|
||||||
|
|
||||||
|
// Helper untuk menghitung dan set unit_price = total_price / total_weight
|
||||||
|
const updateUnitPrice = (tp: number, tw: number) => {
|
||||||
|
if (tw > 0 && tp > 0) {
|
||||||
|
setFieldValue('unit_price', roundPrice(tp / tw));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'price_per_convertion':
|
case 'price_per_convertion': {
|
||||||
case 'total_peti':
|
// Recalculate total_price = (price_per_convertion × total_peti) + price_sisa_berat
|
||||||
case 'price_sisa_berat': {
|
if (pricePerConvertion > 0 && totalPeti > 0) {
|
||||||
// Recalculate total_price
|
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
|
||||||
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
|
setFieldValue('total_price', roundPrice(totalPrice));
|
||||||
setFieldValue('total_price', roundPrice(totalPrice));
|
// Recalculate unit_price = total_price / total_weight
|
||||||
// Recalculate unit_price (normalized for BE)
|
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
||||||
if (qty > 0) {
|
updateUnitPrice(totalPrice, totalWeight);
|
||||||
setFieldValue('unit_price', roundPrice(totalPrice / qty));
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'total_peti': {
|
||||||
|
// Recalculate total_weight = (weight_per_convertion × total_peti) + sisa_berat
|
||||||
|
let totalWeight = 0;
|
||||||
|
if (weightPerConvertion > 0 && totalPeti > 0) {
|
||||||
|
totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
||||||
|
setFieldValue('total_weight', roundWeight(totalWeight));
|
||||||
|
// Recalculate avg_weight = total_weight / qty
|
||||||
|
if (qty > 0) {
|
||||||
|
setFieldValue('avg_weight', preciseWeight(totalWeight / qty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Recalculate total_price = (price_per_convertion × total_peti) + price_sisa_berat
|
||||||
|
if (pricePerConvertion > 0 && totalPeti > 0) {
|
||||||
|
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
|
||||||
|
setFieldValue('total_price', roundPrice(totalPrice));
|
||||||
|
// Recalculate unit_price = total_price / total_weight
|
||||||
|
updateUnitPrice(totalPrice, totalWeight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'price_sisa_berat': {
|
||||||
|
// Recalculate total_price
|
||||||
|
if (pricePerConvertion > 0 && totalPeti > 0) {
|
||||||
|
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
|
||||||
|
setFieldValue('total_price', roundPrice(totalPrice));
|
||||||
|
// Recalculate unit_price = total_price / total_weight
|
||||||
|
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
||||||
|
updateUnitPrice(totalPrice, totalWeight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'weight_per_convertion': {
|
||||||
|
// Recalculate total_weight = (weight_per_convertion × total_peti) + sisa_berat
|
||||||
|
if (weightPerConvertion > 0 && totalPeti > 0) {
|
||||||
|
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
||||||
|
setFieldValue('total_weight', roundWeight(totalWeight));
|
||||||
|
// Recalculate avg_weight = total_weight / qty
|
||||||
|
if (qty > 0) {
|
||||||
|
setFieldValue('avg_weight', preciseWeight(totalWeight / qty));
|
||||||
|
}
|
||||||
|
// Recalculate unit_price = total_price / total_weight
|
||||||
|
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
|
||||||
|
updateUnitPrice(totalPrice, totalWeight);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'weight_per_convertion':
|
|
||||||
case 'sisa_berat': {
|
case 'sisa_berat': {
|
||||||
// Recalculate total_weight
|
// Recalculate total_weight
|
||||||
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
if (weightPerConvertion > 0 && totalPeti > 0) {
|
||||||
setFieldValue('total_weight', roundWeight(totalWeight));
|
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
||||||
// Recalculate avg_weight
|
setFieldValue('total_weight', roundWeight(totalWeight));
|
||||||
if (qty > 0) {
|
// Recalculate avg_weight = total_weight / qty
|
||||||
setFieldValue('avg_weight', preciseWeight(totalWeight / qty));
|
if (qty > 0) {
|
||||||
|
setFieldValue('avg_weight', preciseWeight(totalWeight / qty));
|
||||||
|
}
|
||||||
|
// Recalculate unit_price = total_price / total_weight
|
||||||
|
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
|
||||||
|
updateUnitPrice(totalPrice, totalWeight);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -250,10 +309,9 @@ export const calculateTelurPeti = (
|
|||||||
roundPrice((totalPrice - priceSisaBerat) / totalPeti)
|
roundPrice((totalPrice - priceSisaBerat) / totalPeti)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Update unit_price (normalized for BE)
|
// Update unit_price = total_price / total_weight
|
||||||
if (qty > 0) {
|
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
|
||||||
setFieldValue('unit_price', roundPrice(totalPrice / qty));
|
updateUnitPrice(totalPrice, totalWeight);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -38,6 +38,8 @@ export type BaseSalesOrder = {
|
|||||||
vehicle_number: string;
|
vehicle_number: string;
|
||||||
marketing_type: string;
|
marketing_type: string;
|
||||||
convertion_unit: string;
|
convertion_unit: string;
|
||||||
|
total_peti: number;
|
||||||
|
weight_per_convertion: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BaseDeliveryOrder = {
|
export type BaseDeliveryOrder = {
|
||||||
|
|||||||
Reference in New Issue
Block a user