From c230c8000bfde80331d4447692356fa2c62a7451 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Sat, 20 Dec 2025 08:52:34 +0700 Subject: [PATCH] refactor(FE-355,356,257): Use API summary per_weight_range for HPP reports --- .../sale/export/HppPerkandangExport.tsx | 226 +++++++----------- .../report/sale/tab/HppPerKandangTab.tsx | 96 ++++++-- 2 files changed, 162 insertions(+), 160 deletions(-) diff --git a/src/components/pages/report/sale/export/HppPerkandangExport.tsx b/src/components/pages/report/sale/export/HppPerkandangExport.tsx index 72e7cbaa..790efef7 100644 --- a/src/components/pages/report/sale/export/HppPerkandangExport.tsx +++ b/src/components/pages/report/sale/export/HppPerkandangExport.tsx @@ -9,7 +9,11 @@ import { Font, pdf, } from '@react-pdf/renderer'; -import { HppPerKandangReport } from '@/types/api/report/hpp-per-kandang'; +import { + HppPerKandangReport, + HppPerKandangRow, + HppPerKandangPerWeightRange, +} from '@/types/api/report/hpp-per-kandang'; import { formatDate, formatNumber, formatCurrency } from '@/lib/helper'; Font.register({ @@ -148,74 +152,6 @@ interface HppPerKandangExportParams { }; } -const rekapitulasiData = (data: HppPerKandangReport['rows']) => { - const groups: { [key: string]: HppPerKandangReport['rows'] } = {}; - - data.forEach((item) => { - const key = `${item.weight_range.weight_min}-${item.weight_range.weight_max}`; - if (!groups[key]) { - groups[key] = []; - } - groups[key].push(item); - }); - - return Object.entries(groups) - .map(([key, items]) => ({ - weight_min: items[0].weight_range.weight_min, - weight_max: items[0].weight_range.weight_max, - items, - total_remaining_chicken_birds: items.reduce( - (sum, item) => sum + item.remaining_chicken_birds, - 0 - ), - total_remaining_chicken_weight_kg: items.reduce( - (sum, item) => sum + item.remaining_chicken_weight_kg, - 0 - ), - average_weight_kg: - items.reduce((sum, item) => sum + item.remaining_chicken_weight_kg, 0) / - items.reduce((sum, item) => sum + item.remaining_chicken_birds, 0), - total_hpp_rp: items.reduce((sum, item) => sum + item.hpp_rp, 0), - total_remaining_value_rp: items.reduce( - (sum, item) => sum + item.remaining_value_rp, - 0 - ), - total_egg_production_pieces: items.reduce( - (sum, item) => sum + (item.egg_production_pieces || 0), - 0 - ), - total_egg_production_kg: items.reduce( - (sum, item) => sum + (item.egg_production_kg || 0), - 0 - ), - total_egg_value_rp: items.reduce( - (sum, item) => sum + (item.egg_value_rp || 0), - 0 - ), - average_egg_hpp_rp_per_kg: - items.reduce((sum, item) => sum + (item.egg_hpp_rp_per_kg || 0), 0) / - items.length, - average_doc_price_rp: - items.reduce((sum, item) => sum + item.average_doc_price_rp, 0) / - items.length, - all_feed_suppliers: [ - ...new Set( - items.flatMap( - (item) => item.feed_suppliers?.map((s) => s.alias || s.name) || [] - ) - ), - ], - all_doc_suppliers: [ - ...new Set( - items.flatMap( - (item) => item.doc_suppliers?.map((s) => s.alias || s.name) || [] - ) - ), - ], - })) - .sort((a, b) => a.weight_min - b.weight_min); -}; - const getParameterText = (params: HppPerKandangExportParams['params']) => { const paramsText = []; @@ -260,7 +196,7 @@ const createPDFDocument = ( data: HppPerKandangExportParams['data'], params: HppPerKandangExportParams['params'] ) => { - const rekapitulasiByWeightRange = rekapitulasiData(data.rows); + const rekapitulasiByWeightRange = data.summary?.per_weight_range || []; return ( @@ -328,71 +264,81 @@ const createPDFDocument = ( {/* Table Body - Rekapitulasi */} - {rekapitulasiByWeightRange.map((group, index) => ( - - - - {group.weight_min.toFixed(2)} -{' '} - {group.weight_max.toFixed(2)} - + {rekapitulasiByWeightRange.map( + (group: HppPerKandangPerWeightRange, index: number) => ( + + + {group.label} + + + {formatNumber(group.remaining_chicken_birds)} + + + + {formatNumber(group.remaining_chicken_weight_kg)} + + + + {formatNumber(group.avg_weight_kg)} + + + - + + + - + + + + {group.feed_suppliers + ?.map( + (s: { alias?: string; name: string }) => + s.alias || s.name + ) + .join(' | ') || '-'} + + + + + {group.doc_suppliers + ?.map( + (s: { alias?: string; name: string }) => + s.alias || s.name + ) + .join(' | ') || '-'} + + + + {formatCurrency(group.average_doc_price_rp)} + + + - + + + + {formatCurrency( + group.remaining_chicken_birds > 0 + ? group.hpp_rp / group.remaining_chicken_birds + : 0 + )} + + + + - + + + {formatCurrency(group.remaining_value_rp)} + - - - {formatNumber(group.total_remaining_chicken_birds)} - - - - - {formatNumber(group.total_remaining_chicken_weight_kg)} - - - - {formatNumber(group.average_weight_kg)} - - - {formatNumber(group.total_egg_production_pieces)} - - - {formatNumber(group.total_egg_production_kg)} - - - {group.all_feed_suppliers.join(' | ')} - - - {group.all_doc_suppliers.join(' | ')} - - - {formatCurrency(group.average_doc_price_rp)} - - - {formatCurrency(group.total_egg_value_rp)} - - - - {formatCurrency( - group.total_remaining_chicken_birds > 0 - ? group.total_hpp_rp / - group.total_remaining_chicken_birds - : 0 - )} - - - - {formatCurrency(group.average_egg_hpp_rp_per_kg)} - - - {formatCurrency(group.total_remaining_value_rp)} - - - ))} + ) + )} @@ -451,7 +397,7 @@ const createPDFDocument = ( {/* Table Body - Detail Per Kandang */} - {data.rows.map((item, index) => ( + {data.rows.map((item: HppPerKandangRow, index: number) => ( {item.feed_suppliers - ?.map((s) => s.alias || s.name) + ?.map( + (s: { alias?: string; name: string }) => + s.alias || s.name + ) .join(' | ')} {item.doc_suppliers - ?.map((s) => s.alias || s.name) + ?.map( + (s: { alias?: string; name: string }) => + s.alias || s.name + ) .join(' | ')} diff --git a/src/components/pages/report/sale/tab/HppPerKandangTab.tsx b/src/components/pages/report/sale/tab/HppPerKandangTab.tsx index e7081f84..7da3ff36 100644 --- a/src/components/pages/report/sale/tab/HppPerKandangTab.tsx +++ b/src/components/pages/report/sale/tab/HppPerKandangTab.tsx @@ -15,7 +15,11 @@ import { SaleReportApi } from '@/services/api/report/marketing-sale'; import Table from '@/components/Table'; import { ColumnDef, Row } from '@tanstack/react-table'; import { formatCurrency, formatNumber } from '@/lib/helper'; -import { HppPerKandangReport } from '@/types/api/report/hpp-per-kandang'; +import { + HppPerKandangReport, + HppPerKandangRow, + HppPerKandangPerWeightRange, +} from '@/types/api/report/hpp-per-kandang'; import { isResponseSuccess } from '@/lib/api-helper'; import { useTableFilter } from '@/services/hooks/useTableFilter'; import Button from '@/components/Button'; @@ -225,6 +229,17 @@ const HppPerKandangTab = () => { ? hppPerKandang.data.summary : undefined; + const summaryTotal = + isResponseSuccess(hppPerKandang) && hppPerKandang?.data?.summary?.total + ? hppPerKandang.data.summary.total + : undefined; + + const perWeightRangeSummary = + isResponseSuccess(hppPerKandang) && + hppPerKandang?.data?.summary?.per_weight_range + ? hppPerKandang.data.summary.per_weight_range + : []; + const period = isResponseSuccess(hppPerKandang) && hppPerKandang?.data?.period ? hppPerKandang.data.period @@ -271,25 +286,49 @@ const HppPerKandangTab = () => { // ===== TABLE COLUMNS DEFINITION ===== const totals: Totals = useMemo(() => { + if (summaryTotal && perWeightRangeSummary.length > 0) { + const totalAverageDocPrice = + perWeightRangeSummary.reduce( + (acc: number, item: HppPerKandangPerWeightRange) => + acc + (item.average_doc_price_rp || 0), + 0 + ) / perWeightRangeSummary.length; + + return { + total_hpp_rp: perWeightRangeSummary.reduce( + (acc: number, item: HppPerKandangPerWeightRange) => + acc + (item.hpp_rp || 0), + 0 + ), + total_average_doc_price_rp: totalAverageDocPrice, + }; + } + + if (data.length > 0) { + return { + total_hpp_rp: data.reduce( + (acc: number, item: HppPerKandangRow) => acc + (item.hpp_rp || 0), + 0 + ), + total_average_doc_price_rp: + data.reduce( + (acc: number, item: HppPerKandangRow) => + acc + (item.average_doc_price_rp || 0), + 0 + ) / data.length, + }; + } + return { - total_hpp_rp: - data.length > 0 - ? data.reduce((acc, item) => acc + (item.hpp_rp || 0), 0) - : 0, - total_average_doc_price_rp: - data.length > 0 - ? data.reduce( - (acc, item) => acc + (item.average_doc_price_rp || 0), - 0 - ) / data.length - : 0, + total_hpp_rp: 0, + total_average_doc_price_rp: 0, }; - }, [summary]); + }, [summaryTotal, perWeightRangeSummary, data]); const allFeedSuppliers = useMemo(() => { const suppliers = new Set(); - data.forEach((item) => { - item.feed_suppliers?.forEach((s) => { + data.forEach((item: HppPerKandangRow) => { + item.feed_suppliers?.forEach((s: { alias?: string; name: string }) => { suppliers.add(s.alias || s.name); }); }); @@ -298,8 +337,8 @@ const HppPerKandangTab = () => { const allDocSuppliers = useMemo(() => { const suppliers = new Set(); - data.forEach((item) => { - item.doc_suppliers?.forEach((s) => { + data.forEach((item: HppPerKandangRow) => { + item.doc_suppliers?.forEach((s: { alias?: string; name: string }) => { suppliers.add(s.alias || s.name); }); }); @@ -327,7 +366,7 @@ const HppPerKandangTab = () => { const summary = allDataForExport.summary; const excelData: { [key: string]: string | number }[] = allExportData.map( - (item, index) => ({ + (item: HppPerKandangRow, index: number) => ({ No: index + 1, Kandang: item.kandang?.name || '', 'Rentang Bobot': item.weight_range @@ -339,10 +378,13 @@ const HppPerKandangTab = () => { 'Produksi Telur (Butir)': item.egg_production_pieces || 0, 'Produksi Telur (KG)': item.egg_production_kg || 0, 'Feed (Supplier)': - item.feed_suppliers?.map((s) => s.alias || s.name).join(' | ') || - '', + item.feed_suppliers + ?.map((s: { alias?: string; name: string }) => s.alias || s.name) + .join(' | ') || '', 'DOC (Supplier)': - item.doc_suppliers?.map((s) => s.alias || s.name).join(' | ') || '', + item.doc_suppliers + ?.map((s: { alias?: string; name: string }) => s.alias || s.name) + .join(' | ') || '', 'Rata-Rata Harga DOC (RP)': item.average_doc_price_rp || 0, 'Nilai Nominal Telur (RP)': item.egg_value_rp || 0, 'HPP Ayam (RP)': item.hpp_rp || 0, @@ -588,7 +630,11 @@ const HppPerKandangTab = () => { accessorKey: 'feed_suppliers', cell: (props) => { const suppliers = props.row.original.feed_suppliers; - return suppliers?.map((s) => s.alias || s.name).join(' | ') || '-'; + return ( + suppliers + ?.map((s: { alias?: string; name: string }) => s.alias || s.name) + .join(' | ') || '-' + ); }, footer: () => (
@@ -602,7 +648,11 @@ const HppPerKandangTab = () => { accessorKey: 'doc_suppliers', cell: (props) => { const suppliers = props.row.original.doc_suppliers; - return suppliers?.map((s) => s.alias || s.name).join(' | ') || '-'; + return ( + suppliers + ?.map((s: { alias?: string; name: string }) => s.alias || s.name) + .join(' | ') || '-' + ); }, footer: () => (