mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 23:35:45 +00:00
refactor(FE-356): Refactor weight-range grouping and format currency
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
|||||||
pdf,
|
pdf,
|
||||||
} from '@react-pdf/renderer';
|
} from '@react-pdf/renderer';
|
||||||
import { HppPerKandangReport } from '@/types/api/report/hpp-per-kandang';
|
import { HppPerKandangReport } from '@/types/api/report/hpp-per-kandang';
|
||||||
import { formatDate, formatNumber } from '@/lib/helper';
|
import { formatDate, formatNumber, formatCurrency } from '@/lib/helper';
|
||||||
|
|
||||||
Font.register({
|
Font.register({
|
||||||
family: 'Helvetica',
|
family: 'Helvetica',
|
||||||
@@ -148,88 +148,72 @@ interface HppPerKandangExportParams {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WeightRangeGroup {
|
const rekapitulasiData = (data: HppPerKandangReport['rows']) => {
|
||||||
weight_min: number;
|
const groups: { [key: string]: HppPerKandangReport['rows'] } = {};
|
||||||
weight_max: number;
|
|
||||||
items: HppPerKandangReport['rows'];
|
|
||||||
totals: {
|
|
||||||
total_remaining_chicken_birds: number;
|
|
||||||
total_remaining_chicken_weight_kg: number;
|
|
||||||
average_weight_kg: number;
|
|
||||||
total_hpp_rp: number;
|
|
||||||
total_remaining_value_rp: number;
|
|
||||||
all_feed_suppliers: string[];
|
|
||||||
all_doc_suppliers: string[];
|
|
||||||
average_doc_price_rp: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupDataByWeightRange = (
|
|
||||||
data: HppPerKandangReport['rows'],
|
|
||||||
summary: HppPerKandangReport['summary']
|
|
||||||
): WeightRangeGroup[] => {
|
|
||||||
const groups: {
|
|
||||||
[key: string]: WeightRangeGroup;
|
|
||||||
} = {};
|
|
||||||
|
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
const key = `${item.weight_range.weight_min}-${item.weight_range.weight_max}`;
|
const key = `${item.weight_range.weight_min}-${item.weight_range.weight_max}`;
|
||||||
if (!groups[key]) {
|
if (!groups[key]) {
|
||||||
groups[key] = {
|
groups[key] = [];
|
||||||
weight_min: item.weight_range.weight_min,
|
|
||||||
weight_max: item.weight_range.weight_max,
|
|
||||||
items: [],
|
|
||||||
totals: {
|
|
||||||
total_remaining_chicken_birds: 0,
|
|
||||||
total_remaining_chicken_weight_kg: 0,
|
|
||||||
average_weight_kg: 0,
|
|
||||||
total_hpp_rp: 0,
|
|
||||||
total_remaining_value_rp: 0,
|
|
||||||
all_feed_suppliers: [],
|
|
||||||
all_doc_suppliers: [],
|
|
||||||
average_doc_price_rp: 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
groups[key].push(item);
|
||||||
groups[key].items.push(item);
|
|
||||||
|
|
||||||
groups[key].totals.total_remaining_chicken_birds +=
|
|
||||||
item.remaining_chicken_birds;
|
|
||||||
groups[key].totals.total_remaining_chicken_weight_kg +=
|
|
||||||
item.remaining_chicken_weight_kg;
|
|
||||||
groups[key].totals.total_hpp_rp += item.hpp_rp;
|
|
||||||
groups[key].totals.total_remaining_value_rp += item.remaining_value_rp;
|
|
||||||
|
|
||||||
item.feed_suppliers?.forEach((supplier) => {
|
|
||||||
const alias = supplier.alias || supplier.name;
|
|
||||||
if (!groups[key].totals.all_feed_suppliers.includes(alias)) {
|
|
||||||
groups[key].totals.all_feed_suppliers.push(alias);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
item.doc_suppliers?.forEach((supplier) => {
|
|
||||||
const alias = supplier.alias || supplier.name;
|
|
||||||
if (!groups[key].totals.all_doc_suppliers.includes(alias)) {
|
|
||||||
groups[key].totals.all_doc_suppliers.push(alias);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.values(groups).forEach((group) => {
|
return Object.entries(groups)
|
||||||
group.totals.average_weight_kg =
|
.map(([key, items]) => ({
|
||||||
group.totals.total_remaining_chicken_weight_kg /
|
weight_min: items[0].weight_range.weight_min,
|
||||||
group.totals.total_remaining_chicken_birds;
|
weight_max: items[0].weight_range.weight_max,
|
||||||
group.totals.average_doc_price_rp =
|
items,
|
||||||
group.items.length > 0
|
total_remaining_chicken_birds: items.reduce(
|
||||||
? group.items.reduce(
|
(sum, item) => sum + item.remaining_chicken_birds,
|
||||||
(sum, item) => sum + item.average_doc_price_rp,
|
0
|
||||||
0
|
),
|
||||||
) / group.items.length
|
total_remaining_chicken_weight_kg: items.reduce(
|
||||||
: 0;
|
(sum, item) => sum + item.remaining_chicken_weight_kg,
|
||||||
});
|
0
|
||||||
|
),
|
||||||
return Object.values(groups).sort((a, b) => a.weight_min - b.weight_min);
|
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 getParameterText = (params: HppPerKandangExportParams['params']) => {
|
||||||
@@ -246,27 +230,11 @@ const getParameterText = (params: HppPerKandangExportParams['params']) => {
|
|||||||
return paramsText;
|
return paramsText;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTotalsForExport = (data: HppPerKandangReport['rows']) => {
|
|
||||||
const totalHppRp = data.reduce((sum, item) => sum + (item.hpp_rp || 0), 0);
|
|
||||||
const avgDocPrice =
|
|
||||||
data.length > 0
|
|
||||||
? data.reduce((sum, item) => sum + (item.average_doc_price_rp || 0), 0) /
|
|
||||||
data.length
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return {
|
|
||||||
total_hpp_rp: totalHppRp,
|
|
||||||
total_average_doc_price_rp: avgDocPrice,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const createPDFDocument = (
|
const createPDFDocument = (
|
||||||
data: HppPerKandangExportParams['data'],
|
data: HppPerKandangExportParams['data'],
|
||||||
params: HppPerKandangExportParams['params']
|
params: HppPerKandangExportParams['params']
|
||||||
) => {
|
) => {
|
||||||
const summary = data.summary;
|
const rekapitulasiByWeightRange = rekapitulasiData(data.rows);
|
||||||
const exportTotals = getTotalsForExport(data.rows);
|
|
||||||
const groupedByWeightRange = groupDataByWeightRange(data.rows, summary);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Document>
|
<Document>
|
||||||
@@ -334,12 +302,12 @@ const createPDFDocument = (
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Table Body - Rekapitulasi */}
|
{/* Table Body - Rekapitulasi */}
|
||||||
{groupedByWeightRange.map((group, index) => (
|
{rekapitulasiByWeightRange.map((group, index) => (
|
||||||
<View
|
<View
|
||||||
key={index}
|
key={index}
|
||||||
style={[
|
style={[
|
||||||
pdfStyles.tableRow,
|
pdfStyles.tableRow,
|
||||||
index < groupedByWeightRange.length - 1
|
index < rekapitulasiByWeightRange.length - 1
|
||||||
? pdfStyles.tableBorderBottom
|
? pdfStyles.tableBorderBottom
|
||||||
: {},
|
: {},
|
||||||
]}
|
]}
|
||||||
@@ -352,82 +320,50 @@ const createPDFDocument = (
|
|||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
<Text>
|
<Text>
|
||||||
{formatNumber(group.totals.total_remaining_chicken_birds)}
|
{formatNumber(group.total_remaining_chicken_birds)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
<Text>
|
<Text>
|
||||||
{formatNumber(
|
{formatNumber(group.total_remaining_chicken_weight_kg)}
|
||||||
group.totals.total_remaining_chicken_weight_kg
|
|
||||||
)}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>{formatNumber(group.totals.average_weight_kg)}</Text>
|
<Text>{formatNumber(group.average_weight_kg)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
<Text>
|
<Text>{formatNumber(group.total_egg_production_pieces)}</Text>
|
||||||
{formatNumber(
|
|
||||||
group.items.reduce(
|
|
||||||
(sum, item) => sum + (item.egg_production_pieces || 0),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
<Text>
|
<Text>{formatNumber(group.total_egg_production_kg)}</Text>
|
||||||
{formatNumber(
|
|
||||||
group.items.reduce(
|
|
||||||
(sum, item) => sum + (item.egg_production_kg || 0),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
|
<View style={[pdfStyles.tableCell, { flex: 1.5 }]}>
|
||||||
<Text>{group.totals.all_feed_suppliers.join(' | ')}</Text>
|
<Text>{group.all_feed_suppliers.join(' | ')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCell, { flex: 1.2 }]}>
|
||||||
<Text>{group.totals.all_doc_suppliers.join(' | ')}</Text>
|
<Text>{group.all_doc_suppliers.join(' | ')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>{formatNumber(group.totals.average_doc_price_rp)}</Text>
|
<Text>{formatCurrency(group.average_doc_price_rp)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>
|
<Text>{formatCurrency(group.total_egg_value_rp)}</Text>
|
||||||
{formatNumber(
|
|
||||||
group.items.reduce(
|
|
||||||
(sum, item) => sum + (item.egg_value_rp || 0),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
<Text>
|
<Text>
|
||||||
{formatNumber(
|
{formatCurrency(
|
||||||
group.totals.total_remaining_chicken_birds > 0
|
group.total_remaining_chicken_birds > 0
|
||||||
? group.totals.total_hpp_rp /
|
? group.total_hpp_rp /
|
||||||
group.totals.total_remaining_chicken_birds
|
group.total_remaining_chicken_birds
|
||||||
: 0
|
: 0
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>
|
<Text>{formatCurrency(group.average_egg_hpp_rp_per_kg)}</Text>
|
||||||
{formatNumber(
|
|
||||||
group.items.reduce(
|
|
||||||
(sum, item) => sum + (item.egg_hpp_rp_per_kg || 0),
|
|
||||||
0
|
|
||||||
) / group.items.length || 0
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>
|
<Text>{formatCurrency(group.total_remaining_value_rp)}</Text>
|
||||||
{formatNumber(group.totals.total_remaining_value_rp)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
@@ -541,19 +477,19 @@ const createPDFDocument = (
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>{formatNumber(item.average_doc_price_rp)}</Text>
|
<Text>{formatCurrency(item.average_doc_price_rp)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>{formatNumber(item.egg_value_rp)}</Text>
|
<Text>{formatCurrency(item.egg_value_rp)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 0.8 }]}>
|
||||||
<Text>{formatNumber(item.hpp_rp)}</Text>
|
<Text>{formatCurrency(item.hpp_rp)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1 }]}>
|
||||||
<Text>{formatNumber(item.egg_hpp_rp_per_kg)}</Text>
|
<Text>{formatCurrency(item.egg_hpp_rp_per_kg)}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
<View style={[pdfStyles.tableCellRight, { flex: 1.2 }]}>
|
||||||
<Text>{formatNumber(item.remaining_value_rp)}</Text>
|
<Text>{formatCurrency(item.remaining_value_rp)}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user