This commit is contained in:
Saufi
2026-06-03 08:51:22 +08:00
commit a14d43fe34
347 changed files with 38197 additions and 0 deletions

209
docs/02-architecture.md Normal file
View File

@@ -0,0 +1,209 @@
# Initial Architecture
## Technology Stack
- Backend: Laravel 13.12.0, installed through `laravel/laravel` 13.8.0.
- Database: MySQL.
- Views: Blade.
- Styling: Bootstrap 5 with Bootstrap Icons.
- JavaScript: Vite-managed assets, jQuery where it improves progressive enhancement, plus selected UI helpers.
- Queue: Laravel queue system for email and heavier export-related tasks where useful.
- Mail: Laravel Mail and Notifications with Markdown mail templates.
- Authorization: Laravel policies, gates, middleware, and `spatie/laravel-permission`.
- Auditing: `spatie/laravel-activitylog` plus domain-specific history tables where a structured audit timeline is needed.
- Export: OpenSpout for current PHP 8.5 compatibility. `maatwebsite/excel` remains the preferred package from the original requirement but was not installable in this environment during Phase 1.
## Phase 1 Implemented Structure
Implemented:
- Breeze auth controllers and routes.
- Generic `/register` routes disabled.
- Bootstrap-based `layouts.app`, `layouts.guest`, and navigation.
- Role-aware dashboards:
- `/admin/dashboard`
- `/kewangan/dashboard`
- `/ppm/dashboard`
- `/ktm/dashboard`
- `/pemohon/dashboard`
- `/dashboard` role redirect.
- Spatie role middleware aliases:
- `role`
- `permission`
- `role_or_permission`
- `RolePermissionSeeder`.
- Default Admin seed account from `config/prn.php`.
## Application Structure
Planned directories:
```text
app/
Actions/
Exports/
Http/
Controllers/
Requests/
Middleware/
Models/
Notifications/
Policies/
Services/
Support/
```
Guidelines:
- Controllers orchestrate requests and responses only.
- Form Request classes validate input and authorize request-specific actions.
- Policies enforce model-level access.
- Services hold business rules and transactional workflows.
- Action classes may be used for high-value operations such as approving applications, changing assignments, registering KTM-created KP, and recording attendance.
- Export classes live in `app/Exports`.
- Report filters and query preparation live in services, not controllers.
## Architectural Layers
### Presentation Layer
- Blade templates with Bootstrap 5.
- Responsive layouts for desktop, tablet, and mobile.
- Shared layout components for navigation, cards, filters, badges, breadcrumbs, tables, empty states, and modals.
- Mobile-friendly table alternatives for high-density data.
### HTTP Layer
- Named routes.
- Route groups by role and module.
- Middleware for authentication, role, registration period, and public QR validation.
- Route model binding using internal IDs for authenticated admin areas where safe.
- Public routes use UUID/ULID identifiers only.
### Domain Layer
Core services:
- `RegistrationPeriodService`
- `VacancyService`
- `ApplicationService`
- `AssignmentService`
- `KtmTeamService`
- `PpmScopeService`
- `BankVerificationService`
- `AttendanceService`
- `WheelchairService`
- `ExportLoggingService`
- `SensitiveDataMaskingService`
Potential action classes:
- `SubmitPublicApplication`
- `CreateKtmApplicant`
- `ApproveApplication`
- `RejectApplication`
- `ChangeApplicantRole`
- `AssignStaffToSaluran`
- `RecordAttendance`
- `VerifyBankDetails`
- `RecordWheelchairTransaction`
### Data Layer
- Eloquent models and relationships.
- Foreign keys for domain integrity.
- Soft deletes for records that should remain auditable.
- Domain history tables for applications and assignments.
- Activity log for actor/value snapshots and operational traceability.
## Role-Based Areas
Planned route groups:
```text
/dashboard
/admin/...
/ppm/...
/ktm/...
/kewangan/...
/pohon/{pusat_mengundi_uuid}
```
Expected access:
- `Admin`: full operational management.
- `Admin Kewangan`: finance verification and finance exports only.
- `PPM`: assigned Pusat Mengundi only.
- `KTM`: assigned Saluran/team only.
- `Pemohon`: public form and own submission flow only if login is later required.
## Public Identifier Strategy
- Public QR links must use UUID or ULID stored on `pusat_mengundis.public_uuid` or equivalent.
- Internal auto-increment IDs must not appear in public application URLs.
- Uploaded documents are accessed only through authenticated authorization checks and signed/temporary download responses where needed.
## Dual-Role Assignment Strategy
The system must support a PPM who is also KTM. This should not be modeled as a single role column on a user or application.
Planned approach:
- Use `users` for login identity.
- Use `applications` or staff records for applicant/staff biographical and banking data.
- Use `staff_assignments` as the canonical placement table.
- A person can have multiple active `staff_assignments` within the same election when business rules allow it.
- `staff_assignments` references `position_id`, `pusat_mengundi_id`, optional `saluran_mengundi_id`, and optional supervisor/team references.
- Uniqueness constraints prevent invalid duplicate active assignments, while allowing explicitly permitted dual role such as PPM + KTM.
## Audit Strategy
Use two audit levels:
- Structured domain histories for application status and assignment changes.
- General activity log for before/after data changes, actor, timestamp, source, and notes.
Audit targets:
- Application approval/rejection.
- Role changes.
- Assignment changes.
- Document upload/change.
- Bank verification.
- Admin edits after registration closes.
- Attendance updates.
- Wheelchair transactions.
- Excel exports.
## File Storage Strategy
- IC documents and bank statements are stored on Laravel private storage disk.
- Public symlink storage must not expose sensitive uploads.
- File validation must restrict MIME type, size, and extension.
- Document access must pass policy checks.
- File records should be stored in `application_documents` with document type, disk, path, original name, MIME type, size, uploader, and timestamps.
## Export Strategy
- `maatwebsite/excel` will generate XLSX exports.
- Every export inserts a row into `export_logs`.
- Export logs include generated_by, generated_at, report_type, filter parameters, and file name.
- Export services prepare queries and filters.
- Export classes only shape spreadsheet data.
## Queue and Mail Strategy
- KTM-created applicant email notification should use Laravel Notifications or Mailables.
- Queue should be enabled for mail in production.
- Local development can use log mailer or local mail catcher.
- Admin-keyed records do not trigger bank account email requests.
## Security Principles
- Use CSRF protection for all form submissions.
- Use policies and middleware for every protected module.
- Validate uploads strictly.
- Store sensitive files privately.
- Mask IC, bank account, phone, and email where full values are unnecessary.
- Avoid raw SQL unless justified and documented.
- Use transactions for approval, assignment, finance verification, and attendance updates.