2025-12-19 00:46:38 +07:00
# Asset Management System
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00

2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
Sistem Manajemen Aset berbasis Laravel untuk pencatatan aset fisik end-to-end: **registrasi aset + identifikasi (QR/RFID/NFC), movement, disposal + reverse, maintenance, audit/stocktake, approval workflow, laporan (Excel/PDF), changelog, dan pengaturan sistem berbasis database ** .
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
Project ini dibuat dengan fokus pada **best practice ** , **clean code ** , dan siap untuk dikembangkan menjadi open-source.
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
## Daftar Isi
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
- [Fitur Utama ](#fitur-utama )
- [Arsitektur Singkat ](#arsitektur-singkat )
- [Kebutuhan Sistem ](#kebutuhan-sistem )
- [Quick Start (Local Development) ](#quick-start-local-development )
- [Setup Wizard (First Run) ](#setup-wizard-first-run )
- [Akun Default (Sample Data) ](#akun-default-sample-data )
- [RBAC (Role & Permission) ](#rbac-role--permission )
- [System Settings (Database-driven) ](#system-settings-database-driven )
- [Identifikasi Aset (QR/RFID/NFC) ](#identifikasi-aset-qrrfidnfc )
- [Transaksi Aset ](#transaksi-aset )
- [Approval Workflow ](#approval-workflow )
- [Authentication, 2FA, Session Timeout ](#authentication-2fa-session-timeout )
- [Audit Trail & Logging ](#audit-trail--logging )
- [Import/Export Aset ](#importexport-aset )
- [Laporan (Excel & PDF) ](#laporan-excel--pdf )
- [Landing Page & Public Asset View (QR Scan) ](#landing-page--public-asset-view-qr-scan )
- [Notifikasi Email (SMTP) ](#notifikasi-email-smtp )
- [Notifikasi Terjadwal (Command) ](#notifikasi-terjadwal-command )
- [Maintenance Mode (Read-only) ](#maintenance-mode-read-only )
- [Testing ](#testing )
- [Deployment Notes ](#deployment-notes )
- [Contributing ](#contributing )
2025-12-19 09:18:52 +07:00
- [Dokumentasi Lengkap ](#dokumentasi-lengkap )
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
## Fitur Utama
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**1) User Management + RBAC (Spatie Permission)**
- Role & permission berbasis UUID
- Pembatasan akses per modul melalui middleware `permission:*`
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**2) Master Data**
- Status Aset, Kelas Aset, Unit, Departemen, Person in Charge, Pengguna Aset, Kategori, Lokasi, Warranty, Vendor Contract
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**3) Manajemen Aset**
- Registrasi aset dengan kode otomatis
- Foto/thumbnail aset (multi foto) tersimpan di storage
- QR code otomatis menuju halaman publik detail aset (tanpa login)
- RFID/NFC tag (opsional + bisa auto-generate via setting)
- Arsip/retensi + soft delete + restore
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**4) Transaksi Aset**
- Movement (mutasi lokasi/departemen/user)
- Disposal + Reverse Disposal
- Audit/Stocktake
- Maintenance (planned/in_progress/completed + dukungan flow approval `pending` )
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**5) Approval Workflow**
- Permintaan approval untuk movement/disposal/maintenance (pending/approved/rejected)
- Halaman approvals untuk approver
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**6) Laporan**
- Export Excel (multi sheet) + PDF untuk aset dan transaksi
- Filter laporan (date range, lokasi, dsb.) sesuai halaman laporan
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
**7) Landing & Dokumentasi**
- Landing one-page untuk memperkenalkan sistem
- Public asset view untuk QR scan: `GET /asset-view/{asset}`
- Dokumentasi API internal app: `GET /api-docs`
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
## Arsitektur Singkat
- **Framework:** Laravel
- **Template UI:** Vyzor (Bootstrap)
- **Settings:** disimpan di tabel `settings` dan diakses melalui `App\Services\System\SystemSettingService`
- **Audit log:** file log khusus channel `asset_activity` (bukan database)
- **UUID:** hampir seluruh tabel inti menggunakan UUID sebagai primary key
Folder penting:
- `app/Services/` → business logic (tanpa repository pattern)
- `app/Http/Controllers/` → controller tipis, delegasi ke service
- `database/seeders/` → sample data
- `resources/views/` → Blade UI
## Kebutuhan Sistem
- PHP 8.2+ (sesuaikan dengan `composer.json` )
- Composer
- Node.js + NPM (Vite build)
- Database: MySQL/MariaDB (production) / SQLite (testing)
- (Opsional) Laragon untuk dev di Windows
## Quick Start (Local Development)
1) Install dependency PHP & JS
```bash
composer install
npm install
```
2) Siapkan `.env`
```bash
cp .env.example .env
php artisan key:generate
```
3) Jalankan Vite
```bash
npm run dev
```
4) Jalankan aplikasi
```bash
php artisan serve
```
5) Buat symbolic link storage (wajib untuk foto aset & QR)
```bash
php artisan storage:link
```
## Setup Wizard (First Run)
Saat aplikasi pertama kali dijalankan dan **koneksi database belum siap ** , middleware akan mengarahkan ke wizard:
- `GET /setup`
Wizard terdiri dari 2 tahap besar:
1) **Database Setup **
- Aplikasi akan menampilkan panduan mengisi `.env` (DB_HOST, DB_DATABASE, DB_USERNAME, DB_PASSWORD)
- Tombol migrasi tersedia:
- `Migrate & Seed Minimal (RBAC)` → seed `RbacSeeder` + `SettingSeeder`
- `Migrate + Sample Data (Full Seed)` → seed `DatabaseSeeder`
2) **Wizard Aplikasi (4 langkah) **
- Step 1: buat user admin
- Step 2: isi nilai setting (form dibentuk dari data di tabel `settings` )
- Step 3: buat master data dasar
- Step 4: buat aset pertama (sample)
## Akun Default (Sample Data)
Jika memilih **Full Seed ** , akun admin default dibuat oleh `database/seeders/RbacSeeder.php` :
- Email: `admin@example.com`
- Password: `password123`
## RBAC (Role & Permission)
RBAC memakai `spatie/laravel-permission` yang sudah disesuaikan untuk UUID:
- Primary key role/permission: `uuid`
- Pivot model: `model_uuid` (lihat `config/permission.php` )
Permission dasar (seed):
- `settings.manage`
- `users.manage` , `roles.manage` , `permissions.manage`
- `assets.view` , `assets.manage`
- `movements.manage` , `disposals.manage` , `audits.manage` , `maintenance.manage`
- `reports.view` , `approvals.manage`
Role dasar (seed):
- `super-admin` , `asset-manager` , `auditor` , `maintenance` , `viewer`
Catatan scoping data:
- Model `Asset` memiliki `scopeForUser()` dan `isVisibleTo()` untuk pembatasan berbasis departemen/lokasi.
- (Opsional) Permission `assets.view_all` dapat ditambahkan untuk bypass scoping (lihat `app/Models/Asset.php` ).
## System Settings (Database-driven)
Setting disimpan di tabel `settings` dan dapat dikelola lewat:
- Dashboard: `GET /dashboard/settings`
- Setup Wizard step 2: `GET /setup?step=2`
Setting dibaca via `App\Services\System\SystemSettingService` :
- Default berasal dari `config/system.php`
- Nilai DB akan override default
Contoh setting penting (lihat `database/seeders/SettingSeeder.php` ):
- `asset.code_prefix` , `asset.qr_enabled` , `asset.qr_format` , `asset.qr_size`
- `asset.rfid_enabled` , `asset.nfc_enabled` , `asset.rfid_auto_generate` , `asset.nfc_auto_generate`
- `maintenance.readonly_mode`
- `security.audit_log` , `security.session_idle_minutes` , `security.two_factor_enforced`
- `integration.api_key` , `integration.webhook_*`
- `asset.import_*` (import limit/dedupe/default lookup)
## Identifikasi Aset (QR/RFID/NFC)
**QR Code**
- Dibuat otomatis saat aset dibuat/di-update (jika `asset.qr_enabled = true` )
- Tersimpan di `storage/app/public/qr/`
- Isi QR mengarah ke public asset view: `route('assets.public.show')` (`/asset-view/{asset}` )
**RFID/NFC**
- Disimpan sebagai `rfid_tag` dan `nfc_tag` di tabel `assets`
- Bisa diwajibkan (`asset.rfid_required` / `asset.nfc_required` ) dan/atau auto-generate (`asset.rfid_auto_generate` / `asset.nfc_auto_generate` ) oleh `AssetService` .
## Transaksi Aset
1) **Movement **
- Membuat record `asset_movements`
- Jika auto-approve aktif, aset akan ikut berubah: lokasi/departemen/user
2) **Disposal **
- Membuat record `asset_disposals`
- Jika approved, aset diarahkan ke status `DISPOSED` (jika status ini ada)
- Reverse disposal mengembalikan status/lokasi/departemen sebelumnya
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
3) **Audit/Stocktake **
- Membuat record `asset_audits` (matched/missing/damaged)
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
4) **Maintenance **
- Membuat record `asset_maintenances`
- Flow status: `pending` (menunggu approval) → `planned` → `in_progress` → `completed`
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
## Approval Workflow
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
Approval disimpan di tabel `asset_approval_requests` (morph ke movement/disposal/maintenance):
- Status: `pending` , `approved` , `rejected`
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
Halaman approvals:
- `GET /dashboard/approvals` (butuh permission `approvals.manage` )
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
## Authentication, 2FA, Session Timeout
**Login/Register**
- Login: `GET /login` / `POST /login`
- Register: `GET /register` / `POST /register`
- Logout: `POST /logout`
**2FA (TOTP 6 digit)**
- User dapat mengaktifkan 2FA dari menu profile:
- `GET /dashboard/profile`
- Flow login:
- Jika `two_factor_enabled = true` , setelah password benar user akan diarahkan ke:
- `GET /two-factor-challenge`
- User memasukkan 6 digit dari aplikasi authenticator (Google Authenticator/1Password/Authy) melalui:
- `POST /two-factor-challenge`
**Session Timeout (idle timeout)**
- Middleware `session.timeout` memaksa logout ketika tidak ada aktivitas selama X menit.
- Setting terkait:
- `security.session_idle_minutes`
## Audit Trail & Logging
**1) Request Audit (End-to-end)**
- Middleware `audit.request` mencatat request non-GET beserta durasi response.
- Disimpan via `ActivityLogger::audit()` .
**2) Log Aktivitas Domain**
- Helper:
- `asset_activity_log(...)`
- `asset_request_log(...)`
- Service: `app/Services/Logging/ActivityLogger.php`
**Output log**
- Channel: `asset_activity`
- Lokasi: `storage/logs/asset-activity.log` (daily rotation)
- ENV yang relevan:
- `ASSET_LOG_FILE` , `ASSET_LOG_LEVEL` , `ASSET_LOG_DAYS`
## Import/Export Aset
**Import**
- UI import ada di halaman daftar aset (`/dashboard/assets` )
- Mendukung:
- `Preview` (tanpa menyimpan) + ringkasan create/update/invalid
- `Import` langsung (create/update)
- Gambar dari:
- URL (`image_url` ) * (jika `asset.import_allow_remote_images = true`) *
- ZIP upload (`images_zip` ) dengan mapping nama file (`image_file` )
Sample file import tersedia:
- `public/samples/assets_import_sample.csv`
**Export**
- CSV export (limit 2000 rows) tersedia via route:
- `GET /dashboard/assets-export`
## Laporan (Excel & PDF)
Menu laporan:
- `GET /dashboard/reports/assets`
- `GET /dashboard/reports/movements`
- `GET /dashboard/reports/disposals`
- `GET /dashboard/reports/audits`
Export:
- Excel: multi-sheet (termasuk relasi utama)
- PDF: layout khusus report
## Landing Page & Public Asset View (QR Scan)
Landing:
- `GET /` atau `GET /landing`
Public asset view (tanpa login):
- `GET /asset-view/{asset}`
Transaksi dari halaman public (wajib login + permission terkait):
- Movement: `POST /asset-view/{asset}/movement`
- Disposal: `POST /asset-view/{asset}/disposal`
- Maintenance: `POST /asset-view/{asset}/maintenance`
## Notifikasi Email (SMTP)
Notifikasi saat approval menggunakan **Laravel Notifications ** (channel `mail` ):
- Approver menerima email “approval requested”
- Requester menerima email “approval approved/rejected”
Agar email terkirim, konfigurasi SMTP pada `.env` (contoh):
```env
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@example .com"
MAIL_FROM_NAME="Asset Management System"
```
## Notifikasi Terjadwal (Command)
Tersedia command untuk reminder sederhana (mencatat ke log `asset_activity` ):
```bash
php artisan asset:notify-due
```
Anda bisa menjadwalkannya via cron (contoh setiap hari jam 08:00):
```cron
0 8 * * * cd /path/to/project && php artisan asset:notify-due >> /dev/null 2>&1
```
## Maintenance Mode (Read-only)
Jika setting `maintenance.readonly_mode = true` :
- Middleware `maintenance.readonly` akan memblokir aksi tulis.
- Dashboard menampilkan badge “Mode Read-only Aktif”.
## Testing
Menjalankan test (SQLite):
```bash
php artisan test
```
## Deployment Notes
Checklist singkat production:
- `APP_ENV=production` , `APP_DEBUG=false` , `APP_KEY` sudah terisi
- `php artisan migrate --force`
- `php artisan storage:link`
- `npm run build` (atau gunakan build artifact yang sudah ada di `public/build` )
- Pastikan permission folder:
- `storage/` dan `bootstrap/cache/` writable
## Contributing
2025-12-01 06:41:22 +07:00
2025-12-19 00:46:38 +07:00
Kontribusi sangat diterima.
- Gunakan style & struktur yang sudah ada (controller tipis, logic di service)
- Tambahkan test untuk fitur baru bila memungkinkan
- Buat PR kecil dan fokus per fitur
2025-12-19 09:18:52 +07:00
## Dokumentasi Lengkap
Dokumentasi teknis terperinci (alur, setting, workflow, integrasi, notifikasi, dsb.) tersedia di:
- `documentation/guide.md`