Appearance
ERP Mobile App
ERPMobileApps is the Flutter application for ERP end-users — accountants, managers, HR personnel, and warehouse staff. It provides mobile access to the most time-sensitive ERP workflows: attendance tracking, invoice approval, leave management, and purchase order approvals.
Overview
| Property | Value |
|---|---|
| Directory | ERPMobileApps/ |
| Platform | Android, iOS |
| Backend services | AppsPortal.Apis, HR.Apis, Inventory.Apis |
| Keycloak realm | microtec |
| Offline support | Partial (attendance check-in/out, read-only item lookup) |
| Auth flow | Keycloak OIDC / PKCE |
Features
Attendance Management
- Clock-in / clock-out with GPS location capture
- Shift schedule view — current and upcoming shifts
- Attendance history — view own records by date range
- Location-aware check-in: the backend validates that check-in location matches an assigned work location
Offline mode for attendance: if the device has no connectivity, the check-in event is stored locally and synced when connectivity is restored (using a local SQLite queue).
Sales Invoices
- View list of sales invoices with status filters (Draft, Posted, Paid)
- Invoice detail view — line items, totals, customer info
- Quick-approve workflow for invoices pending manager approval
- ZATCA QR code display for e-invoicing compliance
Approvals Inbox
- Unified approval inbox across modules: purchase orders, leave requests, payment vouchers, sales discounts
- One-tap approve or reject with required comment field
- Push notification badge updates when new approvals arrive
- Approval history — view past decisions with timestamps
Leave Management
- View leave balance by type (annual, sick, emergency)
- Submit leave requests with date range and type
- Track pending requests — see current status (Pending, Approved, Rejected)
- Manager view — approve or reject team members' leave requests
Purchase Orders (Mobile Review)
- View list of purchase orders assigned for review
- PO detail — vendor, items, quantities, prices, delivery date
- Approve, reject, or request amendment with comment
- Link to attached documents (from Attachment.Apis)
Inventory — Item Lookup
- Search items by name, barcode, or code
- View stock levels per warehouse
- Available offline for items cached in the last sync
Backend Integration
The MobileAPIClients package contains auto-generated Dart clients for every endpoint. The app never constructs raw HTTP requests.
Architecture
The app follows a layered clean architecture with dependency inversion:
ERPMobileApps/
├── lib/
│ ├── core/
│ │ ├── config/ # Environment config (API URL, Keycloak URL)
│ │ ├── di/ # GetIt dependency injection setup
│ │ ├── navigation/ # Route definitions (go_router)
│ │ ├── network/ # HTTP client setup, interceptors
│ │ └── sync/ # Offline sync queue manager
│ ├── data/
│ │ ├── api/ # API client wrappers (thin layer over MobileAPIClients)
│ │ ├── local/ # SQLite (drift), secure storage, shared prefs
│ │ └── repositories/ # Repository implementations
│ ├── domain/
│ │ ├── entities/ # Attendance, Invoice, LeaveRequest, PurchaseOrder, Item
│ │ ├── repositories/ # Abstract repository interfaces
│ │ └── use_cases/ # Business logic (ClockIn, ApprovePO, SubmitLeave)
│ ├── presentation/
│ │ ├── auth/ # Login screen, Keycloak PKCE callback
│ │ ├── home/ # Navigation hub, notification badge
│ │ ├── attendance/ # Clock-in/out, shifts, history
│ │ ├── invoices/ # Invoice list, detail, approval
│ │ ├── approvals/ # Unified approval inbox
│ │ ├── leaves/ # Leave balance, request, approval
│ │ ├── purchase_orders/ # PO review and approval
│ │ └── inventory/ # Item search and stock lookup
│ └── main.dart
├── android/
├── ios/
├── melos.yaml
└── pubspec.yamlState Management
The app uses flutter_bloc (BLoC pattern) for state management. Each feature has its own Bloc:
presentation/
├── attendance/
│ ├── bloc/
│ │ ├── attendance_bloc.dart
│ │ ├── attendance_event.dart
│ │ └── attendance_state.dart
│ ├── screens/
│ └── widgets/BLoC events are dispatched from screens; BLoC states drive the UI rebuild. Effects (API calls) live inside the BLoC, delegating to use cases from the domain layer.
Offline Sync
Attendance events use a local sync queue backed by SQLite (drift):
- User clocks in — event saved to local DB with
SyncStatus.pending. - If connectivity is available, the event is immediately sent to HR.Apis.
- If offline, the
SyncManagerretries on reconnect usingconnectivity_plusstream. - On sync success, the local record is marked
SyncStatus.synced.
Shared Libraries Used
| Library | Usage in ERPMobileApps |
|---|---|
MobileDesignSystem | All UI — buttons, cards, bottom sheets, typography, ERP colour palette |
MobileAPIClients | Generated Dart clients for AppsPortal.Apis, HR.Apis, Inventory.Apis |
MobileSharedComp | Keycloak PKCE auth flow, secure token storage, base screen class, sync utilities |
Setup and Running
bash
cd ERPMobileApps
# First-time setup — bootstraps all packages and submodules
melos run init
# Install / update dependencies
melos run get
# Run in debug mode (ensure a device or emulator is connected)
melos run run
# Build Android APK
melos run build-apk
# Run tests
melos run testAuthentication Flow
The Keycloak redirect URI for the ERP app is com.microtec.erp://callback. This must be registered in the microtec realm Keycloak client.
Push Notifications
The app receives push notifications via Firebase Cloud Messaging (FCM) on Android and APNs on iOS:
| Notification type | Trigger | Source |
|---|---|---|
| New approval request | PO, leave, or invoice created | AppsPortal.Apis → Notification.Apis |
| Leave request decision | Manager approves/rejects | HR.Apis → Notification.Apis |
| Attendance reminder | Clock-in or clock-out reminder | HR.Apis scheduled job |
Environment Configuration
dart
// lib/core/config/environment.dart
class Environment {
static const apiBaseUrl = String.fromEnvironment('API_BASE_URL');
static const keycloakUrl = String.fromEnvironment('KEYCLOAK_URL');
static const realm = String.fromEnvironment('KEYCLOAK_REALM', defaultValue: 'microtec');
}| Environment | API Base URL | Keycloak URL |
|---|---|---|
| dev | https://gateway.microtec-test.com | https://keycloak.microtec-test.com |
| stage | https://gateway.microtecstage.com | https://keycloak.microtecstage.com |
| production | https://gateway.onlinemicrotec.com.sa | https://keycloak.onlinemicrotec.com.sa |
Pass configuration at build time:
bash
flutter build apk \
--dart-define=API_BASE_URL=https://gateway.microtecstage.com \
--dart-define=KEYCLOAK_URL=https://keycloak.microtecstage.comTroubleshooting
Clock-in fails with location permission error
- Ensure the app has location permissions granted on the device.
- On Android 12+, background location requires a separate "Allow all the time" permission.
- Test with the device's GPS turned on — the app requires a real GPS fix, not network location.
Approvals inbox shows empty despite pending items
- Confirm the user's Keycloak role includes the relevant approval role (
approvals.po.view,approvals.leave.view). - Check the device's internet connectivity — the inbox is not cached offline.
- Pull-to-refresh to force a reload.
Melos bootstrap fails after pulling new changes
bash
cd ERPMobileApps
flutter clean
melos run init