load->model('DynamicModel', 'dm'); if (!$this->session->userdata('logged_in')) { redirect('auth'); } } public function index() { if($this->session->userdata('role') != 'Admin'){ show_error('Akses ditolak', 403); } $data = ["active_menu" => "buku_besar"]; $this->load->view('partials/header', $data); $this->load->view('buku_besar/layout'); $this->load->view('partials/footer'); } // ========================= // GET ACCOUNTS (FILTER) // ========================= public function get_accounts() { $data = $this->dm->setTable('accounts') ->where(array('company_id'=>(int)$this->companycontext->id(),'is_active'=>1,'allow_posting'=>1)) ->order_by('kode_akun','ASC') ->get(); echo json_encode($data); } // ========================= // GET DATA BUKU BESAR // ========================= public function get_data() { $account_id = (int) $this->input->get('account_id'); $start = (string) ($this->input->get('start_date') ?: date('Y-m-01')); $end = (string) ($this->input->get('end_date') ?: date('Y-m-d')); $companyId = (int) $this->companycontext->id(); if (!$account_id || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $start) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $end) || $end < $start) { return $this->output->set_content_type('application/json')->set_status_header(422)->set_output(json_encode(array('status'=>false,'message'=>'Akun dan periode Buku Besar tidak valid.'))); } $account = $this->db->get_where('accounts', array('id'=>$account_id,'company_id'=>$companyId))->row(); if (!$account) { return $this->output->set_content_type('application/json')->set_status_header(404)->set_output(json_encode(array('status'=>false,'message'=>'Akun tidak ditemukan pada perusahaan aktif.'))); } $openingRow = $this->db->select('COALESCE(SUM(journal_details.debit),0) debit,COALESCE(SUM(journal_details.kredit),0) kredit', false) ->from('journal_details')->join('journals','journals.id=journal_details.journal_id') ->where(array('journals.company_id'=>$companyId,'journal_details.account_id'=>$account_id)) ->where_in('journals.status', array('posted','reversed'))->where('journals.tanggal <', $start)->get()->row(); $normalDebit = in_array($account->tipe, array('asset','expense'), true); $opening = $normalDebit ? (float)$openingRow->debit-(float)$openingRow->kredit : (float)$openingRow->kredit-(float)$openingRow->debit; $this->db->select(' journals.tanggal, journals.no_ref, journals.keterangan, journal_details.debit, journal_details.kredit, accounts.nama_akun, accounts.tipe '); $this->db->from('journal_details'); $this->db->join('journals','journals.id = journal_details.journal_id'); $this->db->join('accounts','accounts.id = journal_details.account_id'); $this->db->where_in('journals.status', array('posted', 'reversed')); $this->db->where('journals.company_id', $companyId); $this->db->where('journal_details.account_id', $account_id); $this->db->where('journals.tanggal >=', $start); $this->db->where('journals.tanggal <=', $end); // 🔥 FILTER DEBIT/KREDIT TIDAK BOLEH 0 SEMUA $this->db->group_start(); $this->db->where('journal_details.debit >', 0); $this->db->or_where('journal_details.kredit >', 0); $this->db->group_end(); $this->db->order_by('journals.tanggal','ASC')->order_by('journals.id','ASC')->order_by('journal_details.id','ASC'); $rows = $this->db->get()->result(); // ========================= // HITUNG SALDO BERJALAN // ========================= $saldo = $opening; $totalDebit = 0; $totalKredit = 0; $result = []; foreach ($rows as $r) { // LOGIKA SALDO BERDASARKAN TIPE AKUN if (in_array($r->tipe, ['asset','expense'])) { $saldo += ($r->debit - $r->kredit); } else { $saldo += ($r->kredit - $r->debit); } $totalDebit += (float) $r->debit; $totalKredit += (float) $r->kredit; $result[] = [ 'tanggal' => $r->tanggal, 'no_ref' => $r->no_ref, 'keterangan' => $r->keterangan, 'debit' => $r->debit, 'kredit' => $r->kredit, 'saldo' => $saldo ]; } return $this->output->set_content_type('application/json')->set_output(json_encode(array( 'status'=>true, 'data'=>$result, 'summary'=>array( 'saldo_awal'=>round($opening,2), 'total_debit'=>round($totalDebit,2), 'total_kredit'=>round($totalKredit,2), 'saldo_akhir'=>round($saldo,2), ), ))); } }