=====================================
FILE: application\controllers\admin\Laporan.php
FULL PATH: C:\xampp\htdocs\sistemkos\application\controllers\admin\Laporan.php
=====================================

<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Laporan extends CI_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('admin/Laporan_model');
        $this->load->library('session');
        $this->load->helper('url');

        if (!$this->session->userdata('admin_logged_in')) {
            redirect('admin/login');
        }

        // Ambil semua kos milik admin → untuk validasi akses laporan
        $this->load->model('admin/Kos_model');
        $kos_admin = $this->Kos_model->get_by_admin($this->session->userdata('admin_id'));

        // simpan ID kos ke array
        $this->admin_kos_ids = array_map(function($k){
            return $k->id_kos;
        }, $kos_admin);
    }

    // Helper untuk cek apakah laporan milik admin
    private function _is_laporan_milik_admin($id_kos_laporan)
    {
        return in_array($id_kos_laporan, $this->admin_kos_ids);
    }


    public function index()
    {
        $data['title'] = 'Data Laporan - SistemKOS';

        $id_admin = $this->session->userdata('admin_id');

        $this->load->model('admin/Kos_model');
        $kos_admin = $this->Kos_model->get_by_admin($id_admin);

        $data['laporan'] = [];
        foreach ($kos_admin as $kos) {
            $laporan_kos = $this->Laporan_model->get_by_kos($kos->id_kos);
            $data['laporan'] = array_merge($data['laporan'], $laporan_kos);
        }

        $data['nama_kos_aktif'] = 'Semua Kos Milik Anda';

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


    public function detail($id)
    {
        $data['laporan'] = $this->Laporan_model->get_by_id($id);
        if (!$data['laporan']) {
            show_404();
        }

        // FIXED: cek apakah laporan milik admin
        if (!$this->_is_laporan_milik_admin($data['laporan']->id_kos)) {
            show_error('Anda tidak memiliki akses ke laporan ini.', 403);
        }

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


    public function tambah()
    {
        if ($this->input->post()) {
            $data = [
                'id_penghuni' => $this->input->post('id_penghuni'),
                'judul' => $this->input->post('judul'),
                'deskripsi' => $this->input->post('deskripsi'),
                'status' => $this->input->post('status')
            ];

            $id_kos = $this->session->userdata('id_kos');
            if ($id_kos) {
                $data['id_kos'] = $id_kos;
            }

            if (!empty($_FILES['gambar']['name'])) {
                $upload_result = $this->_upload_gambar();
                if ($upload_result['status']) {
                    $data['gambar'] = $upload_result['file_name'];
                } else {
                    $this->session->set_flashdata('error', $upload_result['message']);
                    redirect('admin/laporan/tambah');
                }
            }

            if ($this->Laporan_model->insert($data)) {
                $this->session->set_flashdata('success', 'Laporan berhasil ditambahkan.');
                redirect('admin/laporan');
            } else {
                $this->session->set_flashdata('error', 'Gagal menambahkan laporan.');
                redirect('admin/laporan/tambah');
            }
        }

        $data['title'] = 'Tambah Laporan - SistemKOS';
        $this->load->view('admin/laporan/tambah', $data);
    }


    public function edit($id)
    {
        $laporan = $this->Laporan_model->get_by_id($id);

        if (!$laporan || !$this->_is_laporan_milik_admin($laporan->id_kos)) {
            show_error('Anda tidak memiliki akses ke laporan ini.', 403);
        }

        $data['laporan'] = $laporan;

        if ($this->input->post()) {
            $update_data = [
                'id_penghuni' => $this->input->post('id_penghuni'),
                'judul' => $this->input->post('judul'),
                'deskripsi' => $this->input->post('deskripsi'),
                'status' => $this->input->post('status')
            ];

            if (!empty($_FILES['gambar']['name'])) {

                if (!empty($laporan->gambar) && file_exists('./asset/laporan/' . $laporan->gambar)) {
                    unlink('./asset/laporan/' . $laporan->gambar);
                }

                $upload_result = $this->_upload_gambar();
                if ($upload_result['status']) {
                    $update_data['gambar'] = $upload_result['file_name'];
                } else {
                    $this->session->set_flashdata('error', $upload_result['message']);
                    redirect('admin/laporan/edit/' . $id);
                }
            }

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

        $data['title'] = 'Edit Laporan - SistemKOS';
        $this->load->view('admin/laporan/edit', $data);
    }



    public function ubah_status($id)
    {
        $status = $this->input->post('status');

        $laporan = $this->Laporan_model->get_by_id($id);

        // FIXED
        if (!$this->_is_laporan_milik_admin($laporan->id_kos)) {
            show_error('Anda tidak memiliki akses mengubah status laporan ini.', 403);
        }

        if ($this->Laporan_model->update_status($id, $status)) {
            $this->session->set_flashdata('success', 'Status laporan berhasil diperbarui.');
        } else {
            $this->session->set_flashdata('error', 'Gagal memperbarui status laporan.');
        }
        redirect('admin/laporan');
    }


    public function hapus($id)
    {
        $laporan = $this->Laporan_model->get_by_id($id);

        if (!$this->_is_laporan_milik_admin($laporan->id_kos)) {
            show_error('Anda tidak memiliki akses menghapus laporan ini.', 403);
        }

        if ($laporan && !empty($laporan->gambar)) {
            $file_path = './asset/laporan/' . $laporan->gambar;
            if (file_exists($file_path)) {
                unlink($file_path);
            }
        }

        $this->Laporan_model->delete($id);
        $this->session->set_flashdata('success', 'Laporan berhasil dihapus.');
        redirect('admin/laporan');
    }



    public function hapus_gambar($id)
    {
        $laporan = $this->Laporan_model->get_by_id($id);

        if (!$this->_is_laporan_milik_admin($laporan->id_kos)) {
            show_error('Anda tidak memiliki akses ke laporan ini.', 403);
        }

        if ($laporan && !empty($laporan->gambar)) {
            $file_path = './asset/laporan/' . $laporan->gambar;
            if (file_exists($file_path)) {
                unlink($file_path);
            }

            $this->Laporan_model->update($id, ['gambar' => NULL]);
            $this->session->set_flashdata('success', 'Gambar berhasil dihapus.');
        } else {
            $this->session->set_flashdata('error', 'Gambar tidak ditemukan.');
        }

        redirect('admin/laporan/edit/' . $id);
    }


    public function export()
    {
        $id_kos = $this->session->userdata('id_kos');
        $data_laporan = $this->Laporan_model->get_laporan_1_bulan_terakhir($id_kos);

        $filename = 'Laporan_1_Bulan_Terakhir_' . date('Ymd_His') . '.xls';
        header("Content-Type: application/vnd.ms-excel");
        header("Content-Disposition: attachment; filename=\"$filename\"");
        header("Pragma: no-cache");
        header("Expires: 0");
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        table { border-collapse: collapse; width: 100%; }
        th { background:#4CAF50; color:white; padding:8px; border:1px solid #ddd; }
        td { padding:8px; border:1px solid #ddd; }
        tr:nth-child(even){ background:#f2f2f2; }
    </style>
</head>
<body>
    <h3>Laporan 1 Bulan Terakhir</h3>
    <table>
        <thead>
            <tr>
                <th>ID Laporan</th>
                <th>Nama Kos</th>
                <th>ID Penghuni</th>
                <th>Nama Penghuni</th>
                <th>Judul</th>
                <th>Deskripsi</th>
                <th>Gambar</th>
                <th>Status</th>
                <th>Tanggal Laporan</th>
                <th>Tanggal Selesai</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($data_laporan as $data): ?>
                <tr>
                    <td><?= $data['id_laporan'] ?></td>
                    <td><?= $data['nama_kos'] ?></td>
                    <td><?= $data['id_penghuni'] ?></td>
                    <td><?= $data['nama_penghuni'] ?></td>
                    <td><?= $data['judul'] ?></td>
                    <td><?= $data['deskripsi'] ?></td>
                    <td><?= $data['gambar'] ?: '-' ?></td>
                    <td><?= ucfirst($data['status']) ?></td>
                    <td><?= $data['tanggal_laporan'] ?></td>
                    <td><?= $data['tanggal_selesai'] ?: '-' ?></td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</body>
</html>
<?php
        exit;
    }


    private function _upload_gambar()
    {
        if (!is_dir('./asset/laporan')) {
            mkdir('./asset/laporan', 0755, true);
        }

        $config['upload_path']   = './asset/laporan/';
        $config['allowed_types'] = 'jpg|jpeg|png|gif';
        $config['max_size']      = 2048;
        $config['encrypt_name']  = TRUE;

        $this->load->library('upload', $config);

        if ($this->upload->do_upload('gambar')) {
            return [
                'status' => true,
                'file_name' => $this->upload->data('file_name')
            ];
        } else {
            return [
                'status' => false,
                'message' => $this->upload->display_errors()
            ];
        }
    }
}




=====================================
FILE: application\models\admin\Laporan_model.php
FULL PATH: C:\xampp\htdocs\sistemkos\application\models\admin\Laporan_model.php
=====================================

<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Laporan_model extends CI_Model
{

    private $table = 'laporan';

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

    // ========== METHOD UNTUK DASHBOARD ==========

    // Hitung semua laporan
    public function count_all()
    {
        return $this->db->count_all($this->table);
    }

    // Hitung laporan berdasarkan status
    public function count_by_status($status)
    {
        $this->db->where('status', $status);
        return $this->db->count_all_results($this->table);
    }

    // Ambil aktivitas terbaru untuk dashboard
    public function get_recent_activities($limit = 10)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni');
        $this->db->from($this->table);
        $this->db->join('penghuni', 'penghuni.id_penghuni = laporan.id_penghuni', 'left');
        $this->db->order_by('laporan.tanggal_laporan', 'DESC');
        $this->db->limit($limit);
        $query = $this->db->get();
        return $query->result();
    }

    // ========== METHOD UNTUK LAPORAN (CRUD) ==========

    // Ambil semua laporan (join dengan tabel penghuni)
    // DITAMBAHKAN FILTER OPSIONAL BERDASARKAN id_kos
    public function get_all($id_kos = null)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni');
        $this->db->from('laporan');
        $this->db->join('penghuni', 'laporan.id_penghuni = penghuni.id_penghuni', 'left');

        // 🔹 Filter agar hanya laporan dari kos admin login yang tampil
        if ($id_kos !== null) {
            $this->db->where('laporan.id_kos', $id_kos);
        }

        $this->db->order_by('laporan.tanggal_laporan', 'DESC');
        return $this->db->get()->result();
    }

    // Ambil laporan berdasarkan id
    public function get_by_id($id)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni');
        $this->db->from('laporan');
        $this->db->join('penghuni', 'laporan.id_penghuni = penghuni.id_penghuni', 'left');
        $this->db->where('laporan.id_laporan', $id);
        return $this->db->get()->row();
    }

    // 🔹 Ambil laporan berdasarkan id_kos (untuk keamanan edit/detail)
    public function get_by_kos($id_kos)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni');
        $this->db->from('laporan');
        $this->db->join('penghuni', 'laporan.id_penghuni = penghuni.id_penghuni', 'left');
        $this->db->where('laporan.id_kos', $id_kos);
        $this->db->order_by('laporan.tanggal_laporan', 'DESC');
        return $this->db->get()->result();
    }

    // Insert laporan baru
    public function insert($data)
    {
        return $this->db->insert($this->table, $data);
    }

    // Update laporan
    public function update($id, $data)
    {
        $this->db->where('id_laporan', $id);
        return $this->db->update($this->table, $data);
    }

    // Update status laporan
    public function update_status($id, $status)
    {
        $data = ['status' => $status];
        if ($status == 'Selesai') {
            $data['tanggal_selesai'] = date('Y-m-d H:i:s');
        }
        $this->db->where('id_laporan', $id);
        return $this->db->update('laporan', $data);
    }

    // Hapus laporan
    public function delete($id)
    {
        return $this->db->delete('laporan', ['id_laporan' => $id]);
    }

    // ========== EXPORT LAPORAN 1 BULAN TERAKHIR ==========

    // ========== EXPORT LAPORAN 1 BULAN TERAKHIR ==========
    public function get_laporan_1_bulan_terakhir($id_kos)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni, kos.nama_kos');
        $this->db->from('laporan');
        $this->db->join('penghuni', 'laporan.id_penghuni = penghuni.id_penghuni', 'left');
        $this->db->join('kos', 'penghuni.id_kos = kos.id_kos', 'left');

        // Pakai filter dari tabel penghuni (bukan laporan)
        $this->db->where('penghuni.id_kos', $id_kos);
        $this->db->where('laporan.tanggal_laporan >=', date('Y-m-d', strtotime('-1 month')));
        $this->db->order_by('laporan.tanggal_laporan', 'DESC');

        $query = $this->db->get();
        log_message('debug', 'Jumlah laporan ditemukan: ' . $query->num_rows()); // 👈 debug

        return $query->result_array();
    }




    // ===================== DASHBOARD BERDASARKAN KOS =====================

    // Hitung semua laporan berdasarkan id_kos
    public function count_all_by_kos($id_kos)
    {
        $this->db->where('id_kos', $id_kos);
        return $this->db->count_all_results($this->table);
    }

    // Hitung laporan berdasarkan status dan id_kos
    public function count_by_status_kos($status, $id_kos)
    {
        $this->db->where('status', $status);
        $this->db->where('id_kos', $id_kos);
        return $this->db->count_all_results($this->table);
    }

    // Ambil aktivitas terbaru berdasarkan id_kos
    public function get_recent_activities_kos($id_kos, $limit = 10)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni');
        $this->db->from($this->table);
        $this->db->join('penghuni', 'penghuni.id_penghuni = laporan.id_penghuni', 'left');
        $this->db->where('laporan.id_kos', $id_kos);
        $this->db->order_by('laporan.tanggal_laporan', 'DESC');
        $this->db->limit($limit);
        return $this->db->get()->result();
    }
    // Ambil aktivitas terbaru dari semua kos milik admin tertentu
    public function get_recent_activities_by_admin($id_admin, $limit = 10)
    {
        $this->db->select('laporan.*, penghuni.nama_penghuni, kos.nama_kos');
        $this->db->from('laporan');
        $this->db->join('penghuni', 'penghuni.id_penghuni = laporan.id_penghuni', 'left');
        $this->db->join('kos', 'kos.id_kos = laporan.id_kos', 'left');
        $this->db->where('kos.id_admin', $id_admin);
        $this->db->order_by('laporan.tanggal_laporan', 'DESC');
        $this->db->limit($limit);
        return $this->db->get()->result();
    }
}




