let lastResponse = null;
$(document).ready(function () {
// $("#modaltanggal").modal("show");
// const hariIni = flatpickr("#tanggalCari", {
// dateFormat: "Y-m-d", // ini yang tampil ke user
// altInput: true,
// altFormat: "Y-m-d",
// defaultDate: "today",
// onChange: function (selectedDate, dateStr, instance) {
// loadData();
// },
// });
//
const date = $("#tanggalCari").datepicker({
format: "yyyy-mm-dd",
autoclose: true,
todayHighlight: true,
});
$("#tanggalCari").datepicker("setDate", new Date());
$("#tanggalCari").on("changeDate", function (e) {
const tanggalCari = $("#tanggalCari").val();
$("#tanggal-trans").text("Tanggal : " + tanggalCari);
loadData();
});
const tanggalCari = $("#tanggalCari").val();
// $("#harianToggle").on("change", loadData);
// Set tanggal default ke hari ini
// console.log("value asli (ke server):", $("#tanggalCari").val());
// console.log("value tampilan:", $("input[data-input]").val()); // tampilan: 30-07-2026
// realtime trigger
// $("#tanggalCari").on("change", $("#tanggalCari").val());
$("#harianToggle").on("change", loadData);
// var today = Date.now().format("yyyy-mm-dd");
// $("#tanggalCari").val();
// $("#tanggalCari").val(getToday());
loadData();
// lastResponse = loadData();
// $('.btn-export-excel').on('click', function () {
$(document).on("click", ".btn-export-excel", function (e) {
// e.preventDefault();
$("#cash td").each(function () {
const raw = $(this).data("value");
if (raw !== undefined) {
$(this).text(raw);
}
});
const table = document.getElementById("cetak");
const wb = XLSX.utils.table_to_book(table, { sheet: "Sheet 1" });
XLSX.writeFile(wb, `monthlyReport.xlsx`);
console.log(e);
});
$(".btn-export-pdf").on("click", async function () {
// $('.cetak').css('display','block');
// $('.user').css('display','block');
// const { jsPDF } = window.jspdf;
// const doc = new jsPDF("p", "pt", "a4");
// // ambil elemen tabel
// const table = document.getElementById("cetak");
// const canvas = await html2canvas(table, { scale: 2 });
// const imgData = canvas.toDataURL("image/png");
// const imgWidth = doc.internal.pageSize.getWidth();
// const imgHeight = (canvas.height * imgWidth) / canvas.width;
// doc.addImage(imgData, "PNG", 0, 20, imgWidth, imgHeight);
// doc.save(`Rekap Harian.pdf`);
//
// jsPDF Autotable
if (!lastResponse) {
alert("Data belum tersedia");
return;
}
printPDF(lastResponse.vehicle);
});
// console.log(document.getElementById("cetak"));
// console.log(document.getElementById("date-table"));
});
function loadData(tanggalMulai, tanggalAkhir) {
let tanggal = $("#tanggalCari").val();
let harian = $("#harianToggle").is(":checked") ? 1 : 0;
if (harian == 1) $("#harian").text("By : Harian");
else $("#harian").text("By : Shift");
// console.log(harian);
// console.log(tanggal);
if (!tanggal) return;
// Contoh: Load data dengan AJAX
$.ajax({
url: "/report/laporan-semua-transaksi/vehicle", // Ganti dengan route Anda
type: "GET",
data: {
tanggal: tanggal,
harian: harian,
},
beforeSend: function () {
console.log("Loading data...");
},
success: function (response) {
lastResponse = response; // ✅ tambah ini
tableVehicle(response.vehicle);
tableOfficer(response.officer);
tablePayment(response.payment);
// // Update tabel dengan data yang diterima
// let html = "";
// let onData = "";
// let jmlCashCasual = 0;
// let incomeCashCasual = 0;
// let jmlCashlessCasual = 0;
// let incomeCashlessCasual = 0;
// let grandTotal = 0;
// response.tunai.forEach(function (cash) {
// // cari pasangan non tunai
// let cashless = response.nontunai.find((nt) => String(nt.id_kendaraan) === String(cash.id_kendaraan));
// // fallback aman
// cashless = cashless || {
// nontunai: 0,
// nonTunaiOut: 0,
// keluar: {
// casual: { jumlah: 0, income: 0 },
// lost: { jumlah: 0, income: 0 },
// member: { jumlah: 0, income: 0 },
// },
// totalCashless: 0,
// };
// let casualIn = cash.total;
// let tunaiOut = cash.tunaiOut;
// // ===== DATA TUNAI =====
// let tCasual = cash.keluar.casual;
// let tLost = cash.keluar.lost;
// let tMember = cash.keluar.member;
// let tManual = cash.keluar.manual;
// // ===== DATA NON TUNAI =====
// let nonTunaiOut = cashless.nonTunaiOut;
// let nCasual = cashless.keluar.casual;
// let nLost = cashless.keluar.lost;
// let nMember = cashless.keluar.member;
// let nManual = cashless.keluar.manual;
// let totalTunai = cash.totalCash || 0;
// let totalNonTunai = cashless.totalCashless || 0;
// jmlCashCasual += cash.keluar.casual.jumlah;
// incomeCashCasual += cash.keluar.casual.income;
// jmlCashlessCasual += cashless.keluar.casual.jumlah;
// incomeCashlessCasual += cashless.keluar.casual.income;
// grandTotal += totalTunai + totalNonTunai;
// // let casualCash = cash.keluar.casual;
// // let lostCash = cash.keluar.lost;
// // let memberCash = cash.keluar.member;
// // let casualIn = cash.total;
// // let casualNon = cashless ? cashless.keluar.casual : { jumlah: 0, income: 0 };
// // let lostNon = cashless ? cashless.keluar.lost : { jumlah: 0, income: 0 };
// // let memberNon = cashless ? cashless.keluar.member : { jumlah: 0, income: 0 };
// // let totalIncome =
// // (cash.totalCash || 0);
// // html += `
// //
// // | ${cash.jenis_mobil} |
// //
// // ${casualIn} |
// // ${cash.tunaiOut} |
// //
// // ${casualCash.jumlah} |
// // ${rupiah(casualCash.income)} |
// //
// // ${lostCash.jumlah} |
// // ${rupiah(lostCash.income)} |
// //
// // ${memberCash.jumlah} |
// // ${rupiah(memberCash.income)} |
// //
// // 0 |
// // 0 |
// //
// // 0 |
// // 0 |
// //
// // 0 |
// // 0 |
// //
// // ${rupiah(totalIncome)} |
// //
// // `;
// html += `
//
// | ${cash.jenis_mobil} |
// Tunai |
// ${casualIn} |
// ${tunaiOut} |
// ${tCasual.jumlah} |
// ${rupiah(tCasual.income)} |
// ${tLost.jumlah} |
// ${rupiah(tLost.income)} |
// ${tMember.jumlah} |
// ${rupiah(tMember.income)} |
// ${tManual.jumlah} |
// ${rupiah(tManual.income)} |
// 0 |
// 0 |
// 0 |
// 0 |
// ${rupiah(totalTunai)} |
//
//
// | Non Tunai |
// ${casualIn} |
// ${nonTunaiOut} |
// ${nCasual.jumlah} |
// ${rupiah(nCasual.income)} |
// ${nLost.jumlah} |
// ${rupiah(nLost.income)} |
// ${nMember.jumlah} |
// ${rupiah(nMember.income)} |
// ${nManual.jumlah} |
// ${rupiah(nManual.income)} |
// 0 |
// 0 |
// 0 |
// 0 |
// ${rupiah(totalNonTunai)} |
//
// `;
// });
// // ===== FOOTER TOTAL =====
// html += `
//
// | TOTAL |
// Tunai |
// 0 |
// 0 |
// ${rupiah(jmlCashCasual)} |
// ${rupiah(incomeCashCasual)} |
// 0 |
//
//
// | NON TUNAI |
// 0 |
// 0 |
// ${jmlCashlessCasual} |
// ${rupiah(incomeCashlessCasual)} |
// 0 |
//
//
// | GRAND TOTAL |
// |
// ${jmlCashCasual + jmlCashlessCasual} |
// ${rupiah(incomeCashCasual + incomeCashlessCasual)} |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// |
// ${rupiah(grandTotal)} |
//
// `;
// // console.log('TUNAI:', cash.id_kendaraan, cash);
// // console.log('CASHLESS FOUND:', cashless);
// $("#table-data").html(html);
// response.overNight.forEach(function (on) {
// if (!on.jenis_mobil) return;
// let overnight = on.overNight;
// let onExpired = on.onExpired;
// onData += `
//
// | ${on.jenis_mobil} |
// ${overnight} |
// ${onExpired} |
// 0 |
//
// `;
// });
// $("#table-overnight").html(onData);
// console.log(response);
},
error: function (xhr) {
console.log("Error:", xhr);
alert("Terjadi kesalahan saat memuat data");
},
});
}
function rupiah(angka) {
return new Intl.NumberFormat("id-ID").format(angka || 0);
}
function getToday() {
const d = new Date();
const tgl = String(d.getDate()).padStart(2, "0");
const bulan = String(d.getMonth() + 1).padStart(2, "0");
const tahun = d.getFullYear();
return `${tgl}-${bulan}-${tahun}`;
}
function tableVehicle(response) {
// Update tabel dengan data yang diterima
let html = "";
let onData = "";
let jmlCashCasual = 0;
let incomeCashCasual = 0;
let jmlCashlessCasual = 0;
let incomeCashlessCasual = 0;
let grandTotal = 0;
response.tunai.forEach(function (cash) {
// cari pasangan non tunai
let cashless = response.nontunai.find((nt) => String(nt.id_kendaraan) === String(cash.id_kendaraan));
// fallback aman
cashless = cashless || {
nontunai: 0,
nonTunaiOut: 0,
keluar: {
casual: { jumlah: 0, income: 0 },
lost: { jumlah: 0, income: 0 },
member: { jumlah: 0, income: 0 },
},
totalCashless: 0,
};
let casualIn = cash.total;
let tunaiOut = cash.tunaiOut;
// ===== DATA TUNAI =====
let tCasual = cash.keluar.casual;
let tLost = cash.keluar.lost;
let tMember = cash.keluar.member;
let tManual = cash.keluar.manual;
// ===== DATA NON TUNAI =====
let nonTunaiOut = cashless.nonTunaiOut;
let nCasual = cashless.keluar.casual;
let nLost = cashless.keluar.lost;
let nMember = cashless.keluar.member;
let nManual = cashless.keluar.manual;
let totalTunai = cash.totalCash || 0;
let totalNonTunai = cashless.totalCashless || 0;
jmlCashCasual += cash.keluar.casual.jumlah;
incomeCashCasual += cash.keluar.casual.income;
jmlCashlessCasual += cashless.keluar.casual.jumlah;
incomeCashlessCasual += cashless.keluar.casual.income;
grandTotal += totalTunai + totalNonTunai;
// let casualCash = cash.keluar.casual;
// let lostCash = cash.keluar.lost;
// let memberCash = cash.keluar.member;
// let casualIn = cash.total;
// let casualNon = cashless ? cashless.keluar.casual : { jumlah: 0, income: 0 };
// let lostNon = cashless ? cashless.keluar.lost : { jumlah: 0, income: 0 };
// let memberNon = cashless ? cashless.keluar.member : { jumlah: 0, income: 0 };
// let totalIncome =
// (cash.totalCash || 0);
// html += `
//
// | ${cash.jenis_mobil} |
//
// ${casualIn} |
// ${cash.tunaiOut} |
//
// ${casualCash.jumlah} |
// ${rupiah(casualCash.income)} |
//
// ${lostCash.jumlah} |
// ${rupiah(lostCash.income)} |
//
// ${memberCash.jumlah} |
// ${rupiah(memberCash.income)} |
//
// 0 |
// 0 |
//
// 0 |
// 0 |
//
// 0 |
// 0 |
//
// ${rupiah(totalIncome)} |
//
// `;
html += `
| ${cash.jenis_mobil} |
Tunai |
${casualIn} |
${tunaiOut} |
${tCasual.jumlah} |
${rupiah(tCasual.income)} |
${tLost.jumlah} |
${rupiah(tLost.income)} |
${tMember.jumlah} |
${rupiah(tMember.income)} |
${tManual.jumlah} |
${rupiah(tManual.income)} |
0 |
0 |
0 |
0 |
${rupiah(totalTunai)} |
| Non Tunai |
${casualIn} |
${nonTunaiOut} |
${nCasual.jumlah} |
${rupiah(nCasual.income)} |
${nLost.jumlah} |
${rupiah(nLost.income)} |
${nMember.jumlah} |
${rupiah(nMember.income)} |
${nManual.jumlah} |
${rupiah(nManual.income)} |
0 |
0 |
0 |
0 |
${rupiah(totalNonTunai)} |
`;
});
// ===== FOOTER TOTAL =====
html += `
| TOTAL |
Tunai |
0 |
0 |
${rupiah(jmlCashCasual)} |
${rupiah(incomeCashCasual)} |
|
${rupiah(incomeCashCasual)} |
| NON TUNAI |
0 |
0 |
${jmlCashlessCasual} |
${rupiah(incomeCashlessCasual)} |
|
${rupiah(incomeCashlessCasual)} |
| GRAND TOTAL |
|
${jmlCashCasual + jmlCashlessCasual} |
${rupiah(incomeCashCasual + incomeCashlessCasual)} |
|
|
|
|
|
|
|
|
|
|
${rupiah(grandTotal)} |
`;
// console.log('TUNAI:', cash.id_kendaraan, cash);
// console.log('CASHLESS FOUND:', cashless);
$("#table-data").html(html);
response.overNight.forEach(function (on) {
if (!on.jenis_mobil) return;
let overnight = on.overNight;
let onExpired = on.onExpired;
onData += `
| ${on.jenis_mobil} |
${overnight} |
${onExpired} |
0 |
`;
});
$("#table-overnight").html(onData);
console.log(response);
}
function tableOfficer(response) {
// Update tabel dengan data yang diterima
console.log(response);
let html = "";
let onData = "";
let jmlCashCasual = 0;
let incomeCashCasual = 0;
let jmlCashlessCasual = 0;
let incomeCashlessCasual = 0;
let grandTotal = 0;
response.tunai.forEach(function (cash) {
// cari pasangan non tunai
let cashless = response.nontunai.find((nt) => String(nt.id_petugas) === String(cash.id_petugas));
// fallback aman
cashless = cashless || {
nontunai: 0,
nonTunaiOut: 0,
keluar: {
casual: { jumlah: 0, income: 0 },
lost: { jumlah: 0, income: 0 },
member: { jumlah: 0, income: 0 },
},
totalCashless: 0,
};
let petugas = cash.petugas === null ? "NO-OP" : cash.petugas;
let casualIn = cash.total;
let tunaiOut = cash.tunaiOut;
// ===== DATA TUNAI =====
let tCasual = cash.keluar.casual;
let tLost = cash.keluar.lost;
let tMember = cash.keluar.member;
let tManual = cash.keluar.manual;
// ===== DATA NON TUNAI =====
let nonTunaiOut = cashless.nonTunaiOut;
let nCasual = cashless.keluar.casual;
let nLost = cashless.keluar.lost;
let nMember = cashless.keluar.member;
let nManual = cashless.keluar.manual ?? 0;
let totalTunai = cash.totalCash || 0;
let totalNonTunai = cashless.totalCashless || 0;
jmlCashCasual += cash.keluar.casual.jumlah;
incomeCashCasual += cash.keluar.casual.income;
jmlCashlessCasual += cashless.keluar.casual.jumlah;
incomeCashlessCasual += cashless.keluar.casual.income;
grandTotal += totalTunai + totalNonTunai;
// let casualCash = cash.keluar.casual;
// let lostCash = cash.keluar.lost;
// let memberCash = cash.keluar.member;
// let casualIn = cash.total;
// let casualNon = cashless ? cashless.keluar.casual : { jumlah: 0, income: 0 };
// let lostNon = cashless ? cashless.keluar.lost : { jumlah: 0, income: 0 };
// let memberNon = cashless ? cashless.keluar.member : { jumlah: 0, income: 0 };
// let totalIncome =
// (cash.totalCash || 0);
// html += `
//
// | ${cash.jenis_mobil} |
//
// ${casualIn} |
// ${cash.tunaiOut} |
//
// ${casualCash.jumlah} |
// ${rupiah(casualCash.income)} |
//
// ${lostCash.jumlah} |
// ${rupiah(lostCash.income)} |
//
// ${memberCash.jumlah} |
// ${rupiah(memberCash.income)} |
//
// 0 |
// 0 |
//
// 0 |
// 0 |
//
// 0 |
// 0 |
//
// ${rupiah(totalIncome)} |
//
// `;
html += `
| ${petugas} |
Tunai |
${casualIn} |
${tunaiOut} |
${tCasual.jumlah} |
${rupiah(tCasual.income)} |
${tLost.jumlah} |
${rupiah(tLost.income)} |
${tMember.jumlah} |
${rupiah(tMember.income)} |
${tManual.jumlah} |
${rupiah(tManual.income)} |
0 |
0 |
0 |
|
${rupiah(totalTunai)} |
| Non Tunai |
${casualIn} |
${nonTunaiOut} |
${nCasual.jumlah} |
${rupiah(nCasual.income)} |
${nLost.jumlah} |
${rupiah(nLost.income)} |
${nMember.jumlah} |
${rupiah(nMember.income)} |
${nManual.jumlah} |
${rupiah(nManual.income)} |
0 |
0 |
0 |
0 |
${rupiah(totalNonTunai)} |
`;
});
// ===== FOOTER TOTAL =====
html += `
| TOTAL |
Tunai |
0 |
0 |
${rupiah(jmlCashCasual)} |
${rupiah(incomeCashCasual)} |
${rupiah(incomeCashCasual)} |
| NON TUNAI |
0 |
0 |
${jmlCashlessCasual} |
${rupiah(incomeCashlessCasual)} |
${rupiah(incomeCashlessCasual)} |
| GRAND TOTAL |
|
${jmlCashCasual + jmlCashlessCasual} |
${rupiah(incomeCashCasual + incomeCashlessCasual)} |
|
|
|
|
|
|
|
|
|
|
${rupiah(grandTotal)} |
`;
// console.log('TUNAI:', cash.id_kendaraan, cash);
// console.log('CASHLESS FOUND:', cashless);
$("#officer-data").html(html);
// response.overNight.forEach(function (on) {
// if (!on.jenis_mobil) return;
// let overnight = on.overNight;
// let onExpired = on.onExpired;
// onData += `
//
// | ${on.jenis_mobil} |
// ${overnight} |
// ${onExpired} |
// 0 |
//
// `;
// });
// $("#table-overnight").html(onData);
// console.log(response);
}
function tablePayment(response) {
// Update tabel dengan data yang diterima
console.log(response);
let html = "";
let onData = "";
let jmlCashCasual = 0;
let incomeCashCasual = 0;
let jmlCashlessCasual = 0;
let incomeCashlessCasual = 0;
let grandTotal = 0;
response.tunai.forEach(function (cash) {
// cari pasangan non tunai
let cashless = response.nontunai.find((nt) => String(nt.typePayment) === String(cash.typePayment));
// fallback aman
cashless = cashless || {
nontunai: 0,
nonTunaiOut: 0,
keluar: {
casual: { jumlah: 0, income: 0 },
lost: { jumlah: 0, income: 0 },
member: { jumlah: 0, income: 0 },
},
totalCashless: 0,
};
let payment = paymentType(cash.typePayment);
// let payment = cash.typePayment;
let casualIn = cash.total;
let tunaiOut = cash.tunaiOut;
// ===== DATA TUNAI =====
let tCasual = cash.keluar.casual;
let tLost = cash.keluar.lost;
let tMember = cash.keluar.member;
let tManual = cash.keluar.manual;
// ===== DATA NON TUNAI =====
let nonTunaiOut = cashless.nonTunaiOut;
let nCasual = cashless.keluar.casual;
let nLost = cashless.keluar.lost;
let nMember = cashless.keluar.member;
let nManual = cashless.keluar.manual ?? 0;
let totalTunai = cash.totalCash || 0;
let totalNonTunai = cashless.totalCashless || 0;
jmlCashCasual += cash.keluar.casual.jumlah;
incomeCashCasual += cash.keluar.casual.income;
jmlCashlessCasual += cashless.keluar.casual.jumlah;
incomeCashlessCasual += cashless.keluar.casual.income;
grandTotal += totalTunai + totalNonTunai;
html += `
| ${payment} |
Tunai |
${casualIn} |
${tunaiOut} |
${tCasual.jumlah} |
${rupiah(tCasual.income)} |
${tLost.jumlah} |
${rupiah(tLost.income)} |
${tMember.jumlah} |
${rupiah(tMember.income)} |
${tManual.jumlah} |
${rupiah(tManual.income)} |
0 |
0 |
0 |
|
${rupiah(totalTunai)} |
| Non Tunai |
${casualIn} |
${nonTunaiOut} |
${nCasual.jumlah} |
${rupiah(nCasual.income)} |
${nLost.jumlah} |
${rupiah(nLost.income)} |
${nMember.jumlah} |
${rupiah(nMember.income)} |
${nManual.jumlah} |
${rupiah(nManual.income)} |
0 |
0 |
0 |
0 |
${rupiah(totalNonTunai)} |
`;
});
// ===== FOOTER TOTAL =====
html += `
| TOTAL |
Tunai |
0 |
0 |
${rupiah(jmlCashCasual)} |
${rupiah(incomeCashCasual)} |
${rupiah(incomeCashCasual)} |
| NON TUNAI |
0 |
0 |
${jmlCashlessCasual} |
${rupiah(incomeCashlessCasual)} |
${rupiah(incomeCashlessCasual)} |
| GRAND TOTAL |
|
${jmlCashCasual + jmlCashlessCasual} |
${rupiah(incomeCashCasual + incomeCashlessCasual)} |
|
|
|
|
|
|
|
|
|
|
${rupiah(grandTotal)} |
`;
// console.log('TUNAI:', cash.id_kendaraan, cash);
// console.log('CASHLESS FOUND:', cashless);
$("#payment-data").html(html);
}
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;
}
function printPDF(vehicle) {
const { jsPDF } = window.jspdf;
const doc = new jsPDF({
orientation: "portait", // portrait kesempitan buat 16 kolom
unit: "mm",
format: "a4",
});
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 Kendaraan", pageWidth / 2, 18, { align: "center" });
doc.setFont("helvetica", "normal");
doc.setFontSize(9);
doc.text("Tanggal : " + (vehicle.date ?? "-"), pageWidth / 2, 23, { align: "center" });
doc.text("By : Harian", pageWidth - 14, 12, { align: "right" });
// ===== SUSUN BODY TABEL =====
const body = [];
let totalTunaiJml = 0,
totalTunaiNilai = 0;
let totalNonTunaiJml = 0,
totalNonTunaiNilai = 0;
let grandTotal = 0;
vehicle.tunai.forEach(function (cash) {
const cashless = 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
body.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
body.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),
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" } },
]);
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
body.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),
]);
body.push([
{ content: "NON TUNAI", styles: { fillColor: [255, 193, 7], fontStyle: "bold" } },
"",
"",
{ content: totalNonTunaiJml, styles: { fontStyle: "bold" } },
rupiah(totalNonTunaiNilai),
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
rupiah(totalNonTunaiNilai),
]);
body.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: body,
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 = 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,
});
doc.save(`Rekap Harian - ${vehicle.date}.pdf`);
}