The in-house pharmacy of Lady Rafat Medical Centre, Karachi. 2025 to 2026
Point of sale and stock control for a clinic pharmacy
The pharmacy kept its stock in a 56-sheet Excel workbook, and nothing tied sales to supplier deliveries, returns or what customers owed. I built a Laravel 12 system around a sales counter run from the keyboard, with an 80mm thermal receipt, purchases and returns that move stock by fixed rules, and pay-later accounts for named customers.
- Sheets in the Excel workbook the stock lived in
- 56
- Thermal receipt that prints itself
- 80mm
- Return window, with super-admin sign-off
- 30 days
How the pharmacy system works
The problem
Fifty-six sheets, and nothing joined up
The pharmacy kept its stock in one Excel workbook with 56 sheets. Nothing tied a sale to the supplier delivery that stocked it, to a return, or to the balance a customer owed.
Step one
Moving the stock across
I wrote an analyser to study the packing formats in the workbook, then a template importer. It finds the header row by itself, matches columns by name so their order does not matter, and has a dry-run mode, so an import can be checked before anything is saved. It updates medicines that already exist by title, creates missing companies and categories, and retries when a generated code is already taken.
Every item is stocked and priced per selling unit, such as a tablet, a bottle or a packet, with 33 unit types to choose from.
Step two
A counter run from the keyboard
Cashiers press F2 to search by name or code, move around the cart with the arrow keys, save with Ctrl+S and cancel with Esc. They take cash, card or bank transfer, or put the sale on pay-later against a named customer.
The browser will not add an out-of-stock item or sell more than is on the shelf, and the server checks each item’s stock again. The receipt is laid out for an 80mm thermal roll and prints by itself.
Step three
Stock moves by fixed rules
A sale takes stock off the shelf. A supplier purchase can be edited and saved again without counting stock twice: each save reverses the purchase’s earlier lines, then applies the new ones and sets the retail price at an 18% markup. Once the supplier is paid, the purchase is locked.
Returns must come within 30 days, cannot exceed what was sold, and run inside database transactions. A cashier raises a return, only a super-admin can approve and complete it, and only then does the stock go back.
The result
What is owed, and what sold
Every customer’s page shows what they owe on pay-later sales, and a debt can be marked paid with the method used. The dashboard charts sales and revenue over the last seven days and shows what is low or out of stock. The sales, inventory and staff reports export to Excel and PDF.
How it fits together
How stock moves
- A sale is savedEach item comes off the shelf after the browser, then the server, checks its stock
- A sale is deletedIts items go back on the shelf
- A purchase is savedIts earlier lines are reversed and the new ones applied, so saving again never counts stock twice. Retail is set at an 18% markup
- A purchase is deletedIts stock comes back out
- The supplier is paidThe purchase is locked against edits
- A return is completedOnly after a super-admin approves it, within 30 days of the sale and never for more than was sold
Who can do what
Cashier
- Sells at the terminal and prints the receipt
- Adds customers, including from the terminal
- Raises returns, but cannot approve them
Super-admin
- Approves, completes or rejects returns
- Manages users and their roles
- Runs the reports and exports them