You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fast · Offline · Secure Android Point-of-Sale for Kenyan mini-markets
Built with Kotlin + Jetpack Compose 🇰🇪
📱 Screenshots
Login
Dashboard
New Sale
Checkout
Credit Payment
Customer Search
✨ 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
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)
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