Kaasa · Technology
Builtforaphonewithaqueueinfrontofit,notalaptopwithWi-Fi.
This page is for the person who asks "but how does it actually work": the shop owner's nephew who does IT, the auditor, the incubator reviewer. Three properties decide every engineering call, in this order: the numbers must be right, the shop must be able to bill without internet, and a bill must take seconds.
Thebillissavedonthephonefirst.Always.
Kaasa is one Flutter and Dart codebase for Android and Windows. On the device it keeps a full relational database — Drift on top of SQLite — encrypted with SQLCipher. The encryption key sits in the Android Keystore or Windows DPAPI, never in the app's own files. Staff PINs are hashed with a per-member salt and never synced.
Every user-facing write goes to that local database before anything else. A sync outbox then queues it for the server and retries when a connection returns. No screen waits on the network to let the cashier move on. Offline is a normal state in the code and in the copy, not an error state.
Orders, items, payments, stock movements and khata entries are append-only. A correction is a reversing entry, never an edit. Cached totals such as stock on hand or a customer's balance are computed by the server from those events; the app shows a local computation until sync catches up.
Money is a decimal end to end, stored as text-backed decimal, formatted with Indian digit grouping, and rounded once at the documented boundary using the shop's own rounding rule. There is no floating-point number anywhere a rupee travels.
Voiceisaninputmethod,notasecondbillingsystem.
When a cashier says "rendu attar, oru bottle perfume", the audio goes to Kaasa's own voice gateway, which forwards it to a Tamil and English speech provider chosen by a routing table on the server. The app never names a vendor and never holds a provider key. Switching the speech provider is a database update, not an app release.
The transcript that comes back is not the bill. A deterministic parser on the device matches the words against this shop's catalogue — in phonetic space, against a closed vocabulary of the items the shop actually sells, plus the aliases its staff use — and decides item, quantity and unit. The result becomes the same cart operation a tap produces. Pricing, tax, rounding and invoice numbering never know voice was involved. Voice can fill and edit a cart; payment always needs a tap.
Voice billing needs internet today, because the speech model runs in the cloud. Tap billing works fully offline. An on-device Tamil engine (sherpa-onnx with a Conformer model downloaded on Wi-Fi) is on the roadmap and will not be marketed until it passes a real-counter benchmark. Voice bills are metered per plan, since each one has a real cost; when a shop runs out, tap billing continues and a top-up is offered, never charged on its own.
Audio is processed and discarded. It is retained only if the shop switches on the "help improve voice recognition" setting, which is off by default.
AGSTengine,notataxcalculator.
Four decisions are kept separate: what is being sold, where the supply legally occurs, which rule governs it, and what the arithmetic is. Fusing them is invisible at an over-the-counter sale and wrong the moment a delivery address exists.
- Place of supply is resolved by named, versioned rules from the IGST Act — goods collected at the counter, goods delivered, services to a registered or unregistered recipient — and the method used is recorded on the bill, so an assumption is inspectable later.
- CGST + SGST or IGST follows from the shop's state and the place of supply. Shops not registered for GST issue bills of supply without tax.
- HSN codes are aligned to the GSTN master, because a return can no longer contain a code the software invented. B2B lines require an HSN before the bill can be finalised.
- Rule 31D valuation. Pan masala, tobacco and cigarettes are taxed on the printed retail sale price, not the discounted transaction value. The engine carries valuation method as a first-class field, so a pan shop's bills are right.
- Credit notes for returns carry the original rate. Monthly GSTR-1 and GSTR-3B summaries are built from the same records the bills were cut from.
- Rates are data. Slabs, thresholds and effective dates live on the server with history, so a notification changes a row, not an APK. E-invoice and e-way bill are available as an add-on.
Printingthatworkswiththeprinteryoualreadybought.
Thermal receipts are rendered to ESC/POS for 58 mm and 80 mm printers over Bluetooth, USB or LAN, with Tamil rendered correctly on the roll. A4 PDF invoices in colour go to any printer, email or WhatsApp. Printing never waits for the server: the receipt is produced from the local record.
Theserverownsthethingsabusinesschanges.
The backend is managed Postgres in Mumbai, with row-level security on every table that holds shop data: a query from one shop cannot return another shop's rows. The app talks to one versioned API surface and never to tables directly, through a single package that is the only place a vendor SDK appears — so moving providers is one package and one base URL.
Plans, prices, limits, tax rates, feature flags, languages and speech providers all live in server configuration, cached on the device with a last-known-good fallback. What a plan allows is checked against a server-signed entitlement token, never a local boolean. If a subscription lapses, the token keeps the shop billing for a 30-day grace period; sync, exports and cloud voice lock first, local billing never does.
Payments are verified server-side with the gateway before any subscription changes. Neither the app nor a webhook body is trusted to say "paid".
Encryption, residency, retention, subprocessors and responsible disclosure are on the security page.
