The challenge
A private clinic group operating in-house pharmacies at several of its branches was tracking medicine stock at the box level in a spreadsheet per branch. Batch numbers and expiry dates were recorded, when they were recorded at all, on the physical packaging only — so identifying what needed to be pulled from the shelf after a supplier notice meant physically checking every branch.
Dispensing was disconnected from stock. A pharmacist handed over medication and, separately, someone decremented a count later in the day, which meant the recorded quantity and the shelf quantity routinely disagreed. Because each branch kept its own file, a branch could be out of an item while another branch held surplus that nobody could see, and transfers between branches were arranged informally with no record of what left and what arrived.
Controlled medicines needed a register that could stand up to inspection, and the group needed reordering to be driven by actual consumption rather than by a pharmacist noticing a shelf looked empty.
Our approach
We built a pharmacy inventory and dispensing system where stock is tracked per batch, not per product — every unit on hand belongs to a specific batch with its own expiry date and supplier reference. That makes expiry visibility and recall handling a query rather than a physical audit, and it lets the system dispense on a first-expiring-first-out basis by default rather than leaving batch choice to whoever reaches the shelf first.
Dispensing and stock movement were made the same transaction. A dispense against a prescription decrements the specific batch it came from at the moment it happens, so the recorded quantity is a consequence of the dispensing record rather than a separate number maintained alongside it. Every movement — receipt, dispense, transfer, adjustment, write-off — is an immutable ledger entry with a reason and an acting user, so current stock is derived from the movement history and any discrepancy can be traced to the entry that caused it rather than argued about.
Branches share one inventory view while keeping their own stock positions, so a pharmacist can see availability across the group and raise a transfer that is confirmed on receipt at the destination — an in-transit state, not an unrecorded handover. Controlled medicines are flagged at the product level and dispensing them requires additional recorded authorization, producing a register with a complete, attributable movement history. Reorder points are set per branch and per product and evaluated against actual consumption, so replenishment is prompted by the data rather than by observation.
Outcome
Stock is now tracked by batch and expiry across every branch from one view, and identifying affected units after a supplier notice is a lookup rather than a shelf-by-shelf check. Recorded quantities move as a direct consequence of dispensing rather than being reconciled afterwards, and inter-branch transfers and controlled-medicine dispensing both leave a complete, attributable record.


