Lompat ke konten Lompat ke sidebar Lompat ke footer

Source Code Aplikasi Laporan Laba Rugi Usaha Ayam Petelur

Manajemen Keuangan Digital

Source Code Laporan Laba Rugi Usaha Ayam Petelur

Mengelola keuangan usaha ayam petelur kini tidak lagi rumit. Dengan bantuan teknologi cloud, Anda dapat mencatat setiap transaksi penjualan telur dan pembelian pakan secara real-time. Artikel ini membagikan source code aplikasi berbasis Google Apps Script yang elegan dan mudah digunakan.

Apa itu Laporan Laba Rugi?

Laba Rugi adalah bagian dari laporan keuangan suatu perusahaan yang dihasilkan pada suatu periode akuntansi yang menjabarkan unsur-unsur pendapatan dan beban perusahaan sehingga menghasilkan suatu laba (atau rugi) bersih.

  • Laba: Terjadi jika total pendapatan lebih besar dari total biaya operasional.
  • Rugi: Terjadi jika biaya operasional membengkak melebihi pemasukan dari penjualan.

Mengenal Usaha Ayam Petelur

Usaha ayam petelur adalah bisnis peternakan yang berfokus pada produksi telur konsumsi. Keberhasilan usaha ini sangat bergantung pada manajemen pakan, kesehatan ayam, dan yang paling krusial adalah pencatatan arus kas. Mengingat harga pakan yang fluktuatif, peternak harus tahu persis berapa margin keuntungan per kilogram telur yang dihasilkan.

Apa itu Google Apps Script (GAS)?

Google Apps Script adalah bahasa pemrograman berbasis JavaScript yang dikembangkan oleh Google untuk pengembangan aplikasi ringan di ekosistem Google Workspace. Dengan GAS, kita bisa menyulap Google Sheets menjadi database yang canggih dengan tampilan antarmuka web (Web App).

Langkah-Langkah Implementasi

1
Buka Google Sheets baru dan beri nama "AyamLayer Pro". Salin ID Spreadsheet di URL (antara /d/ dan /edit).
2
Klik menu Extensions > Apps Script.
3
Buat file baru bernama Code.gs dan tempelkan Kode GS di bawah ini. Jangan lupa ganti SPREADSHEET_ID dengan ID milik Anda.
4
Klik tombol (+) di Apps Script, pilih HTML, beri nama index, dan tempelkan Kode Index HTML.
5
Klik Deploy > New Deployment. Pilih tipe "Web App", set "Who has access" ke "Anyone", lalu klik Deploy.
File: Code.gs
/**
 * AyamLayer Pro - Cloud Edition (Optimized)
 */

const SPREADSHEET_ID = "1rHoFZEsluITUD2ipnJJ7fUX8IgNQQaj1w5dPEVUjdBM";

function doGet() {
  return HtmlService.createTemplateFromFile('index')
    .evaluate()
    .setTitle('AyamLayer Pro - Cloud')
    .addMetaTag('viewport', 'width=device-width, initial-scale=1')
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

function getSheet() {
  let ss;
  try {
    ss = SpreadsheetApp.openById(SPREADSHEET_ID);
  } catch (e) {
    throw new Error("Akses Spreadsheet Ditolak. Periksa ID dan Izin.");
  }

  let sheet = ss.getSheetByName("Data_Transaksi");
  if (!sheet) {
    sheet = ss.insertSheet("Data_Transaksi");
    const headers = ["ID", "TANGGAL", "WAKTU", "JENIS", "KATEGORI", "NOMINAL", "KETERANGAN"];
    sheet.getRange(1, 1, 1, headers.length).setValues([headers])
         .setFontWeight("bold")
         .setBackground("#f59e0b")
         .setFontColor("white")
         .setHorizontalAlignment("center");
    sheet.setFrozenRows(1);
  }
  return sheet;
}

function saveTransaction(data) {
  try {
    const sheet = getSheet();
    const uniqueId = "TRX-" + Utilities.getUuid().substring(0, 8).toUpperCase();
    
    const dateParts = data.date.split('-'); 
    const dateObj = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);

    sheet.appendRow([
      uniqueId,
      dateObj,
      data.time,
      data.type,
      data.category,
      Number(data.amount) || 0,
      data.note || "-"
    ]);
    
    SpreadsheetApp.flush();
    return { success: true, id: uniqueId };
  } catch (e) {
    return { success: false, error: e.toString() };
  }
}

function getTransactions() {
  try {
    const sheet = getSheet();
    const values = sheet.getDataRange().getValues();
    if (values.length <= 1) return [];

    const headers = values[0].map(h => h.toString().toLowerCase().trim());
    const rows = values.slice(1);

    return rows
      .filter(row => row[0]) 
      .map(row => {
        let obj = {};
        headers.forEach((header, i) => {
          let val = row[i];
          if (val instanceof Date) {
            val = Utilities.formatDate(val, Session.getScriptTimeZone(), "yyyy-MM-dd");
          }
          if (header === 'nominal') val = Number(val) || 0;
          obj[header] = val;
        });
        return obj;
      }).reverse();
  } catch (e) {
    return [];
  }
}

function deleteTransactionById(id) {
  try {
    const sheet = getSheet();
    const data = sheet.getDataRange().getValues();
    for (let i = 1; i < data.length; i++) {
      if (data[i][0].toString() === id.toString()) {
        sheet.deleteRow(i + 1);
        return { success: true };
      }
    }
    return { success: false, error: "Data tidak ditemukan." };
  } catch (e) {
    return { success: false, error: e.toString() };
  }
}
File: index.html
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AyamLayer Pro - Finansial Cloud</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;600;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    
    <style>
        :root { --primary-gold: #f59e0b; --primary-dark: #1e293b; }
        body { font-family: 'Plus Jakarta Sans', sans-serif; background: #f8fafc; color: var(--primary-dark); }
        .card { border: none; border-radius: 15px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); }
        .btn-gold { background: var(--primary-gold); color: white; border-radius: 10px; font-weight: 700; border: none; }
        .btn-gold:hover { background: #d97706; color: white; }
        #loader { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.8); backdrop-filter: blur(5px); display: none; flex-direction: column; justify-content: center; align-items: center; z-index: 9999; }
        .nav-custom { background: var(--primary-dark); color: white; }
        .chart-container { position: relative; height: 250px; width: 100%; }
    </style>
</head>
<body>
<!-- Aplikasi Berjalan di Sini -->
</body>
</html>