283 lines
11 KiB
Markdown
283 lines
11 KiB
Markdown
# 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](#ciri-utama)
|
||
- [Keperluan Sistem](#keperluan-sistem)
|
||
- [Pemasangan](#pemasangan)
|
||
- [Akaun Contoh](#akaun-contoh)
|
||
- [Peraturan Perniagaan Penting](#peraturan-perniagaan-penting)
|
||
- [Senarai Semak Dinamik & Enjin Formula](#senarai-semak-dinamik--enjin-formula)
|
||
- [Peranan & Kebenaran](#peranan--kebenaran)
|
||
- [Keselamatan & Jejak Audit](#keselamatan--jejak-audit)
|
||
- [Ujian](#ujian)
|
||
- [Struktur Pangkalan Data](#struktur-pangkalan-data)
|
||
|
||
---
|
||
|
||
## Ciri Utama
|
||
|
||
1. **Autentikasi & Kawalan Akses** — log masuk/keluar, papan pemuka mengikut peranan, polisi & kebenaran, jejak audit penuh.
|
||
2. **Pengurusan Perunding** — JPP mendaftar akaun perunding; satu perunding boleh urus banyak pusat data.
|
||
3. **Pengurusan Pusat Data** — maklumat pusat data, perunding semasa, sejarah penugasan.
|
||
4. **Kitaran Pelaporan / Pembaharuan Lesen** — tahun pelaporan dikira automatik, tarikh tutup boleh dikonfigur.
|
||
5. **Pembina Templat Senarai Semak Dinamik** — JPP boleh tambah/ubah/buang seksyen, skop, item & formula **tanpa perubahan kod**.
|
||
6. **Modul Serahan Perunding** — isi senarai semak, muat naik PDF, simpan draf, hantar muktamad, jawab pembetulan.
|
||
7. **Muat Naik Dokumen & Versi** — PDF sahaja, hash fail, sejarah versi, muat turun dilindungi polisi.
|
||
8. **Aliran Kerja Semakan JPP** — tukar status, tugaskan pegawai, kunci/buka kunci, salinan keras, permohonan pembetulan.
|
||
9. **Modul Komen/Perbualan** — perbualan setiap serahan, mesej dalaman/luaran, soft delete dengan rekod audit.
|
||
10. **Senarai Peringatan** — pusat data yang belum serah untuk kitaran aktif, sorotan lampau tempoh.
|
||
11. **Papan Pemuka & Laporan** — statistik karbon A/B/C/D/E mengikut tahun, trend, pecahan status.
|
||
12. **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
|
||
|
||
```bash
|
||
# 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`:
|
||
|
||
```dotenv
|
||
DB_CONNECTION=mysql
|
||
DB_HOST=127.0.0.1
|
||
DB_PORT=3306
|
||
DB_DATABASE=mbip_datacenter
|
||
DB_USERNAME=root
|
||
DB_PASSWORD=1234
|
||
```
|
||
|
||
```bash
|
||
# 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
|
||
|
||
1. Pembaharuan lesen dibuat **pada/sebelum 1 Disember** setiap tahun (tarikh tutup boleh dikonfigur).
|
||
2. Tempoh lesen ialah **1 tahun**.
|
||
3. Perunding mesti serahkan bacaan/laporan karbon **Januari–Disember** bagi tahun pelaporan.
|
||
4. **Tahun pelaporan = Tahun pembaharuan − 2.** Contoh: pembaharuan **2028** ⇒ data pelaporan **2026**.
|
||
5. JPP boleh konfigur tarikh tutup tahunan (Tetapan → Kitaran).
|
||
6. Perunding mesti isi borang senarai semak **dan** muat naik laporan PDF sebelum pembaharuan diteruskan.
|
||
7. 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`).
|
||
|
||
```bash
|
||
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)
|
||
```bash
|
||
# 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)
|
||
```bash
|
||
./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.internal` menyambung ke MySQL pada host Ubuntu yang sama
|
||
(dipetakan melalui `extra_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.sh` automatik 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)
|
||
|
||
```bash
|
||
npm run build # binaan produksi aset (manifest dalam public/build)
|
||
```
|
||
|
||
© Majlis Bandaraya Iskandar Puteri (MBIP).
|