$(document).ready(function () { $(".btn-export-pdf").on("click", async function () { const data = window.ReportApp?.lastResponse; if (!data) { alert("Data belum tersedia"); return; } printPDF(data); }); }); function printPDF(data) { const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: "portrait", // portrait kesempitan buat 16 kolom unit: "mm", format: "a4", }); console.log(data.vehicle.date); const pageWidth = doc.internal.pageSize.getWidth(); // ===== HEADER ===== doc.setFont("helvetica", "bold"); doc.setFontSize(12); doc.text("MENTENG SQUARE - RAYA PARKING - RAYA Parking", 14, 12); doc.setFontSize(11); doc.text("Rekap Transaksi Per Kendaraan", pageWidth / 2, 18, { align: "center" }); doc.setFont("helvetica", "normal"); doc.setFontSize(9); doc.text("Tanggal : " + (data.vehicle.date ?? "-"), pageWidth / 2, 23, { align: "center" }); doc.text("By : " + (data.vehicle.reportTime ?? "-"), pageWidth - 14, 12, { align: "right" }); // doc.text("By : Harian", pageWidth - 14, 12, { align: "right" }); // ===== SUSUN BODY TABEL ===== const vehicleBody = []; // init print nontunai let vehicleCashCasualJml = 0, vehicleCashCasualNilai = 0; let vehicleCashLostJml = 0, vehicleCashLostNilai = 0; let vehicleCashPassJml = 0, vehicleCashPassNilai = 0; let vehicleCashManualJml = 0, vehicleCashManualNilai = 0; let vehicleCashManualMixJml = 0, vehicleCashManualMixNilai = 0; let vehicleCashMasalahJml = 0, vehicleCashMasalahNilai = 0; let vehicleCashTotal = 0; // init print nontunai let vehicleCashlessCasualJml = 0, vehicleCashlessCasualNilai = 0; let vehicleCashlessLostJml = 0, vehicleCashlessLostNilai = 0; let vehicleCashlessPassJml = 0, vehicleCashlessPassNilai = 0; let vehicleCashlessManualJml = 0, vehicleCashlessManualNilai = 0; let vehicleCashlessManualMixJml = 0, vehicleCashlessManualMixNilai = 0; let vehicleCashlessMasalahJml = 0, vehicleCashlessMasalahNilai = 0; let vehicleCashlessTotal = 0; let grandTotal = 0; data.vehicle.tunai.forEach(function (cash) { const cashless = data.vehicle.nontunai.find((nt) => String(nt.id_kendaraan) === String(cash.id_kendaraan)) || { nonTunaiOut: 0, keluar: { casual: { jumlah: 0, income: 0 }, lost: { jumlah: 0, income: 0 }, member: { jumlah: 0, income: 0 }, manual: { jumlah: 0, income: 0 }, }, totalCashless: 0, }; // debugger; const tCasual = cash.keluar.casual; const tLost = cash.keluar.lost; const tMember = cash.keluar.member; const tManual = cash.keluar.manual; const tManualMix = cash.keluar.manualmix ?? { jumlah: 0, income: 0 }; const tMasalah = cash.keluar.masalah ?? { jumlah: 0, income: 0 }; const vehicleCashTotal = cash.totalCash || 0; const nCasual = cashless.keluar.casual; const nLost = cashless.keluar.lost; const nMember = cashless.keluar.member; const nManual = cashless.keluar.manual; const nManualMix = cashless.keluar.manualmix ?? { jumlah: 0, income: 0 }; const nMasalah = cashless.keluar.masalah ?? { jumlah: 0, income: 0 }; const vehicleCashlessTotal = cashless.totalCashless || 0; // baris TUNAI vehicleBody.push([ { content: cash.jenis_mobil, rowSpan: 2, styles: { valign: "middle" } }, { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, cash.total, cash.tunaiOut, tCasual.jumlah, rupiah(tCasual.income), tLost.jumlah, rupiah(tLost.income), tMember.jumlah, rupiah(tMember.income), tManual.jumlah, rupiah(tManual.income), tManualMix.jumlah || 0, rupiah(tManualMix.income), tMasalah.jumlah, rupiah(tMasalah.income), { content: rupiah(cash.totalCash), styles: { valign: "middle", fontStyle: "bold" } }, ]); // baris NON TUNAI vehicleBody.push([ { content: "Non Tunai", styles: { fillColor: [255, 193, 7], textColor: 0, fontStyle: "bold" } }, cash.total, cashless.nonTunaiOut, nCasual.jumlah, rupiah(nCasual.income), nLost.jumlah, rupiah(nLost.income), nMember.jumlah, rupiah(nMember.income), nManual.jumlah, rupiah(nManual.income), tManualMix.jumlah, rupiah(tManualMix.income), nMasalah.jumlah, rupiah(nMasalah.income), { content: rupiah(cashless.totalCashless), styles: { valign: "middle", fontStyle: "bold" } }, ]); // init sum cash vehicleCashCasualJml += tCasual.jumlah; vehicleCashCasualNilai += tCasual.income || 0; vehicleCashLostJml += tLost.jumlah; vehicleCashLostNilai += tLost.income; vehicleCashPassJml += tMember.jumlah; vehicleCashPassNilai += tMember.income; vehicleCashManualJml += tManual.jumlah; vehicleCashManualNilai += tManual.income; vehicleCashManualMixJml += tManualMix.jumlah; vehicleCashManualMixNilai += tManualMix.income; vehicleCashMasalahJml += tMasalah.jumlah; vehicleCashMasalahNilai += tMasalah.income; // totalTunaiNilai = "X"; // init sum cashless vehicleCashlessCasualJml += nCasual.jumlah; vehicleCashlessCasualNilai += nCasual.income || 0; vehicleCashlessLostJml += nLost.jumlah; vehicleCashlessLostNilai += nLost.income; vehicleCashlessPassJml += nMember.jumlah; vehicleCashlessPassNilai += nMember.income; vehicleCashlessManualJml += nManual.jumlah; vehicleCashlessManualNilai += nManual.income; vehicleCashlessManualMixJml += nManualMix.jumlah; vehicleCashlessManualMixNilai += nManualMix.income; vehicleCashlessMasalahJml += nMasalah.jumlah; vehicleCashlessMasalahNilai += nMasalah.income; // init sum grandTotal subTotalCash = vehicleCashCasualNilai + vehicleCashLostNilai + vehicleCashPassNilai + vehicleCashManualNilai + vehicleCashlessManualMixNilai + vehicleCashlessMasalahNilai; subTotalCashless = vehicleCashlessCasualNilai + vehicleCashlessLostNilai + vehicleCashlessPassNilai + vehicleCashlessManualNilai + vehicleCashlessManualMixNilai + vehicleCashlessMasalahNilai; grandTotal = (subTotalCash || 0) + (subTotalCashless || 0); }); // baris TOTAL & GRAND TOTAL vehicleBody.push([ { content: "SUB TOTAL\nKENDARAAN", rowSpan: 2, styles: { fontStyle: "bold" } }, { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, "", "", vehicleCashCasualJml, rupiah(vehicleCashCasualNilai), vehicleCashLostJml, rupiah(vehicleCashLostNilai), vehicleCashPassJml, rupiah(vehicleCashPassNilai), vehicleCashManualJml, rupiah(vehicleCashManualNilai), vehicleCashManualMixJml, rupiah(vehicleCashManualMixNilai), vehicleCashMasalahJml, rupiah(vehicleCashMasalahNilai), rupiah(subTotalCash), ]); vehicleBody.push([ { content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } }, "", "", { content: vehicleCashlessCasualJml, styles: { fontStyle: "bold" } }, rupiah(vehicleCashlessCasualNilai), vehicleCashlessLostJml, rupiah(vehicleCashlessLostNilai), vehicleCashlessPassJml, rupiah(vehicleCashlessPassNilai), vehicleCashlessManualJml, rupiah(vehicleCashlessManualNilai), vehicleCashlessManualMixJml, rupiah(vehicleCashlessManualMixNilai), vehicleCashlessMasalahJml, rupiah(vehicleCashlessMasalahNilai), rupiah(subTotalCashless), ]); vehicleBody.push([ { content: "GRAND TOTAL\nKENDARAAN", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } }, { content: vehicleCashCasualJml + vehicleCashlessCasualJml, styles: { fontStyle: "bold" } }, //Jumlah Casual rupiah(vehicleCashCasualNilai + vehicleCashlessCasualNilai), //Income Casual { content: vehicleCashLostJml + vehicleCashlessLostJml, styles: { fontStyle: "bold" } }, //Jumlah Lost rupiah(vehicleCashLostNilai + vehicleCashlessLostNilai), //Income Tiket Hilang vehicleCashPassJml + vehicleCashlessPassJml, //Jumlah Member rupiah(vehicleCashPassNilai + vehicleCashlessPassNilai), //Income Member vehicleCashManualJml + vehicleCashlessManualJml, //Jumlah Tiket Manual rupiah(vehicleCashManualNilai + vehicleCashlessManualNilai), //Income Tiket Manual vehicleCashManualMixJml + vehicleCashlessManualMixJml, rupiah(vehicleCashManualMixNilai + vehicleCashlessManualMixNilai), vehicleCashMasalahJml + vehicleCashlessMasalahJml, rupiah(vehicleCashMasalahNilai + vehicleCashlessMasalahNilai), { content: rupiah(grandTotal), styles: { fontStyle: "bold" } }, ]); // ===== HEADER 2 BARIS (grouping) ===== const head = [ [ { content: "Jenis Kend", rowSpan: 2, colSpan: 2 }, { content: "Jenis Transaksi", colSpan: 2 }, { content: "Casual", colSpan: 2 }, { content: "Tiket Hilang", colSpan: 2 }, { content: "Member", colSpan: 2 }, { content: "Manual Input", colSpan: 2 }, { content: "Manual Mix", colSpan: 2 }, { content: "Tiket Masalah", colSpan: 2 }, { content: "Pendapatan", rowSpan: 2 }, ], [ "Masuk", "Keluar", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", ], ]; doc.autoTable({ head: head, body: vehicleBody, startY: 28, theme: "grid", styles: { fontSize: 6, halign: "center", valign: "middle", lineColor: [200, 200, 200] }, headStyles: { fillColor: [230, 230, 230], textColor: 0, fontStyle: "bold" }, columnStyles: { 0: { halign: "left" } }, }); // ===== TABEL OVER NIGHT (di bawah tabel utama) ===== const onBody = data.vehicle.overNight.map((on) => [ on.jenis_mobil ?? "-", on.overNight, on.onExpired, (on.overNight || 0) + (on.onExpired || 0), ]); //================================================================== //===================== Print table officer ======================== //================================================================== const officerStartY = doc.lastAutoTable.finalY + 15; const officerBody = []; // init print nont tunai let officerCashCasualJml = 0, officerCashCasualNilai = 0; let officerCashLostJml = 0, officerCashLostNilai = 0; let officerCashPassJml = 0, officerCashPassNilai = 0; let officerCashManualJml = 0, officerCashManualNilai = 0; let officerCashManualMixJml = 0, officerCashManualMixNilai = 0; let officerCashMasalahJml = 0, officerCashMasalahNilai = 0; // init print nont tunai let ptotalNonTunaiJml = 0, ptotalNonTunaiNilai = 0; let officerCashlessCasualJml = 0, officerCashlessCasualNilai = 0; let officerCashlessLostJml = 0, officerCashlessLostNilai = 0; let officerCashlessPassJml = 0, officerCashlessPassNilai = 0; let officerCashlessManualJml = 0, officerCashlessManualNilai = 0; let officerCashlessManualMixJml = 0, officerCashlessManualMixNilai = 0; let officerCashlessMasalahJml = 0, officerCashlessMasalahNilai = 0; let pgrandTotal = 0; data.officer.tunai.forEach(function (cash) { const cashless = data.officer.nontunai.find((nt) => String(nt.petugas) === String(cash.petugas)) || { nonTunaiOut: 0, keluar: { casual: { jumlah: 0, income: 0 }, lost: { jumlah: 0, income: 0 }, member: { jumlah: 0, income: 0 }, manual: { jumlah: 0, income: 0 }, }, totalCashless: 0, }; // debugger; const tCasual = cash.keluar.casual; const tLost = cash.keluar.lost; const tMember = cash.keluar.member; const tManual = cash.keluar.manual; const tMasalah = cash.keluar.masalah ?? { jumlah: 0, income: 0 }; const tManualMix = cash.keluar.manualmix ?? { jumlah: 0, income: 0 }; const totalTunai = cash.totalCash || 0; const nCasual = cashless.keluar.casual; const nLost = cashless.keluar.lost; const nMember = cashless.keluar.member; const nManual = cashless.keluar.manual; const nMasalah = cashless.keluar.masalah ?? { jumlah: 0, income: 0 }; const nManualMix = cashless.keluar.manualmix ?? { jumlah: 0, income: 0 }; const totalNonTunai = cashless.totalCashless || 0; // baris TUNAI officerBody.push([ { content: cash.petugas?.trim() ? cash.petugas : "NO-OP", rowSpan: 2, styles: { valign: "middle" }, }, { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, cash.total, cash.tunaiOut, tCasual.jumlah, rupiah(tCasual.income), tLost.jumlah, rupiah(tLost.income), tMember.jumlah, rupiah(tMember.income), tManual.jumlah, rupiah(tManual.income), 0, 0, tMasalah.jumlah, rupiah(tMasalah.income), { content: rupiah(cash.totalCash), styles: { valign: "middle", fontStyle: "bold" } }, ]); // baris NON TUNAI officerBody.push([ { content: "Non Tunai", styles: { fillColor: [255, 193, 7], textColor: 0, fontStyle: "bold" } }, cash.total, cashless.nonTunaiOut, nCasual.jumlah, rupiah(nCasual.income), nLost.jumlah, cash.totalCashless, nMember.jumlah, rupiah(nMember.income), nManual.jumlah, rupiah(nManual.income), 0, 0, nMasalah.jumlah, rupiah(nMasalah.income), { content: rupiah(cashless.totalCashless), styles: { valign: "middle", fontStyle: "bold" } }, ]); ptotalNonTunaiJml += nCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah; ptotalNonTunaiNilai += cashless.totalCashless || 0; pgrandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0); officerCashCasualJml += tCasual.jumlah; officerCashCasualNilai += tCasual.income || 0; officerCashLostJml += tLost.jumlah; officerCashLostNilai += tLost.income; officerCashPassJml += tMember.jumlah; officerCashPassNilai += tMember.income; officerCashManualJml += tManual.jumlah; officerCashManualNilai += tManual.income; officerCashManualMixJml += tManualMix.jumlah; officerCashManualMixNilai += tManualMix.income; officerCashMasalahJml += tMasalah.jumlah; officerCashMasalahNilai += tMasalah.income; // init sum cashless officerCashlessCasualJml += nCasual.jumlah; officerCashlessCasualNilai += nCasual.income || 0; officerCashlessLostJml += nLost.jumlah; officerCashlessLostNilai += nLost.income; officerCashlessPassJml += nMember.jumlah; officerCashlessPassNilai += nMember.income; officerCashlessManualJml += nManual.jumlah; officerCashlessManualNilai += nManual.income; officerCashlessManualMixJml += nManualMix.jumlah; officerCashlessManualMixNilai += nManualMix.income; officerCashlessMasalahJml += nMasalah.jumlah; officerCashlessMasalahNilai += nMasalah.income; // sub total cash/ init sum grandTotal subTotalCash = officerCashCasualNilai + officerCashLostNilai + officerCashPassNilai + officerCashManualNilai + officerCashlessManualMixNilai + officerCashlessMasalahNilai; subTotalCashless = officerCashlessCasualNilai + officerCashlessLostNilai + officerCashlessPassNilai + officerCashlessManualNilai + officerCashlessManualMixNilai + officerCashlessMasalahNilai; }); // baris TOTAL & GRAND TOTAL officerBody.push([ { content: "SUB TOTAL\NPer Petugas", rowSpan: 2, styles: { fontStyle: "bold" } }, { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, "", "", { content: officerCashCasualJml, styles: { fontStyle: "bold" } }, rupiah(officerCashCasualNilai), officerCashLostJml, rupiah(officerCashLostNilai), officerCashPassJml, rupiah(officerCashPassNilai), officerCashManualJml, rupiah(officerCashManualNilai), officerCashManualMixJml, rupiah(officerCashManualMixNilai), officerCashMasalahJml, rupiah(officerCashMasalahNilai), rupiah(subTotalCash), ]); officerBody.push([ { content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } }, "", "", { content: officerCashlessCasualJml, styles: { fontStyle: "bold" } }, rupiah(officerCashlessCasualNilai), officerCashlessLostJml, rupiah(officerCashlessLostNilai), officerCashlessPassJml, rupiah(officerCashlessPassNilai), officerCashlessManualJml, rupiah(officerCashlessManualNilai), officerCashlessManualMixJml, rupiah(officerCashlessManualMixNilai), officerCashlessMasalahJml, rupiah(officerCashlessMasalahNilai), rupiah(subTotalCashless), ]); officerBody.push([ { content: "GRAND TOTAL\nPETUGAS", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } }, { content: officerCashCasualJml + officerCashlessCasualJml, styles: { fontStyle: "bold" } }, //Jumlah Casual rupiah(officerCashCasualNilai + officerCashlessCasualNilai), //Income Casual { content: officerCashLostJml + officerCashlessLostJml, styles: { fontStyle: "bold" } }, //Jumlah Lost rupiah(officerCashLostNilai + officerCashlessLostNilai), //Income Tiket Hilang officerCashPassJml + officerCashlessPassJml, //Jumlah Member rupiah(officerCashPassNilai + officerCashlessPassNilai), //Income Member officerCashManualJml + officerCashlessManualJml, //Jumlah Tiket Manual rupiah(officerCashManualNilai + officerCashlessManualNilai), //Income Tiket Manual officerCashManualMixJml + officerCashlessManualMixJml, rupiah(officerCashManualMixNilai + officerCashlessManualMixNilai), officerCashMasalahJml + officerCashlessMasalahJml, rupiah(officerCashMasalahNilai + officerCashlessMasalahNilai), { content: rupiah(grandTotal), styles: { fontStyle: "bold" } }, ]); // ===== HEADER 2 BARIS (grouping) ===== const officerHead = [ [ { content: "Nama Petugas", rowSpan: 2, colSpan: 2 }, { content: "Jenis Transaksi", colSpan: 2 }, { content: "Casual", colSpan: 2 }, { content: "Tiket Hilang", colSpan: 2 }, { content: "Member", colSpan: 2 }, { content: "Manual Input", colSpan: 2 }, { content: "Manual Mix", colSpan: 2 }, { content: "Tiket Masalah", colSpan: 2 }, { content: "Pendapatan", rowSpan: 2 }, ], [ "Masuk", "Keluar", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", ], ]; // doc.addPage(); doc.setFont("helvetica", "bold"); doc.setFontSize(11); doc.text("Rekap Transaksi Per Petugas", pageWidth / 2, officerStartY - 6, { align: "center" }); doc.setFont("helvetica", "normal"); doc.setFontSize(9); doc.text("Tanggal : " + (data.officer.date ?? "-"), pageWidth / 2, officerStartY - 2, { align: "center" }); doc.text("By : " + (data.vehicle.reportTime ?? "-"), pageWidth - 14, officerStartY - 2, { align: "right" }); doc.autoTable({ head: officerHead, body: officerBody, startY: officerStartY, // lastAutoTable: finalY + 15, theme: "grid", styles: { fontSize: 6, halign: "center", valign: "middle", lineColor: [200, 200, 200] }, headStyles: { fillColor: [230, 230, 230], textColor: 0, fontStyle: "bold" }, columnStyles: { 0: { halign: "left" } }, }); //==================================== //======== Print table payment ======= //==================================== const paymentStartY = doc.lastAutoTable.finalY + 15; const paymentBody = []; // let payTotalTunaiJml = 0, // payTotalTunaiNilai = 0; // init print nont tunai let paymentCashCasualJml = 0, paymentCashCasualNilai = 0; let paymentCashLostJml = 0, paymentCashLostNilai = 0; let paymentCashPassJml = 0, paymentCashPassNilai = 0; let paymentCashManualJml = 0, paymentCashManualNilai = 0; let paymentCashManualMixJml = 0, paymentCashManualMixNilai = 0; let paymentCashMasalahJml = 0, paymentCashMasalahNilai = 0; // init print nont tunai // let ptotalNonTunaiJml = 0, // ptotalNonTunaiNilai = 0; let paymentCashlessCasualJml = 0, paymentCashlessCasualNilai = 0; let paymentCashlessLostJml = 0, paymentCashlessLostNilai = 0; let paymentCashlessPassJml = 0, paymentCashlessPassNilai = 0; let paymentCashlessManualJml = 0, paymentCashlessManualNilai = 0; let paymentCashlessManualMixJml = 0, paymentCashlessManualMixNilai = 0; let paymentCashlessMasalahJml = 0, paymentCashlessMasalahNilai = 0; // let payTotalNonTunaiJml = 0, // payTotalNonTunaiNilai = 0; let payGrandTotal = 0; data.payment.tunai.forEach(function (cash) { const cashless = data.payment.nontunai.find((nt) => String(nt.typePayment) === String(cash.typePayment)) || { nonTunaiOut: 0, keluar: { casual: { jumlah: 0, income: 0 }, lost: { jumlah: 0, income: 0 }, member: { jumlah: 0, income: 0 }, manual: { jumlah: 0, income: 0 }, }, totalCashless: 0, }; // debugger; let typePayment = paymentType(cash.typePayment); const tCasual = cash.keluar.casual; const tLost = cash.keluar.lost; const tMember = cash.keluar.member; const tManual = cash.keluar.manual; const tManualMix = cash.keluar.manualmix ?? { jumlah: 0, income: 0 }; const tMasalah = cash.keluar.masalah ?? { jumlah: 0, income: 0 }; const totalTunai = cash.totalCash || 0; const nCasual = cashless.keluar.casual; const nLost = cashless.keluar.lost; const nMember = cashless.keluar.member; const nManual = cashless.keluar.manual; const nManualMix = cashless.keluar.manualmix ?? { jumlah: 0, income: 0 }; const nMasalah = cashless.keluar.masalah ?? { jumlah: 0, income: 0 }; const totalNonTunai = cashless.totalCashless || 0; // baris TUNAI paymentBody.push([ { content: typePayment, rowSpan: 2, styles: { valign: "middle" }, }, { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, cash.total, cash.tunaiOut, tCasual.jumlah, rupiah(tCasual.income), tLost.jumlah, rupiah(tLost.income), tMember.jumlah, rupiah(tMember.income), tManual.jumlah, rupiah(tManual.income), 0, 0, tMasalah.jumlah, rupiah(tMasalah.income), { content: rupiah(cash.totalCash), styles: { valign: "middle", fontStyle: "bold" } }, ]); // baris NON TUNAI paymentBody.push([ { content: "Non Tunai", styles: { fillColor: [255, 193, 7], textColor: 0, fontStyle: "bold" } }, cash.total, cashless.nonTunaiOut, nCasual.jumlah, rupiah(nCasual.income), nLost.jumlah, rupiah(nLost.income), nMember.jumlah, rupiah(nMember.income), nManual.jumlah, rupiah(nManual.income), 0, 0, nMasalah.jumlah, rupiah(nMasalah.income), { content: rupiah(cashless.totalCashless), styles: { valign: "middle", fontStyle: "bold" } }, ]); // payTotalTunaiJml += tCasual.jumlah + tLost.jumlah + tMember.jumlah + tManual.jumlah + tMasalah.jumlah; // payTotalTunaiNilai += cash.totalCash || 0; // payTotalNonTunaiJml += nCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah; // payTotalNonTunaiNilai += cashless.totalCashless || 0; // payGrandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0); paymentCashCasualJml += tCasual.jumlah; paymentCashCasualNilai += tCasual.income || 0; paymentCashLostJml += tLost.jumlah; paymentCashLostNilai += tLost.income; paymentCashPassJml += tMember.jumlah; paymentCashPassNilai += tMember.income; paymentCashManualJml += tManual.jumlah; paymentCashManualNilai += tManual.income; paymentCashManualMixJml += tManualMix.jumlah; paymentCashManualMixNilai += tManualMix.income; paymentCashMasalahJml += tMasalah.jumlah; paymentCashMasalahNilai += tMasalah.income; // init sum cashless paymentCashlessCasualJml += nCasual.jumlah; paymentCashlessCasualNilai += nCasual.income || 0; paymentCashlessLostJml += nLost.jumlah; paymentCashlessLostNilai += nLost.income; paymentCashlessPassJml += nMember.jumlah; paymentCashlessPassNilai += nMember.income; paymentCashlessManualJml += nManual.jumlah; paymentCashlessManualNilai += nManual.income; paymentCashlessManualMixJml += nManualMix.jumlah; paymentCashlessManualMixNilai += nManualMix.income; paymentCashlessMasalahJml += nMasalah.jumlah; paymentCashlessMasalahNilai += nMasalah.income; // sub total cash/ init sum grandTotal subTotalCash = paymentCashCasualNilai + paymentCashLostNilai + paymentCashPassNilai + paymentCashManualNilai + paymentCashlessManualMixNilai + paymentCashlessMasalahNilai; subTotalCashless = paymentCashlessCasualNilai + paymentCashlessLostNilai + paymentCashlessPassNilai + paymentCashlessManualNilai + paymentCashlessManualMixNilai + paymentCashlessMasalahNilai; }); // baris TOTAL & GRAND TOTAL paymentBody.push([ { content: "SUB TOTAL\NPer Pembayaran", rowSpan: 2, styles: { fontStyle: "bold" } }, { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, "", "", { content: paymentCashCasualJml, styles: { fontStyle: "bold" } }, rupiah(paymentCashCasualNilai), paymentCashLostJml, rupiah(paymentCashLostNilai), paymentCashPassJml, rupiah(paymentCashPassNilai), paymentCashManualJml, rupiah(paymentCashManualNilai), paymentCashManualMixJml, rupiah(paymentCashManualMixNilai), paymentCashMasalahJml, rupiah(paymentCashMasalahNilai), rupiah(subTotalCash), ]); paymentBody.push([ { content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } }, "", "", { content: paymentCashlessCasualJml, styles: { fontStyle: "bold" } }, rupiah(paymentCashlessCasualNilai), paymentCashlessLostJml, rupiah(paymentCashlessLostNilai), paymentCashlessPassJml, rupiah(paymentCashlessPassNilai), paymentCashlessManualJml, rupiah(paymentCashlessManualNilai), paymentCashlessManualMixJml, rupiah(paymentCashlessManualMixNilai), paymentCashlessMasalahJml, rupiah(paymentCashlessMasalahNilai), rupiah(subTotalCashless), ]); paymentBody.push([ { content: "GRAND TOTAL\nPEMBAYARAN", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } }, { content: paymentCashCasualJml + paymentCashlessCasualJml, styles: { fontStyle: "bold" } }, //Jumlah Casual rupiah(paymentCashCasualNilai + paymentCashlessCasualNilai), //Income Casual { content: paymentCashLostJml + paymentCashlessLostJml, styles: { fontStyle: "bold" } }, //Jumlah Lost rupiah(paymentCashLostNilai + paymentCashlessLostNilai), //Income Tiket Hilang paymentCashPassJml + paymentCashlessPassJml, //Jumlah Member rupiah(paymentCashPassNilai + paymentCashlessPassNilai), //Income Member paymentCashManualJml + paymentCashlessManualJml, //Jumlah Tiket Manual rupiah(paymentCashManualNilai + paymentCashlessManualNilai), //Income Tiket Manual paymentCashManualMixJml + paymentCashlessManualMixJml, rupiah(paymentCashManualMixNilai + paymentCashlessManualMixNilai), paymentCashMasalahJml + paymentCashlessMasalahJml, rupiah(paymentCashMasalahNilai + paymentCashlessMasalahNilai), { content: rupiah(grandTotal), styles: { fontStyle: "bold" } }, ]); // ===== HEADER 2 BARIS (grouping) ===== const paymentHead = [ [ { content: "Jenis Pembayaran", rowSpan: 2, colSpan: 2 }, { content: "Jenis Transaksi", colSpan: 2 }, { content: "Casual", colSpan: 2 }, { content: "Tiket Hilang", colSpan: 2 }, { content: "Member", colSpan: 2 }, { content: "Manual Input", colSpan: 2 }, { content: "Manual Mix", colSpan: 2 }, { content: "Tiket Masalah", colSpan: 2 }, { content: "Pendapatan", rowSpan: 2 }, ], [ "Masuk", "Keluar", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", "JML", "Nilai", ], ]; // doc.addPage(); doc.setFont("helvetica", "bold"); doc.setFontSize(11); doc.text("Rekap Transaksi Per Pembayaran", pageWidth / 2, paymentStartY - 6, { align: "center" }); doc.setFont("helvetica", "normal"); doc.setFontSize(9); doc.text("Tanggal : " + (data.vehicle.date ?? "-"), pageWidth / 2, paymentStartY - 2, { align: "center" }); doc.text("By : " + (data.vehicle.reportTime ?? "-"), pageWidth - 14, paymentStartY - 2, { align: "right" }); doc.autoTable({ head: paymentHead, body: paymentBody, startY: paymentStartY, // lastAutoTable: finalY + 15, theme: "grid", styles: { fontSize: 6, halign: "center", valign: "middle", lineColor: [200, 200, 200] }, headStyles: { fillColor: [230, 230, 230], textColor: 0, fontStyle: "bold" }, columnStyles: { 0: { halign: "left" } }, }); doc.save(`Rekap Harian - ${data.vehicle.date}.pdf`); } function paymentType(value) { switch (value) { case 2: value = "Mandiri"; break; case 3: value = "BRIZZI"; break; case 4: value = "TapCash"; break; case 5: value = "Flazz"; break; case 9: value = "QRIS"; break; default: value = "Tunai"; } return value; }