Skip to content

Repository files navigation

MiniMart POS

🛒 MiniMart POS

Fast · Offline · Secure Android Point-of-Sale for Kenyan mini-markets

Built with Kotlin + Jetpack Compose 🇰🇪

Release Build Android Kotlin Room DB


📱 Screenshots

Login Dashboard New Sale
Login Dashboard New Sale
Checkout Credit Payment Customer Search
Checkout Credit Customer

✨ Features

🛍️ New Sale

  • Camera barcode scanner (ML Kit — EAN-13, UPC, QR, Code-128, Code-39, Data Matrix)
  • Bluetooth / USB HID barcode scanner support
  • Weighing scale support (PLU) — decodes variable-weight EAN-13 barcodes, auto-calculates price from weight × price/kg, weight persisted in sale records and correctly shown (not "×1") on both the in-app and shareable PDF receipt
  • Continuous scan mode with animated laser overlay, corner brackets, green flash confirmation, and live scan counter badge
  • Product search by name or barcode with live dropdown
  • Cart with quantity stepper, per-item discounts
  • Inclusive VAT — tax extracted from price, not added on top
  • Cart badge on bottom nav shows pending item count when navigating away

💳 Checkout & Payments

  • Cash — quick-amount buttons, real change calculation
  • M-Pesa — ref number field
  • Credit — customer wallet or buy-on-account (negative balance allowed)
  • Split payment — combine credit + cash in one transaction
  • Customer selector with search + contacts import — debtors (customers who owe money) are clearly flagged in red, not shown the same as a zero balance
  • Cash drawer auto-opens on cash payment (configurable)
  • Haptic feedback confirms every completed sale
  • All money displays respect the app's configurable currency setting (no screen is hardcoded to "KES")

👤 Customer Credit System

  • Register customers with name, phone, email
  • Credit wallet — deposits, deductions on purchases
  • Buy on account — negative balance allowed
  • Full transaction history per customer
  • Credit Ledger — all non-zero balances at a glance
    • 🔴 Debtors (negative, owe money) shown first with "OWES [currency] X" in red
    • 🟢 Wallet balances shown in green
    • Two summary stats: "Owed to Shop" + "Wallet Credit"
    • Same red/green treatment applied consistently across the customer list, customer detail sheet, and the checkout customer picker

🌐 Multi-Device LAN Sync

  • No internet, no cloud — pure local WiFi sync
  • Pairing code authentication — 6-digit code shown on server device, required on client device — any WiFi visitor cannot read or inject data
  • Server device: toggle "Act as Sync Server", share the displayed code
  • Client device: enter server IP + pairing code → Sync Now
  • Pending-changes amber badge + progress spinner during sync

🗃️ Cash Drawer

  • ESC/POS kick via thermal printer RJ11 port
  • Direct Bluetooth cash drawer support
  • Auto-opens on cash payment (toggle) · Test button in Settings

📦 Inventory & Products

  • Add/edit: price, cost, stock, category, SKU, unit, tax rate
  • Supplier info + reorder quantity · Batch number + expiry date
  • Color-coded expiry urgency badges · Low-stock background alerts (WorkManager)
  • Stock adjustments with reason log
  • PLU / Weighing scale toggle per product (PLU code + price/kg)
  • Delete confirmation clearly warns the action is permanent

📊 Reports & Analytics

  • Revenue vs yesterday (real % comparison, flips red when down)
  • Dashboard auto-refreshes at midnight — "today" always means today
  • Transaction count, average basket, top-selling items
  • Reports & Expenses use proper calendar week (Mon–Sun) and calendar month, not rolling 7/30-day windows
  • Sales History: color-coded payment method chips (💵 Cash / 📱 M-Pesa / 🤝 Credit / 🔀 Split)
  • Quick Void on COMPLETED sales from the history list (Manager+)

👥 Role-Based Access Control

Permission Owner Manager Cashier
Process sales
Apply discounts
View reports
Edit products
Void sales
Multi-device sync
User management

Route-level AccessGuard bounces unauthorized users automatically. Cannot remove the last active Owner account (permanent lockout protection). Removing a user requires an explicit two-step confirmation.

