first commit
This commit is contained in:
282
README.md
Normal file
282
README.md
Normal file
@@ -0,0 +1,282 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user