diff --git a/src/components/pages/report/sale/export/HppPerkandangExportPDF.tsx b/src/components/pages/report/sale/export/HppPerkandangExportPDF.tsx index 3a76d8f4..94c24e93 100644 --- a/src/components/pages/report/sale/export/HppPerkandangExportPDF.tsx +++ b/src/components/pages/report/sale/export/HppPerkandangExportPDF.tsx @@ -2,7 +2,6 @@ import { Page, - Text, View, Document, StyleSheet, @@ -21,6 +20,8 @@ import { PdfTbodyCell, PdfTfootCell, } from '@/components/helper/pdf/table'; +import { PdfParamBadge } from '@/components/helper/pdf/badge/PdfParamBadge'; +import { PdfTypography } from '@/components/helper/pdf/typography/PdfTypography'; Font.register({ family: 'Helvetica', @@ -37,27 +38,6 @@ const pdfStyles = StyleSheet.create({ titleSection: { marginBottom: 10, }, - mainTitle: { - fontSize: 14, - fontWeight: 'bold', - marginBottom: 5, - color: '#1f74bf', - }, - supplierTitle: { - fontSize: 12, - fontWeight: 'bold', - marginBottom: 8, - color: '#1f74bf', - }, - parameterBadge: { - backgroundColor: '#F5F5F5', - color: '#333333', - padding: 4, - borderRadius: 4, - fontSize: 8, - marginRight: 8, - marginBottom: 4, - }, parameterContainer: { flexDirection: 'row', flexWrap: 'wrap', @@ -70,7 +50,7 @@ const pdfStyles = StyleSheet.create({ interface HppPerKandangExportParams { data: HppPerKandangReport; - params: { + params?: { area_name?: string; location_name?: string; kandang_name?: string; @@ -82,44 +62,11 @@ interface HppPerKandangExportParams { }; } -const getParameterText = (params: HppPerKandangExportParams['params']) => { - const paramsText = []; - - if (params.area_name && params.area_name !== 'Semua Area') { - paramsText.push(`Area: ${params.area_name}`); - } - - if (params.location_name && params.location_name !== 'Semua Lokasi') { - paramsText.push(`Lokasi: ${params.location_name}`); - } - - if (params.kandang_name && params.kandang_name !== 'Semua Kandang') { - paramsText.push(`Kandang: ${params.kandang_name}`); - } - - if (params.period) { - const formattedDate = formatDate(params.period, 'DD MMM YYYY'); - paramsText.push(`Tanggal: ${formattedDate}`); - } - - if (params.weight_min || params.weight_max) { - const weightRange = - params.weight_min && params.weight_max - ? `${params.weight_min} - ${params.weight_max} kg` - : params.weight_min - ? `≥ ${params.weight_min} kg` - : `≤ ${params.weight_max} kg`; - paramsText.push(`Rentang Bobot: ${weightRange}`); - } - - if (params.show_unrecorded === 'true') { - paramsText.push('Tampilkan: Tanpa Recording'); - } - - const currentDate = formatDate(new Date().toISOString(), 'DD MMM YYYY HH:mm'); - paramsText.push(`Dicetak: ${currentDate}`); - - return paramsText; +const formatSuppliers = ( + suppliers: { alias?: string; name: string }[] | null | undefined +): string => { + if (!suppliers || suppliers.length === 0) return '-'; + return suppliers.map((s) => s.alias || s.name).join(' | '); }; // Helper functions for PdfTable - Rekapitulasi @@ -133,65 +80,79 @@ const getRekapitulasiColumns = (): PdfColumn[] => [ flex: 1.2, align: 'right', }, - { key: 'feed_supplier', header: 'Feed (Supplier)', flex: 1.5, align: 'left' }, - { key: 'doc_supplier', header: 'DOC (Supplier)', flex: 1.2, align: 'left' }, + { + key: 'feed_supplier', + header: 'Feed (Supplier)', + flex: 1.5, + align: 'left', + }, + { + key: 'doc_supplier', + header: 'DOC (Supplier)', + flex: 1.2, + align: 'left', + }, { key: 'rata_harga_doc', header: 'Rata-Rata Harga DOC', flex: 1.2, align: 'right', }, - { key: 'hpp_telur', header: 'HPP Telur (RP/KG)', flex: 1.2, align: 'right' }, - { key: 'nominal_sisa', header: 'Nominal Sisa', flex: 1.2, align: 'right' }, + { + key: 'hpp_telur', + header: 'HPP Telur (Rp/Kg)', + flex: 1.2, + align: 'right', + }, + { + key: 'nominal_sisa', + header: 'Nominal Sisa', + flex: 1.2, + align: 'right', + }, ]; const getRekapitulasiData = ( perWeightRange: HppPerKandangPerWeightRange[] ): PdfTbodyCell[][] => { return perWeightRange.map((group) => [ - { key: 'rentang_bw', value: group.label, align: 'center' }, + { key: 'rentang_bw', value: group.label || '-' }, { key: 'sisa_butir', - value: formatNumber(group.egg_production_pieces), + value: formatNumber(group.egg_production_pieces || 0), align: 'right', }, { key: 'sisa_kg', - value: formatNumber(group.egg_production_kg), + value: formatNumber(group.egg_production_kg || 0), align: 'right', }, { key: 'rata_rata_bobot', - value: formatNumber(group.avg_weight_kg), + value: formatNumber(group.avg_weight_kg || 0), align: 'right', }, { key: 'feed_supplier', - value: - group.feed_suppliers - ?.map((s: { alias?: string; name: string }) => s.alias || s.name) - .join(' | ') || '-', + value: formatSuppliers(group.feed_suppliers), }, { key: 'doc_supplier', - value: - group.doc_suppliers - ?.map((s: { alias?: string; name: string }) => s.alias || s.name) - .join(' | ') || '-', + value: formatSuppliers(group.doc_suppliers), }, { key: 'rata_harga_doc', - value: formatCurrency(group.average_doc_price_rp), + value: formatCurrency(group.average_doc_price_rp || 0), align: 'right', }, { key: 'hpp_telur', - value: formatCurrency(group.egg_hpp_rp_per_kg), + value: formatCurrency(group.egg_hpp_rp_per_kg || 0), align: 'right', }, { key: 'nominal_sisa', - value: formatCurrency(group.egg_value_rp), + value: formatCurrency(group.egg_value_rp || 0), align: 'right', }, ]); @@ -210,21 +171,45 @@ const getDetailColumns = (): PdfColumn[] => [ }, { key: 'sisa_butir', header: 'Sisa Butir', flex: 0.8, align: 'right' }, { key: 'sisa_kg', header: 'Sisa Kg (Telur)', flex: 0.8, align: 'right' }, - { key: 'feed_supplier', header: 'Feed (Supplier)', flex: 1.2, align: 'left' }, - { key: 'doc_supplier', header: 'DOC (Supplier)', flex: 1, align: 'left' }, + { + key: 'feed_supplier', + header: 'Feed (Supplier)', + flex: 1.2, + align: 'left', + }, + { + key: 'doc_supplier', + header: 'DOC (Supplier)', + flex: 1, + align: 'left', + }, { key: 'rata_harga_doc', header: 'Rata-Rata Harga DOC', flex: 1.2, align: 'right', }, - { key: 'hpp_telur', header: 'HPP Telur (RP/KG)', flex: 1, align: 'right' }, - { key: 'nominal_sisa', header: 'Nominal Sisa', flex: 1.2, align: 'right' }, + { + key: 'hpp_telur', + header: 'HPP Telur (Rp/Kg)', + flex: 1, + align: 'right', + }, + { + key: 'nominal_sisa', + header: 'Nominal Sisa', + flex: 1.2, + align: 'right', + }, ]; -const getDetailData = (rows: HppPerKandangRow[]): PdfTbodyCell[][] => { +const getDetailData = ( + rows: HppPerKandangRow[], + allFeedSuppliers: string, + allDocSuppliers: string +): PdfTbodyCell[][] => { return rows.map((item, index) => [ - { key: 'no', value: index + 1, align: 'center' }, + { key: 'no', value: index + 1 }, { key: 'kandang', value: item.kandang?.name || '-' }, { key: 'rentang_bw', @@ -232,131 +217,146 @@ const getDetailData = (rows: HppPerKandangRow[]): PdfTbodyCell[][] => { }, { key: 'rata_rata_bobot', - value: formatNumber(item.avg_weight_kg), + value: formatNumber(item.avg_weight_kg || 0), align: 'right', }, { key: 'sisa_butir', - value: formatNumber(item.egg_production_pieces), + value: formatNumber(item.egg_production_pieces || 0), align: 'right', }, { key: 'sisa_kg', - value: formatNumber(item.egg_production_kg), + value: formatNumber(item.egg_production_kg || 0), align: 'right', }, { key: 'feed_supplier', - value: - item.feed_suppliers - ?.map((s: { alias?: string; name: string }) => s.alias || s.name) - .join(' | ') || '-', + value: formatSuppliers(item.feed_suppliers), }, { key: 'doc_supplier', - value: - item.doc_suppliers - ?.map((s: { alias?: string; name: string }) => s.alias || s.name) - .join(' | ') || '-', + value: formatSuppliers(item.doc_suppliers), }, { key: 'rata_harga_doc', - value: formatCurrency(item.average_doc_price_rp), + value: formatCurrency(item.average_doc_price_rp || 0), align: 'right', }, { key: 'hpp_telur', - value: formatCurrency(item.egg_hpp_rp_per_kg), + value: formatCurrency(item.egg_hpp_rp_per_kg || 0), align: 'right', }, { key: 'nominal_sisa', - value: formatCurrency(item.egg_value_rp), + value: formatCurrency(item.egg_value_rp || 0), align: 'right', }, ]); }; const getDetailFooter = ( - summary: HppPerKandangReport['summary'] + summary: HppPerKandangReport['summary'], + allFeedSuppliers: string, + allDocSuppliers: string ): PdfTfootCell[] => { if (!summary?.total) return []; - const allFeedSuppliers = - summary.total.feed_suppliers - ?.map((s: { alias?: string; name: string }) => s.alias || s.name) - .join(' | ') || '-'; - - const allDocSuppliers = - summary.total.doc_suppliers - ?.map((s: { alias?: string; name: string }) => s.alias || s.name) - .join(' | ') || '-'; - return [ { key: 'no', value: 'TOTAL' }, { key: 'kandang', value: 'ALL' }, { key: 'rentang_bw', value: '-' }, { key: 'rata_rata_bobot', - value: formatNumber(summary.total.average_weight_kg), + value: formatNumber(summary.total.average_weight_kg || 0), align: 'right', }, { key: 'sisa_butir', - value: formatNumber(summary.total.total_egg_production_pieces), + value: formatNumber(summary.total.total_egg_production_pieces || 0), align: 'right', }, { key: 'sisa_kg', - value: formatNumber(summary.total.total_egg_production_kg), + value: formatNumber(summary.total.total_egg_production_kg || 0), align: 'right', }, { key: 'feed_supplier', value: allFeedSuppliers }, { key: 'doc_supplier', value: allDocSuppliers }, { key: 'rata_harga_doc', - value: formatCurrency(summary.total.total_average_doc_price_rp), + value: formatCurrency(summary.total.total_average_doc_price_rp || 0), align: 'right', }, { key: 'hpp_telur', - value: formatCurrency(summary.total.average_egg_hpp_rp_per_kg), + value: formatCurrency(summary.total.average_egg_hpp_rp_per_kg || 0), align: 'right', }, { key: 'nominal_sisa', - value: formatCurrency(summary.total.total_egg_value_rp), + value: formatCurrency(summary.total.total_egg_value_rp || 0), align: 'right', }, ]; }; const createPDFDocument = ( - data: HppPerKandangExportParams['data'], - params: HppPerKandangExportParams['params'] + params: HppPerKandangExportParams, + allFeedSuppliers: string, + allDocSuppliers: string ) => { - const rekapitulasiByWeightRange = data.summary?.per_weight_range || []; + const rekapitulasiByWeightRange = params.data.summary?.per_weight_range || []; + + const weightRangeText = + params.params?.weight_min || params.params?.weight_max + ? params.params.weight_min && params.params.weight_max + ? `${params.params.weight_min} - ${params.params.weight_max} kg` + : params.params.weight_min + ? `≥ ${params.params.weight_min} kg` + : `≤ ${params.params.weight_max} kg` + : '-'; return ( {/* Title and Parameters */} - + Laporan > HPP Harian Kandang - + - {getParameterText(params).map((param, index) => ( - - {param} - - ))} + + Area: {params.params?.area_name || 'Semua Area'} + + + Lokasi: {params.params?.location_name || 'Semua Lokasi'} + + + Kandang: {params.params?.kandang_name || 'Semua Kandang'} + + + Periode:{' '} + {params.params?.period + ? formatDate(params.params.period, 'DD MMM YYYY') + : '-'} + + Rentang Bobot: {weightRangeText} + {params.params?.show_unrecorded === 'true' && ( + Tampilkan: Tanpa Recording + )} + + Dicetak: {formatDate(new Date(), 'DD MMM YYYY HH:mm')} + {/* Rekapitulasi Section */} - Rekapitulasi + + Rekapitulasi + - Detail Per Kandang + + Detail Per Kandang + @@ -379,10 +393,15 @@ const createPDFDocument = ( }; export const generateHppPerKandangPDF = async ( - data: HppPerKandangExportParams['data'], - params: HppPerKandangExportParams['params'] + params: HppPerKandangExportParams, + allFeedSuppliers: string, + allDocSuppliers: string ): Promise => { - const PDFDocument = createPDFDocument(data, params); + const PDFDocument = createPDFDocument( + params, + allFeedSuppliers, + allDocSuppliers + ); try { const blob = await pdf(PDFDocument).toBlob(); @@ -390,7 +409,8 @@ export const generateHppPerKandangPDF = async ( const link = document.createElement('a'); link.href = url; - const period = params.period || formatDate(new Date(), 'YYYY-MM-DD'); + const period = + params.params?.period || formatDate(new Date(), 'YYYY-MM-DD'); link.download = `laporan-hpp-harian-kandang-periode-${period}.pdf`; document.body.appendChild(link); diff --git a/src/components/pages/report/sale/tab/HppPerKandangTab.tsx b/src/components/pages/report/sale/tab/HppPerKandangTab.tsx index 9e4d4004..d9690792 100644 --- a/src/components/pages/report/sale/tab/HppPerKandangTab.tsx +++ b/src/components/pages/report/sale/tab/HppPerKandangTab.tsx @@ -406,16 +406,23 @@ const HppPerKandangTab = () => { .join(', ') || 'Semua Kandang' : 'Semua Kandang'; - await generateHppPerKandangPDF(allDataForExport, { - area_name: areaName, - location_name: locationName, - kandang_name: kandangName, - period: tableFilterState.period, - weight_min: tableFilterState.weight_min, - weight_max: tableFilterState.weight_max, - show_unrecorded: tableFilterState.show_unrecorded.toString(), - sort_by: tableFilterState.sort_by, - }); + await generateHppPerKandangPDF( + { + data: allDataForExport, + params: { + area_name: areaName, + location_name: locationName, + kandang_name: kandangName, + period: tableFilterState.period, + weight_min: tableFilterState.weight_min, + weight_max: tableFilterState.weight_max, + show_unrecorded: tableFilterState.show_unrecorded.toString(), + sort_by: tableFilterState.sort_by, + }, + }, + allFeedSuppliers, + allDocSuppliers + ); toast.success('PDF berhasil dibuat dan diunduh.'); } catch { @@ -429,6 +436,8 @@ const HppPerKandangTab = () => { areaOptions, locationOptions, kandangOptions, + allFeedSuppliers, + allDocSuppliers, ]); const getTableColumns = (): ColumnDef[] => {