import { exportDataGrid as exportToExcel } from 'devextreme/excel_exporter' import { saveAs } from 'file-saver' import { jsPDF } from 'jspdf' import autoTable from 'jspdf-autotable' import { Workbook } from 'exceljs' import { setHeaderStyle } from '@/report/utils/xlsx' import { formatNumber, formatPercentage } from '@/utils/numbers' import { getMonthNameShort } from '@/utils/texts' import { exportToWord } from './doc/MonalisaLK_PenurunanJumlahKomplain_DOC' const reportName = 'Penurunan Jumlah Komplain' const fontSize = 5 const getGroupParent = (reportMeta: any) => { if (reportMeta.ulp.id != 0) { return { parent: reportMeta.ulp.name, summaryName: reportMeta.ulp.name, summaryKey: 'nama_ulp' } } if (reportMeta.up3.id != 0) { return { parent: reportMeta.up3.name, summaryName: reportMeta.up3.name, summaryKey: 'nama_up3' } } if (reportMeta.uid.id != 0) { return { parent: reportMeta.uid.name, summaryName: reportMeta.uid.name, summaryKey: 'nama_uid' } } if (reportMeta.regional.id != 0) { return { parent: reportMeta.regional.name, summaryName: reportMeta.regional.name, summaryKey: 'nama_regional' } } return '' } const groupingData = (data: any, reportMeta: any) => { const groupedData: any = {} if (reportMeta.regional.id == 0) { data.forEach((item: any) => { const { nama_regional } = item if (!groupedData[nama_regional]) { groupedData[nama_regional] = { data: [] } } groupedData[nama_regional].data.push(item) }) for (const regional in groupedData) { const data = groupedData[regional].data data.forEach((item: any) => { if (!groupedData[regional].summary) { groupedData[regional].summary = { total_keluhan_tahun_sebelumnya: 0, total_gangguan_tahun_sebelumnya: 0, total_keluhan_informasi_tahun_sebelumnya: 0, total_gangguan_informasi_tahun_sebelumnya: 0, // total_informasi_tahun_sebelumnya // total_tahun_sebelumnya total_keluhan_tahun_ini: 0, total_gangguan_tahun_ini: 0, total_keluhan_informasi_tahun_ini: 0, total_gangguan_informasi_tahun_ini: 0 // total_informasi_tahun_ini // total_tahun_ini // delta_keluhan // delta_gangguan // delta_informasi // persen_delta_keluhan // persen_delta_gangguan // persen_delta_informasi // persen_delta_total } } groupedData[regional].summary.total_keluhan_tahun_sebelumnya += item.total_keluhan_tahun_sebelumnya groupedData[regional].summary.total_gangguan_tahun_sebelumnya += item.total_gangguan_tahun_sebelumnya groupedData[regional].summary.total_keluhan_informasi_tahun_sebelumnya += item.total_keluhan_informasi_tahun_sebelumnya groupedData[regional].summary.total_gangguan_informasi_tahun_sebelumnya += item.total_gangguan_informasi_tahun_sebelumnya groupedData[regional].summary.total_keluhan_tahun_ini += item.total_keluhan_tahun_ini groupedData[regional].summary.total_gangguan_tahun_ini += item.total_gangguan_tahun_ini groupedData[regional].summary.total_keluhan_informasi_tahun_ini += item.total_keluhan_informasi_tahun_ini groupedData[regional].summary.total_gangguan_informasi_tahun_ini += item.total_gangguan_informasi_tahun_ini }) } return groupedData } else { const groupParent = getGroupParent(reportMeta) if (groupParent === '') { return { data, parent: '', summaryName: '' } } data.forEach((item: any) => { const group = item[groupParent.summaryKey] if (!groupedData[group]) { groupedData[group] = [] } groupedData[group].push(item) }) return { data: groupedData, parent: groupParent.parent, summaryName: groupParent.summaryName } } } const formatData = (rawData: any, reportMeta: any) => { const formattedData: any = [] const total: any = { total_keluhan_tahun_sebelumnya: 0, total_gangguan_tahun_sebelumnya: 0, total_keluhan_informasi_tahun_sebelumnya: 0, total_gangguan_informasi_tahun_sebelumnya: 0, // total_informasi_tahun_sebelumnya // total_tahun_sebelumnya total_keluhan_tahun_ini: 0, total_gangguan_tahun_ini: 0, total_keluhan_informasi_tahun_ini: 0, total_gangguan_informasi_tahun_ini: 0 // total_informasi_tahun_ini // total_tahun_ini // delta_keluhan // delta_gangguan // delta_informasi // persen_delta_keluhan // persen_delta_gangguan // persen_delta_informasi // persen_delta_total } if (reportMeta.regional.id == 0) { const data = groupingData(rawData, reportMeta) const formattedData: any = [] formattedData.push([{ content: 'NASIONAL', colSpan: 20, styles: { fontStyle: 'bold' } }]) let no = 1 for (const regional in data) { const summary = data[regional].summary const total_informasi_tahun_sebelumnya = summary.total_keluhan_informasi_tahun_sebelumnya + summary.total_gangguan_informasi_tahun_sebelumnya const total_tahun_sebelumnya = summary.total_keluhan_tahun_sebelumnya + summary.total_gangguan_tahun_sebelumnya + total_informasi_tahun_sebelumnya const total_informasi_tahun_ini = summary.total_keluhan_informasi_tahun_ini + summary.total_gangguan_informasi_tahun_ini const total_tahun_ini = summary.total_keluhan_tahun_ini + summary.total_gangguan_tahun_ini + total_informasi_tahun_ini const delta_keluhan = summary.total_keluhan_tahun_sebelumnya - summary.total_keluhan_tahun_ini const delta_gangguan = summary.total_gangguan_tahun_sebelumnya - summary.total_gangguan_tahun_ini const delta_informasi = total_informasi_tahun_sebelumnya - total_informasi_tahun_ini const persen_delta_keluhan = 40 * (delta_keluhan / summary.total_keluhan_tahun_sebelumnya) const persen_delta_gangguan = 40 * (delta_gangguan / summary.total_gangguan_tahun_sebelumnya) const persen_delta_informasi = 20 * (delta_informasi / total_informasi_tahun_sebelumnya) const persen_delta_total = persen_delta_keluhan + persen_delta_gangguan + persen_delta_informasi formattedData.push([ regional, formatNumber(summary.total_keluhan_tahun_sebelumnya), formatNumber(summary.total_gangguan_tahun_sebelumnya), formatNumber(summary.total_keluhan_informasi_tahun_sebelumnya), formatNumber(summary.total_gangguan_informasi_tahun_sebelumnya), formatNumber(total_informasi_tahun_sebelumnya), formatNumber(total_tahun_sebelumnya), formatNumber(summary.total_keluhan_tahun_ini), formatNumber(summary.total_gangguan_tahun_ini), formatNumber(summary.total_keluhan_informasi_tahun_ini), formatNumber(summary.total_gangguan_informasi_tahun_ini), formatNumber(total_informasi_tahun_ini), formatNumber(total_tahun_ini), formatNumber(delta_keluhan), formatNumber(delta_gangguan), formatNumber(delta_informasi), formatPercentage( !persen_delta_keluhan || !!isFinite(persen_delta_keluhan) ? 0 : persen_delta_keluhan ), formatPercentage( !persen_delta_gangguan || !!isFinite(persen_delta_gangguan) ? 0 : persen_delta_gangguan ), formatPercentage( !persen_delta_informasi || !!isFinite(persen_delta_informasi) ? 0 : persen_delta_informasi ), formatPercentage( !persen_delta_total || !!isFinite(persen_delta_total) ? 0 : persen_delta_total ) ]) total.total_keluhan_tahun_sebelumnya += summary.total_keluhan_tahun_sebelumnya total.total_gangguan_tahun_sebelumnya += summary.total_gangguan_tahun_sebelumnya total.total_keluhan_informasi_tahun_sebelumnya += summary.total_keluhan_informasi_tahun_sebelumnya total.total_gangguan_informasi_tahun_sebelumnya += summary.total_gangguan_informasi_tahun_sebelumnya total.total_keluhan_tahun_ini += summary.total_keluhan_tahun_ini total.total_gangguan_tahun_ini += summary.total_gangguan_tahun_ini total.total_keluhan_informasi_tahun_ini += summary.total_keluhan_informasi_tahun_ini total.total_gangguan_informasi_tahun_ini += summary.total_gangguan_informasi_tahun_ini } const total_informasi_tahun_sebelumnya = total.total_keluhan_informasi_tahun_sebelumnya + total.total_gangguan_informasi_tahun_sebelumnya const total_tahun_sebelumnya = total.total_keluhan_tahun_sebelumnya + total.total_gangguan_tahun_sebelumnya + total_informasi_tahun_sebelumnya const total_informasi_tahun_ini = total.total_keluhan_informasi_tahun_ini + total.total_gangguan_informasi_tahun_ini const total_tahun_ini = total.total_keluhan_tahun_ini + total.total_gangguan_tahun_ini + total_informasi_tahun_ini const delta_keluhan = total.total_keluhan_tahun_sebelumnya - total.total_keluhan_tahun_ini const delta_gangguan = total.total_gangguan_tahun_sebelumnya - total.total_gangguan_tahun_ini const delta_informasi = total_informasi_tahun_sebelumnya - total_informasi_tahun_ini const persen_delta_keluhan = 40 * (delta_keluhan / total.total_keluhan_tahun_sebelumnya) const persen_delta_gangguan = 40 * (delta_gangguan / total.total_gangguan_tahun_sebelumnya) const persen_delta_informasi = 20 * (delta_informasi / total_informasi_tahun_sebelumnya) const persen_delta_total = persen_delta_keluhan + persen_delta_gangguan + persen_delta_informasi formattedData.push([ { content: 'TOTAL', styles: { fontStyle: 'bold' } }, formatNumber(total.total_keluhan_tahun_sebelumnya), formatNumber(total.total_gangguan_tahun_sebelumnya), formatNumber(total.total_keluhan_informasi_tahun_sebelumnya), formatNumber(total.total_gangguan_informasi_tahun_sebelumnya), formatNumber(total_informasi_tahun_sebelumnya), formatNumber(total_tahun_sebelumnya), formatNumber(total.total_keluhan_tahun_ini), formatNumber(total.total_gangguan_tahun_ini), formatNumber(total.total_keluhan_informasi_tahun_ini), formatNumber(total.total_gangguan_informasi_tahun_ini), formatNumber(total_informasi_tahun_ini), formatNumber(total_tahun_ini), formatNumber(delta_keluhan), formatNumber(delta_gangguan), formatNumber(delta_informasi), formatPercentage( !persen_delta_keluhan || !!isFinite(persen_delta_keluhan) ? 0 : persen_delta_keluhan ), formatPercentage( !persen_delta_gangguan || !!isFinite(persen_delta_gangguan) ? 0 : persen_delta_gangguan ), formatPercentage( !persen_delta_informasi || !!isFinite(persen_delta_informasi) ? 0 : persen_delta_informasi ), formatPercentage( !persen_delta_total || !!isFinite(persen_delta_total) ? 0 : persen_delta_total ) ]) return formattedData } else { const tempData = groupingData(rawData, reportMeta) const data = tempData.data[tempData.summaryName] || tempData.data const formattedData: any = [] let parentName = tempData.parent let summaryName = tempData.summaryName ? tempData.summaryName : 'Seluruh Unit' data.forEach((item: any) => { total.total_keluhan_tahun_sebelumnya += item.total_keluhan_tahun_sebelumnya total.total_gangguan_tahun_sebelumnya += item.total_gangguan_tahun_sebelumnya total.total_keluhan_informasi_tahun_sebelumnya += item.total_keluhan_informasi_tahun_sebelumnya total.total_gangguan_informasi_tahun_sebelumnya += item.total_gangguan_informasi_tahun_sebelumnya total.total_keluhan_tahun_ini += item.total_keluhan_tahun_ini total.total_gangguan_tahun_ini += item.total_gangguan_tahun_ini total.total_keluhan_informasi_tahun_ini += item.total_keluhan_informasi_tahun_ini total.total_gangguan_informasi_tahun_ini += item.total_gangguan_informasi_tahun_ini }) const total_informasi_tahun_sebelumnya = total.total_keluhan_informasi_tahun_sebelumnya + total.total_gangguan_informasi_tahun_sebelumnya const total_tahun_sebelumnya = total.total_keluhan_tahun_sebelumnya + total.total_gangguan_tahun_sebelumnya + total_informasi_tahun_sebelumnya const total_informasi_tahun_ini = total.total_keluhan_informasi_tahun_ini + total.total_gangguan_informasi_tahun_ini const total_tahun_ini = total.total_keluhan_tahun_ini + total.total_gangguan_tahun_ini + total_informasi_tahun_ini const delta_keluhan = total.total_keluhan_tahun_sebelumnya - total.total_keluhan_tahun_ini const delta_gangguan = total.total_gangguan_tahun_sebelumnya - total.total_gangguan_tahun_ini const delta_informasi = total_informasi_tahun_sebelumnya - total_informasi_tahun_ini const persen_delta_keluhan = 40 * (delta_keluhan / total.total_keluhan_tahun_sebelumnya) const persen_delta_gangguan = 40 * (delta_gangguan / total.total_gangguan_tahun_sebelumnya) const persen_delta_informasi = 20 * (delta_informasi / total_informasi_tahun_sebelumnya) const persen_delta_total = persen_delta_keluhan + persen_delta_gangguan + persen_delta_informasi formattedData.push([{ content: parentName, colSpan: 20, styles: { fontStyle: 'bold' } }]) const result = [ formatNumber(total.total_keluhan_tahun_sebelumnya), formatNumber(total.total_gangguan_tahun_sebelumnya), formatNumber(total.total_keluhan_informasi_tahun_sebelumnya), formatNumber(total.total_gangguan_informasi_tahun_sebelumnya), formatNumber(total_informasi_tahun_sebelumnya), formatNumber(total_tahun_sebelumnya), formatNumber(total.total_keluhan_tahun_ini), formatNumber(total.total_gangguan_tahun_ini), formatNumber(total.total_keluhan_informasi_tahun_ini), formatNumber(total.total_gangguan_informasi_tahun_ini), formatNumber(total_informasi_tahun_ini), formatNumber(total_tahun_ini), formatNumber(delta_keluhan), formatNumber(delta_gangguan), formatNumber(delta_informasi), formatPercentage( !persen_delta_keluhan || !!isFinite(persen_delta_keluhan) ? 0 : persen_delta_keluhan ), formatPercentage( !persen_delta_gangguan || !!isFinite(persen_delta_gangguan) ? 0 : persen_delta_gangguan ), formatPercentage( !persen_delta_informasi || !!isFinite(persen_delta_informasi) ? 0 : persen_delta_informasi ), formatPercentage( !persen_delta_total || !!isFinite(persen_delta_total) ? 0 : persen_delta_total ) ] formattedData.push([summaryName, ...result]) formattedData.push([{ content: 'TOTAL', styles: { fontStyle: 'bold' } }, ...result]) return formattedData } } const exportToPDF = (reportMeta: any, rawData: any, preview: boolean = false) => { const day = new Date().toLocaleString('id-ID', { weekday: 'long' }) const date = new Date().getDate() const month = new Date().toLocaleString('id-ID', { month: 'long' }) const year = new Date().getFullYear() const data = formatData(rawData, 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() ], [ 'REGIONAL', ':', reportMeta.regional ? reportMeta.regional.name.toUpperCase() : 'Semua Regional'.toUpperCase() ] ], styles: { fontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold' }, theme: 'plain', startY: 10 }) autoTable(doc, { head: [[`${reportName}`.toUpperCase()], ['s.d. ' + reportMeta.periode]], styles: { fontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold', halign: 'center' }, theme: 'plain', startY: 23 }) autoTable(doc, { head: [ [ { content: 'Nama Unit', rowSpan: 3 }, { content: 's.d. ' + getMonthNameShort(reportMeta.currentMonth) + ' ' + reportMeta.lastYear, colSpan: 6 }, { content: 's.d. ' + getMonthNameShort(reportMeta.currentMonth) + ' ' + reportMeta.currentYear, colSpan: 6 }, { content: 'Delta Penurunan', colSpan: 3 }, { content: '% Penurunan YoY', colSpan: 4 } ], [ { content: 'Keluhan', rowSpan: 2 }, { content: 'Gangguan', rowSpan: 2 }, { content: 'Informasi', colSpan: 3 }, { content: 'Total Komplain', rowSpan: 2 }, { content: 'Keluhan', rowSpan: 2 }, { content: 'Gangguan', rowSpan: 2 }, { content: 'Informasi', colSpan: 3 }, { content: 'Total Komplain', rowSpan: 2 }, { content: 'Keluhan', rowSpan: 2 }, { content: 'Gangguan', rowSpan: 2 }, { content: 'Informasi', rowSpan: 2 }, { content: 'Keluhan', rowSpan: 2 }, { content: 'Gangguan', rowSpan: 2 }, { content: 'Informasi', rowSpan: 2 }, { content: '% Total', rowSpan: 2 } ], ['Keluhan', 'Gangguan', 'Total', 'Keluhan', 'Gangguan', 'Total'], [ '1', '2', '3', '4', '5', '6=4+5', '7=2+3+6', '8', '9', '10', '11', '12=10+11', '13=8+9+12', '14=2-8', '15=3-9', '16=6-12', '17=40%*(14/2)', '18=40%*(15/3)', '19=20%*(16/6)', '20=17+18+19' ] ], body: data, styles: { fontSize, 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() }) } if (data.cell.text[0] === 'TOTAL') { for (const key in data.row.cells) { data.row.cells[key].styles.fillColor = [192, 192, 192] data.row.cells[key].styles.fontStyle = 'bold' } } }, startY: 30 }) autoTable(doc, { head: [ [`${day}, ${date}-${month}-${year}`], [ { content: '(.........................................)', styles: { minCellHeight: 8, valign: 'bottom' } } ] ], styles: { fontSize, cellPadding: 0.1, textColor: [0, 0, 0], fontStyle: 'bold', halign: 'center' }, theme: 'plain', tableWidth: 50, margin: { left: 230 } }) if (preview) { doc.setProperties({ title: `${reportName}` }) window.open(doc.output('bloburl')) } else { doc.save(`Laporan ${reportName}.pdf`, { returnPromise: true }).then(() => { console.log('pdf berhasil disimpan') }) } } const exportToXLSX = (reportMeta: any, e: any) => { 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, `UNIT LAYANAN PELANGGAN : ${ reportMeta.ulp ? reportMeta.ulp.name.toUpperCase() : 'Semua Unit Layanan Pelanggan'.toUpperCase() }` ) setHeaderStyle( worksheet, 5, 1, `REGIONAL : ${ reportMeta.regional ? reportMeta.regional.name.toUpperCase() : 'Semua Regional'.toUpperCase() }` ) setHeaderStyle(worksheet, 7, 1, `${reportName}`.toUpperCase(), true) setHeaderStyle(worksheet, 8, 1, reportMeta.periode, true) worksheet.mergeCells('A1:T1') worksheet.mergeCells('A2:T2') worksheet.mergeCells('A3:T3') worksheet.mergeCells('A4:T4') worksheet.mergeCells('A5:T5') worksheet.mergeCells('A7:T7') worksheet.mergeCells('A8:T8') exportToExcel({ component: e.component, worksheet, autoFilterEnabled: true, topLeftCell: { row: 10, column: 1 }, loadPanel: { enabled: false } }).then(() => { workbook.xlsx.writeBuffer().then((buffer: any) => { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), `Laporan ${reportName}.xlsx`) }) }) e.cancel = true } const exportToDOCX = (reportMeta: any, rawData: any) => { exportToWord(reportMeta, formatData(rawData, reportMeta), `Laporan ${reportName}`, null) } export { exportToPDF, exportToXLSX, exportToDOCX }