import { exportDataGrid as exportToExcel } from 'devextreme/excel_exporter' import { Document, AlignmentType, Packer, Paragraph, Table, TableCell, TableRow, VerticalAlign, TextRun, WidthType, PageOrientation } from 'docx' import { saveAs } from 'file-saver' import { jsPDF } from 'jspdf' import autoTable from 'jspdf-autotable' import { Workbook } from 'exceljs' import { formatWaktu } from '@/components/Form/FiltersType/reference' import { setHeaderStyle } from '@/report/utils/xlsx' import { formatNumber, formatPercentage } from '@/utils/numbers' const reportName = 'Rekapitulasi Keluhan All' const fontSize = 5 const detailFontSize = 5 const groupingData = (data: any) => { const groupedData: any = {} data.forEach((item: any) => { const { nama_regional, nama_uid } = item if (!groupedData[nama_regional]) { groupedData[nama_regional] = {} } if (!groupedData[nama_regional][nama_uid]) { groupedData[nama_regional][nama_uid] = { data: [] } } groupedData[nama_regional][nama_uid].data.push(item) }) for (const regional in groupedData) { for (const uid in groupedData[regional]) { const data = groupedData[regional][uid].data data.forEach((item: any) => { if (!groupedData[regional][uid].summary) { groupedData[regional][uid].summary = { total: 0, total_selesai: 0, total_inproses: 0, avg_durasi_response: [], max_durasi_response: 0, min_durasi_response: 0, total_diatas_sla_response: 0, total_dibawah_sla_response: 0, avg_durasi_recovery: [], max_durasi_recovery: 0, min_durasi_recovery: 0, total_diatas_sla_recovery: 0, total_dibawah_sla_recovery: 0 } } groupedData[regional][uid].summary.total += item.total groupedData[regional][uid].summary.total_selesai += item.total_selesai groupedData[regional][uid].summary.total_inproses += item.total_inproses groupedData[regional][uid].summary.avg_durasi_response.push(item.avg_durasi_response) groupedData[regional][uid].summary.max_durasi_response = groupedData[regional][uid].summary.max_durasi_response < item.max_durasi_response ? item.max_durasi_response : groupedData[regional][uid].summary.max_durasi_response groupedData[regional][uid].summary.min_durasi_response = groupedData[regional][uid].summary.min_durasi_response > item.min_durasi_response ? item.min_durasi_response : groupedData[regional][uid].summary.min_durasi_response groupedData[regional][uid].summary.total_diatas_sla_response += item.total_diatas_sla_response groupedData[regional][uid].summary.total_dibawah_sla_response += item.total_dibawah_sla_response groupedData[regional][uid].summary.avg_durasi_recovery.push(item.avg_durasi_recovery) groupedData[regional][uid].summary.max_durasi_recovery = groupedData[regional][uid].summary.max_durasi_recovery < item.max_durasi_recovery ? item.max_durasi_recovery : groupedData[regional][uid].summary.max_durasi_recovery groupedData[regional][uid].summary.min_durasi_recovery = groupedData[regional][uid].summary.min_durasi_recovery > item.min_durasi_recovery ? item.min_durasi_recovery : groupedData[regional][uid].summary.min_durasi_recovery groupedData[regional][uid].summary.total_diatas_sla_recovery += item.total_diatas_sla_recovery groupedData[regional][uid].summary.total_dibawah_sla_recovery += item.total_dibawah_sla_recovery }) } } return groupedData } const formatData = (rawData: any) => { const data = groupingData(rawData) const formattedData: any = [] for (const regional in data) { let no = 1 const total: any = { total: 0, total_selesai: 0, total_inproses: 0, avg_durasi_response: [], max_durasi_response: [], min_durasi_response: [], total_diatas_sla_response: 0, total_dibawah_sla_response: 0, avg_durasi_recovery: [], max_durasi_recovery: [], min_durasi_recovery: [], total_diatas_sla_recovery: 0, total_dibawah_sla_recovery: 0 } formattedData.push([{ content: regional, colSpan: 17, styles: { fontStyle: 'bold' } }]) for (const uid in data[regional]) { const summary = data[regional][uid].summary const avgDurasiResponse = summary.avg_durasi_response.length ? summary.avg_durasi_response.reduce((a: any, b: any) => a + b) / summary.avg_durasi_response.length : 0 const avgDurasiRecovery = summary.avg_durasi_recovery.length ? summary.avg_durasi_recovery.reduce((a: any, b: any) => a + b) / summary.avg_durasi_recovery.length : 0 formattedData.push([ { content: no++, styles: { halign: 'right' } }, uid, formatNumber(summary.total), formatNumber(summary.total_selesai), summary.total_selesai != summary.total ? formatPercentage((summary.total_selesai / summary.total) * 100) : '100%', formatNumber(summary.total_inproses), formatPercentage( !summary.total_inproses || !summary.total ? '0%' : (summary.total_inproses / summary.total) * 100 ), formatNumber(avgDurasiResponse), formatWaktu(summary.max_durasi_response), formatWaktu(summary.min_durasi_response), formatNumber(summary.total_diatas_sla_response), formatNumber(summary.total_dibawah_sla_response), formatNumber(avgDurasiRecovery), formatWaktu(summary.max_durasi_recovery), formatWaktu(summary.min_durasi_recovery), formatNumber(summary.total_diatas_sla_recovery), formatNumber(summary.total_dibawah_sla_recovery) ]) total.total += summary.total total.total_selesai += summary.total_selesai total.total_inproses += summary.total_inproses total.avg_durasi_response.push(avgDurasiResponse) total.max_durasi_response.push(summary.max_durasi_response) total.min_durasi_response.push(summary.min_durasi_response) total.total_diatas_sla_response += summary.total_diatas_sla_response total.total_dibawah_sla_response += summary.total_dibawah_sla_response total.avg_durasi_recovery.push(avgDurasiRecovery) total.max_durasi_recovery.push(summary.max_durasi_recovery) total.min_durasi_recovery.push(summary.min_durasi_recovery) total.total_diatas_sla_recovery += summary.total_diatas_sla_recovery total.total_dibawah_sla_recovery += summary.total_dibawah_sla_recovery } formattedData.push([ { content: 'TOTAL', colSpan: 2, styles: { fontStyle: 'bold' } }, formatNumber(total.total), formatNumber(total.total_selesai), formatPercentage( !total.total_selesai || !total.total ? '0%' : (total.total_selesai / total.total) * 100 ), formatNumber(total.total_inproses), formatPercentage( !total.total_inproses || !total.total ? '0%' : (total.total_inproses / total.total) * 100 ), formatNumber( total.avg_durasi_response.length ? total.avg_durasi_response.reduce((a: any, b: any) => a + b) / total.avg_durasi_response.length : 0 ), formatWaktu(Math.max(...total.max_durasi_response)), formatWaktu(Math.min(...total.min_durasi_response)), formatNumber(total.total_diatas_sla_response), formatNumber(total.total_dibawah_sla_response), formatNumber( total.avg_durasi_recovery.length ? total.avg_durasi_recovery.reduce((a: any, b: any) => a + b) / total.avg_durasi_recovery.length : 0 ), formatWaktu(Math.max(...total.max_durasi_recovery)), formatWaktu(Math.min(...total.min_durasi_recovery)), formatNumber(total.total_diatas_sla_recovery), formatNumber(total.total_dibawah_sla_recovery) ]) } return formattedData } const formatMetaData = (reportMeta: any) => { const periode = reportMeta.periode ? reportMeta.periode.split(' s/d ') : '' let dateFromFormat = '' let dateToFormat = '' let dayTo = '' if (periode != '') { const dateFrom = new Date(periode[0].split('-').reverse().join('-')) const dateTo = new Date(periode[1].split('-').reverse().join('-')) dateFromFormat = `${dateFrom.getDate()}-${dateFrom.toLocaleString('default', { month: 'long' })}-${dateFrom.getFullYear()}` dateToFormat = `${dateTo.getDate()}-${dateTo.toLocaleString('default', { month: 'long' })}-${dateTo.getFullYear()}` dayTo = dateTo.toLocaleString('default', { weekday: 'long' }) } return { dateFromFormat, dateToFormat, dayTo } } const exportToPDF = (reportMeta: any, rawData: any, preview: boolean = false) => { const data = formatData(rawData) const meta = formatMetaData(reportMeta) const doc = new jsPDF({ orientation: 'landscape' }) autoTable(doc, { head: [ ['PT. PLN(Persero)', '', ''], [ { content: 'UNIT INDUK', styles: { cellWidth: 40 } }, { content: ':', styles: { cellWidth: 1 } }, reportMeta.uid ? reportMeta.uid.name.toUpperCase() : 'Semua Unit Induk Distribusi/Wilayah'.toUpperCase() ], [ 'UNIT PELAKSANA PELAYANAN PELANGGAN', ':', reportMeta.up3 ? reportMeta.up3.name.toUpperCase() : 'Semua Unit Pelaksanaan Pelayanan Pelanggan'.toUpperCase() ], [ 'UNIT LAYANAN PELANGGAN', ':', reportMeta.ulp ? reportMeta.ulp.name.toUpperCase() : 'Semua Unit Layanan Pelanggan'.toUpperCase() ] ], styles: { fontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold' }, theme: 'plain', startY: 10 }) autoTable(doc, { head: [ [`${reportName}`.toUpperCase()], [`PERIODE TANGGAL : ${meta.dateFromFormat} SD TGL ${meta.dateToFormat}`] ], styles: { fontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold', halign: 'center' }, theme: 'plain', startY: 23 }) autoTable(doc, { head: [ [ { content: 'No', rowSpan: 2 }, { content: 'Nama Unit', rowSpan: 2 }, { content: 'Response Time', colSpan: 10 }, { content: 'Penyelesaian', colSpan: 5 } ], [ 'Total', 'Selesai', '%', 'Inproses', '%', 'Rata-Rata', 'Max', 'Min', '>SLA', 'SLA', ' { console.log('pdf berhasil disimpan') }) } } const exportDetailToPDF = (reportMeta: any, rawData: any) => { const meta = formatMetaData(reportMeta) const doc = new jsPDF({ orientation: 'landscape' }) autoTable(doc, { head: [['PT. PLN(Persero)']], styles: { fontSize: detailFontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold' }, theme: 'plain', startY: 10, margin: 5 }) autoTable(doc, { head: [ [`Daftar Detail ${reportName}`.toUpperCase()], [`PERIODE TANGGAL : ${meta.dateFromFormat} SD TGL ${meta.dateToFormat}`] ], styles: { fontSize: detailFontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold', halign: 'center' }, theme: 'plain', startY: 18, margin: 5 }) autoTable(doc, { head: [ [ 'No', 'No Laporan', 'Tgl Lapor', 'Dalam Proses Bidang', 'Selesai Bidang Unit', 'Durasi Response Time', 'Durasi Recovery Time', 'Status', 'IDPEL/NO METER', 'Nama Pelapor', 'Alamat Pelapor', 'No Telp Pelapor', 'Keterangan Pelapor', 'Rayon', 'Uraian', 'Response Pelanggan' ] ], body: rawData.map((item: any, i: any) => [ { content: i + 1, styles: { halign: 'right' } }, item.no_laporan, item.waktu_lapor, item.waktu_response, item.waktu_recovery, item.durasi_response_time ? formatWaktu(item.durasi_response_time) : '-', item.durasi_recovery_time ? formatWaktu(item.durasi_recovery_time) : '-', item.status_akhir, item.idpel_nometer, item.nama_pelapor, item.alamat_pelapor, item.no_telp_pelapor, item.keterangan_pelapor, item.nama_ulp, item.uraian, item.respon_pelanggan ]), styles: { fontSize: detailFontSize, cellPadding: 1, lineColor: [0, 0, 0], lineWidth: 0.1, cellWidth: 'auto' }, rowPageBreak: 'auto', headStyles: { fillColor: [192, 192, 192], textColor: [0, 0, 0], fontStyle: 'bold', cellWidth: 'wrap', halign: 'center', valign: 'middle' }, bodyStyles: { textColor: [0, 0, 0] }, didParseCell: function (data) { if (data.row.section === 'head') { data.cell.text = data.cell.text.map(function (word: any) { return word.toUpperCase() }) } }, startY: 24, margin: 5 }) autoTable(doc, { head: [ [`${meta.dayTo}, ${meta.dateToFormat}`], [ { content: '(.........................................)', styles: { minCellHeight: 8, valign: 'bottom' } } ] ], styles: { fontSize: detailFontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold', halign: 'center' }, theme: 'plain', tableWidth: 50, margin: { left: 230 } }) doc.save(`Laporan Detail ${reportName}.pdf`, { returnPromise: true }).then(() => { console.log('pdf berhasil disimpan') }) } const exportToXLSX = (reportMeta: any, e: any) => { const meta = formatMetaData(reportMeta) const workbook = new Workbook() const worksheet = workbook.addWorksheet(`${reportName}`) setHeaderStyle(worksheet, 1, 1, 'PT. PLN(Persero)') setHeaderStyle( worksheet, 2, 1, `UNIT INDUK : ${ reportMeta.uid ? reportMeta.uid.name.toUpperCase() : 'Semua Unit Induk Distribusi/Wilayah'.toUpperCase() }` ) setHeaderStyle( worksheet, 3, 1, `UNIT PELAKSANA PELAYANAN PELANGGAN : ${ reportMeta.up3 ? reportMeta.up3.name.toUpperCase() : 'Semua Unit Pelaksanaan Pelayanan Pelanggan'.toUpperCase() }` ) setHeaderStyle( worksheet, 4, 1, `POSKO : ${ reportMeta.posko ? reportMeta.posko.name.toUpperCase() : 'Semua Posko'.toUpperCase() }` ) setHeaderStyle(worksheet, 7, 8, `${reportName}`.toUpperCase(), true) setHeaderStyle( worksheet, 8, 8, `PERIODE TANGGAL : ${meta.dateFromFormat} SD TGL ${meta.dateToFormat}`, true ) worksheet.mergeCells('A1:F1') worksheet.mergeCells('A2:F2') worksheet.mergeCells('A3:F3') worksheet.mergeCells('A4:F4') worksheet.mergeCells('H7:J7') worksheet.mergeCells('H8:J8') exportToExcel({ component: e.component, worksheet, autoFilterEnabled: true, topLeftCell: { row: 10, column: 1 } }).then(() => { workbook.xlsx.writeBuffer().then((buffer: any) => { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), `Laporan ${reportName}.xlsx`) }) }) e.cancel = true } const exportDetailToXLSX = (reportMeta: any, e: any) => { const meta = formatMetaData(reportMeta) const workbook = new Workbook() const worksheet = workbook.addWorksheet(`Detail ${reportName}`) setHeaderStyle(worksheet, 1, 1, 'PT. PLN(Persero)') setHeaderStyle(worksheet, 3, 8, `Daftar Detail ${reportName}`.toUpperCase(), true) setHeaderStyle( worksheet, 4, 8, `PERIODE TANGGAL : ${meta.dateFromFormat} SD TGL ${meta.dateToFormat}`, true ) worksheet.mergeCells('H3:J3') worksheet.mergeCells('H4:J4') exportToExcel({ component: e.component, worksheet, autoFilterEnabled: true, topLeftCell: { row: 6, column: 1 } }).then(() => { workbook.xlsx.writeBuffer().then((buffer: any) => { saveAs( new Blob([buffer], { type: 'application/octet-stream' }), `Laporan Detail ${reportName}.xlsx` ) }) }) e.cancel = true } export { exportToPDF, exportToXLSX, exportDetailToPDF, exportDetailToXLSX }