Client project

DawaPoint

A pharmacy point of sale and stock system for Kenyan chemists — it sells by pack, strip or single tablet, hands out the earliest-expiring stock first, takes M-Pesa at the till, and keeps the controlled-drugs register and insurance claims in the same place.

year
2026
role
Product design & full-stack engineering
type
Client project
stack
10 technologies
DawaPoint counter — barcode search, the fast-moving medicines priced by capsule, strip and pack, today's receipts on the till, and an empty cart ready to take cash, M-Pesa or cardDawaPoint product catalogue — each medicine with its units and prices, stock on hand, stock value, earliest expiry date and whether it is over the counter or prescription-onlyDawaPoint goods received — notes from six pharmaceutical suppliers, each posted to stock as batchesDawaPoint insurance claims — awaiting payment, submitted and rejected totals, and a new claim against a receipt with member number, policy, pre-authorisation code and co-pay

The problem

A Kenyan retail chemist sells the same medicine by the pack, the strip and the single tablet, and most systems model one unit — so staff divide in their heads and the stock count drifts. Expiry quietly eats margin when nobody can see which batch goes off next. M-Pesa is checked on a cashier's own phone, cash variances have no owner, the internet and power both drop, controlled-drug records are what a PPB inspection looks at first, and insurers pay only on itemised, correctly referenced claims.

My approach

I built it as a counter first: scan or type, Enter adds, function keys for tender, hold and recall, and every product priced per unit it is sold in. Behind the counter sits a batch-level stock ledger fed by goods-received notes, so the till can sell first-expiry-first-out; shifts that open with a float and close with a blind count; M-Pesa prompts sent from the till; a prescription and controlled-drugs register; insurance claims raised against receipts; supplier balances and reports. It shipped with a written acceptance script, staff training sheets and an owner's handover pack, not just the software.

How it's built

  • A pnpm/Turborepo monorepo: a Next.js 16 back office and point-of-sale terminal (installable PWA), a Hono API, and shared packages for domain logic, the database, auth, Zod contracts and design tokens.
  • Domain rules — money, units of measure, access control, first-expiry-first-out allocation, pricing and reordering — live in a package with no I/O at all, tested on their own.
  • PostgreSQL row-level security: the API connects as a role that owns nothing, and every tenant table filters on a tenant id set per transaction, so one pharmacy's query cannot read another's rows even by mistake.
  • The audit trail is an append-only table whose rows are SHA-256 chained; an endpoint recomputes the chain to prove nothing was edited after the fact.
  • The counter keeps selling offline: catalogue and prices cached in IndexedDB, sales held in a durable outbox and synced when the connection returns.
  • M-Pesa through Daraja STK Push from the till, confirmed by callback with a status query as the fallback, and a simulator for training without real money.

Highlights

  • Sells the way a chemist does — by pack, strip or single tablet, each with its own price — while stock is held in base units, so the count still adds up.
  • Every supplier delivery creates batches with expiry dates, and the counter hands out the earliest-expiring first.
  • Prescription and controlled medicines are flagged on the product; a controlled sale goes into a register that needs a witness.
  • Insurance claims raised against the receipt, tracked from draft to paid, and exported for the insurer's portal.
  • An audit log that can prove it has not been edited.