- PHP 53.5%
- JavaScript 24.6%
- Blade 16.6%
- HTML 4.3%
- CSS 0.9%
|
|
||
|---|---|---|
| .claude | ||
| .githooks | ||
| .github/workflows | ||
| app | ||
| bootstrap | ||
| config | ||
| database | ||
| deploy | ||
| docs | ||
| lang | ||
| portal | ||
| public | ||
| resources | ||
| routes | ||
| storage | ||
| tests | ||
| yard | ||
| .editorconfig | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| artisan | ||
| composer.json | ||
| composer.lock | ||
| package-lock.json | ||
| package.json | ||
| phpunit.xml | ||
| pint.json | ||
| README.md | ||
| vite.config.js | ||
| vite.portal.config.js | ||
| vite.yard.config.js | ||
VMERP — VME Enterprise Resource Planning
Sistem ERP internal PT. VME Process untuk perusahaan fabrikasi Oil & Gas. Mengintegrasikan 12 department operasional ke dalam satu platform data tunggal.
| Dokumen kebutuhan | docs/PRD.md |
| Rincian M0 | docs/M0-BREAKDOWN.md |
| Keputusan arsitektur | PRD Section 7.6 — ADR-001 |
Tech Stack
| Layer | Teknologi |
|---|---|
| Bahasa | PHP 8.5 (minimal 8.5.12 — tambalan PHP2Shell) |
| Framework | Laravel 13 |
| Database | PostgreSQL 17 |
| Frontend | Blade + Tailwind CSS 4 + Alpine.js 3 |
| Build | Vite |
| Excel | maatwebsite/excel (PhpSpreadsheet) |
barryvdh/laravel-dompdf |
|
| Audit log | spatie/laravel-activitylog |
Menjalankan di Lokal (Laragon)
Prasyarat
- Laragon dengan PHP 8.5.12+ dan PostgreSQL 15+
- Composer 2.x
- Node.js 20+
Ekstensi PHP wajib: pdo_pgsql, pgsql, mbstring, zip, gd, intl, fileinfo, openssl, curl.
Langkah
git clone <repo> vmerp
cd vmerp
composer install
npm install
cp .env.example .env
php artisan key:generate
Sesuaikan koneksi database di .env:
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=vmerp
DB_USERNAME=postgres
DB_PASSWORD=<password lokal Anda>
Seluruh URL dipaksa https:// secara bawaan (URL::forceScheme('https') di
AppServiceProvider::boot()). Laragon dan php artisan serve berjalan tanpa sertifikat TLS,
jadi matikan hanya di .env lokal — jangan disalin ke server:
VMERP_FORCE_HTTPS=false
Buat database lalu jalankan migration:
createdb -h 127.0.0.1 -U postgres -E UTF8 vmerp
php artisan migrate --seed
Jalankan aplikasi:
npm run dev
php artisan serve
Akses http://localhost:8000 — atau http://vmerp.test bila memakai auto-virtualhost Laragon.
Akun awal
Dibuat oleh SuperAdminSeeder. Kredensial ada di database/seeders/SuperAdminSeeder.php
dan wajib diganti sebelum dipakai di staging/production.
Portal Karir (Recruitment)
Halaman publik tempat pelamar mengirim lamaran — salah satu dari dua bagian VMERP tanpa login (yang lain: form Safety Observation Card). Lamaran yang masuk dinilai, diverifikasi, lalu dijadikan karyawan oleh HRD di dalam ERP.
Alamat
| Path | Isi |
|---|---|
/karir/ |
Formulir lamaran 4 langkah: posisi → biodata, selfie & KTP → CV & sertifikat → pengalaman kerja |
/karir/?posisi={slug} |
Formulir dengan posisi sudah terpilih — untuk tautan di iklan lowongan |
/karir/lowongan/{slug} |
Detail lowongan (dibuka di tab baru, tombol salin tautan, kartu pratinjau WhatsApp/LinkedIn) |
?lang=en |
Tambahkan pada alamat mana pun untuk versi bahasa Inggris (bawaan: Indonesia) |
/api/karir/lowongan |
API publik: lowongan yang dibuka |
/api/karir/lowongan/{slug} |
API publik: satu lowongan |
/api/karir/lowongan/{slug}/header |
Gambar header iklan (1000 × 200) |
/api/karir/lamaran |
API publik: kirim lamaran (POST, dibatasi per IP) |
Di dalam ERP: HRD › Job Vacancy (lowongan & gambar header) dan HRD › Applicant Register (penilaian, verifikasi, Jadi Karyawan).
Contoh lokal: http://localhost:8000/karir/ · http://localhost:8000/karir/lowongan/welder-batam-vac260001.
Menyalakan
Portal mati secara bawaan. Nyalakan di .env, lalu (di server) php artisan optimize:
VMERP_CAREER_PORTAL_ENABLED=true
Email konfirmasi pelamar memakai MAIL_* — bawaan log hanya menulis ke storage/logs.
Folder
| Folder | Isi |
|---|---|
portal/ |
Sumber — index.html (formulir), lowongan.html (detail), src/ (JS, CSS, kamus ID/EN di i18n.js) |
public/karir-app/ |
Hasil build — ikut di-commit, jangan diedit manual |
routes/public.php |
Route publik /karir/*, /api/karir/*, /soc, /api/soc/* (PublicGuard + throttle, tanpa auth) |
app/Http/Controllers/Career/ |
API publik & penyaji halaman portal |
app/Services/Recruitment/ |
Penyimpan lamaran, penilaian, Jadi Karyawan, olah gambar header |
storage/app/applicants/ |
Berkas pelamar (selfie, KTP, CV, sertifikat) — privat |
Halaman /karir/... selalu disajikan Laravel dari public/karir-app/. Folder hasil build sengaja
tidak bernama karir: folder bernama sama dengan route membuat server memotong awalan path,
dan /karir/lowongan/{slug} tidak ditemukan.
Build
npm run build:portal # setelah mengubah portal/ — ikutkan public/karir-app/ dalam commit
npm run dev:portal # server pengembangan portal (http://localhost:5180/karir-app/)
Server produksi tidak butuh Node.js: hasil build ikut di git.
Safety Observation Card (HSE)
Form publik tempat karyawan melaporkan observasi keselamatan — tindakan/kondisi tidak aman, near miss, praktik baik — tanpa login, biasanya dari ponsel lewat QR yang ditempel di yard. Pertanyaannya disusun HSE sendiri di ERP; kartu yang masuk ditinjau HSE.
| Path | Isi |
|---|---|
/soc |
Form observasi (dua bahasa, ?lang=en) |
/api/soc/form |
API publik: pertanyaan aktif, project & area |
/api/soc/observasi |
API publik: kirim kartu (POST, dibatasi per IP) |
Di dalam ERP: HSE › Form SOC (susun pertanyaan: jawaban singkat, paragraf, pilihan ganda, kotak centang, dropdown, ya/tidak, skala, angka, tanggal, jam, foto, judul bagian · tautan, QR, poster cetak) dan HSE › Safety Observation (daftar kartu, tinjauan status & catatan HSE, export dengan satu kolom per pertanyaan).
Nyalakan di .env (mati secara bawaan, terpisah dari Portal Karir): VMERP_SOC_PORTAL_ENABLED=true.
Pertanyaan awal — dari kartu "Safety Observations Card - Online" HSE VME (docs/hse soc.docx) —
diisi php artisan db:seed --class=SocQuestionSeeder; seeder ini hanya mengisi Form SOC yang masih
kosong, jadi susunan yang sudah diubah HSE tidak pernah tertimpa.
Sumber halamannya portal/soc.html + portal/src/soc.js, ikut npm run build:portal.
Dokumentasi
Halaman Dokumentasi di ERP (/dokumentasi, menu Dokumentasi) terbuka untuk setiap user yang login.
Daftar dokumennya di config/documentation.php; setiap dokumen satu view di resources/views/docs/pages/.
| Dokumen | Path | Sumber |
|---|---|---|
| General Flowchart | /dokumentasi/general-flowchart |
docs/flowchart/general-flowchart.cjs → node docs/flowchart/general-flowchart.cjs membangkitkan ulang SVG-nya |
| Video Alur Kerja | /dokumentasi/video-alur-kerja |
resources/docs/media/alur-kerja-vmerp.mp4 — dirender dari storage/app/video/general-flowchart/ (lihat scenes.js) |
| Product Requirements (PRD) | /dokumentasi/prd |
docs/PRD.md, dirender langsung (tabel, daftar isi, diagram mermaid) — mengubah berkasnya cukup |
Dokumen Markdown baru cukup didaftarkan dengan 'source' => 'docs/NAMA.md' di config/documentation.php.
Video dan gambar dokumentasi disimpan di resources/docs/media/ dan wajib didaftarkan di kunci media config yang sama.
Struktur Direktori
app/
├── Http/
│ ├── Controllers/{Department}/ 12 department + Career (portal publik)
│ ├── Requests/{Department}/ Form Request validation
│ └── Middleware/ CheckPrivilege, PublicGuard, SetProjectContext
├── Models/ Eloquent
├── Policies/ Otorisasi per model
├── Services/
│ ├── Import/ Import Engine generik
│ ├── Export/ Export Engine generik
│ ├── Approval/ Approval Engine berjenjang
│ ├── Privilege/ Resolver hak akses efektif
│ └── Progress/ Kalkulasi progress fabrikasi
├── Repositories/ Query agregasi & laporan
├── Jobs/ Import besar, export, report
├── Observers/ Kolom audit otomatis
└── Traits/ HasAuditColumns, Approvable
database/
├── migrations/
├── seeders/
└── templates/ Template Excel import per modul
resources/views/
├── layouts/ app, auth, print, public
├── components/ x-data-table, x-filter-bar, dst
└── {department}/
portal/ Portal Karir & form SOC — sumber frontend publik
public/
├── build/ Aset ERP hasil build (ikut di git)
└── karir-app/ Portal Karir & form SOC hasil build (ikut di git)
storage/app/
├── imports/ Arsip file import per batch
├── documents/ Drawing, foto, sertifikat
├── applicants/ Berkas pelamar: selfie, KTP, CV, sertifikat (privat)
└── exports/
Konvensi
Rincian lengkap ada di PRD Section 7.4. Ringkasnya:
- Controller tipis — validasi di Form Request, logika di Service, query kompleks di Repository
- Wajib
with()untuk relasi yang tampil di tabel — mencegah N+1 - Dilarang menyusun SQL dengan konkatenasi string; raw query wajib memakai parameter binding
- Blade
{{ }}(auto-escape);{!! !!}wajib melewati review - Tabel
snake_casejamak, kolomsnake_case, PKid, FK{table_singular}_id - Model
PascalCasetunggal - Kolom audit wajib di tabel transaksi — diisi otomatis lewat observer
Quality Gate
Kode tidak dinyatakan layak merge oleh penilaian manual, melainkan oleh dua gerbang yang sama-sama harus lulus: code style (Pint · PSR-12) dan seluruh test.
Pasang git hook (sekali per clone)
composer hooks
Perintah itu mengarahkan core.hooksPath ke folder .githooks/ yang ikut ter-commit,
sehingga seluruh anggota tim memakai hook yang sama:
| Hook | Kapan | Yang dijalankan |
|---|---|---|
pre-commit |
tiap commit | Pint hanya pada berkas PHP yang di-stage, hasil perapiannya ikut di-stage |
pre-push |
tiap push | Pint seluruh repositori + php artisan test |
Pemisahannya disengaja: commit tetap ringan, tetapi tidak ada kode gagal yang sampai ke remote.
Dalam keadaan darurat hook dapat dilewati dengan git push --no-verify — dan pipeline CI
tetap akan menangkapnya.
Perintah
composer lint # rapikan code style
composer lint:check # periksa saja, tidak mengubah berkas
composer test # feature & unit test
composer check # gerbang penuh: lint:check + test
Pipeline
.github/workflows/ci.yml menjalankan gerbang yang sama pada setiap push dan pull request
ke master dan develop, di atas PostgreSQL 17 — versi yang sama dengan produksi.
Wajib dilakukan saat repositori dipasang di GitHub: aktifkan branch protection pada
masterdandevelop, lalu tetapkan job Quality Gate sebagai required status check. Tanpa itu pipeline hanya memberi tanda merah tanpa menghalangi merge.
Kewajiban pengujian setiap modul
Setiap modul CRUD wajib punya feature test yang menurunkan Tests\Support\CrudModuleTestCase
dengan tiga skenario minimal:
- akses ditolak tanpa hak (403), dan datanya tetap utuh
- CRUD berhasil dengan hak
- satu aturan bisnis utama modul tersebut
Skenario ketiga dideklarasikan abstract, sehingga modul tidak dapat lolos hanya dengan mewarisi.
Contoh penerapannya ada di tests/Feature/Crud/SupplierModuleTest.php.
Kewajiban ini ditagih otomatis oleh tests/Feature/Foundation/ModuleTestCoverageTest.php:
begitu ada modul CRUD baru yang route-nya tidak disebut satu berkas uji pun, pipeline gagal
dan merge tertahan. Test yang sama juga memastikan tidak ada route CRUD yang lolos tanpa
middleware privilege.
Perintah yang Sering Dipakai
php artisan migrate:fresh --seed # reset database dari nol
php artisan queue:work # worker antrean (import besar, export, report)
php artisan schedule:work # scheduler (alert, retensi data, refresh MV)
php artisan optimize:clear # bersihkan seluruh cache
Catatan Keamanan
- Folder
excel/berisi data operasional nyata dari department dan tidak di-commit ke Git. - Berkas pelamar di
storage/app/applicants/bersifat privat — hanya dapat diunduh lewat controller ber-otorisasi, tidak pernah lewat URL langsung. - Portal Karir publik (
/karir/*) berjalan di route group terpisah tanpa middleware ERP. Lihat PRD Section 10.10.1.6 dan risiko R-16.