210 lines
6.8 KiB
Markdown
210 lines
6.8 KiB
Markdown
# 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.
|