docs: add complete project README and setup guide

This commit is contained in:
Arya Dwi Putra
2025-12-19 00:46:38 +07:00
parent 73875c3ab2
commit f2a72237a2
2 changed files with 348 additions and 46 deletions

389
README.md
View File

@@ -1,61 +1,360 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
# Asset Management System
<p align="center">
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
![Asset Management System](public/build/assets/images/brand-logos/toggle-logo.png)
## About Laravel
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**.
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
Project ini dibuat dengan fokus pada **best practice**, **clean code**, dan siap untuk dikembangkan menjadi open-source.
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
## Daftar Isi
Laravel is accessible, powerful, and provides tools required for large, robust applications.
- [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)
## Learning Laravel
## Fitur Utama
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
**1) User Management + RBAC (Spatie Permission)**
- Role & permission berbasis UUID
- Pembatasan akses per modul melalui middleware `permission:*`
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
**2) Master Data**
- Status Aset, Kelas Aset, Unit, Departemen, Person in Charge, Pengguna Aset, Kategori, Lokasi, Warranty, Vendor Contract
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
**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
## Laravel Sponsors
**4) Transaksi Aset**
- Movement (mutasi lokasi/departemen/user)
- Disposal + Reverse Disposal
- Audit/Stocktake
- Maintenance (planned/in_progress/completed + dukungan flow approval `pending`)
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com).
**5) Approval Workflow**
- Permintaan approval untuk movement/disposal/maintenance (pending/approved/rejected)
- Halaman approvals untuk approver
### Premium Partners
**6) Laporan**
- Export Excel (multi sheet) + PDF untuk aset dan transaksi
- Filter laporan (date range, lokasi, dsb.) sesuai halaman laporan
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
- **[Redberry](https://redberry.international/laravel-development/)**
- **[Active Logic](https://activelogic.com)**
**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`
## 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
3) **Audit/Stocktake**
- Membuat record `asset_audits` (matched/missing/damaged)
4) **Maintenance**
- Membuat record `asset_maintenances`
- Flow status: `pending` (menunggu approval) → `planned``in_progress``completed`
## Approval Workflow
Approval disimpan di tabel `asset_approval_requests` (morph ke movement/disposal/maintenance):
- Status: `pending`, `approved`, `rejected`
Halaman approvals:
- `GET /dashboard/approvals` (butuh permission `approvals.manage`)
## 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
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
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

View File

@@ -11,7 +11,10 @@ class SessionTimeout
public function handle(Request $request, Closure $next): Response
{
if ($request->user()) {
$timeout = config('system.security.session_idle_timeout_minutes', 30);
// Mengikuti key setting yang disimpan di database (`security.session_idle_minutes`).
// Fallback ke key lama jika ada, agar backward compatible.
$timeout = (int) (config('system.security.session_idle_minutes')
?? config('system.security.session_idle_timeout_minutes', 30));
$last = session('last_active_at');
if ($last && now()->diffInMinutes($last) >= $timeout) {