//Kode HTML
<!DOCTYPE html>
<html>
<head>
    <base target="_top">
    <title>Buku Kas TPQ Al Qurabiy</title>
    <!-- Memuat Tailwind CSS untuk styling -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Memuat SweetAlert untuk notifikasi yang lebih baik -->
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
    <style>
        /* Custom CSS untuk spinner/loader */
        .loader-spinner {
            border: 8px solid #f3f3f3; /* Light grey */
            border-top: 8px solid #16a34a; /* Green */
            border-radius: 50%;
            width: 60px;
            height: 60px;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
             0% { transform: rotate(0deg); }
             100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body class="bg-gray-100 text-gray-800">
    <div id="loader" class="hidden fixed inset-0 bg-gray-900 bg-opacity-50 flex
items-center justify-center z-50">
        <div class="loader-spinner"></div>
    </div>
    <div class="container mx-auto p-4 md:p-8">
        <!-- Header Aplikasi -->
        <header class="text-center mb-8 p-6 bg-white rounded-lg shadow-md">
             <h1 class="text-3xl font-bold text-green-700">Buku Kas Digital</h1>
             <h2 class="text-xl text-gray-600">Taman Pendidikan Al-Qur'an Al
Qurabiy</h2>
             <p class="text-sm text-gray-500 mt-1">Balongcino, Desa Blaru, Kecamatan
Badas, Kab. Kediri</p>
        </header>
        <main class="grid grid-cols-1 lg:grid-cols-3 gap-8">
              <!-- Kolom Kiri: Form Input & Laporan -->
              <div class="lg:col-span-1 space-y-6">
                <!-- Form Tambah Transaksi -->
                <div class="bg-white p-6 rounded-lg shadow-md">
                    <h3 class="text-lg font-semibold mb-4 border-b pb-2">Tambah
Transaksi Baru</h3>
                    <form id="kasForm" class="space-y-4">
                        <div>
                            <label for="tanggal" class="block text-sm font-medium
text-gray-700">Tanggal</label>
                            <input type="date" id="tanggal" name="tanggal" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-
500 focus:ring-green-500 sm:text-sm">
                        </div>
                        <div>
                            <label for="keterangan" class="block text-sm font-
medium text-gray-700">Keterangan</label>
                            <input type="text" id="keterangan" name="keterangan"
required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm
focus:border-green-500 focus:ring-green-500 sm:text-sm" placeholder="Contoh: Infaq
bulan Januari">
                        </div>
                        <div>
                            <label for="masuk" class="block text-sm font-medium
text-gray-700">Pemasukan (Debit)</label>
                            <input type="number" id="masuk" name="masuk" class="mt-
1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-500
focus:ring-green-500 sm:text-sm" placeholder="0">
                        </div>
                        <div>
                            <label for="keluar" class="block text-sm font-medium
text-gray-700">Pengeluaran (Kredit)</label>
                            <input type="number" id="keluar" name="keluar"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-
500 focus:ring-green-500 sm:text-sm" placeholder="0">
                        </div>
                        <button type="submit" class="w-full bg-green-600 hover:bg-
green-700 text-white font-bold py-2 px-4 rounded-lg shadow-md transition duration-
300">
                            Simpan Transaksi
                        </button>
                    </form>
                </div>
                <!-- Opsi Laporan -->
                <div class="bg-white p-6 rounded-lg shadow-md">
                    <h3 class="text-lg font-semibold mb-4 border-b pb-2">Cetak
Laporan PDF</h3>
                    <div class="space-y-2 mb-4">
                         <label for="filterBulan" class="block text-sm font-medium
text-gray-700">Laporan Bulanan</label>
                         <div class="flex gap-2">
                             <input type="month" id="filterBulan" class="block w-
full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring-green-
500 sm:text-sm">
                             <button id="btnCetakBulan" class="bg-blue-600
hover:bg-blue-700 text-white font-bold py-2 px-3 rounded-lg shadow-md transition
duration-300">
                                 Cetak
                             </button>
                         </div>
                    </div>
                    <div class="space-y-2 mb-4">
                         <label class="block text-sm font-medium text-gray-
700">Laporan Sesuai Tanggal</label>
                         <div class="flex flex-col sm:flex-row gap-2">
                            <input type="date" id="startDate" class="block w-full
rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring-green-500
sm:text-sm">
                            <input type="date" id="endDate" class="block w-full
rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring-green-500
sm:text-sm">
                         </div>
                         <button id="btnCetakRange" class="mt-2 w-full bg-blue-600
hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg shadow-md transition
duration-300">
                             Cetak
                         </button>
                    </div>
                    <div class="space-y-2">
                         <label for="filterTahun" class="block text-sm font-medium
text-gray-700">Rekap Tahunan</label>
                         <div class="flex gap-2">
                             <input type="number" id="filterTahun" class="block w-
full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring-green-
500 sm:text-sm" placeholder="Contoh: 2024" min="2000" max="2100">
                             <button id="btnCetakTahun" class="bg-purple-600
hover:bg-purple-700 text-white font-bold py-2 px-3 rounded-lg shadow-md transition
duration-300">
                                 Cetak
                             </button>
                         </div>
                    </div>
                </div>
            </div>
            <!-- Kolom Kanan: Tabel Data Kas -->
            <div class="lg:col-span-2 bg-white p-6 rounded-lg shadow-md">
                <div class="flex justify-between items-center mb-4 border-b pb-2">
                    <h3 class="text-lg font-semibold">Jurnal Kas Harian</h3>
                    <button id="refreshBtn" class="bg-gray-200 hover:bg-gray-300
text-gray-800 font-bold py-2 px-4 rounded-lg transition duration-300">
                        Refresh Data
                    </button>
                </div>
                <div class="overflow-x-auto max-h-[600px]">
                    <table id="kasTable" class="min-w-full divide-y divide-gray-
200">
                        <thead class="bg-gray-50 sticky top-0">
                            <tr>
                                 <th class="px-6 py-3 text-left text-xs font-medium
text-gray-500 uppercase tracking-wider">Tanggal</th>
                                 <th class="px-6 py-3 text-left text-xs font-medium
text-gray-500 uppercase tracking-wider">Keterangan</th>
                                 <th class="px-6 py-3 text-left text-xs font-medium
text-gray-500 uppercase tracking-wider">Masuk</th>
                                 <th class="px-6 py-3 text-left text-xs font-medium
text-gray-500 uppercase tracking-wider">Keluar</th>
                                 <th class="px-6 py-3 text-left text-xs font-medium
text-gray-500 uppercase tracking-wider">Sisa Saldo</th>
                            </tr>
                        </thead>
                        <tbody id="kasTableBody" class="bg-white divide-y divide-
gray-200">
                             <tr><td colspan="5" class="text-center p-8">Memuat
data...</td></tr>
                         </tbody>
                     </table>
                 </div>
             </div>
        </main>
    </div>
    <script>
        function showLoader()
{ document.getElementById('loader').classList.remove('hidden'); }
        function hideLoader()
{ document.getElementById('loader').classList.add('hidden'); }
        function loadKasData() {
            showLoader();
            google.script.run
                .withSuccessHandler(data => {
                    const tableBody = document.getElementById('kasTableBody');
                    tableBody.innerHTML = '';
                    if (data && data.length > 0) {
                        data.reverse().forEach(row => {
                            const tr = document.createElement('tr');
                            let formattedDate = 'Tanggal tidak valid'; // Teks
default jika tanggal bermasalah
                            // Periksa apakah ada nilai tanggal (tidak null atau
undefined)
                            if (row && row[1]) {
                                const dateObj = new Date(row[1]);
                                // Periksa apakah objek tanggal yang dibuat valid
sebelum diformat
                                if (!isNaN(dateObj.getTime())) {
                                    formattedDate = dateObj.toLocaleDateString('id-
ID', { day: '2-digit', month: 'short', year: 'numeric' });
                                }
                            }
                             tr.innerHTML = `
                                 <td class="px-6 py-4 whitespace-nowrap text-sm
text-gray-900">${formattedDate}</td>
                                 <td class="px-6 py-4 whitespace-nowrap text-sm
text-gray-900">${row[2]}</td>
                                 <td class="px-6 py-4 whitespace-nowrap text-sm
text-green-600 text-right">${formatRupiah(row[3])}</td>
                                 <td class="px-6 py-4 whitespace-nowrap text-sm
text-red-600 text-right">${formatRupiah(row[4])}</td>
                                 <td class="px-6 py-4 whitespace-nowrap text-sm
text-gray-900 font-medium text-right">${formatRupiah(row[5])}</td>
                             `;
                             tableBody.appendChild(tr);
                        });
                    } else {
                        tableBody.innerHTML = '<tr><td colspan="5" class="text-
center p-8 text-gray-500">Belum ada data transaksi.</td></tr>';
                    }
                    hideLoader();
                })
                .withFailureHandler(err => {
                    Swal.fire('Error Memuat Data', err.message, 'error');
                    hideLoader();
                })
                .getKasData();
        }
        function formatRupiah(angka) {
            return new Intl.NumberFormat('id-ID', { style: 'currency', currency:
'IDR', minimumFractionDigits: 0 }).format(angka);
        }
        function downloadPdf(base64Data, fileName) {
            const byteCharacters = atob(base64Data);
            const byteNumbers = new Array(byteCharacters.length);
            for (let i = 0; i < byteCharacters.length; i++) {
                byteNumbers[i] = byteCharacters.charCodeAt(i);
            }
            const byteArray = new Uint8Array(byteNumbers);
            const blob = new Blob([byteArray], { type: 'application/pdf' });
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = fileName;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
        document.addEventListener('DOMContentLoaded', () => {
            if (typeof google === 'undefined' || !google.script.run) {
                hideLoader();
                Swal.fire({
                     icon: 'error',
                     title: 'Koneksi Gagal',
                     text: 'Aplikasi tidak dapat terhubung ke server. Pastikan Anda
membuka dari URL Web App yang benar.',
                     footer: 'Kesalahan: "google.script.run" tidak ditemukan.'
                });
                document.querySelectorAll('button, input').forEach(el =>
el.disabled = true);
                document.getElementById('kasTableBody').innerHTML = '<tr><td
colspan="5" class="text-center p-8 text-red-500">Koneksi ke server
gagal.</td></tr>';
                return;
            }
            document.getElementById('tanggal').valueAsDate = new Date();
            document.getElementById('filterTahun').value = new
Date().getFullYear();
            loadKasData();
            document.getElementById('kasForm').addEventListener('submit',
function(e) {
                e.preventDefault();
                showLoader();
                    const formData = {
                        tanggal: this.tanggal.value,
                        keterangan: this.keterangan.value,
                        masuk: this.masuk.value,
                        keluar: this.keluar.value
                    };
                    google.script.run
                        .withSuccessHandler(response => {
                            Swal.fire('Sukses!', response, 'success');
                            this.reset();
                            document.getElementById('tanggal').valueAsDate = new
Date();
                            loadKasData();
                        })
                        .withFailureHandler(err => {
                            Swal.fire('Gagal Menyimpan', err.message, 'error');
                            hideLoader();
                        })
                        .addKasData(formData);
              });
            document.getElementById('refreshBtn').addEventListener('click',
loadKasData);
              document.getElementById('btnCetakBulan').addEventListener('click', ()
=> {
                    const monthInput = document.getElementById('filterBulan').value;
                    if (!monthInput) {
                        Swal.fire('Perhatian', 'Silakan pilih bulan terlebih dahulu.',
'warning');
                    return;
                }
                const [year, month] = monthInput.split('-');
                const startDate = new Date(year, month - 1, 1);
                const endDate = new Date(year, month, 0);
                const reportTitle = `Bulan ${startDate.toLocaleString('id-ID',
{ month: 'long', year: 'numeric' })}`;
                showLoader();
                google.script.run
                    .withSuccessHandler(result => {
                        downloadPdf(result.data, result.fileName);
                        hideLoader();
                    })
                    .withFailureHandler(err => { Swal.fire('Gagal Cetak PDF',
err.message, 'error'); hideLoader(); })
                    .createPdfReport(startDate.toISOString().split('T')[0],
endDate.toISOString().split('T')[0], reportTitle);
            });
              document.getElementById('btnCetakRange').addEventListener('click', ()
=> {
                const startDate = document.getElementById('startDate').value;
                const endDate = document.getElementById('endDate').value;
                if (!startDate || !endDate) {
                     Swal.fire('Perhatian', 'Silakan isi tanggal mulai dan tanggal
akhir.', 'warning');
                     return;
                }
                   if (new Date(startDate) > new Date(endDate)) {
                      Swal.fire('Perhatian', 'Tanggal mulai tidak boleh lebih besar
dari tanggal akhir.', 'warning');
                      return;
                 }
                 const formattedStart = new Date(startDate).toLocaleDateString('id-
ID', { day: '2-digit', month: 'long', year: 'numeric' });
                 const formattedEnd = new Date(endDate).toLocaleDateString('id-ID',
{ day: '2-digit', month: 'long', year: 'numeric' });
                 const reportTitle = `Periode ${formattedStart} s/d $
{formattedEnd}`;
                showLoader();
                google.script.run
                    .withSuccessHandler(result => {
                        downloadPdf(result.data, result.fileName);
                        hideLoader();
                    })
                    .withFailureHandler(err => { Swal.fire('Gagal Cetak PDF',
err.message, 'error'); hideLoader(); })
                    .createPdfReport(startDate, endDate, reportTitle);
            });
            document.getElementById('btnCetakTahun').addEventListener('click', ()
=> {
                const year = document.getElementById('filterTahun').value;
                if (!year) {
                      Swal.fire('Perhatian', 'Silakan masukkan tahun terlebih
dahulu.', 'warning');
                    return;
                }
                showLoader();
                google.script.run
                    .withSuccessHandler(result => {
                         downloadPdf(result.data, result.fileName);
                         hideLoader();
                    })
                    .withFailureHandler(err => { Swal.fire('Gagal Cetak PDF',
err.message, 'error'); hideLoader(); })
                    .createYearlyRecap(year);
            });
        });
    </script>
</body>
</html>
//KODE GS
// ===============================================================
//                KONFIGURASI GOOGLE SHEET
// ===============================================================
const SHEET_ID = '1vBZY6VuhIhD_z-aZ05Dq4bXw8EgXRKI1CTNAPLiacZ8';
const SHEET_NAME = 'Kas';
// ===============================================================
//          FUNGSI UTAMA UNTUK MENAMPILKAN WEB APP
// ===============================================================
function doGet() {
    return HtmlService.createHtmlOutputFromFile('index')
      .setTitle('Buku Kas TPQ Al Qurabiy')
      .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.DEFAULT);
}
// ===============================================================
//           FUNGSI UNTUK MENGAMBIL SEMUA DATA KAS
// ===============================================================
function getKasData() {
   try {
     const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(SHEET_NAME);
     const dataRange = sheet.getDataRange();
     const values = dataRange.getValues().slice(1); // Ambil semua data kecuali
header
    // **PERBAIKAN KRUSIAL:**
    // Memastikan semua tanggal dikonversi ke format standar (ISO String)
    // sebelum dikirim ke aplikasi web. Ini menangani kasus di mana
    // Google Sheet mungkin mengirim tanggal sebagai string atau objek Date.
    return values.map(row => {
      const originalDate = row[1]; // Kolom Tanggal ada di indeks 1
      if (originalDate) {
        // Coba buat objek Date yang valid dari nilai apa pun di sel
        const dateObj = new Date(originalDate);
        // Jika berhasil (bukan tanggal yang tidak valid), ubah ke format ISO
lengkap
        if (dateObj && !isNaN(dateObj.getTime())) {
          row[1] = dateObj.toISOString();
        } else {
          // Jika tidak bisa di-parse, kirim null agar tidak menyebabkan error di
aplikasi web
          row[1] = null;
        }
      }
      return row;
    });
  } catch (e) {
    throw new Error('Gagal mengambil data dari Google Sheet. Pastikan ID Sheet dan
nama Sheet sudah benar. Error: ' + e.message);
  }
}
// ===============================================================
//             FUNGSI UNTUK MENAMBAHKAN DATA BARU
// ===============================================================
function addKasData(formData) {
   try {
     const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(SHEET_NAME);
     const lastRow = sheet.getLastRow();
      let saldoSebelumnya = 0;
      if (lastRow > 1) {
        saldoSebelumnya = parseFloat(sheet.getRange(lastRow, 6).getValue()) || 0;
      }
      const masuk = parseFloat(formData.masuk) || 0;
      const keluar = parseFloat(formData.keluar) || 0;
      const sisaSaldo = saldoSebelumnya + masuk - keluar;
      const newRow = [
         new Date(), // Timestamp (Kolom A)
         new Date(formData.tanggal), // Tanggal (Kolom B)
         formData.keterangan, // Keterangan (Kolom C)
         masuk, // Masuk (Kolom D)
         keluar, // Keluar (Kolom E)
         sisaSaldo // Sisa (Kolom F)
      ];
      sheet.appendRow(newRow);
      return 'Transaksi berhasil disimpan!';
    } catch (e) {
      throw new Error('Gagal menyimpan data ke Google Sheet. Error: ' + e.message);
    }
}
// ===============================================================
//          FUNGSI UNTUK MEMBUAT LAPORAN PDF (BULANAN/RANGE)
// ===============================================================
function createPdfReport(startDate, endDate, reportTitle) {
   const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(SHEET_NAME);
   const allData = sheet.getDataRange().getValues().slice(1);
    const start = new Date(startDate);
    start.setHours(0, 0, 0, 0);
    const end = new Date(endDate);
    end.setHours(23, 59, 59, 999);
  const filteredData = allData.filter(row => {
    if (!row[1] || isNaN(new Date(row[1]).getTime())) return false; // Lewati baris
dengan tanggal tidak valid
    const rowDate = new Date(row[1]);
    return rowDate >= start && rowDate <= end;
  });
    if (filteredData.length === 0) {
      throw new Error('Tidak ada data transaksi pada periode yang dipilih.');
    }
  let saldoAwal = 0;
  // Mencari saldo awal dari baris sebelum transaksi pertama yang difilter
  const firstTransactionTimestamp = filteredData[0][0];
  const firstTransactionIndexInAllData = allData.findIndex(row => new
Date(row[0]).getTime() === new Date(firstTransactionTimestamp).getTime());
    if (firstTransactionIndexInAllData > 0) {
      saldoAwal = parseFloat(allData[firstTransactionIndexInAllData - 1][5]) || 0;
    }
    let totalMasuk = 0;
    let totalKeluar = 0;
    let rowsHtml = filteredData.map(row => {
      const tanggal = new Date(row[1]).toLocaleDateString('id-ID');
      const masuk = parseFloat(row[3] || 0);
      const keluar = parseFloat(row[4] || 0);
      totalMasuk += masuk;
    totalKeluar += keluar;
    return `
       <tr>
         <td>${tanggal}</td>
         <td>${row[2]}</td>
         <td class="currency">${formatRupiah(masuk)}</td>
         <td class="currency">${formatRupiah(keluar)}</td>
       </tr>
    `;
  }).join('');
  const saldoAkhir = saldoAwal + totalMasuk - totalKeluar;
  const htmlContent = `
    <html>
      <head>
        <style>
           body { font-family: 'Helvetica', 'Arial', sans-serif; font-size: 10pt;
color: #333; }
           .header { text-align: center; margin-bottom: 20px; border-bottom: 2px
solid #000; padding-bottom: 10px; }
           .header h1 { margin: 0; font-size: 16pt; }
           .header h2 { margin: 0; font-size: 14pt; font-weight: normal; }
           .header p { margin: 5px 0 0; font-size: 9pt; }
           .report-title { text-align: center; margin-bottom: 20px; font-size: 12pt;
font-weight: bold; text-decoration: underline;}
           table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
           th, td { border: 1px solid #999; padding: 6px; text-align: left; }
           th { background-color: #f2f2f2; font-weight: bold; }
           .summary-table { width: 50%; margin-left: 50%; }
           .summary-table td { border: none; }
           .currency { text-align: right; }
           .footer { margin-top: 40px; font-size: 10pt; }
           .signatures { margin-top: 60px; width: 100%; text-align: center; }
           .signature-box { display: inline-block; width: 45%; }
        </style>
      </head>
      <body>
        <div class="header">
           <h1>BUKU KAS</h1>
           <h2>TAMAN PENDIDIKAN AL-QUR'AN AL QURABIY</h2>
           <p>Balongcino, Desa Blaru, Kecamatan Badas, Kab. Kediri</p>
        </div>
        <div class="report-title">LAPORAN KAS ${reportTitle.toUpperCase()}</div>
        <table>
           <thead>
             <tr>
               <th>Tanggal</th>
               <th>Keterangan</th>
               <th>Pemasukan</th>
               <th>Pengeluaran</th>
             </tr>
           </thead>
           <tbody>
             <tr>
               <td colspan="2"><b>Saldo Awal</b></td>
               <td class="currency"
colspan="2"><b>${formatRupiah(saldoAwal)}</b></td>
             </tr>
             ${rowsHtml}
           </tbody>
         </table>
         <table class="summary-table">
           <tr><td>Total Pemasukan</td><td class="currency">$
{formatRupiah(totalMasuk)}</td></tr>
           <tr><td>Total Pengeluaran</td><td class="currency">$
{formatRupiah(totalKeluar)}</td></tr>
           <tr><td><b>Saldo Akhir</b></td><td class="currency"><b>$
{formatRupiah(saldoAkhir)}</b></td></tr>
         </table>
         <div class="footer">
           <p>Balongcino, ${new Date().toLocaleDateString('id-ID', {day:'2-digit',
month:'long', year:'numeric'})}</p>
           <div class="signatures">
             <div class="signature-box">
                <p>Bendahara,</p>
                <br><br><br>
                <p>(___________________)</p>
             </div>
             <div class="signature-box">
                <p>Ketua,</p>
                <br><br><br>
                <p>(___________________)</p>
             </div>
           </div>
         </div>
       </body>
     </html>
  `;
    const blob = Utilities.newBlob(htmlContent, MimeType.HTML).getAs(MimeType.PDF);
    const fileName = `Laporan_Kas_${reportTitle.replace(/ /g, '_')}.pdf`;
    return {
       data: Utilities.base64Encode(blob.getBytes()),
       fileName: fileName
    };
}
// ===============================================================
//           FUNGSI UNTUK MEMBUAT REKAP TAHUNAN
// ===============================================================
function createYearlyRecap(year) {
   const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(SHEET_NAME);
   const allData = sheet.getDataRange().getValues().slice(1);
    const filteredData = allData.filter(row => {
      if (!row[1] || isNaN(new Date(row[1]).getTime())) return false;
      return new Date(row[1]).getFullYear() == year
    });
    if (filteredData.length === 0) {
      throw new Error(`Tidak ada data transaksi pada tahun ${year}.`);
    }
    const monthlyRecap = Array(12).fill(0).map(() => ({ masuk: 0, keluar: 0 }));
    filteredData.forEach(row => {
      const month = new Date(row[1]).getMonth(); // 0 = Januari, 11 = Desember
    monthlyRecap[month].masuk += parseFloat(row[3] || 0);
    monthlyRecap[month].keluar += parseFloat(row[4] || 0);
  });
  let totalMasukTahunan = 0;
  let totalKeluarTahunan = 0;
  const monthNames = ["Januari", "Februari", "Maret", "April", "Mei", "Juni",
"Juli", "Agustus", "September", "Oktober", "November", "Desember"];
  let rowsHtml = monthlyRecap.map((recap, index) => {
    totalMasukTahunan += recap.masuk;
    totalKeluarTahunan += recap.keluar;
    return `
       <tr>
         <td>${monthNames[index]}</td>
         <td class="currency">${formatRupiah(recap.masuk)}</td>
         <td class="currency">${formatRupiah(recap.keluar)}</td>
       </tr>
    `;
  }).join('');
  const htmlContent = `
    <html>
      <head>
        <style>
           body { font-family: 'Helvetica', 'Arial', sans-serif; font-size: 10pt;
color: #333; }
           .header { text-align: center; margin-bottom: 20px; border-bottom: 2px
solid #000; padding-bottom: 10px; }
           .header h1 { margin: 0; font-size: 16pt; }
           .header h2 { margin: 0; font-size: 14pt; font-weight: normal; }
           .header p { margin: 5px 0 0; font-size: 9pt; }
           .report-title { text-align: center; margin-bottom: 20px; font-size: 12pt;
font-weight: bold; text-decoration: underline;}
           table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
           th, td { border: 1px solid #999; padding: 6px; text-align: left; }
           th { background-color: #f2f2f2; font-weight: bold; }
           .currency { text-align: right; }
           .footer { margin-top: 40px; font-size: 10pt; }
           .signatures { margin-top: 60px; width: 100%; text-align: center; }
           .signature-box { display: inline-block; width: 45%; }
        </style>
      </head>
      <body>
        <div class="header">
           <h1>REKAP KAS TAHUNAN</h1>
           <h2>TAMAN PENDIDIKAN AL-QUR'AN AL QURABIY</h2>
           <p>Balongcino, Desa Blaru, Kecamatan Badas, Kab. Kediri</p>
        </div>
        <div class="report-title">TAHUN ${year}</div>
        <table>
           <thead>
             <tr>
               <th>Bulan</th>
               <th>Total Pemasukan</th>
               <th>Total Pengeluaran</th>
             </tr>
           </thead>
           <tbody>
             ${rowsHtml}
             <tr>
                <td><b>TOTAL</b></td>
                <td class="currency"><b>${formatRupiah(totalMasukTahunan)}</b></td>
                <td class="currency"><b>${formatRupiah(totalKeluarTahunan)}</b></td>
             </tr>
           </tbody>
         </table>
         <div class="footer">
           <p>Balongcino, ${new Date().toLocaleDateString('id-ID', {day:'2-digit',
month:'long', year:'numeric'})}</p>
           <div class="signatures">
             <div class="signature-box">
                <p>Bendahara,</p>
                <br><br><br>
                <p>(___________________)</p>
             </div>
             <div class="signature-box">
                <p>Ketua,</p>
                <br><br><br>
                <p>(___________________)</p>
             </div>
           </div>
         </div>
       </body>
     </html>
  `;
    const blob = Utilities.newBlob(htmlContent, MimeType.HTML).getAs(MimeType.PDF);
    const fileName = `Rekap_Kas_Tahunan_${year}.pdf`;
    return {
       data: Utilities.base64Encode(blob.getBytes()),
       fileName: fileName
    };
}
// ===============================================================
//                  FUNGSI BANTUAN (HELPER)
// ===============================================================
function formatRupiah(angka) {
   if (angka === null || angka === undefined || isNaN(parseFloat(angka))) {
     return "Rp 0";
   }
   return "Rp " + parseFloat(angka).toLocaleString('id-ID');
}