diff --git a/src/components/pages/report/logistic-stock/tab/PurchasesPerSupplierTab.tsx b/src/components/pages/report/logistic-stock/tab/PurchasesPerSupplierTab.tsx index 0762352a..75ac0a57 100644 --- a/src/components/pages/report/logistic-stock/tab/PurchasesPerSupplierTab.tsx +++ b/src/components/pages/report/logistic-stock/tab/PurchasesPerSupplierTab.tsx @@ -25,6 +25,7 @@ import MenuItem from '@/components/menu/MenuItem'; import Menu from '@/components/menu/Menu'; import { generatePurchasesPerSupplierPDF } from '@/components/pages/report/logistic-stock/export/PurchasesPerSupplierExport'; import toast from 'react-hot-toast'; +import * as XLSX from 'xlsx'; interface Totals { totalQty: number; @@ -314,8 +315,138 @@ const PurchasesPerSupplierTab = () => { ); const handleExportExcel = useCallback(() => { - toast.error('Export to Excel functionality will be implemented.'); - }, []); + if (allExportData.length === 0) { + toast.error('Tidak ada data untuk diekspor.'); + return; + } + + try { + const groupedBySupplier: { [key: string]: typeof allExportData } = {}; + + allExportData.forEach((item) => { + const supplierName = item.supplier?.name || 'Unknown Supplier'; + if (!groupedBySupplier[supplierName]) { + groupedBySupplier[supplierName] = []; + } + groupedBySupplier[supplierName].push(item); + }); + + const workbook = XLSX.utils.book_new(); + + const areaName = tableFilterState.area_id + ? areaOptions.find( + (opt) => opt.value === Number(tableFilterState.area_id) + )?.label || 'Semua Area' + : 'Semua Area'; + + const supplierName = tableFilterState.supplier_id + ? supplierOptions.find( + (opt) => opt.value === Number(tableFilterState.supplier_id) + )?.label || 'Semua Supplier' + : 'Semua Supplier'; + + const startDate = tableFilterState.start_date || 'all'; + const endDate = tableFilterState.end_date || 'all'; + + Object.entries(groupedBySupplier).forEach( + ([supplierName, supplierData]) => { + const totals = supplierData.reduce( + (acc, item) => ({ + totalQty: acc.totalQty + (item.qty || 0), + totalPrice: acc.totalPrice + (item.unit_price || 0), + totalPurchaseAmount: + acc.totalPurchaseAmount + (item.purchase_value || 0), + totalTransport: + acc.totalTransport + (item.transport_unit_price || 0), + totalValueTransport: + acc.totalValueTransport + (item.transport_value || 0), + totalJumlah: acc.totalJumlah + (item.total_amount || 0), + }), + { + totalQty: 0, + totalPrice: 0, + totalPurchaseAmount: 0, + totalTransport: 0, + totalValueTransport: 0, + totalJumlah: 0, + } + ); + + const excelData: { [key: string]: string | number }[] = + supplierData.map((item, index) => ({ + No: index + 1, + 'Tanggal Terima': item.receive_date + ? formatDate(item.receive_date, 'DD MMM YYYY') + : '', + 'Tanggal PO': item.po_date + ? formatDate(item.po_date, 'DD MMM YYYY') + : '', + 'No. Referensi': item.po_number || '', + 'Nama Produk': item.product?.name || '', + Tujuan: item.warehouse?.name || '', + QTY: item.qty || 0, + 'Harga Beli (Rp)': item.unit_price || 0, + 'Value Harga Beli (Rp)': item.purchase_value || 0, + 'Transport (Rp)': item.transport_unit_price || 0, + 'Value Transport (Rp)': item.transport_value || 0, + 'Jumlah (Rp)': item.total_amount || 0, + Ekspedisi: item.expedition || '', + 'Surat Jalan': item.delivery_number || '', + })); + + excelData.push({ + No: 'Total', + 'Tanggal Terima': '', + 'Tanggal PO': '', + 'No. Referensi': '', + 'Nama Produk': '', + Tujuan: '', + QTY: totals.totalQty, + 'Harga Beli (Rp)': totals.totalPrice, + 'Value Harga Beli (Rp)': totals.totalPurchaseAmount, + 'Transport (Rp)': totals.totalTransport, + 'Value Transport (Rp)': totals.totalValueTransport, + 'Jumlah (Rp)': totals.totalJumlah, + Ekspedisi: '', + 'Surat Jalan': '', + }); + + const worksheet = XLSX.utils.json_to_sheet(excelData); + + const colWidths = [ + { wch: 5 }, // No + { wch: 15 }, // Tanggal Terima + { wch: 15 }, // Tanggal PO + { wch: 15 }, // No. Referensi + { wch: 30 }, // Nama Produk + { wch: 20 }, // Tujuan + { wch: 10 }, // QTY + { wch: 18 }, // Harga Beli + { wch: 20 }, // Value Harga Beli + { wch: 15 }, // Transport + { wch: 20 }, // Value Transport + { wch: 18 }, // Jumlah + { wch: 15 }, // Ekspedisi + { wch: 15 }, // Surat Jalan + ]; + worksheet['!cols'] = colWidths; + + const sheetName = + supplierName.length > 31 + ? supplierName.substring(0, 31) + : supplierName; + XLSX.utils.book_append_sheet(workbook, worksheet, sheetName); + } + ); + + const filename = `Laporan_Pembelian_Per_Supplier_${areaName}_${supplierName}_${startDate}_to_${endDate}.xlsx`; + + XLSX.writeFile(workbook, filename); + toast.success('Excel berhasil dibuat dan diunduh.'); + } catch { + toast.error('Gagal membuat Excel. Silakan coba lagi.'); + } + }, [allExportData, tableFilterState, areaOptions, supplierOptions]); const handleExportPdf = useCallback(async () => { if (allExportData.length === 0) {