Skip to content

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

PropertyValue
DirectoryERPMobileApps/
PlatformAndroid, iOS
Backend servicesAppsPortal.Apis, HR.Apis, Inventory.Apis
Keycloak realmmicrotec
Offline supportPartial (attendance check-in/out, read-only item lookup)
Auth flowKeycloak 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.yaml

State 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):

  1. User clocks in — event saved to local DB with SyncStatus.pending.
  2. If connectivity is available, the event is immediately sent to HR.Apis.
  3. If offline, the SyncManager retries on reconnect using connectivity_plus stream.
  4. On sync success, the local record is marked SyncStatus.synced.

Shared Libraries Used

LibraryUsage in ERPMobileApps
MobileDesignSystemAll UI — buttons, cards, bottom sheets, typography, ERP colour palette
MobileAPIClientsGenerated Dart clients for AppsPortal.Apis, HR.Apis, Inventory.Apis
MobileSharedCompKeycloak 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 test

Authentication 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 typeTriggerSource
New approval requestPO, leave, or invoice createdAppsPortal.Apis → Notification.Apis
Leave request decisionManager approves/rejectsHR.Apis → Notification.Apis
Attendance reminderClock-in or clock-out reminderHR.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');
}
EnvironmentAPI Base URLKeycloak URL
devhttps://gateway.microtec-test.comhttps://keycloak.microtec-test.com
stagehttps://gateway.microtecstage.comhttps://keycloak.microtecstage.com
productionhttps://gateway.onlinemicrotec.com.sahttps://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.com

Troubleshooting

Clock-in fails with location permission error

  1. Ensure the app has location permissions granted on the device.
  2. On Android 12+, background location requires a separate "Allow all the time" permission.
  3. 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

  1. Confirm the user's Keycloak role includes the relevant approval role (approvals.po.view, approvals.leave.view).
  2. Check the device's internet connectivity — the inbox is not cached offline.
  3. Pull-to-refresh to force a reload.

Melos bootstrap fails after pulling new changes

bash
cd ERPMobileApps
flutter clean
melos run init

Internal Documentation — Microtec Platform Team