Melengkapi laporan semua transaksi with print

This commit is contained in:
2026-07-31 17:43:17 +07:00
parent d2e6f70bf6
commit d1bfa4f2eb
5 changed files with 929 additions and 228 deletions
+696
View File
@@ -0,0 +1,696 @@
$(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 : Harian", pageWidth - 14, 12, { align: "right" });
// ===== SUSUN BODY TABEL =====
const vehicleBody = [];
let totalTunaiJml = 0,
totalTunaiNilai = 0;
let totalNonTunaiJml = 0,
totalNonTunaiNilai = 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 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 nMasalah = cashless.keluar.masalah ?? { jumlah: 0, income: 0 };
const totalNonTunai = 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),
0,
0,
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),
0,
0,
nMasalah.jumlah,
rupiah(nMasalah.income),
{ content: rupiah(cashless.totalCashless), styles: { valign: "middle", fontStyle: "bold" } },
]);
totalTunaiJml += tCasual.jumlah + tLost.jumlah + tMember.jumlah + tManual.jumlah + tMasalah.jumlah;
totalTunaiNilai += cash.totalCash || 0;
totalNonTunaiJml += nCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah;
totalNonTunaiNilai += cashless.totalCashless || 0;
grandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0);
});
// baris TOTAL & GRAND TOTAL
vehicleBody.push([
{ content: "TOTAL", rowSpan: 2, styles: { fontStyle: "bold" } },
{ content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } },
"",
"",
{ content: totalTunaiJml, styles: { fontStyle: "bold" } },
rupiah(totalTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(totalTunaiNilai),
]);
vehicleBody.push([
{ content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } },
"",
"",
{ content: totalNonTunaiJml, styles: { fontStyle: "bold" } },
rupiah(totalNonTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(totalNonTunaiNilai),
]);
vehicleBody.push([
{ content: "GRAND TOTAL", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } },
{ content: totalTunaiJml + totalNonTunaiJml, styles: { fontStyle: "bold" } },
{ content: rupiah(totalTunaiNilai + totalNonTunaiNilai), styles: { fontStyle: "bold" } },
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
{ 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),
]);
doc.setFont("helvetica", "bold");
doc.setFontSize(8);
doc.text("Kendaraan yang masih menginap (Over Night)", 14, doc.lastAutoTable.finalY + 10);
doc.autoTable({
head: [["Jenis Kend", "Menginap", "ON (Expired)", "Total"]],
body: onBody,
startY: doc.lastAutoTable.finalY + 13,
theme: "grid",
styles: { fontSize: 7, cellPadding: 1 },
headStyles: { fontSize: 8, fillColor: [230, 230, 230], textColor: 0 },
tableWidth: 100,
});
///===================== Print table officer ================================////
const officerStartY = doc.lastAutoTable.finalY + 15;
const officerBody = [];
let ptotalTunaiJml = 0,
ptotalTunaiNilai = 0;
let ptotalNonTunaiJml = 0,
ptotalNonTunaiNilai = 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 totalTunai = cash.totalCash || 0;
const oCasual = 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 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,
oCasual.jumlah,
rupiah(oCasual.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" } },
]);
ptotalTunaiJml += tCasual.jumlah + tLost.jumlah + tMember.jumlah + tManual.jumlah + tMasalah.jumlah;
ptotalTunaiNilai += cash.totalCash || 0;
ptotalNonTunaiJml += oCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah;
ptotalNonTunaiNilai += cashless.totalCashless || 0;
pgrandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0);
});
// baris TOTAL & GRAND TOTAL
officerBody.push([
{ content: "TOTAL", rowSpan: 2, styles: { fontStyle: "bold" } },
{ content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } },
"",
"",
{ content: ptotalTunaiJml, styles: { fontStyle: "bold" } },
rupiah(ptotalTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(ptotalTunaiNilai),
]);
officerBody.push([
{ content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } },
"",
"",
{ content: ptotalNonTunaiJml, styles: { fontStyle: "bold" } },
rupiah(ptotalNonTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(ptotalNonTunaiNilai),
]);
officerBody.push([
{ content: "GRAND TOTAL", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } },
{ content: ptotalTunaiJml + ptotalNonTunaiJml, styles: { fontStyle: "bold" } },
{ content: rupiah(ptotalTunaiNilai + ptotalNonTunaiNilai), styles: { fontStyle: "bold" } },
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
// "",
// "",
{ content: rupiah(pgrandTotal), styles: { fontStyle: "bold" } },
]);
// ===== HEADER 2 BARIS (grouping) =====
const officerHead = [
[
{ 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.addPage();
doc.setFont("helvetica", "bold");
doc.setFontSize(11);
doc.text("Rekap Transaksi Per Petugas", pageWidth / 2, officerStartY - 5, { align: "center" });
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;
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 tMasalah = cash.keluar.masalah ?? { jumlah: 0, income: 0 };
const totalTunai = cash.totalCash || 0;
const oCasual = 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 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,
oCasual.jumlah,
rupiah(oCasual.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" } },
]);
ptotalTunaiJml += tCasual.jumlah + tLost.jumlah + tMember.jumlah + tManual.jumlah + tMasalah.jumlah;
ptotalTunaiNilai += cash.totalCash || 0;
ptotalNonTunaiJml += oCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah;
ptotalNonTunaiNilai += cashless.totalCashless || 0;
pgrandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0);
});
// baris TOTAL & GRAND TOTAL
paymentBody.push([
{ content: "TOTAL", rowSpan: 2, styles: { fontStyle: "bold" } },
{ content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } },
"",
"",
{ content: ptotalTunaiJml, styles: { fontStyle: "bold" } },
rupiah(ptotalTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(ptotalTunaiNilai),
]);
paymentBody.push([
{ content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } },
"",
"",
{ content: ptotalNonTunaiJml, styles: { fontStyle: "bold" } },
rupiah(ptotalNonTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(ptotalNonTunaiNilai),
]);
paymentBody.push([
{ content: "GRAND TOTAL", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } },
{ content: ptotalTunaiJml + ptotalNonTunaiJml, styles: { fontStyle: "bold" } },
{ content: rupiah(ptotalTunaiNilai + ptotalNonTunaiNilai), styles: { fontStyle: "bold" } },
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
// "",
// "",
{ content: rupiah(pgrandTotal), styles: { fontStyle: "bold" } },
]);
// ===== HEADER 2 BARIS (grouping) =====
const paymentHead = [
[
{ 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.addPage();
doc.setFont("helvetica", "bold");
doc.setFontSize(11);
doc.text("Rekap Transaksi Per Petugas", pageWidth / 2, paymentStartY - 5, { align: "center" });
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" } },
});
// ===== TABEL OVER NIGHT (di bawah tabel utama) =====
// const ponBody = data.payment.overNight.map((on) => [
// on.jenis_mobil ?? "-",
// on.overNight,
// on.onExpired,
// (on.overNight || 0) + (on.onExpired || 0),
// ]);
// doc.setFont("helvetica", "bold");
// doc.setFontSize(8);
// doc.text("Kendaraan yang masih menginap (Over Night)", 14, doc.lastAutoTable.finalY + 10);
// doc.autoTable({
// phead: [["Jenis Kend", "Menginap", "ON (Expired)", "Total"]],
// body: ponBody,
// startY: doc.lastAutoTable.finalY + 13,
// theme: "grid",
// styles: { fontSize: 7, cellPadding: 1 },
// headStyles: { fontSize: 8, fillColor: [230, 230, 230], textColor: 0 },
// tableWidth: 100,
// });
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;
}
File diff suppressed because one or more lines are too long
+227 -224
View File
@@ -1,3 +1,5 @@
window.ReportApp = window.ReportAp || {};
window.ReportApp.lastResponse = null;
let lastResponse = null; let lastResponse = null;
$(document).ready(function () { $(document).ready(function () {
@@ -41,20 +43,20 @@ $(document).ready(function () {
// lastResponse = loadData(); // lastResponse = loadData();
// $('.btn-export-excel').on('click', function () { // $('.btn-export-excel').on('click', function () {
$(document).on("click", ".btn-export-excel", function (e) { // $(document).on("click", ".btn-export-excel", function (e) {
// e.preventDefault(); // // e.preventDefault();
$("#cash td").each(function () { // $("#cash td").each(function () {
const raw = $(this).data("value"); // const raw = $(this).data("value");
if (raw !== undefined) { // if (raw !== undefined) {
$(this).text(raw); // $(this).text(raw);
} // }
}); // });
const table = document.getElementById("cetak"); // const table = document.getElementById("cetak");
const wb = XLSX.utils.table_to_book(table, { sheet: "Sheet 1" }); // const wb = XLSX.utils.table_to_book(table, { sheet: "Sheet 1" });
XLSX.writeFile(wb, `monthlyReport.xlsx`); // XLSX.writeFile(wb, `monthlyReport.xlsx`);
console.log(e); // console.log(e);
}); // });
$(".btn-export-pdf").on("click", async function () { $(".btn-export-pdf").on("click", async function () {
// $('.cetak').css('display','block'); // $('.cetak').css('display','block');
@@ -103,6 +105,7 @@ function loadData(tanggalMulai, tanggalAkhir) {
console.log("Loading data..."); console.log("Loading data...");
}, },
success: function (response) { success: function (response) {
window.ReportApp.lastResponse = response;
lastResponse = response; // ✅ tambah ini lastResponse = response; // ✅ tambah ini
tableVehicle(response.vehicle); tableVehicle(response.vehicle);
tableOfficer(response.officer); tableOfficer(response.officer);
@@ -934,240 +937,240 @@ function paymentType(value) {
return value; return value;
} }
function printPDF(vehicle) { // function printPDF(vehicle) {
const { jsPDF } = window.jspdf; // const { jsPDF } = window.jspdf;
const doc = new jsPDF({ // const doc = new jsPDF({
orientation: "portait", // portrait kesempitan buat 16 kolom // orientation: "portait", // portrait kesempitan buat 16 kolom
unit: "mm", // unit: "mm",
format: "a4", // format: "a4",
}); // });
const pageWidth = doc.internal.pageSize.getWidth(); // const pageWidth = doc.internal.pageSize.getWidth();
// ===== HEADER ===== // // ===== HEADER =====
doc.setFont("helvetica", "bold"); // doc.setFont("helvetica", "bold");
doc.setFontSize(12); // doc.setFontSize(12);
doc.text("MENTENG SQUARE - RAYA PARKING - RAYA Parking", 14, 12); // doc.text("MENTENG SQUARE - RAYA PARKING - RAYA Parking", 14, 12);
doc.setFontSize(11); // doc.setFontSize(11);
doc.text("Rekap Transaksi Kendaraan", pageWidth / 2, 18, { align: "center" }); // doc.text("Rekap Transaksi Kendaraan", pageWidth / 2, 18, { align: "center" });
doc.setFont("helvetica", "normal"); // doc.setFont("helvetica", "normal");
doc.setFontSize(9); // doc.setFontSize(9);
doc.text("Tanggal : " + (vehicle.date ?? "-"), pageWidth / 2, 23, { align: "center" }); // doc.text("Tanggal : " + (vehicle.date ?? "-"), pageWidth / 2, 23, { align: "center" });
doc.text("By : Harian", pageWidth - 14, 12, { align: "right" }); // doc.text("By : Harian", pageWidth - 14, 12, { align: "right" });
// ===== SUSUN BODY TABEL ===== // // ===== SUSUN BODY TABEL =====
const body = []; // const body = [];
let totalTunaiJml = 0, // let totalTunaiJml = 0,
totalTunaiNilai = 0; // totalTunaiNilai = 0;
let totalNonTunaiJml = 0, // let totalNonTunaiJml = 0,
totalNonTunaiNilai = 0; // totalNonTunaiNilai = 0;
let grandTotal = 0; // let grandTotal = 0;
vehicle.tunai.forEach(function (cash) { // vehicle.tunai.forEach(function (cash) {
const cashless = vehicle.nontunai.find((nt) => String(nt.id_kendaraan) === String(cash.id_kendaraan)) || { // const cashless = vehicle.nontunai.find((nt) => String(nt.id_kendaraan) === String(cash.id_kendaraan)) || {
nonTunaiOut: 0, // nonTunaiOut: 0,
keluar: { // keluar: {
casual: { jumlah: 0, income: 0 }, // casual: { jumlah: 0, income: 0 },
lost: { jumlah: 0, income: 0 }, // lost: { jumlah: 0, income: 0 },
member: { jumlah: 0, income: 0 }, // member: { jumlah: 0, income: 0 },
manual: { jumlah: 0, income: 0 }, // manual: { jumlah: 0, income: 0 },
}, // },
totalCashless: 0, // totalCashless: 0,
}; // };
// debugger; // // debugger;
const tCasual = cash.keluar.casual; // const tCasual = cash.keluar.casual;
const tLost = cash.keluar.lost; // const tLost = cash.keluar.lost;
const tMember = cash.keluar.member; // const tMember = cash.keluar.member;
const tManual = cash.keluar.manual; // const tManual = cash.keluar.manual;
const tMasalah = cash.keluar.masalah ?? { jumlah: 0, income: 0 }; // const tMasalah = cash.keluar.masalah ?? { jumlah: 0, income: 0 };
const totalTunai = cash.totalCash || 0; // const totalTunai = cash.totalCash || 0;
const nCasual = cashless.keluar.casual; // const nCasual = cashless.keluar.casual;
const nLost = cashless.keluar.lost; // const nLost = cashless.keluar.lost;
const nMember = cashless.keluar.member; // const nMember = cashless.keluar.member;
const nManual = cashless.keluar.manual; // const nManual = cashless.keluar.manual;
const nMasalah = cashless.keluar.masalah ?? { jumlah: 0, income: 0 }; // const nMasalah = cashless.keluar.masalah ?? { jumlah: 0, income: 0 };
const totalNonTunai = cashless.totalCashless || 0; // const totalNonTunai = cashless.totalCashless || 0;
// baris TUNAI // // baris TUNAI
body.push([ // body.push([
{ content: cash.jenis_mobil, rowSpan: 2, styles: { valign: "middle" } }, // { content: cash.jenis_mobil, rowSpan: 2, styles: { valign: "middle" } },
{ content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, // { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } },
cash.total, // cash.total,
cash.tunaiOut, // cash.tunaiOut,
tCasual.jumlah, // tCasual.jumlah,
rupiah(tCasual.income), // rupiah(tCasual.income),
tLost.jumlah, // tLost.jumlah,
rupiah(tLost.income), // rupiah(tLost.income),
tMember.jumlah, // tMember.jumlah,
rupiah(tMember.income), // rupiah(tMember.income),
tManual.jumlah, // tManual.jumlah,
rupiah(tManual.income), // rupiah(tManual.income),
0, // 0,
0, // 0,
tMasalah.jumlah, // tMasalah.jumlah,
rupiah(tMasalah.income), // rupiah(tMasalah.income),
{ content: rupiah(cash.totalCash), styles: { valign: "middle", fontStyle: "bold" } }, // { content: rupiah(cash.totalCash), styles: { valign: "middle", fontStyle: "bold" } },
]); // ]);
// baris NON TUNAI // // baris NON TUNAI
body.push([ // body.push([
{ content: "Non Tunai", styles: { fillColor: [255, 193, 7], textColor: 0, fontStyle: "bold" } }, // { content: "Non Tunai", styles: { fillColor: [255, 193, 7], textColor: 0, fontStyle: "bold" } },
cash.total, // cash.total,
cashless.nonTunaiOut, // cashless.nonTunaiOut,
nCasual.jumlah, // nCasual.jumlah,
rupiah(nCasual.income), // rupiah(nCasual.income),
nLost.jumlah, // nLost.jumlah,
// rupiah(nLost.income), // // rupiah(nLost.income),
cash.totalCashless, // cash.totalCashless,
nMember.jumlah, // nMember.jumlah,
rupiah(nMember.income), // rupiah(nMember.income),
nManual.jumlah, // nManual.jumlah,
rupiah(nManual.income), // rupiah(nManual.income),
0, // 0,
0, // 0,
nMasalah.jumlah, // nMasalah.jumlah,
rupiah(nMasalah.income), // rupiah(nMasalah.income),
{ content: rupiah(cashless.totalCashless), styles: { valign: "middle", fontStyle: "bold" } }, // { content: rupiah(cashless.totalCashless), styles: { valign: "middle", fontStyle: "bold" } },
]); // ]);
totalTunaiJml += tCasual.jumlah + tLost.jumlah + tMember.jumlah + tManual.jumlah + tMasalah.jumlah; // totalTunaiJml += tCasual.jumlah + tLost.jumlah + tMember.jumlah + tManual.jumlah + tMasalah.jumlah;
totalTunaiNilai += cash.totalCash || 0; // totalTunaiNilai += cash.totalCash || 0;
totalNonTunaiJml += nCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah; // totalNonTunaiJml += nCasual.jumlah + nLost.jumlah + nMember.jumlah + nManual.jumlah + nMasalah.jumlah;
totalNonTunaiNilai += cashless.totalCashless || 0; // totalNonTunaiNilai += cashless.totalCashless || 0;
grandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0); // grandTotal += (cash.totalCash || 0) + (cashless.totalCashless || 0);
}); // });
// baris TOTAL & GRAND TOTAL // // baris TOTAL & GRAND TOTAL
body.push([ // body.push([
{ content: "TOTAL", rowSpan: 2, styles: { fontStyle: "bold" } }, // { content: "TOTAL", rowSpan: 2, styles: { fontStyle: "bold" } },
{ content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } }, // { content: "Tunai", styles: { fillColor: [40, 167, 69], textColor: 255, fontStyle: "bold" } },
"", // "",
"", // "",
{ content: totalTunaiJml, styles: { fontStyle: "bold" } }, // { content: totalTunaiJml, styles: { fontStyle: "bold" } },
rupiah(totalTunaiNilai), // rupiah(totalTunaiNilai),
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
rupiah(totalTunaiNilai), // rupiah(totalTunaiNilai),
]); // ]);
body.push([ // body.push([
{ content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } }, // { content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } },
"", // "",
"", // "",
{ content: totalNonTunaiJml, styles: { fontStyle: "bold" } }, // { content: totalNonTunaiJml, styles: { fontStyle: "bold" } },
rupiah(totalNonTunaiNilai), // rupiah(totalNonTunaiNilai),
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
rupiah(totalNonTunaiNilai), // rupiah(totalNonTunaiNilai),
]); // ]);
body.push([ // body.push([
{ content: "GRAND TOTAL", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } }, // { content: "GRAND TOTAL", colSpan: 4, styles: { fontStyle: "bold", halign: "center" } },
{ content: totalTunaiJml + totalNonTunaiJml, styles: { fontStyle: "bold" } }, // { content: totalTunaiJml + totalNonTunaiJml, styles: { fontStyle: "bold" } },
{ content: rupiah(totalTunaiNilai + totalNonTunaiNilai), styles: { fontStyle: "bold" } }, // { content: rupiah(totalTunaiNilai + totalNonTunaiNilai), styles: { fontStyle: "bold" } },
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
"", // "",
{ content: rupiah(grandTotal), styles: { fontStyle: "bold" } }, // { content: rupiah(grandTotal), styles: { fontStyle: "bold" } },
]); // ]);
// ===== HEADER 2 BARIS (grouping) ===== // // ===== HEADER 2 BARIS (grouping) =====
const head = [ // const head = [
[ // [
{ content: "Jenis Kend", rowSpan: 2, colSpan: 2 }, // { content: "Jenis Kend", rowSpan: 2, colSpan: 2 },
{ content: "Jenis Transaksi", colSpan: 2 }, // { content: "Jenis Transaksi", colSpan: 2 },
{ content: "Casual", colSpan: 2 }, // { content: "Casual", colSpan: 2 },
{ content: "Tiket Hilang", colSpan: 2 }, // { content: "Tiket Hilang", colSpan: 2 },
{ content: "Member", colSpan: 2 }, // { content: "Member", colSpan: 2 },
{ content: "Manual Input", colSpan: 2 }, // { content: "Manual Input", colSpan: 2 },
{ content: "Manual Mix", colSpan: 2 }, // { content: "Manual Mix", colSpan: 2 },
{ content: "Tiket Masalah", colSpan: 2 }, // { content: "Tiket Masalah", colSpan: 2 },
{ content: "Pendapatan", rowSpan: 2 }, // { content: "Pendapatan", rowSpan: 2 },
], // ],
[ // [
"Masuk", // "Masuk",
"Keluar", // "Keluar",
"JML", // "JML",
"Nilai", // "Nilai",
"JML", // "JML",
"Nilai", // "Nilai",
"JML", // "JML",
"Nilai", // "Nilai",
"JML", // "JML",
"Nilai", // "Nilai",
"JML", // "JML",
"Nilai", // "Nilai",
"JML", // "JML",
"Nilai", // "Nilai",
], // ],
]; // ];
doc.autoTable({ // doc.autoTable({
head: head, // head: head,
body: body, // body: body,
startY: 28, // startY: 28,
theme: "grid", // theme: "grid",
styles: { fontSize: 6, halign: "center", valign: "middle", lineColor: [200, 200, 200] }, // styles: { fontSize: 6, halign: "center", valign: "middle", lineColor: [200, 200, 200] },
headStyles: { fillColor: [230, 230, 230], textColor: 0, fontStyle: "bold" }, // headStyles: { fillColor: [230, 230, 230], textColor: 0, fontStyle: "bold" },
columnStyles: { 0: { halign: "left" } }, // columnStyles: { 0: { halign: "left" } },
}); // });
// ===== TABEL OVER NIGHT (di bawah tabel utama) ===== // // ===== TABEL OVER NIGHT (di bawah tabel utama) =====
const onBody = vehicle.overNight.map((on) => [ // const onBody = vehicle.overNight.map((on) => [
on.jenis_mobil ?? "-", // on.jenis_mobil ?? "-",
on.overNight, // on.overNight,
on.onExpired, // on.onExpired,
(on.overNight || 0) + (on.onExpired || 0), // (on.overNight || 0) + (on.onExpired || 0),
]); // ]);
doc.setFont("helvetica", "bold"); // doc.setFont("helvetica", "bold");
doc.setFontSize(8); // doc.setFontSize(8);
doc.text("Kendaraan yang masih menginap (Over Night)", 14, doc.lastAutoTable.finalY + 10); // doc.text("Kendaraan yang masih menginap (Over Night)", 14, doc.lastAutoTable.finalY + 10);
doc.autoTable({ // doc.autoTable({
head: [["Jenis Kend", "Menginap", "ON (Expired)", "Total"]], // head: [["Jenis Kend", "Menginap", "ON (Expired)", "Total"]],
body: onBody, // body: onBody,
startY: doc.lastAutoTable.finalY + 13, // startY: doc.lastAutoTable.finalY + 13,
theme: "grid", // theme: "grid",
styles: { fontSize: 7, cellPadding: 1 }, // styles: { fontSize: 7, cellPadding: 1 },
headStyles: { fontSize: 8, fillColor: [230, 230, 230], textColor: 0 }, // headStyles: { fontSize: 8, fillColor: [230, 230, 230], textColor: 0 },
tableWidth: 100, // tableWidth: 100,
}); // });
doc.save(`Rekap Harian - ${vehicle.date}.pdf`); // doc.save(`Rekap Harian - ${vehicle.date}.pdf`);
} // }
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -24,7 +24,7 @@
<div class="card-header"> <div class="card-header">
<div class="col d-flex align-items-center gap-2"> <div class="col d-flex align-items-center gap-2">
<div class="col-sm-2"> <div class="col-sm-2">
<input type="date" class="form-control" id="tanggalCari" name="tanggal_mulai" required> <input type="date" lang=id class="form-control" id="tanggalCari" name="tanggal_mulai" required>
<!--<input type="text" id="tanggalCari" ... style="display:none"> <!-- asli, hidden, format Y-m-d --> <!--<input type="text" id="tanggalCari" ... style="display:none"> <!-- asli, hidden, format Y-m-d -->
<!--<input type="text" class="form-control flatpickr-input" ...>--> <!--<input type="text" class="form-control flatpickr-input" ...>-->
</div> </div>
@@ -46,8 +46,7 @@
<h4 class="card-title"> <h4 class="card-title">
{{ ($locationSettings->namalokasi) ?? '' }} - {{ ($locationSettings->namaperusahaan) ?? '' }} {{ ($locationSettings->namalokasi) ?? '' }} - {{ ($locationSettings->namaperusahaan) ?? '' }}
</h4> </h4>
<h5 class="text-center"> <h5 class="card-title text-center">Rekap Transaksi Kendaraan
<strong>Rekap Transaksi Kendaraan</strong>
<div class="mx-auto mt-1" id="tanggal-trans"></div> <div class="mx-auto mt-1" id="tanggal-trans"></div>
</h5> </h5>
<!-- BARIS TANGGAL & BY --> <!-- BARIS TANGGAL & BY -->
@@ -198,5 +197,6 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.31/jspdf.plugin.autotable.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.31/jspdf.plugin.autotable.min.js"></script>
<script src="{{ asset('js/report/report-vehicle.js') }}"></script> <script src="{{ asset('js/report/report-vehicle.min.js') }}"></script>
<script src="{{ asset('js/report/report-print.min.js') }}"></script>
@endsection @endsection