Langsung ke konten utama

Kodegs

const SHEET_SETTINGS = "SETTINGS"; const SHEET_TRX = "TRANSAKSI"; /* ===== WEB APP ===== */ function doGet(){ return HtmlService.createHtmlOutputFromFile("Index") .setTitle("Dashboard Konter") .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL); } /* ===== SETTINGS HELPERS ===== */ function _getSettingsSheet(){ const ss = SpreadsheetApp.getActive(); let sh = ss.getSheetByName(SHEET_SETTINGS); if (!sh){ sh = ss.insertSheet(SHEET_SETTINGS); sh.getRange("A1:B1").setValues([["KEY","VALUE"]]); sh.getRange("A2:B3").setValues([["SALDO_AWAL_BANK",0],["SALDO_AWAL_CASH",0]]); } return sh; } function _getSetting(key, def){ const sh = _getSettingsSheet(); const v = sh.getDataRange().getValues(); for (let i=1;i= a && t <= b; } /* ===== API: SALDO AWAL ===== */ function api_getSaldoAwal(){ const bank = _getSetting("SALDO_AWAL_BANK", 0); const cash = _getSetting("SALDO_AWAL_CASH", 0); return { bank, cash }; } function api_setSaldoAwal(data){ const bank = Number(data.bank || 0); const cash = Number(data.cash || 0); _setSetting("SALDO_AWAL_BANK", bank); _setSetting("SALDO_AWAL_CASH", cash); _appendTrx_([new Date(),"SALDO_AWAL",0,0,"","",0,0,0,0,"Set saldo awal"]); return true; } /* ===== API: SETOR/TARIK ===== */ function api_setorTarik(data){ let bank = _getSetting("SALDO_AWAL_BANK", 0); let cash = _getSetting("SALDO_AWAL_CASH", 0); const nominal = Number(data.nominal || 0); const jenis = String(data.jenis || "").toUpperCase(); const catatan = String(data.catatan || ""); let dCash = 0, dBank = 0; if (jenis === "SETOR"){ dCash = -nominal; dBank = +nominal; } else { dBank = -nominal; dCash = +nominal; } bank += dBank; cash += dCash; _setSetting("SALDO_AWAL_BANK", bank); _setSetting("SALDO_AWAL_CASH", cash); _appendTrx_([new Date(),"SETOR_TARIK",nominal,0,"",jenis,dCash,dBank,nominal,0,catatan]); return { bank, cash }; } /* ===== API: TOPUP DANA ===== */ function api_topupDana(data){ let bank = _getSetting("SALDO_AWAL_BANK", 0); let cash = _getSetting("SALDO_AWAL_CASH", 0); const nominal = Number(data.nominal || 0); const admin = Number(data.admin || 0); const posisi = String(data.posisi || "LUAR"); const bayar = String(data.bayar || "CASH"); const catatan = String(data.catatan || ""); const totalBayar = posisi === "LUAR" ? nominal + admin : nominal; let dCash = 0, dBank = 0; if (bayar === "BANK") dBank += totalBayar; else dCash += totalBayar; bank += dBank; cash += dCash; _setSetting("SALDO_AWAL_BANK", bank); _setSetting("SALDO_AWAL_CASH", cash); _appendTrx_([new Date(),"TOPUP_DANA",nominal,admin,posisi,bayar,dCash,dBank,totalBayar,admin,catatan]); return { bank, cash, totalBayar, profit: admin }; } /* ===== DASHBOARD (KPI + SALDO) ===== */ function api_getDashboard(){ const saldo = api_getSaldoAwal(); const today = new Date(); today.setHours(0,0,0,0); const sh = _getTrxSheet(); const last = sh.getLastRow(); let omset = 0, profit = 0, count = 0; if (last > 1){ const data = sh.getRange(2,1,last-1,11).getValues(); data.forEach(r=>{ const ts = r[0]; const jenis = String(r[1]||""); const totalBayar = Number(r[8]||0); const pr = Number(r[9]||0); if (_toDateOnly_(ts) === today.getTime()){ // Omset: hitung transaksi jual/topup (setor/tarik tidak dihitung omset) if (jenis === "TOPUP_DANA"){ omset += totalBayar; profit += pr; count++; } } }); } return { saldo, kpi:{ omset, profit, count } }; } /* ===== RIWAYAT (dengan search q) ===== */ function api_listRiwayat(payload){ const q = String(payload?.q || "").toLowerCase().trim(); const sh = _getTrxSheet(); const last = sh.getLastRow(); if (last <= 1) return []; const data = sh.getRange(2,1,last-1,11).getValues(); const rows = data.map(r=>({ ts: r[0], jenis: String(r[1]||""), total: Number(r[8]||0), profit: Number(r[9]||0), catatan: String(r[10]||"") })).reverse(); if (!q) return rows.slice(0,50); return rows.filter(x=>{ return (x.jenis.toLowerCase().includes(q) || x.catatan.toLowerCase().includes(q)); }).slice(0,50); } /* ===== LAPORAN RANGE ===== */ function api_laporanRange(payload){ const from = new Date(payload.from); const to = new Date(payload.to); from.setHours(0,0,0,0); to.setHours(0,0,0,0); const sh = _getTrxSheet(); const last = sh.getLastRow(); if (last <= 1) return { omset:0, profit:0, count:0, rows:[] }; const data = sh.getRange(2,1,last-1,11).getValues(); let omset = 0, profit = 0, count = 0; const rows = []; data.forEach(r=>{ const ts = r[0]; const jenis = String(r[1]||""); const totalBayar = Number(r[8]||0); const pr = Number(r[9]||0); const catatan = String(r[10]||""); if (_inRange_(ts, from, to)){ rows.push({ ts, jenis, total: totalBayar, profit: pr, catatan }); if (jenis === "TOPUP_DANA"){ omset += totalBayar; profit += pr; count++; } } }); rows.sort((a,b)=> new Date(b.ts) - new Date(a.ts)); return { omset, profit, count, rows }; }

Komentar

Postingan populer dari blog ini

Index

Dashboard Konter Dashboard Konter Cash & Bank Saldo Awal Topup DANA Setor/Tarik Riwayat Saldo CASH + BANK CASH Rp 0 BANK Rp 0 TOTAL Rp 0 Refresh Laporan Buka Laporan Filter tanggal + ringkasan profit & total transaksi. Saldo Awal Saldo Bank Saldo Cash Catatan: nilai ini jadi saldo dasar (bank & cash). Batal Simpan Topup DANA ...

Indext ppob

Dashboard Konter Dashboard Konter Cash & Bank — Saldo Awal Reload Omset Hari Ini Rp 0 0 transaksi Profit Hari Ini Rp 0 Admin/fee (akumulasi) Cari Tip: ketik “dana”, “setor”, “tarik”, atau catatan. Topup Setor/Tarik Riwayat Laporan (Range) Saldo CASH + BANK CASH Rp 0 BANK Rp 0 TOTAL ...