Dexova POS — Cashier & Reconciliation
A multi-outlet cashier with Midtrans QRIS, split payments, and per-shift cash reconciliation.
- Role
- Architect & Full-Stack Developer
- Period
- 2025 – present
- Category
- Deep dive · POS
- Source
- Private repo
- Stack
- GoPostgreSQL + sqlcMidtransNext.js (dex-pos)Web Bluetooth (ESC/POS)
Context
Dexova POS serves two personas: cashiers work in the cashier app (dex-pos); owners and managers run products, outlets, and reports from the admin dashboard (dex-fe). The core design goal: a cashier should be productive without lengthy training, while every rupiah stays traceable.
Transaction flow
- Product search + barcode scanning (html5-qrcode), with variants and add-ons.
- Tiered pricing per product: retail, wholesale, member.
- Hold & resume carts — a cashier can serve the next customer without losing a pending transaction.
- Customer selection for member pricing and history.
- Large catalogs stay smooth — the product list is virtualized (TanStack Virtual), and one codebase serves a tablet split-panel layout and a phone slide-up cart.

Payments
Every payment method common in Indonesian retail, in one checkout flow:
- Cash with change calculation.
- Midtrans QRIS — static (one QR for all transactions) and dynamic (per-transaction QR with a locked amount).
- Bank transfer and EDC.
- Split payment — one transaction paid with a combination of methods.
- Promo codes and discounts governed from the admin dashboard.

Shifts & cash reconciliation
The part that separates a serious POS from a sales recorder — per-shift cash accountability:
- Open a shift with opening cash; a single-active-shift rule prevents transactions without an accountable owner.
- Close a shift with reconciliation: the system compares expected cash against the physical cash the cashier counts.
- Shift summaries and daily cash reconciliation are available as owner reports.
Void & returns
- Void for unfinished transactions; partial or full returns for paid ones.
- Stock restores automatically on returns — real-time WebSocket sync with the Inventory module, no manual step.
- Void/return access is role-scoped (cashier vs manager), revocable from the dashboard.
Hardware & reports
- Thermal receipts over Web Bluetooth — a hand-written ESC/POS driver (not an off-the-shelf library), with reprint.
- Owner reports: best sellers, dead stock, margins, taxes, shift summaries — PDF/Excel export.
- Multi-outlet with per-outlet staff placement.

Outcome
- Non-technical cashiers are productive immediately; the transaction flow is built for rush hours.
- Cash is accountable per shift — differences surface the same day.
- Sales, returns, and stock stay consistent because POS and Inventory share one source of data.
Lessons learned
- 01
Reconciliation isn't a reporting feature — it's the trust contract between owner and cashier, and it must exist from the first transaction.
- 02
Automatic stock restoration on returns eliminates an entire class of 'stock doesn't match' bugs.
- 03
Payment integrations (Midtrans) are safest modeled as explicit status flows, never as an assumed 'it worked'.
Read next
Need a system like this?
I take on business-system projects — from architecture planning to an application running in production.