The Problem
Small restaurants need a low‑cost, offline‑first point‑of‑sale app that can track inventory, take orders, and produce printable receipts without relying on external services. Existing commercial solutions are expensive or require constant internet connectivity, creating a barrier for tight‑margin businesses.
What This Does
The repository implements a full Flutter application that runs on Android (and potentially iOS) devices.
lib/main.dartboots the app and injects the top‑levelMyAppwidget.- Navigation is defined in
lib/routes.dart(≈ 729 lines) which maps URL‑style route names to widget factories. - UI components such as the menu, order entry, and analytics live under
lib/ui/andlib/components/. - Business logic for inventory, order persistence, and analytics resides in helper files like
lib/helpers/logger.dartandlib/helpers/breakpoint.dart. - Platform‑specific code for Android is in
android/app/src/main/kotlin/com/evanlu/possystem/MainActivity.kt; iOS stubs are underios/.
The app stores data locally on the device (SQLite via the sqflite package, inferred from pubspec.yaml dependencies) and can export CSV/Excel files through the “Transit” feature (lib/ui/transit/plain_text/export_basic_view.dart).
How It Is Wired
- Startup – Execution begins at
lib/main.dart→runApp(MyApp()). - Dependency injection –
MyAppcreates aMaterialAppwhoseinitialRouteis defined inlib/routes.dart. - Routing –
routes.dartholds a map of route strings to widget builders; each builder pulls required helpers (e.g., inventory service) from a singletonAppProviderdefined elsewhere inlib/. - Feature modules – Inventory – UI in
lib/ui/menu/callsInventoryService(inlib/helpers/) which writes to the local DB. Order flow –lib/ui/order/widgets interact withOrderService; receipt printing usesPrinterHelper(found underlib/helpers/printer.dart). * Analytics –lib/ui/analysis/builds charts from data supplied byAnalyticsRepository. - Platform bridges – Android channel communication is set up in
android/app/src/main/kotlin/com/evanlu/possystem/MainActivity.kt, exposing Bluetooth printer APIs to Dart viaMethodChannel.
Only two internal modules appear in the import graph, with no circular dependencies, so most changes stay local to a single feature folder. The largest blast‑radius files are lib/routes.dart (central navigation) and the oversized test mocks in test/mocks/.
How To Use It
# Clone the repository
git clone https://github.com/moses-y/flutter-pos-system.git
cd flutter-pos-system
# Install Flutter dependencies
flutter pub get
# Run the app on an attached device or emulator
flutter run
No additional environment variables are required; the app reads no external secrets at runtime. For Android builds, Gradle wrappers are configured in android/build.gradle and android/app/build.gradle. iOS build instructions are not present (iOS is “coming soon”).
Real‑World Use
A coffee shop installs the app on a cheap Android tablet. Staff open the menu screen (lib/ui/menu/), add items to an order, and tap “Print receipt”. The receipt is sent over Bluetooth via the PrinterHelper to a thermal printer. End‑of‑day, the manager opens the analytics screen (lib/ui/analysis/) to view sales trends without any internet connection.
Code Health & Issues
Measured findings (static analysis)
- HIGH – Deep nesting – 20 files (e.g.,
lib/ui/transit/formatter/plain_text_formatter.dart) have indentation depth ≥ 10. - HIGH – Duplicated code blocks – 431 six‑line repeats across 85 files (e.g.,
lib/components/style/card_info_text.dart). - MEDIUM – File opened without context manager –
scripts/paint_introduce.py. - MEDIUM – Oversized files –
lib/routes.dart,test/mocks/mock_google_api.mocks.dart,test/services/auth_test.mocks.darteach > 700 lines. - MEDIUM – High branching density – 21 files (e.g.,
lib/helpers/logger.dart) show > 50 branch points per ~150 lines.
Code‑health audit
- CRITICAL – Secrets in workflow –
.github/workflows/deploy-to-playstore.yamlcontainsGH_READ_PAT,GOOGLE_SERVICES_JSON*,PLAY_STORE_UPLOAD_KEY. - HIGH – Unpinned GitHub Actions – All workflow files reference actions by tag (e.g.,
subosito/flutter-action@v2). - HIGH – Missing Gem lockfile –
android/Gemfilehas no accompanyingGemfile.lock. - HIGH – CI never runs tests – No test step in any workflow despite 95 test files.
- MEDIUM – Least‑privilege GITHUB_TOKEN – Workflow lacks explicit
permissionsblock. - MEDIUM – No Dependabot – No
dependabot.ymlto keep dependencies current. - MEDIUM – No dependency‑vulnerability scan – No
dependency-review-actionor similar step. - MEDIUM – Large binaries in repo –
docs/images/ham-burger.jpg(14 MB) andTra-Chi.ttf(8 MB) exceed 5 MB. - LOW – No job timeouts – Workflows omit
timeout-minutes. - LOW – Missing convention files – No
.editorconfig,.gitattributes, or formatter config.
The Bottom Line
The project delivers a functional offline POS app with a clear Flutter codebase, but the code quality suffers from deep nesting, duplicated blocks, and several oversized files. CI security is a serious concern: secrets are exposed in workflows and tests are never executed. For a small restaurant willing to invest in code cleanup and CI hardening, the app provides a solid starting point; teams lacking security expertise should address the critical workflow issues before production use.