N
G
Financial System

Cash Management System.

CodeIgniter 4 Recurring Engine Budget Controlling Multi-Wallet Logic

The Challenge

Kebanyakan aplikasi keuangan hanya mencatat masa lalu (*history*) tanpa memberi kendali untuk masa depan. Pengguna sering lupa mencatat tagihan rutin bulanan atau tidak menyadari bahwa saldo di dompet (*e-wallet*) mereka berbeda dengan saldo Bank aslinya.

Technical Solution

Saya mengimplementasikan Recurring Transaction Engine yang berjalan via CRON Job untuk otomatis mencatat transaksi berulang (seperti langganan Netflix/Spotify).

Selain itu, sistem Multi-Wallet memastikan saldo terpisah secara logis antar akun (Bank, Cash, E-wallet) namun tetap teragregasi secara mulus di dalam satu antarmuka dashboard utama.

Database Logic (Schema Analysis)

Berdasarkan skema `db_cashmanagement.sql`, struktur data dirancang untuk fleksibilitas tinggi. Tabel `recurring_transactions` menyimpan jadwal tagihan, sementara `transfers` mencatat perpindahan uang antar dompet tanpa dianggap sebagai pengeluaran nyata (*Zero-Sum Game*).

  • Soft Deletes: Menggunakan `is_active` flag di tabel *recurring* untuk mencegah kehilangan data riwayat ketika pengguna menghapus jadwal tagihan.
  • Budget Constraints: Tabel `budgets` terhubung secara relasional ke tabel `categories` untuk memicu peringatan jika pengeluaran melebihi batas (70% Warning, 90% Alert).

Recurring Table Structure:

TABLE recurring_transactions (
  id INT PK,
  frequency ENUM('daily', 'monthly'),
  day_of_month TINYINT,
  last_executed DATE,
  is_active TINYINT DEFAULT 1
);
TransactionController.php (Key Logic: Atomic Transfer)

Fitur Transfer antar dompet menggunakan ACID Transaction untuk menjamin konsistensi data. Uang tidak akan pernah hilang ataupun terduplikasi jika terjadi koneksi terputus di tengah proses pertukaran saldo.

public function transferBalance() {
    $this->db->transStart(); // Mulai Transaksi ACID

    try {
        // 1. Kurangi Saldo Pengirim
        $this->walletModel->deductBalance($fromId, $amount);

        // 2. Tambah Saldo Penerima
        $this->walletModel->addBalance($toId, $amount);

        // 3. Catat di Tabel Transfers (Bukan Transactions/Pengeluaran)
        $this->transferModel->save([
            'from_account_id' => $fromId,
            'to_account_id' => $toId,
            'amount' => $amount
        ]);

        $this->db->transComplete(); // Commit perubahan
    } catch (\Exception $e) {
        // Auto Rollback: batalkan semua query jika terjadi satu saja error
        log_message('error', 'Transfer failed: ' . $e->getMessage());
    }
}