Modul 05: Admin Dashboard & CRUD Koleksi Buku

Modul 05: Admin Dashboard & CRUD Koleksi Buku

Berikut adalah seluruh berkas kode program aktual yang digunakan dalam aplikasi SIPAS tanpa potongan atau placeholder. Kode dapat dipelajari dan diketikkan langsung pada Sublime Text 3.

1

Model Dashboard Statistik (Dashboard_model.php)

Lokasi Berkas:

application/models/Dashboard_model.php

application/models/Dashboard_model.php PHP
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Dashboard_model
 * Model untuk menyajikan statistik dashboard admin & user
 */
class Dashboard_model extends CI_Model {

    public function __construct() {
        parent::__construct();
    }

    /**
     * Mengambil ringkasan statistik untuk Admin Dashboard
     */
    public function get_admin_stats() {
        // Total Judul Buku
        $total_buku = $this->db->count_all('buku');

        // Total Eksemplar Stok Seluruh Buku
        $this->db->select_sum('stok');
        $stok_query = $this->db->get('buku')->row();
        $total_stok = $stok_query->stok ? (int) $stok_query->stok : 0;

        // Total Anggota Siswa (Role = user)
        $this->db->where('role', 'user');
        $total_anggota = $this->db->count_all_results('users');

        // Total Transaksi Berstatus 'dipinjam'
        $this->db->where('status', 'dipinjam');
        $total_dipinjam = $this->db->count_all_results('transaksi');

        return [
            'total_buku' => $total_buku,
            'total_stok' => $total_stok,
            'total_anggota' => $total_anggota,
            'total_dipinjam' => $total_dipinjam
        ];
    }

    /**
     * Mengambil 5-10 transaksi terbaru untuk widget admin dashboard
     */
    public function get_recent_transactions($limit = 5) {
        $this->db->select('transaksi.*, users.nama as nama_siswa, buku.judul as judul_buku');
        $this->db->from('transaksi');
        $this->db->join('users', 'users.id = transaksi.user_id', 'left');
        $this->db->join('buku', 'buku.id = transaksi.buku_id', 'left');
        $this->db->order_by('transaksi.created_at', 'DESC');
        $this->db->limit($limit);
        return $this->db->get()->result();
    }

