Customer orders
Cashier taps menu items on the touch-optimized POS. Cart updates instantly with running subtotal.
Mobile (tablet) or web · 44 px touch targets · category filter + SKU search
How it works
Below: the live transaction lifecycle, the offline-sync mechanics, and the 5-day onboarding plan.
The transaction lifecycle
Every sale flows through these six stages — all inside one atomic database transaction. If anything fails, the whole thing rolls back: no half-deducted ingredients, no orphan receipts, no gap in the sequence.
Cashier taps menu items on the touch-optimized POS. Cart updates instantly with running subtotal.
Mobile (tablet) or web · 44 px touch targets · category filter + SKU search
Apply Senior / PWD / Promo / Manual discount. Choose Cash, GCash, Bank transfer, or Charge-to-account.
Senior · PWD require OSCA / PWD ID for audit · 20% off computed server-side
Backend takes a row-lock on the per-branch counter and assigns the next sequential number — zero gaps even under 60 concurrent transactions.
SELECT … FOR UPDATE inside prisma.withTenant transaction
Recipe components multiply by quantity. Ube paste, condensed milk, sugar — each draws down in the commissary in the same transaction.
Atomic with the receipt insert · insufficient stock → CONFLICT, full rollback
The branch running total goes up by the transaction amount. Monotonic — voids reverse stock but never lower the accumulator.
Database CHECK + trigger enforce monotonicity — application bugs cannot violate it
Socket.IO broadcasts pos.transaction.created to the tenant room. HQ sees the receipt within milliseconds.
Receipt prints locally · audit log records cashier, branch, recipe, payment
Offline-first sync
Filipino retail reality: the internet drops. Kusina was designed offline-first from day one — your branches never stop transacting, and reconciliation is automatic when the network returns.
The branch tablet is online. Cashiers transact and HQ sees every receipt within milliseconds. Receipt numbers are assigned live by the server.
Internet goes down — rural area, brownout, ISP outage. The branch app detects the drop and routes every operation to the local SQLite queue instead of the network.
Each transaction is queued locally with a clientId UUID for idempotency. Customers receive a provisional receipt clearly marked PROV. Stock deducts locally so kitchen runs uninterrupted.
Network restored. The SyncFacade batches the queue and POSTs to /v1/sync. Each op carries its clientId — duplicates are de-duplicated, retries are safe. The server allocates official sequential receipts and returns the mapping. Customer-facing reprints are available.
Every operation carries a UUID generated client-side. Re-sending the same op produces no duplicate row.
BIR sequence is owned by the server, not the device. Provisional numbers are local-only and replaced on sync.
recordedAt (when sold) and syncedAt (when posted) are stored. Reports use recordedAt — sales attribute to the right day.
Onboarding
We map your existing menu, recipes, branches and employees. Data migrates from spreadsheets, UTAK, or your current POS. (Days 1–2.)
On-site install of tablets / printers / cash drawers. Cashier + manager training. BIR paperwork prepared in parallel. (Days 3–4.)
Live transactions begin with a CSM on-call. 30-day check-in. Continuous improvements via monthly product releases. (Day 5+.)
BIR Accreditation
Three BIR invariants are enforced by Postgres CHECK constraints and triggers — not by application code that could have bugs.
Receipts allocated per-branch with database row-locks — no gaps even under 60 concurrent transactions.
Z-Reading rows are blocked from UPDATE/DELETE by a database trigger. Once the day closes, it stays closed.
Grand Total Accumulator only increases. Voids reverse stock but never decrease the accumulator — BIR requirement.
Every transaction, void, void-reason and operator is logged with a tamper-evident audit log.
Book a 30-minute walkthrough. We will demo the modules that match your operation and quote a setup plan.