Sistem Pemantauan Kemampanan Pusat Data MBIP
Aplikasi web untuk Majlis Bandaraya Iskandar Puteri (MBIP) bagi memantau kemampanan dan pelaporan karbon pusat data dalam kawasan pentadbiran MBIP. Sistem ini membantu JPP memantau penggunaan karbon, menyemak laporan perunding, merancang program/projek pengurangan karbon, dan menguruskan pelaporan pembaharuan lesen tahunan.
Dibina dengan Laravel 13 + MySQL + Blade + Bootstrap 5 + jQuery (Vite).
Kandungan
- Ciri Utama
- Keperluan Sistem
- Pemasangan
- Akaun Contoh
- Peraturan Perniagaan Penting
- Senarai Semak Dinamik & Enjin Formula
- Peranan & Kebenaran
- Keselamatan & Jejak Audit
- Ujian
- Struktur Pangkalan Data
Ciri Utama
- Autentikasi & Kawalan Akses — log masuk/keluar, papan pemuka mengikut peranan, polisi & kebenaran, jejak audit penuh.
- Pengurusan Perunding — JPP mendaftar akaun perunding; satu perunding boleh urus banyak pusat data.
- Pengurusan Pusat Data — maklumat pusat data, perunding semasa, sejarah penugasan.
- Kitaran Pelaporan / Pembaharuan Lesen — tahun pelaporan dikira automatik, tarikh tutup boleh dikonfigur.
- Pembina Templat Senarai Semak Dinamik — JPP boleh tambah/ubah/buang seksyen, skop, item & formula tanpa perubahan kod.
- Modul Serahan Perunding — isi senarai semak, muat naik PDF, simpan draf, hantar muktamad, jawab pembetulan.
- Muat Naik Dokumen & Versi — PDF sahaja, hash fail, sejarah versi, muat turun dilindungi polisi.
- Aliran Kerja Semakan JPP — tukar status, tugaskan pegawai, kunci/buka kunci, salinan keras, permohonan pembetulan.
- Modul Komen/Perbualan — perbualan setiap serahan, mesej dalaman/luaran, soft delete dengan rekod audit.
- Senarai Peringatan — pusat data yang belum serah untuk kitaran aktif, sorotan lampau tempoh.
- Papan Pemuka & Laporan — statistik karbon A/B/C/D/E mengikut tahun, trend, pecahan status.
- Tetapan & Log Audit — konfigurasi tarikh tutup lalai, had muat naik, toggle peringatan emel.
Keperluan Sistem
- PHP >= 8.3 (diuji pada PHP 8.5)
- Composer 2.x
- MySQL 8.x
- Node.js >= 18 & NPM (untuk binaan aset Vite)
Pemasangan
# 1. Pasang kebergantungan PHP
composer install
# 2. Pasang & bina aset frontend (Bootstrap 5 + jQuery via Vite)
npm install
npm run build # atau `npm run dev` semasa pembangunan
# 3. Fail persekitaran
cp .env.example .env
php artisan key:generate
Kemas kini tetapan pangkalan data dalam .env:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mbip_datacenter
DB_USERNAME=root
DB_PASSWORD=1234
# 4. Cipta pangkalan data (jika belum)
# CREATE DATABASE mbip_datacenter CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 5. Migrasi + semai data (peranan, pengguna contoh, templat senarai semak, data demo)
php artisan migrate:fresh --seed
# 6. Pautan storan (laporan PDF disimpan di storage/app/private)
php artisan storage:link
# 7. Jalankan pelayan
php artisan serve
Lawati http://127.0.0.1:8000 dan log masuk.
Nota muat naik fail: Laporan PDF disimpan pada disk
local(storage/app/private/reports/…), di luar direktori awam. Ia hanya boleh dimuat turun melalui laluan terlindung yang dikuatkuasakan oleh polisi.
Akaun Contoh
Semua kata laluan: password
| Peranan | Emel |
|---|---|
| Super Admin | superadmin@mbip.gov.my |
| JPP Admin | jppadmin@mbip.gov.my |
| Pegawai JPP | pegawai@mbip.gov.my |
| Penolong Pegawai | penolong@mbip.gov.my |
| Kerani | kerani@mbip.gov.my |
| Perunding | perunding@example.com |
Peraturan Perniagaan Penting
- Pembaharuan lesen dibuat pada/sebelum 1 Disember setiap tahun (tarikh tutup boleh dikonfigur).
- Tempoh lesen ialah 1 tahun.
- Perunding mesti serahkan bacaan/laporan karbon Januari–Disember bagi tahun pelaporan.
- Tahun pelaporan = Tahun pembaharuan − 2. Contoh: pembaharuan 2028 ⇒ data pelaporan 2026.
- JPP boleh konfigur tarikh tutup tahunan (Tetapan → Kitaran).
- Perunding mesti isi borang senarai semak dan muat naik laporan PDF sebelum pembaharuan diteruskan.
- Serahan pertama diperlukan sebelum CCC diperoleh; serahan tahunan selepas itu.
Senarai Semak Dinamik & Enjin Formula
Senarai semak tidak ditetapkan dalam kod. Struktur disimpan secara relasi:
checklist_templates -> checklist_sections -> checklist_scopes -> checklist_items
-> checklist_formulas (A = SKOP1 + SKOP2 + SKOP3, dsb.)
Setiap item boleh diberi formula_token (cth: SKOP1, EE, RE, D4I). Formula seksyen merujuk token ini dan token hasil seksyen terdahulu, dinilai mengikut turutan:
| Token | Formula | Maksud |
|---|---|---|
| A | SKOP1 + SKOP2 + SKOP3 |
Jumlah pelepasan karbon |
| B | EE + RE |
Mekanisme pengurangan |
| C | A - B |
Baki karbon |
| D | A - D4I - D4II |
Bersih karbon |
| E | D / A * 100 |
% pengurangan (dengan perlindungan bahagi sifar) |
Formula dinilai oleh App\Services\ExpressionEvaluator — sebuah parser aritmetik selamat (recursive descent, menyokong + - * / ( ) dan pemboleh ubah token). Ia tidak menggunakan eval(), jadi formula yang dikonfigur pengguna JPP adalah selamat. Hasil disimpan dalam submission_results untuk pengagregatan papan pemuka.
JPP boleh ubah semua ini melalui Pembina Templat Senarai Semak (menu sisi → Templat Senarai Semak → Bina).
Peranan & Kebenaran
Menggunakan spatie/laravel-permission. Super Admin memintas semua semakan melalui Gate::before.
| Kebenaran | JPP Admin | Pegawai JPP | Penolong | Kerani | Perunding |
|---|---|---|---|---|---|
| Urus perunding | ✔ | ✔ | |||
| Urus pusat data | ✔ | ✔ | ✔ | ||
| Urus penugasan | ✔ | ✔ | |||
| Urus kitaran | ✔ | ✔ | |||
| Urus templat senarai semak | ✔ | ||||
| Lihat semua serahan | ✔ | ✔ | ✔ | ✔ | |
| Semak serahan | ✔ | ✔ | ✔ | ||
| Kunci/buka kunci | ✔ | ✔ | |||
| Tanda salinan keras | ✔ | ✔ | ✔ | ✔ | |
| Urus serahan sendiri | ✔ | ||||
| Laporan & statistik | ✔ | ✔ | ✔ | ||
| Senarai peringatan | ✔ | ✔ | ✔ | ✔ | |
| Urus pengguna & tetapan | ✔ |
Perunding hanya boleh melihat pusat data & serahan yang ditugaskan kepadanya (dikuatkuasakan oleh SubmissionPolicy & DataCentrePolicy).
Keselamatan & Jejak Audit
- Validasi muat naik PDF sahaja (
mimes:pdf+mimetypes:application/pdf) dengan had saiz boleh dikonfigur. - Fail disimpan di luar laluan awam; muat turun melalui laluan terlindung + polisi.
- Setiap paparan/muat turun/tindakan diberi kuasa melalui polisi.
- Jejak audit (
spatie/laravel-activitylog) bagi: log masuk, perubahan status, kunci/buka kunci, muat naik dokumen, permohonan pembetulan, penugasan perunding, padam komen. - Soft delete pada model utama; komen hanya soft delete (rekod audit dikekalkan).
- Perlindungan CSRF, pengesahan sisi pelayan, indeks pangkalan data pada kunci asing/status/kitaran/perunding/pusat data.
Ujian
Ujian ciri menggunakan SQLite dalam-memori (lihat phpunit.xml).
php artisan test
Liputan ujian utama:
- Perunding tidak boleh akses pusat data perunding lain
- JPP boleh cipta perunding (+ akaun log masuk)
- JPP boleh tugaskan perunding kepada pusat data
- Hanya satu perunding aktif setiap pusat data (sejarah dikekalkan)
- Tahun pelaporan dikira betul daripada tahun pembaharuan
- Perunding boleh hantar senarai semak + PDF (tidak boleh hantar tanpa PDF)
- Perunding tidak boleh edit serahan yang dikunci
- JPP tukar status ke "pembetulan perunding" hanya dengan butiran pembetulan
- Status "selesai" memerlukan tarikh hardcopy dihantar
- Senarai peringatan mengeluarkan perunding selepas serahan
- Pengiraan formula A, B, C, D, E (+ perlindungan bahagi sifar + keutamaan operator)
Struktur Pangkalan Data
users, roles/permissions (spatie), consultants, data_centres, data_centre_consultant_assignments, reporting_cycles, checklist_templates, checklist_sections, checklist_scopes, checklist_items, checklist_formulas, submissions, submission_answers, submission_results, submission_documents, submission_status_histories, submission_correction_requests, submission_comments, app_settings, activity_log.
Pengezanan Docker (Produksi Ubuntu)
Setup Docker mengikut konvensyen projek MBIP yang terbukti (rujukan: spr2026):
PHP 8.4 FPM + Nginx 1.27 (Alpine) + Supervisor, menyambung ke MySQL luaran pada host/LAN.
Fail berkaitan
Dockerfile # imej PHP 8.4 FPM (Debian Bookworm)
docker-compose.yml # servis app + nginx, volume, network
docker-compose.override.yml # override pembangunan (auto-dimuat)
.dockerignore
.env.docker # templat env produksi
deploy.sh # skrip deploy/kemas kini
docker/
├── entrypoint.sh # tunggu MySQL, migrate, seed, cache
├── nginx/{nginx.conf,default.conf}
├── php/{php.ini,www.conf,opcache-dev.ini}
└── supervisor/supervisord.conf # php-fpm + queue worker + scheduler
Langkah deploy pertama (di server Ubuntu)
# 1. Klon kod & masuk direktori
git clone <repo> mbip-datacenter && cd mbip-datacenter
# 2. Sediakan env produksi
cp .env.docker .env
php artisan key:generate --show # salin nilai ke APP_KEY dalam .env
nano .env # isi APP_URL, DB_USERNAME, DB_PASSWORD, DB_HOST
# 3. Pastikan pangkalan data MySQL wujud (pada host/LAN)
# CREATE DATABASE mbip_datacenter CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 4. Deploy (bina imej + aset + naik container + migrate + seed automatik)
chmod +x deploy.sh
./deploy.sh --build
Container app (PHP-FPM) hanya didedahkan kepada nginx dalaman; Nginx didedahkan pada
NGINX_HTTP_PORT (lalai 8010). Letakkan reverse proxy (Nginx/Apache host atau Cloudflare)
untuk TLS/443 di hadapan port ini.
Kemas kini (deploy seterusnya)
./deploy.sh # git pull + npm build + up + migrate + optimize
./deploy.sh --build # paksa bina semula imej (selepas tukar Dockerfile)
./deploy.sh --fresh # migrate:fresh --seed (AMARAN: kosongkan data)
./deploy.sh --logs # ikut log container
./deploy.sh --down # hentikan container
Nota
- MySQL luaran:
DB_HOST=host.docker.internalmenyambung ke MySQL pada host Ubuntu yang sama (dipetakan melaluiextra_hosts: host-gateway). Tukar kepada IP pelayan MySQL jika berasingan. - Aset Vite dibina pada host oleh
deploy.sh(npm run build) dan dihidang terus oleh Nginx daripada./public(lekapan baca-sahaja) — tiada langkah build aset dalam imej. - Laporan PDF disimpan dalam volume
mbip_dc_storage(storage/app/private), kekal merentas deploy, di luar laluan awam. entrypoint.shautomatik menunggu MySQL, jalankan migrasi, semai data kali pertama, dan bina semula cache pada setiap permulaan container.- Supervisor menjalankan php-fpm + queue worker + scheduler dalam container
app.
Binaan Aset (Build)
npm run build # binaan produksi aset (manifest dalam public/build)
© Majlis Bandaraya Iskandar Puteri (MBIP).