mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +00:00
Merge branch 'dev/hotfix/restu' into 'development'
[FEAT/FE] Install ExcelJS and Refactor XLSX Export (Negative Color) See merge request mbugroup/lti-web-client!223
This commit is contained in:
Generated
+923
-10
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"exceljs": "^4.4.0",
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
"html-to-image": "^1.11.13",
|
"html-to-image": "^1.11.13",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import * as XLSX from 'xlsx';
|
import ExcelJS from 'exceljs';
|
||||||
import { formatDate, formatCurrency, formatNumber } from '@/lib/helper';
|
import { formatDate, formatCurrency, formatNumber } from '@/lib/helper';
|
||||||
import { CustomerPaymentReport } from '@/types/api/report/customer-payment';
|
import { CustomerPaymentReport } from '@/types/api/report/customer-payment';
|
||||||
|
|
||||||
@@ -8,104 +8,130 @@ interface CustomerPaymentExportExcelParams {
|
|||||||
data: CustomerPaymentReport[];
|
data: CustomerPaymentReport[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateCustomerPaymentExcel = (
|
export const generateCustomerPaymentExcel = async (
|
||||||
params: CustomerPaymentExportExcelParams
|
params: CustomerPaymentExportExcelParams
|
||||||
): void => {
|
): Promise<void> => {
|
||||||
if (!params.data || params.data.length === 0) {
|
if (!params.data || params.data.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const workbook = XLSX.utils.book_new();
|
const workbook = new ExcelJS.Workbook();
|
||||||
|
|
||||||
params.data.forEach((customerReport) => {
|
const columns = [
|
||||||
|
{ header: 'No', key: 'no', width: 5 },
|
||||||
|
{ header: 'Tanggal DO/Bayar', key: 'transDate', width: 15 },
|
||||||
|
{ header: 'Tanggal Realisasi', key: 'deliveryDate', width: 15 },
|
||||||
|
{ header: 'Aging', key: 'aging', width: 8 },
|
||||||
|
{ header: 'Referensi', key: 'reference', width: 12 },
|
||||||
|
{ header: 'Nomor Polisi', key: 'vehicleNumbers', width: 15 },
|
||||||
|
{ header: 'Ekor/Qty', key: 'qty', width: 10 },
|
||||||
|
{ header: 'Berat (Kg)', key: 'weight', width: 12 },
|
||||||
|
{ header: 'AVG', key: 'avgWeight', width: 10 },
|
||||||
|
{ header: 'Harga/Unit', key: 'unitPrice', width: 15 },
|
||||||
|
{ header: 'Harga Akhir', key: 'finalPrice', width: 15 },
|
||||||
|
{ header: 'Total', key: 'totalPrice', width: 15 },
|
||||||
|
{ header: 'Pembayaran', key: 'paymentAmount', width: 15 },
|
||||||
|
{ header: 'Saldo Piutang', key: 'accountsReceivable', width: 15 },
|
||||||
|
{ header: 'Keterangan', key: 'status', width: 20 },
|
||||||
|
{ header: 'Pengambilan', key: 'pickupInfo', width: 15 },
|
||||||
|
{ header: 'Sales/Marketing', key: 'salesPerson', width: 20 },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const customerReport of params.data) {
|
||||||
const customerData = customerReport.rows;
|
const customerData = customerReport.rows;
|
||||||
const customerName = customerReport.customer.name || 'Unknown Customer';
|
const customerName = customerReport.customer.name || 'Unknown Customer';
|
||||||
|
|
||||||
const excelData: { [key: string]: string | number }[] = customerData.map(
|
const worksheet = workbook.addWorksheet(customerName.substring(0, 31));
|
||||||
(item, index) => ({
|
worksheet.columns = columns;
|
||||||
No: index + 1,
|
|
||||||
'Tanggal DO/Bayar': item.trans_date
|
customerData.forEach((item, index) => {
|
||||||
|
const row = worksheet.addRow({
|
||||||
|
no: index + 1,
|
||||||
|
transDate: item.trans_date
|
||||||
? formatDate(item.trans_date, 'DD MMM YYYY')
|
? formatDate(item.trans_date, 'DD MMM YYYY')
|
||||||
: '',
|
: '',
|
||||||
'Tanggal Realisasi': item.delivery_date
|
deliveryDate: item.delivery_date
|
||||||
? formatDate(item.delivery_date, 'DD MMM YYYY')
|
? formatDate(item.delivery_date, 'DD MMM YYYY')
|
||||||
: '',
|
: '',
|
||||||
Aging: formatNumber(item.aging_day || 0),
|
aging: formatNumber(item.aging_day || 0),
|
||||||
Referensi: item.reference || '',
|
reference: item.reference || '',
|
||||||
'Nomor Polisi': Array.isArray(item.vehicle_numbers)
|
vehicleNumbers: Array.isArray(item.vehicle_numbers)
|
||||||
? item.vehicle_numbers.join(', ')
|
? item.vehicle_numbers.join(', ')
|
||||||
: '',
|
: '',
|
||||||
'Ekor/Qty': formatNumber(item.qty || 0),
|
qty: formatNumber(item.qty || 0),
|
||||||
'Berat (Kg)': formatNumber(item.weight || 0),
|
weight: formatNumber(item.weight || 0),
|
||||||
AVG: formatNumber(item.average_weight || 0),
|
avgWeight: formatNumber(item.average_weight || 0),
|
||||||
'Harga/Unit': formatCurrency(item.unit_price || 0),
|
unitPrice: formatCurrency(item.unit_price || 0),
|
||||||
'Harga Akhir': formatCurrency(item.final_price || 0),
|
finalPrice: formatCurrency(item.final_price || 0),
|
||||||
Total: formatCurrency(item.total_price || 0),
|
totalPrice: formatCurrency(item.total_price || 0),
|
||||||
Pembayaran: formatCurrency(item.payment_amount || 0),
|
paymentAmount: formatCurrency(item.payment_amount || 0),
|
||||||
'Saldo Piutang': formatCurrency(item.accounts_receivable || 0),
|
accountsReceivable: formatCurrency(item.accounts_receivable || 0),
|
||||||
Keterangan: item.status || '',
|
status: item.status || '',
|
||||||
Pengambilan: Array.isArray(item.pickup_info)
|
pickupInfo: Array.isArray(item.pickup_info)
|
||||||
? item.pickup_info.join(', ')
|
? item.pickup_info.join(', ')
|
||||||
: '',
|
: '',
|
||||||
'Sales/Marketing': item.sales_person || '',
|
salesPerson: item.sales_person || '',
|
||||||
})
|
});
|
||||||
);
|
|
||||||
|
const accountsReceivableCell = row.getCell('accountsReceivable');
|
||||||
|
if (
|
||||||
|
accountsReceivableCell.value &&
|
||||||
|
accountsReceivableCell.value.toString().startsWith('-Rp')
|
||||||
|
) {
|
||||||
|
accountsReceivableCell.font = { color: { argb: 'FFFF0000' } };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (customerReport.summary) {
|
if (customerReport.summary) {
|
||||||
excelData.push({
|
const summaryRow = worksheet.addRow({
|
||||||
No: 'Total',
|
no: 'Total',
|
||||||
'Tanggal DO/Bayar': '',
|
transDate: '',
|
||||||
'Tanggal Realisasi': '',
|
deliveryDate: '',
|
||||||
Aging: '',
|
aging: '',
|
||||||
Referensi: '',
|
reference: '',
|
||||||
'Nomor Polisi': '',
|
vehicleNumbers: '',
|
||||||
'Ekor/Qty': formatNumber(customerReport.summary.total_qty || 0),
|
qty: formatNumber(customerReport.summary.total_qty || 0),
|
||||||
'Berat (Kg)': formatNumber(customerReport.summary.total_weight || 0),
|
weight: formatNumber(customerReport.summary.total_weight || 0),
|
||||||
AVG: '',
|
avgWeight: '',
|
||||||
'Harga/Unit': '',
|
unitPrice: '',
|
||||||
'Harga Akhir': formatCurrency(
|
finalPrice: formatCurrency(
|
||||||
customerReport.summary.total_final_amount || 0
|
customerReport.summary.total_final_amount || 0
|
||||||
),
|
),
|
||||||
Total: formatCurrency(customerReport.summary.total_grand_amount || 0),
|
totalPrice: formatCurrency(
|
||||||
Pembayaran: formatCurrency(customerReport.summary.total_payment || 0),
|
customerReport.summary.total_grand_amount || 0
|
||||||
'Saldo Piutang': formatCurrency(
|
),
|
||||||
|
paymentAmount: formatCurrency(
|
||||||
|
customerReport.summary.total_payment || 0
|
||||||
|
),
|
||||||
|
accountsReceivable: formatCurrency(
|
||||||
customerReport.summary.total_accounts_receivable || 0
|
customerReport.summary.total_accounts_receivable || 0
|
||||||
),
|
),
|
||||||
Keterangan: '',
|
status: '',
|
||||||
Pengambilan: '',
|
pickupInfo: '',
|
||||||
'Sales/Marketing': '',
|
salesPerson: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const summaryAccountsReceivableCell =
|
||||||
|
summaryRow.getCell('accountsReceivable');
|
||||||
|
if (
|
||||||
|
summaryAccountsReceivableCell.value &&
|
||||||
|
summaryAccountsReceivableCell.value.toString().startsWith('-Rp')
|
||||||
|
) {
|
||||||
|
summaryAccountsReceivableCell.font = { color: { argb: 'FFFF0000' } };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const worksheet = XLSX.utils.json_to_sheet(excelData);
|
|
||||||
|
|
||||||
const colWidths = [
|
|
||||||
{ wch: 5 }, // No
|
|
||||||
{ wch: 15 }, // Tanggal DO/Bayar
|
|
||||||
{ wch: 15 }, // Tanggal Realisasi
|
|
||||||
{ wch: 8 }, // Aging
|
|
||||||
{ wch: 12 }, // Referensi
|
|
||||||
{ wch: 15 }, // Nomor Polisi
|
|
||||||
{ wch: 10 }, // Ekor/Qty
|
|
||||||
{ wch: 12 }, // Berat
|
|
||||||
{ wch: 10 }, // AVG
|
|
||||||
{ wch: 15 }, // Harga/Unit
|
|
||||||
{ wch: 15 }, // Harga Akhir
|
|
||||||
{ wch: 15 }, // Total
|
|
||||||
{ wch: 15 }, // Pembayaran
|
|
||||||
{ wch: 15 }, // Saldo Piutang
|
|
||||||
{ wch: 20 }, // Keterangan
|
|
||||||
{ wch: 15 }, // Pengambilan
|
|
||||||
{ wch: 20 }, // Sales/Marketing
|
|
||||||
];
|
|
||||||
worksheet['!cols'] = colWidths;
|
|
||||||
|
|
||||||
const sheetName =
|
|
||||||
customerName.length > 31 ? customerName.substring(0, 31) : customerName;
|
|
||||||
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
|
|
||||||
});
|
|
||||||
|
|
||||||
const filename = `laporan-kontrol-pembayaran-customer-dicetak-pada-${formatDate(new Date(), 'YYYY-MM-DD-HHmm')}.xlsx`;
|
const filename = `laporan-kontrol-pembayaran-customer-dicetak-pada-${formatDate(new Date(), 'YYYY-MM-DD-HHmm')}.xlsx`;
|
||||||
|
|
||||||
XLSX.writeFile(workbook, filename);
|
const buffer = await workbook.xlsx.writeBuffer();
|
||||||
|
const blob = new Blob([buffer], {
|
||||||
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
});
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = filename;
|
||||||
|
link.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ const CustomerPaymentTab = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCustomerPaymentExcel({ data: allDataForExport });
|
await generateCustomerPaymentExcel({ data: allDataForExport });
|
||||||
toast.success('Excel berhasil dibuat dan diunduh.');
|
toast.success('Excel berhasil dibuat dan diunduh.');
|
||||||
} catch {
|
} catch {
|
||||||
toast.error('Gagal membuat Excel. Silakan coba lagi.');
|
toast.error('Gagal membuat Excel. Silakan coba lagi.');
|
||||||
|
|||||||
Reference in New Issue
Block a user