🔐 Security

  • Argon2id PIN hashing (t=3, m=64MB, p=4), auto-upgrades legacy SHA-256 on login, constant-time comparison on both paths (no timing side-channel)
  • Biometric login — bound to one explicitly opted-in user per device (Settings → Account). Any fingerprint on the device cannot authenticate as an arbitrary username.
  • Persisted 3-strike lockout — survives force-close, task-kill, and device reboot (stored via DataStore, not in-memory state)
  • 15-minute inactivity auto-logout
  • Persistent audit log at files/audit.log:
    • LOGIN_SUCCESS / LOGIN_FAILED (with attempt count + lockout flag)
    • LOGOUT
    • SALE_COMPLETED (receipt number, amount, payment method)
    • DISCOUNT_APPLIED
    • CREDIT_USED
    • SESSION_EXPIRED
  • Sync pairing code — LAN sync server requires a 6-digit code, preventing unauthorized WiFi devices from reading or injecting data
  • At-rest protection: the database relies on Android's File-Based Encryption (FBE), hardware-backed and enabled by default since Android 7.0 — every supported device (minSdk 26) has it. App-level SQLCipher encryption was evaluated twice and reverted both times due to native-library crashes on startup; FBE was judged the safer, zero-maintenance choice for this app.

💾 Backup & Data

  • One-tap backup to Downloads/MiniMartPOS/backups/
  • Restore requires explicit two-step confirmation — selecting a backup shows exactly what will be lost before anything is overwritten, then the app automatically restarts (WAL/SHM files handled correctly, no manual close needed)
  • 100% offline — Room SQLite v12, no internet required for core operation

🎨 UI / UX

  • Deep dark teal theme — readable in bright retail lighting
  • Time-of-day Swahili greeting: Habari ya asubuhi / mchana / jioni
  • Consistent gradient top bar across all screens
  • Press-scale animation on dashboard action cards
  • Color-coded payment method chips throughout
  • Consistent destructive-action dialogs app-wide (styled red confirm + bordered cancel, clear "cannot be undone" copy) for delete/void/remove/restore
  • Animated scanner overlay: pulsing border, sweeping laser, corner brackets
  • Pull-to-refresh on dashboard (updates today + yesterday revenue)

🏗️ Tech Stack

Layer Technology
Language Kotlin 2.0
UI Jetpack Compose + Material 3
Architecture MVVM · Clean Architecture · Repository
DI Hilt
Database Room 2.6 (SQLite v12), Android FBE at rest
PIN Security Argon2id (argon2-kt 1.4.0)
Camera CameraX + ML Kit Barcode
Sync Custom HTTP server/client over LAN WiFi, pairing-code authenticated
Background WorkManager (low-stock + expiry alerts)
Preferences DataStore + SharedPreferences
Printing Bluetooth ESC/POS
Navigation Navigation Compose
State SavedStateHandle for process-death recovery (e.g. Receipt screen)

🚀 Getting Started

git clone https://github.com/Baker0o7/MiniMart-Pos.git
cd MiniMart-Pos
./gradlew assembleDebug

First-launch credentials

Field Value
Username admin
PIN 1234

📁 Project Structure

app/src/main/kotlin/com/minimart/pos/
├── data/
│   ├── dao/          ProductDao · SaleDao · UserDao · ExpenseDao
│   │                 ShiftDao · CustomerDao · SyncDao
│   ├── db/           AppDatabase (v12) · DatabaseCallback (seed)
│   │                 AppMigrations (v8→v9→v10→v11→v12)
│   ├── entity/       Product · Sale · SaleItem · User · Expense
│   │                 Shift · Customer · CreditTransaction · SyncLog
│   └── repository/   (one per entity + SettingsRepository)
├── di/               DatabaseModule
├── printer/          ThermalPrinter · CashDrawerManager
├── scanner/          MLKitScanner · KeyboardScanner · BluetoothScannerManager
├── sync/             SyncServer · SyncClient
├── ui/
│   ├── screen/       16 screens (Login → CreditOverview)
│   ├── viewmodel/    Per-screen ViewModels + SessionViewModel · SyncViewModel
│   ├── theme/        DT color tokens
│   └── NavGraph.kt   Routes + BottomNavBar (cart badge) + AccessGuard
├── util/             BackupManager · PdfReceiptGenerator · PinHasher
│                     RoleManager · SessionManager · AuditLogger · PluDecoder
│                     UiResult
└── worker/           LowStockWorker · ExpiryAlertWorker

⚙️ CI/CD Signing Secrets

SIGNING_KEY_ALIAS      = minimart
SIGNING_KEY_PASSWORD   = android
SIGNING_STORE_PASSWORD = android

Built with ❤️ for Kenyan mini-markets 🇰🇪

Download APK

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages