Benson Osei-Mensah

Selected work · 03 of 04

Mfaso

Point of sale for a shop where the internet comes and goes, and so does the power.

The problem

A shop in Ghana needed to sell, track stock, give credit to regulars, and know at the end of the day whether the cash and mobile money matched. The internet is intermittent. The power cuts out. The computer is whatever modest laptop is on the counter, and nobody at the shop will ever run a server.

I wrote the success criteria before any code:

  • A walk-in sale takes under ten seconds, keyboard only.
  • The owner can see sales, profit, low stock and who owes money with no internet at all.
  • A power cut never loses a sale the screen said was saved.
  • A dead hard drive loses at most fifteen minutes of work.

The shape of it

Mfaso: one program on the shop computerHTTPHTTPLaunchertray icon, restarts the serverPhones on shop Wi-FioptionalTill screenReact, built inServerone Go binaryReceipt printerSQLiteevery write on diskLocal snapshotsevery 15 minutesCloud copyencrypted, when online
The screen only ever talks HTTP, so a second till is a setting, not a rewrite.

Mfaso is one Go program. Started from the tray, it supervises a local server and opens the till in an app window. The server owns the SQLite database, the receipt printer, backups and updates, and serves the React interface from inside the binary. Because the interface only talks to the server over HTTP, letting a phone on the shop Wi-Fi act as a second till is a configuration change, not a new architecture.

Decisions that mattered

Money is never a float. Amounts are whole pesewas; quantities are whole thousandths of a unit. Nothing is ever deleted: sales are voided, stock is corrected, and every change leaves a new entry.

The ledger is the truth. Every stock movement goes into an append-only ledger. The on-hand count is only a cache of that ledger, updated in the same transaction, and a test asserts the two always agree. If they ever disagree, the count can be rebuilt from history.

A sale is all or nothing. One immediate transaction checks for a duplicate submission, checks stock, writes the sale with each line’s cost at that moment, moves stock, records payments and assigns the receipt number. Any failure rolls back the whole sale. A test fires twenty sales at once against ten items in stock: exactly ten succeed, with receipt numbers that have no gaps and no repeats.

Profit doesn’t rewrite itself. Each sale records the average cost at the time of sale, so last month’s profit stays last month’s profit when prices change. The owner taking cash home is recorded separately from expenses, so it doesn’t make the shop look less profitable than it is.

Built for the power cut. SQLite runs in write-ahead mode with full sync, so a sale is on disk before the screen says so. Every start-up runs an integrity check and falls back to the newest good snapshot if it fails. Snapshots are taken every fifteen minutes when something changed: forty-eight recent ones and thirty dailies kept locally, an encrypted copy sent to cloud storage whenever the internet comes back, and an encrypted export for a USB stick.

Updates that can’t strand a shop. Updates are checked against a signature whose public key is compiled into the program. The database is backed up before any migration, the previous version is kept, and a failed health check rolls back automatically.

Saying no. Electron would have shipped a whole browser to a 4 GB laptop for no gain. A browser-only app couldn’t drive a USB receipt printer reliably, and the data needed one home for a shared till. Phones on the shop Wi-Fi get no offline queue, because two devices selling the same last item offline is how a shop oversells.

What shipped

One installer that turns a counter laptop into a shop system:

  • The till: keyboard-first sales, receipts on a USB or network printer, and cash, mobile money, bank or credit on the same sale.
  • Stock: a catalogue with units and pack sizes, purchases at weighted average cost, and an answer to “what’s running low” at any time.
  • Credit: customers who pay later and suppliers the shop owes, with every balance traced to its sales and payments.
  • Money: a daily cash-up that compares the drawer and mobile money against what the system expects, plus expenses, owner drawings, and profit reports.
  • People: owner, manager and cashier roles with PIN sign-in, discount limits and void rules for each.
  • Safety: backups every fifteen minutes, an encrypted cloud copy, a USB restore, and updates that roll themselves back if anything goes wrong.

The shop runs all day without the internet, and a power cut costs it nothing it had already saved.