diff --git a/.husky/pre-commit b/.husky/pre-commit
index ac8a41c7..f799d12f 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,3 +1,3 @@
npm run format
npm run lint
-npm run typecheck
+npm run typecheck
\ No newline at end of file
diff --git a/src/components/pages/marketing/DeliveryOrderFormModal.tsx b/src/components/pages/marketing/DeliveryOrderFormModal.tsx
index eb488285..d6ace126 100644
--- a/src/components/pages/marketing/DeliveryOrderFormModal.tsx
+++ b/src/components/pages/marketing/DeliveryOrderFormModal.tsx
@@ -199,6 +199,9 @@ const DeliveryOrderFormModal = ({}: { initialValues?: Marketing }) => {
'yyyy-MM-DD'
),
vehicle_number: product.vehicle_number,
+ weight_per_convertion: parseFloat(
+ String(product.weight_per_convertion ?? 0)
+ ),
};
}
})
@@ -432,6 +435,9 @@ const DeliveryOrderFormModal = ({}: { initialValues?: Marketing }) => {
'yyyy-MM-DD'
),
vehicle_number: product.vehicle_number,
+ weight_per_convertion: parseFloat(
+ String(product.weight_per_convertion ?? 0)
+ ),
};
}
})
diff --git a/src/components/pages/marketing/form/MarketingForm.schema.ts b/src/components/pages/marketing/form/MarketingForm.schema.ts
index e34fab4e..f9a3c476 100644
--- a/src/components/pages/marketing/form/MarketingForm.schema.ts
+++ b/src/components/pages/marketing/form/MarketingForm.schema.ts
@@ -151,6 +151,25 @@ export const DeliveryProductToFieldValues = (
value: item.product_warehouse.warehouse.id,
label: item.product_warehouse.warehouse.name,
};
+
+ const initialSisaBerat =
+ item?.total_weight &&
+ salesOrder?.weight_per_convertion &&
+ salesOrder?.total_peti
+ ? Number(item.total_weight) -
+ Number(salesOrder.weight_per_convertion) *
+ Number(salesOrder.total_peti)
+ : 0;
+
+ const initialPricePerConvertion =
+ item?.total_price &&
+ salesOrder?.total_peti &&
+ Number(salesOrder.total_peti) !== 0
+ ? (Number(item.total_price) -
+ initialSisaBerat * Number(item.unit_price || 0)) /
+ Number(salesOrder.total_peti)
+ : Number(item?.unit_price || 0);
+
return {
id: salesOrder?.id,
unit_price: item.unit_price,
@@ -193,6 +212,10 @@ export const DeliveryProductToFieldValues = (
avg_weight: item.avg_weight,
total_price: item.total_price,
},
+ total_peti: salesOrder?.total_peti,
+ weight_per_convertion:
+ item?.weight_per_convertion ?? salesOrder?.weight_per_convertion ?? 0,
+ price_per_convertion: initialPricePerConvertion,
} as DeliveryOrderProductFormValues;
});
@@ -203,6 +226,8 @@ export const mergeSOwithDO = (
deliveryOrders: DeliveryOrderProductFormValues[],
autofill?: boolean
): DeliveryOrderProductFormValues[] => {
+ const hasDeliveryOrders = deliveryOrders.length > 0;
+
return salesOrders.map((so) => {
const delivery = deliveryOrders.find(
(d) => d?.marketing_product_id === so.id
@@ -227,30 +252,50 @@ export const mergeSOwithDO = (
delivery_date: delivery?.delivery_date || undefined,
do_number: delivery?.do_number || undefined,
vehicle_number: delivery?.vehicle_number || so.vehicle_number,
- unit_price: autofill ? delivery?.unit_price : salesOrderUnitPrice,
- total_weight: autofill ? delivery?.total_weight : so.total_weight,
- qty: autofill ? delivery?.qty : so.qty,
- avg_weight: autofill ? delivery?.avg_weight : so.avg_weight,
- total_price: autofill ? delivery?.total_price : so.total_price,
+ unit_price:
+ autofill && hasDeliveryOrders
+ ? delivery?.unit_price
+ : salesOrderUnitPrice,
+ total_weight:
+ autofill && hasDeliveryOrders
+ ? delivery?.total_weight
+ : so.total_weight,
+ qty: autofill && hasDeliveryOrders ? delivery?.qty : so.qty,
+ avg_weight:
+ autofill && hasDeliveryOrders ? delivery?.avg_weight : so.avg_weight,
+ total_price:
+ autofill && hasDeliveryOrders ? delivery?.total_price : so.total_price,
marketing_product: so, // jika ada, override
- uom: autofill ? delivery?.uom : so.uom,
- weight_per_convertion: autofill
- ? delivery?.weight_per_convertion
- : so.weight_per_convertion,
- price_per_convertion: autofill
- ? delivery?.price_per_convertion
- : so.price_per_convertion,
- convertion_unit: autofill
- ? delivery?.convertion_unit
- : so.convertion_unit,
- marketing_type: autofill ? delivery?.marketing_type : so.marketing_type,
- total_peti: autofill ? delivery?.total_peti : so.total_peti,
- price_per_qty: autofill ? delivery?.price_per_qty : salesOrderPricePerQty,
- sisa_berat: autofill ? delivery?.sisa_berat : so.sisa_berat,
- price_sisa_berat: autofill
- ? delivery?.price_sisa_berat
- : so.price_sisa_berat,
- week: autofill ? delivery?.week : so.week,
+ uom: autofill && hasDeliveryOrders ? delivery?.uom : so.uom,
+ weight_per_convertion:
+ autofill && hasDeliveryOrders
+ ? delivery?.weight_per_convertion
+ : so.weight_per_convertion,
+ price_per_convertion:
+ autofill && hasDeliveryOrders
+ ? delivery?.price_per_convertion
+ : so.price_per_convertion,
+ convertion_unit:
+ autofill && hasDeliveryOrders
+ ? delivery?.convertion_unit
+ : so.convertion_unit,
+ marketing_type:
+ autofill && hasDeliveryOrders
+ ? delivery?.marketing_type
+ : so.marketing_type,
+ total_peti:
+ autofill && hasDeliveryOrders ? delivery?.total_peti : so.total_peti,
+ price_per_qty:
+ autofill && hasDeliveryOrders
+ ? delivery?.price_per_qty
+ : salesOrderPricePerQty,
+ sisa_berat:
+ autofill && hasDeliveryOrders ? delivery?.sisa_berat : so.sisa_berat,
+ price_sisa_berat:
+ autofill && hasDeliveryOrders
+ ? delivery?.price_sisa_berat
+ : so.price_sisa_berat,
+ week: autofill && hasDeliveryOrders ? delivery?.week : so.week,
} as DeliveryOrderProductFormValues;
});
};
diff --git a/src/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.tsx b/src/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.tsx
index 781ebf26..6793018b 100644
--- a/src/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.tsx
+++ b/src/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.tsx
@@ -126,18 +126,14 @@ const DeliveryOrderProductForm = ({
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 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)
+ : Number(initialValues?.unit_price || 0);
const initialPriceSisaBerat =
initialValues?.total_price && initialValues?.total_peti
@@ -728,7 +724,7 @@ const DeliveryOrderProductForm = ({
placeholder='Masukan Total Peti'
endAdornment={
- Kg
+ Peti
}
bottomLabel={`1 ${formik.values.convertion_unit?.value.toLowerCase()} = ${formik.values.weight_per_convertion ?? 0} Kg`}
@@ -778,6 +774,9 @@ const DeliveryOrderProductForm = ({
}
errorMessage={formik.errors.total_weight}
placeholder='Masukan Total Bobot'
+ disabled={
+ formik.values.convertion_unit?.value.toLowerCase() === 'peti'
+ }
/>
)}
diff --git a/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx b/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx
index a7f2c73e..5f0031f8 100644
--- a/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx
+++ b/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm.tsx
@@ -61,18 +61,14 @@ 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?.unit_price
- ? Number(initialValues?.unit_price)
- : 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)
+ : Number(initialValues?.unit_price || 0);
const isInitialTelurQty =
initialValues?.marketing_type?.value?.toLowerCase() === 'telur' &&
@@ -624,7 +620,7 @@ const SalesOrderProductForm = ({
placeholder='Masukan Total Peti'
endAdornment={
- Kg
+ Peti
}
bottomLabel={`1 ${formik.values.convertion_unit?.value.toLowerCase()} = ${formik.values.weight_per_convertion ?? 0} Kg`}
@@ -674,6 +670,9 @@ const SalesOrderProductForm = ({
}
errorMessage={formik.errors.total_weight}
placeholder='Masukan Total Bobot'
+ disabled={
+ formik.values.convertion_unit?.value.toLowerCase() === 'peti'
+ }
/>
)}
diff --git a/src/components/pages/marketing/form/table-view/DeliveryOrderProductTable.tsx b/src/components/pages/marketing/form/table-view/DeliveryOrderProductTable.tsx
index a1e0c9de..9c7337ec 100644
--- a/src/components/pages/marketing/form/table-view/DeliveryOrderProductTable.tsx
+++ b/src/components/pages/marketing/form/table-view/DeliveryOrderProductTable.tsx
@@ -85,7 +85,7 @@ const DeliveryOrderProductTable = ({
Value
- {formType !== 'success' &&
+ {/* {formType !== 'success' &&
(formType === 'add_delivery' ||
formType === 'edit_delivery' ||
formType === 'detail') && (
@@ -102,7 +102,7 @@ const DeliveryOrderProductTable = ({
- )}
+ )} */}
|
@@ -141,12 +141,15 @@ const DeliveryOrderProductTable = ({
| Total Bobot |
- {formatNumber(Number(item.total_weight))}
+ {formatNumber(Number(item.total_weight))} Kg
|
)}
- | Total Harga Satuan |
+
+ Total Harga Satuan
+ {item.convertion_unit?.label.toLowerCase() === 'peti' && ' (Kg)'}
+ |
{formatCurrency(parseFloat(item.unit_price as string))}
|
diff --git a/src/components/pages/marketing/form/table-view/SalesOrderProductTable.tsx b/src/components/pages/marketing/form/table-view/SalesOrderProductTable.tsx
index f40f9151..d8e906cf 100644
--- a/src/components/pages/marketing/form/table-view/SalesOrderProductTable.tsx
+++ b/src/components/pages/marketing/form/table-view/SalesOrderProductTable.tsx
@@ -137,8 +137,22 @@ const SalesOrderProductTable = ({
{`${formatNumber(parseFloat(item.qty as string))} ${item.uom || ''}`}
+ {item.convertion_unit?.value.toLowerCase() === 'peti' && (
+
+ | Harga Satuan Per Peti |
+
+ {formatCurrency(
+ parseFloat(item.unit_price as string) *
+ parseFloat(String(item.weight_per_convertion))
+ )}
+ |
+
+ )}
- | Harga Satuan |
+
+ Harga Satuan
+ {item.convertion_unit?.value.toLowerCase() === 'peti' && ' (Kg)'}
+ |
{formatCurrency(parseFloat(item.unit_price as string))}
|
diff --git a/src/components/pages/production/uniformity/form/UniformityForm.tsx b/src/components/pages/production/uniformity/form/UniformityForm.tsx
index 8840c021..80668748 100644
--- a/src/components/pages/production/uniformity/form/UniformityForm.tsx
+++ b/src/components/pages/production/uniformity/form/UniformityForm.tsx
@@ -597,6 +597,7 @@ const UniformityForm = ({
onBlur={formik.handleBlur}
isError={formik.touched.date && Boolean(formik.errors.date)}
errorMessage={formik.errors.date as string}
+ disabled={isNextStep}
/>
{
const filterModal = useModal();
// ===== OPTIONS =====
- const { options: areaOptions, isLoadingOptions: isLoadingAreas } = useSelect(
- AreaApi.basePath,
+ const {
+ options: areaOptions,
+ isLoadingOptions: isLoadingAreas,
+ setInputValue: setAreaInputValue,
+ loadMore: loadMoreArea,
+ } = useSelect(AreaApi.basePath, 'id', 'name', 'search');
+
+ const {
+ options: locationOptions,
+ isLoadingOptions: isLoadingLocations,
+ setInputValue: setLocationInputValue,
+ loadMore: loadMoreLocation,
+ } = useSelect(LocationApi.basePath, 'id', 'name', 'search');
+
+ const {
+ options: kandangOptions,
+ isLoadingOptions: isLoadingKandangs,
+ setInputValue: setKandangInputValue,
+ loadMore: loadMoreKandang,
+ } = useSelect(
+ ProjectFlockKandangApi.basePath,
'id',
- 'name',
+ 'name_with_period',
'search'
);
- const { options: locationOptions, isLoadingOptions: isLoadingLocations } =
- useSelect(LocationApi.basePath, 'id', 'name', 'search');
-
- const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
- useSelect(
- ProjectFlockKandangApi.basePath,
- 'id',
- 'name_with_period',
- 'search'
- );
-
const showUnrecordedOptions = useMemo(
() => [
{ value: 'false', label: 'Sembunyikan' },
@@ -918,6 +926,8 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
isLoading={isLoadingAreas}
isClearable
className={{ wrapper: 'w-full' }}
+ onInputChange={setAreaInputValue}
+ onMenuScrollToBottom={loadMoreArea}
/>
{/* Location Filter */}
@@ -937,6 +947,8 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
isLoading={isLoadingLocations}
isClearable
className={{ wrapper: 'w-full' }}
+ onInputChange={setLocationInputValue}
+ onMenuScrollToBottom={loadMoreLocation}
/>
{/* Kandang Filter */}
@@ -956,6 +968,8 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
isLoading={isLoadingKandangs}
isClearable
className={{ wrapper: 'w-full' }}
+ onInputChange={setKandangInputValue}
+ onMenuScrollToBottom={loadMoreKandang}
/>
{/* Weight Range Filter */}
diff --git a/src/lib/marketing-calculation.ts b/src/lib/marketing-calculation.ts
index 3d4930c5..e957d64f 100644
--- a/src/lib/marketing-calculation.ts
+++ b/src/lib/marketing-calculation.ts
@@ -235,10 +235,8 @@ export const calculateTelurPeti = (
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
setFieldValue('total_price', totalPrice);
// Recalculate unit_price = total_price / total_weight
-
- // TODO: consider sisa berat later
const totalWeight = weightPerConvertion * totalPeti + sisaBerat;
- updateUnitPrice(totalPrice, totalPeti);
+ updateUnitPrice(totalPrice, totalWeight);
}
break;
}
@@ -257,8 +255,8 @@ export const calculateTelurPeti = (
if (pricePerConvertion > 0 && totalPeti > 0) {
const totalPrice = pricePerConvertion * totalPeti + priceSisaBerat;
setFieldValue('total_price', totalPrice);
- // Recalculate unit_price = total_price / total_peti
- updateUnitPrice(totalPrice, totalPeti);
+ // Recalculate unit_price = total_price / totalWeight
+ updateUnitPrice(totalPrice, totalWeight);
}
break;
}
@@ -317,6 +315,15 @@ export const calculateTelurPeti = (
updateUnitPrice(totalPrice, totalWeight);
break;
}
+ case 'qty':
+ // Recalculate avg_weight = total_weight / qty
+ if (qty > 0 && values.total_weight) {
+ setFieldValue(
+ 'avg_weight',
+ preciseWeight(Number(values.total_weight) / qty)
+ );
+ }
+ break;
}
};
diff --git a/src/types/api/marketing/marketing.d.ts b/src/types/api/marketing/marketing.d.ts
index 743493f7..15d34345 100644
--- a/src/types/api/marketing/marketing.d.ts
+++ b/src/types/api/marketing/marketing.d.ts
@@ -61,6 +61,7 @@ export type BaseDelivery = {
avg_weight: number;
total_price: number;
vehicle_number: string;
+ weight_per_convertion: number;
};
export type MarketingProduct = {