    /**
     * Mengambil statistik untuk Siswa / User Dashboard
     */
    public function get_user_stats($user_id) {
        // Total buku tersedia di perpustakaan (stok > 0)
        $this->db->where('stok >', 0);
        $buku_tersedia = $this->db->count_all_results('buku');

        // Total buku sedang dipinjam oleh user ini
        $this->db->where('user_id', $user_id);
        $this->db->where('status', 'dipinjam');
        $sedang_dipinjam = $this->db->count_all_results('transaksi');

        // Total buku sudah dikembalikan oleh user ini
        $this->db->where('user_id', $user_id);
        $this->db->where('status', 'dikembalikan');
        $sudah_kembali = $this->db->count_all_results('transaksi');

        return [
            'buku_tersedia' => $buku_tersedia,
            'sedang_dipinjam' => $sedang_dipinjam,
            'sudah_kembali' => $sudah_kembali
        ];
    }
}
💡 Catatan: Baris komentar (// atau /* */) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
2

Model Koleksi Buku (Buku_model.php)

Lokasi Berkas:

application/models/Buku_model.php

application/models/Buku_model.php PHP
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Buku_model
 * Model untuk pengelolaan data koleksi buku
 */
class Buku_model extends CI_Model {

    private $table = 'buku';

    public function __construct() {
        parent::__construct();
    }

    /**
     * Mengambil semua data buku
     */
    public function get_all($limit = NULL, $offset = NULL) {
        $this->db->order_by('created_at', 'DESC');
        if ($limit !== NULL) {
            $this->db->limit($limit, $offset);
        }
        return $this->db->get($this->table)->result();
    }

    /**
     * Menghitung total buku untuk pagination
     */
    public function count_all($search = NULL, $kategori = NULL) {
        if (!empty($search)) {
            $this->db->group_start();
            $this->db->like('kode_buku', $search);
            $this->db->or_like('judul', $search);
            $this->db->or_like('penulis', $search);
            $this->db->or_like('kategori', $search);
            $this->db->group_end();
        }
        if (!empty($kategori)) {
            $this->db->where('kategori', $kategori);
        }
        return $this->db->count_all_results($this->table);
    }

    /**
     * Pencarian buku dengan filter & pagination
     */
    public function search($search = NULL, $kategori = NULL, $limit = 10, $offset = 0) {
        if (!empty($search)) {
            $this->db->group_start();
            $this->db->like('kode_buku', $search);
            $this->db->or_like('judul', $search);
            $this->db->or_like('penulis', $search);
            $this->db->or_like('kategori', $search);
            $this->db->group_end();
        }
        if (!empty($kategori)) {
            $this->db->where('kategori', $kategori);
        }
        $this->db->order_by('created_at', 'DESC');
        return $this->db->get($this->table, $limit, $offset)->result();
    }

    /**
     * Mengambil daftar kategori unik buku
     */
    public function get_categories() {
        $this->db->distinct();
        $this->db->select('kategori');
        $this->db->where('kategori IS NOT NULL');
        $this->db->where("kategori != ''");
        $this->db->order_by('kategori', 'ASC');
        return $this->db->get($this->table)->result();
    }

    /**
     * Mengambil detail buku berdasarkan ID
     */
    public function get_by_id($id) {
        return $this->db->get_where($this->table, ['id' => $id])->row();
    }

    /**
     * Mengambil data buku berdasarkan Kode Buku
     */
    public function get_by_kode($kode) {
        return $this->db->get_where($this->table, ['kode_buku' => $kode])->row();
    }

    /**
     * Tambah data buku
     */
    public function create($data) {
        return $this->db->insert($this->table, $data);
    }

    /**
     * Perbarui data buku
     */
    public function update($id, $data) {
        $this->db->where('id', $id);
        return $this->db->update($this->table, $data);
    }

    /**
     * Hapus data buku
     */
    public function delete($id) {
        $this->db->where('id', $id);
        return $this->db->delete($this->table);
    }

    /**
     * Kurangi stok buku sebanyak 1
     */
    public function decrease_stock($id) {
        $this->db->set('stok', 'stok - 1', FALSE);
        $this->db->where('id', $id);
        $this->db->where('stok >', 0);
        return $this->db->update($this->table);
    }

    /**
     * Tambah stok buku sebanyak 1
     */
    public function increase_stock($id) {
        $this->db->set('stok', 'stok + 1', FALSE);
        $this->db->where('id', $id);
        return $this->db->update($this->table);
    }

    /**
     * Cek apakah buku memiliki transaksi aktif
     */
    public function has_active_transaction($buku_id) {
        $this->db->where('buku_id', $buku_id);
        $this->db->where('status', 'dipinjam');
        return $this->db->count_all_results('transaksi') > 0;
    }
}
💡 Catatan: Baris komentar (// atau /* */) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
3

Controller Kelola Buku (admin/Buku.php)

Lokasi Berkas:

application/controllers/admin/Buku.php

application/controllers/admin/Buku.php PHP
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Admin Buku Controller
 * CRUD Data Buku
 */
class Buku extends CI_Controller {

    public function __construct() {
        parent::__construct();
        check_admin();
        $this->load->model('Buku_model');
        $this->load->library('pagination');
    }

    /**
     * Daftar Buku dengan Pencarian & Pagination
     */
    public function index() {
        $search = $this->input->get('keyword', TRUE);
        $kategori = $this->input->get('kategori', TRUE);

        $limit = 10;
        $page = $this->input->get('page') ? (int) $this->input->get('page') : 1;
        $offset = ($page - 1) * $limit;

        $total_rows = $this->Buku_model->count_all($search, $kategori);

        // Konfigurasi Pagination Bootstrap 5
        $config['base_url'] = site_url('admin/buku');
        $config['total_rows'] = $total_rows;
        $config['per_page'] = $limit;
        $config['page_query_string'] = TRUE;
        $config['query_string_segment'] = 'page';
        $config['reuse_query_string'] = TRUE;

        $config['full_tag_open'] = '<nav><ul class="pagination pagination-sm mb-0">';
        $config['full_tag_close'] = '</ul></nav>';
        $config['first_link'] = '«';
        $config['first_tag_open'] = '<li class="page-item">';
        $config['first_tag_close'] = '</li>';
        $config['last_link'] = '»';
        $config['last_tag_open'] = '<li class="page-item">';
        $config['last_tag_close'] = '</li>';
        $config['next_link'] = '›';
        $config['next_tag_open'] = '<li class="page-item">';
        $config['next_tag_close'] = '</li>';
        $config['prev_link'] = '‹';
        $config['prev_tag_open'] = '<li class="page-item">';
        $config['prev_tag_close'] = '</li>';
        $config['cur_tag_open'] = '<li class="page-item active"><span class="page-link">';
        $config['cur_tag_close'] = '</span></li>';
        $config['num_tag_open'] = '<li class="page-item">';
        $config['num_tag_close'] = '</li>';
        $config['attributes'] = ['class' => 'page-link'];

        $this->pagination->initialize($config);

        $data['title'] = 'Data Buku - SIPAS';
        $data['buku'] = $this->Buku_model->search($search, $kategori, $limit, $offset);
        $data['categories'] = $this->Buku_model->get_categories();
        $data['pagination'] = $this->pagination->create_links();
        $data['total_rows'] = $total_rows;
        $data['offset'] = $offset;
        $data['limit'] = $limit;
        $data['keyword'] = $search;
        $data['selected_kategori'] = $kategori;

        $this->load->view('admin/buku/index', $data);
    }

    /**
     * Tambah Buku
     */
    public function tambah() {
        $this->form_validation->set_rules('kode_buku', 'Kode Buku', 'required|trim|is_unique[buku.kode_buku]', [
            'required' => 'Kode buku wajib diisi.',
            'is_unique' => 'Kode buku ini sudah digunakan.'
        ]);
        $this->form_validation->set_rules('judul', 'Judul Buku', 'required|trim', [
            'required' => 'Judul buku wajib diisi.'
        ]);
        $this->form_validation->set_rules('penulis', 'Penulis', 'trim');
        $this->form_validation->set_rules('penerbit', 'Penerbit', 'trim');
        $this->form_validation->set_rules('tahun_terbit', 'Tahun Terbit', 'numeric');
        $this->form_validation->set_rules('kategori', 'Kategori', 'trim');
        $this->form_validation->set_rules('stok', 'Stok', 'required|numeric|greater_than_equal_to[0]', [
            'required' => 'Stok buku wajib diisi.',
            'greater_than_equal_to' => 'Stok minimal 0.'
        ]);
        $this->form_validation->set_rules('rak', 'Lokasi Rak', 'trim');
        $this->form_validation->set_rules('deskripsi', 'Deskripsi', 'trim');

        if ($this->form_validation->run() === FALSE) {
            $data['title'] = 'Tambah Buku - SIPAS';
            $this->load->view('admin/buku/tambah', $data);
        } else {
            $insert_data = [
                'kode_buku'    => strtoupper($this->input->post('kode_buku', TRUE)),
                'judul'        => $this->input->post('judul', TRUE),
                'penulis'      => $this->input->post('penulis', TRUE),
                'penerbit'     => $this->input->post('penerbit', TRUE),
                'tahun_terbit' => $this->input->post('tahun_terbit', TRUE) ? (int)$this->input->post('tahun_terbit') : NULL,
                'kategori'     => $this->input->post('kategori', TRUE),
                'stok'         => (int)$this->input->post('stok'),
                'rak'          => $this->input->post('rak', TRUE),
                'deskripsi'    => $this->input->post('deskripsi', TRUE),
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s')
            ];

            if ($this->Buku_model->create($insert_data)) {
                $this->session->set_flashdata('success', 'Data buku berhasil ditambahkan.');
                redirect('admin/buku');
            } else {
                $this->session->set_flashdata('error', 'Gagal menambahkan data buku.');
                redirect('admin/buku/tambah');
            }
        }
    }

    /**
     * Edit Buku
     */
    public function edit($id) {
        $buku = $this->Buku_model->get_by_id($id);
        if (!$buku) {
            $this->session->set_flashdata('error', 'Data buku tidak ditemukan.');
            redirect('admin/buku');
        }

        // Jika kode buku diubah, cek keunikan
        $kode_rule = 'required|trim';
        if ($this->input->post('kode_buku') !== $buku->kode_buku) {
            $kode_rule .= '|is_unique[buku.kode_buku]';
        }

        $this->form_validation->set_rules('kode_buku', 'Kode Buku', $kode_rule);
        $this->form_validation->set_rules('judul', 'Judul Buku', 'required|trim');
        $this->form_validation->set_rules('stok', 'Stok', 'required|numeric|greater_than_equal_to[0]');

        if ($this->form_validation->run() === FALSE) {
            $data['title'] = 'Edit Buku - SIPAS';
            $data['buku'] = $buku;
            $this->load->view('admin/buku/edit', $data);
        } else {
            $update_data = [
                'kode_buku'    => strtoupper($this->input->post('kode_buku', TRUE)),
                'judul'        => $this->input->post('judul', TRUE),
                'penulis'      => $this->input->post('penulis', TRUE),
                'penerbit'     => $this->input->post('penerbit', TRUE),
                'tahun_terbit' => $this->input->post('tahun_terbit', TRUE) ? (int)$this->input->post('tahun_terbit') : NULL,
                'kategori'     => $this->input->post('kategori', TRUE),
                'stok'         => (int)$this->input->post('stok'),
                'rak'          => $this->input->post('rak', TRUE),
                'deskripsi'    => $this->input->post('deskripsi', TRUE),
                'updated_at'   => date('Y-m-d H:i:s')
            ];

            if ($this->Buku_model->update($id, $update_data)) {
                $this->session->set_flashdata('success', 'Data buku berhasil diperbarui.');
                redirect('admin/buku');
            } else {
                $this->session->set_flashdata('error', 'Gagal memperbarui data buku.');
                redirect('admin/buku/edit/' . $id);
            }
        }
    }

    /**
     * Detail Buku
     */
    public function detail($id) {
        $buku = $this->Buku_model->get_by_id($id);
        if (!$buku) {
            $this->session->set_flashdata('error', 'Data buku tidak ditemukan.');
            redirect('admin/buku');
        }

        $data['title'] = 'Detail Buku - ' . $buku->judul;
        $data['buku'] = $buku;
        $this->load->view('admin/buku/detail', $data);
    }

    /**
     * Hapus Buku
     */
    public function hapus($id) {
        $buku = $this->Buku_model->get_by_id($id);
        if (!$buku) {
            $this->session->set_flashdata('error', 'Data buku tidak ditemukan.');
            redirect('admin/buku');
        }

        // Cek apakah masih memiliki transaksi aktif
        if ($this->Buku_model->has_active_transaction($id)) {
            $this->session->set_flashdata('error', 'Buku tidak dapat dihapus karena masih memiliki transaksi aktif peminjaman.');
            redirect('admin/buku');
            return;
        }

        if ($this->Buku_model->delete($id)) {
            $this->session->set_flashdata('success', 'Data buku berhasil dihapus.');
        } else {
            $this->session->set_flashdata('error', 'Gagal menghapus buku. Buku mungkin masih memiliki riwayat transaksi.');
        }
        redirect('admin/buku');
    }
}
💡 Catatan: Baris komentar (// atau /* */) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
← Modul 04: Autentikasi Modul 06: Admin Anggota & Transaksi →