Merge branch 'fix/marketing' into 'development'

[FIX/FE] Marketing - Sales Order Form

See merge request mbugroup/lti-web-client!374
This commit is contained in:
Rivaldi A N S
2026-04-07 10:44:49 +00:00
3 changed files with 120 additions and 94 deletions
@@ -195,7 +195,9 @@ const SalesOrderFormModal = ({
product.marketing_type?.value?.toLowerCase() === 'telur'
? convertionUnitValue === 'PETI'
? 'PETI'
: 'KG' // termasuk "QTY" dan "KG"
: convertionUnitValue === 'QTY'
? 'QTY'
: 'KG'
: undefined;
// Jika value dari data product ada week, kirim "AYAM_PULLET, jika tidak ada kirim "AYAM"
@@ -61,14 +61,36 @@ const SalesOrderProductForm = ({
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 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 initialPricePerConvertion = initialValues?.unit_price
? Number(initialValues?.unit_price)
: 0;
const isInitialTelurQty =
initialValues?.marketing_type?.value?.toLowerCase() === 'telur' &&
initialValues?.convertion_unit?.value?.toLowerCase() === 'qty';
const initialUnitPrice =
isInitialTelurQty &&
Number(initialValues?.total_price || 0) > 0 &&
Number(initialValues?.qty || 0) > 0
? Number(initialValues?.total_price) / Number(initialValues?.qty)
: initialValues?.unit_price || '';
const initialPricePerQty =
isInitialTelurQty &&
Number(initialValues?.total_price || 0) > 0 &&
Number(initialValues?.total_weight || 0) > 0
? Number(initialValues?.total_price) / Number(initialValues?.total_weight)
: (initialValues?.price_per_qty ?? null);
const initialPriceSisaBerat =
initialValues?.total_price && initialValues?.total_peti
@@ -93,7 +115,7 @@ const SalesOrderProductForm = ({
product_warehouse: initialValues?.product_warehouse || null,
product_warehouse_data: initialValues?.product_warehouse_data || null,
product_warehouse_id: initialValues?.product_warehouse_id || undefined,
unit_price: initialValues?.unit_price || '',
unit_price: initialUnitPrice,
total_weight: initialValues?.total_weight || '',
qty: initialValues?.qty || '',
avg_weight: initialValues?.avg_weight || '',
@@ -107,7 +129,7 @@ const SalesOrderProductForm = ({
convertion_unit: initialValues?.convertion_unit || null,
marketing_type: initialValues?.marketing_type || null,
total_peti: initialValues?.total_peti ?? null,
price_per_qty: initialValues?.price_per_qty ?? null,
price_per_qty: initialPricePerQty,
sisa_berat: initialSisaBerat,
price_sisa_berat: initialPriceSisaBerat,
week: initialValues?.week ?? null,
@@ -135,6 +157,11 @@ const SalesOrderProductForm = ({
);
}, [selectedProductWarehouse, formik.values.marketing_type]);
console.log({
initialValues,
values: formik.values,
});
// ===== Options =====
const {
options: warehouseOptions,
@@ -523,7 +550,7 @@ const SalesOrderProductForm = ({
<input
type='radio'
checked={
formik.values.convertion_unit?.value ===
formik.values.convertion_unit?.value.toLowerCase() ===
option.value
}
onChange={() => null}
@@ -546,7 +573,9 @@ const SalesOrderProductForm = ({
} per ${formik.values.convertion_unit?.value}`}
value={formik.values.weight_per_convertion ?? ''}
onChange={(e) => {
const value = Number(e.target.value);
const value = Number(e.target.value)
? Number(e.target.value)
: '';
handleFieldChange('weight_per_convertion', value, () =>
setCurrentInput(e.target.name)
);
@@ -717,35 +746,12 @@ const SalesOrderProductForm = ({
/>
)}
{/* Harga per butir untuk TELUR + QTY */}
{formik.values.marketing_type?.value.toLowerCase() === 'telur' &&
formik.values.convertion_unit?.value.toLowerCase() === 'qty' && (
<NumberInput
required
label='Harga / Butir (Rp)'
name='price_per_qty'
value={formik.values.price_per_qty ?? undefined}
onChange={(e) => {
const value = Number(e.target.value);
handleFieldChange('price_per_qty', value, () =>
setCurrentInput('price_per_qty')
);
}}
isError={
formik.touched.price_per_qty &&
Boolean(formik.errors.price_per_qty)
}
errorMessage={formik.errors.price_per_qty}
placeholder='Masukan Harga per Butir'
/>
)}
{/* Harga Satuan per Uom Produk Warehouse */}
{formik.values.convertion_unit?.value.toLowerCase() !== 'peti' &&
formik.values.convertion_unit?.value.toLowerCase() !== 'kg' && (
<NumberInput
required
label={`Harga / ${formik.values.convertion_unit?.label !== 'qty' ? 'Kg' : (selectedProductWarehouse?.product?.uom?.name ?? 'Produk')} (Rp)`}
label={`Harga / ${formik.values.convertion_unit?.label.toLowerCase() !== 'qty' ? 'Kg' : 'Butir'} (Rp)`}
name='unit_price'
value={formik.values.unit_price}
onChange={(e) => {
@@ -762,6 +768,29 @@ const SalesOrderProductForm = ({
/>
)}
{/* Harga per kg untuk TELUR + QTY */}
{formik.values.marketing_type?.value.toLowerCase() === 'telur' &&
formik.values.convertion_unit?.value.toLowerCase() === 'qty' && (
<NumberInput
required
label='Harga / Kg (Rp)'
name='price_per_qty'
value={formik.values.price_per_qty ?? undefined}
onChange={(e) => {
const value = Number(e.target.value);
handleFieldChange('price_per_qty', value, () =>
setCurrentInput('price_per_qty')
);
}}
isError={
formik.touched.price_per_qty &&
Boolean(formik.errors.price_per_qty)
}
errorMessage={formik.errors.price_per_qty}
placeholder='Masukan Harga per Kg'
/>
)}
{/* Sisa kg diluar peti */}
{formik.values.convertion_unit?.value.toLowerCase() === 'peti' && (
<div className='flex flex-col'>
+52 -57
View File
@@ -76,13 +76,13 @@ export const calculateTrading = (
case 'unit_price':
case 'qty': {
if (unitPrice > 0 && qty > 0) {
setFieldValue('total_price', roundPrice(unitPrice * qty));
setFieldValue('total_price', unitPrice * qty);
}
break;
}
case 'total_price': {
if (totalPrice > 0 && qty > 0) {
setFieldValue('unit_price', roundPrice(totalPrice / qty));
setFieldValue('unit_price', totalPrice / qty);
}
break;
}
@@ -112,7 +112,7 @@ export const calculateAyamPullet = (
case 'qty': {
// total_price = unit_price × week × qty
if (unitPrice > 0 && week > 0 && qty > 0) {
setFieldValue('total_price', roundPrice(unitPrice * week * qty));
setFieldValue('total_price', unitPrice * week * qty);
}
// total_weight = avg_weight × qty
if (avgWeight > 0 && qty > 0) {
@@ -135,7 +135,7 @@ export const calculateAyamPullet = (
case 'total_price': {
// Reverse: unit_price = total_price / (week × qty)
if (totalPrice > 0 && week > 0 && qty > 0) {
setFieldValue('unit_price', roundPrice(totalPrice / (week * qty)));
setFieldValue('unit_price', totalPrice / (week * qty));
}
break;
}
@@ -164,7 +164,7 @@ export const calculateAyam = (field: string, ctx: CalculationContext): void => {
setFieldValue('total_weight', tw);
// total_price = total_weight × unit_price
if (unitPrice > 0) {
setFieldValue('total_price', roundPrice(tw * unitPrice));
setFieldValue('total_price', tw * unitPrice);
}
}
break;
@@ -176,21 +176,21 @@ export const calculateAyam = (field: string, ctx: CalculationContext): void => {
}
// total_price = total_weight × unit_price
if (unitPrice > 0 && totalWeight > 0) {
setFieldValue('total_price', roundPrice(totalWeight * unitPrice));
setFieldValue('total_price', totalWeight * unitPrice);
}
break;
}
case 'unit_price': {
// total_price = total_weight × unit_price
if (unitPrice > 0 && totalWeight > 0) {
setFieldValue('total_price', roundPrice(totalWeight * unitPrice));
setFieldValue('total_price', totalWeight * unitPrice);
}
break;
}
case 'total_price': {
// unit_price = total_price / total_weight
if (totalPrice > 0 && totalWeight > 0) {
setFieldValue('unit_price', roundPrice(totalPrice / totalWeight));
setFieldValue('unit_price', totalPrice / totalWeight);
}
break;
}
@@ -223,7 +223,8 @@ export const calculateTelurPeti = (
// 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));
const unitPrice = tp / tw;
setFieldValue('unit_price', unitPrice);
}
};
@@ -232,10 +233,12 @@ export const calculateTelurPeti = (
// 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));
setFieldValue('total_price', totalPrice);
// Recalculate unit_price = total_price / total_weight
// TODO: consider sisa berat later
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
updateUnitPrice(totalPrice, totalWeight);
updateUnitPrice(totalPrice, totalPeti);
}
break;
}
@@ -253,9 +256,9 @@ export const calculateTelurPeti = (
// 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);
setFieldValue('total_price', totalPrice);
// Recalculate unit_price = total_price / total_peti
updateUnitPrice(totalPrice, totalPeti);
}
break;
}
@@ -263,7 +266,7 @@ export const calculateTelurPeti = (
// Recalculate total_price
if (pricePerConvertion > 0 && totalPeti > 0) {
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
setFieldValue('total_price', roundPrice(totalPrice));
setFieldValue('total_price', totalPrice);
// Recalculate unit_price = total_price / total_weight
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
updateUnitPrice(totalPrice, totalWeight);
@@ -306,7 +309,7 @@ export const calculateTelurPeti = (
if (totalPeti > 0 && totalPrice > priceSisaBerat) {
setFieldValue(
'price_per_convertion',
roundPrice((totalPrice - priceSisaBerat) / totalPeti)
(totalPrice - priceSisaBerat) / totalPeti
);
}
// Update unit_price = total_price / total_weight
@@ -341,10 +344,7 @@ export const calculateTelurKg = (
}
// total_price = total_weight × unit_price
if (pricePerConvertion > 0 && totalWeight > 0) {
setFieldValue(
'total_price',
roundPrice(totalWeight * pricePerConvertion)
);
setFieldValue('total_price', totalWeight * pricePerConvertion);
setFieldValue('unit_price', pricePerConvertion);
}
break;
@@ -352,10 +352,7 @@ export const calculateTelurKg = (
case 'price_per_convertion': {
// total_price = total_weight × price_per_convertion
if (pricePerConvertion > 0 && totalWeight > 0) {
setFieldValue(
'total_price',
roundPrice(totalWeight * pricePerConvertion)
);
setFieldValue('total_price', totalWeight * pricePerConvertion);
setFieldValue('unit_price', pricePerConvertion);
}
break;
@@ -363,11 +360,8 @@ export const calculateTelurKg = (
case 'total_price': {
// unit_price = total_price / total_weight
if (totalPrice > 0 && totalWeight > 0) {
setFieldValue('unit_price', roundPrice(totalPrice / totalWeight));
setFieldValue(
'price_per_convertion',
roundPrice(totalPrice / totalWeight)
);
setFieldValue('unit_price', totalPrice / totalWeight);
setFieldValue('price_per_convertion', totalPrice / totalWeight);
}
break;
}
@@ -376,13 +370,11 @@ export const calculateTelurKg = (
/**
* TELUR + QTY Workaround:
* - User inputs: qty, avg_weight, price_per_qty (harga per butir)
* - User inputs: qty, avg_weight, unit_price (harga per butir)
* - FE calculates:
* - total_weight = avg_weight × qty
* - total_price = qty × price_per_qty
* - unit_price = total_price / total_weight (normalisasi untuk BE)
* - Kirim convertion_unit: "KG" karena BE tidak support "QTY"
* - BE akan hitung: total_price = total_weight × unit_price (hasil sama)
* - total_price = qty × unit_price
* - price_per_qty = total_price / total_weight (harga per kg)
*/
export const calculateTelurQty = (
field: string,
@@ -403,13 +395,13 @@ export const calculateTelurQty = (
if (avgWeight > 0 && qty > 0) {
const tw = roundWeight(avgWeight * qty);
setFieldValue('total_weight', tw);
// total_price = qty × price_per_qty
if (pricePerQty > 0) {
const tp = roundPrice(qty * pricePerQty);
// total_price = qty × unit_price
if (unitPrice > 0) {
const tp = qty * unitPrice;
setFieldValue('total_price', tp);
// unit_price = total_price / total_weight (untuk BE)
// price_per_qty = total_price / total_weight
if (tw > 0) {
setFieldValue('unit_price', roundPrice(tp / tw));
setFieldValue('price_per_qty', tp / tw);
}
}
}
@@ -419,44 +411,47 @@ export const calculateTelurQty = (
// avg_weight = total_weight / qty
if (totalWeight > 0 && qty > 0) {
setFieldValue('avg_weight', preciseWeight(totalWeight / qty));
// Recalculate total_price jika ada unit_price
// Recalculate total_price jika ada harga per butir
if (unitPrice > 0) {
setFieldValue('total_price', roundPrice(totalWeight * unitPrice));
setFieldValue('total_price', qty * unitPrice);
}
}
break;
}
case 'price_per_qty': {
// total_price = qty × price_per_qty
if (pricePerQty > 0 && qty > 0) {
const tp = roundPrice(qty * pricePerQty);
// total_price = total_weight × price_per_qty
if (pricePerQty > 0 && totalWeight > 0) {
const tp = totalWeight * pricePerQty;
setFieldValue('total_price', tp);
// unit_price = total_price / total_weight (untuk BE)
if (totalWeight > 0) {
setFieldValue('unit_price', roundPrice(tp / totalWeight));
// unit_price = total_price / qty
if (qty > 0) {
setFieldValue('unit_price', tp / qty);
}
}
break;
}
case 'total_price': {
// price_per_qty = total_price / qty
// unit_price = total_price / qty
if (totalPrice > 0 && qty > 0) {
setFieldValue('price_per_qty', roundPrice(totalPrice / qty));
// unit_price = total_price / total_weight (untuk BE)
setFieldValue('unit_price', totalPrice / qty);
// price_per_qty = total_price / total_weight
if (totalWeight > 0) {
setFieldValue('unit_price', roundPrice(totalPrice / totalWeight));
setFieldValue('price_per_qty', totalPrice / totalWeight);
}
}
break;
}
case 'unit_price': {
// total_price = total_weight × unit_price
if (unitPrice > 0 && totalWeight > 0) {
setFieldValue('total_price', roundPrice(totalWeight * unitPrice));
// total_price = qty × unit_price
const newTotalPrice = qty * unitPrice;
if (unitPrice > 0 && qty > 0) {
setFieldValue('total_price', newTotalPrice);
}
// price_per_qty = total_price / qty
if (totalPrice > 0 && qty > 0) {
setFieldValue('price_per_qty', roundPrice(totalPrice / qty));
// price_per_qty = total_price / total_weight
if (newTotalPrice > 0 && totalWeight > 0) {
setFieldValue('price_per_qty', newTotalPrice / totalWeight);
}
break;
}