Skip to content

Healthcare SaaS Module · Pharmacy Inventory & Storefront

Pharmacy Inventory & PharmaStock

The pharmacy side of the Simple Green Solutions healthcare platform: an append-only stock ledger, inventory and order management for each pharmacy, the PharmaStock storefront with oversell-proof multi-pharmacy checkout, and operator approval of pharmacies and products.

  • Pharmacy dashboard with revenue trend, stock alerts and a live activity feed. Demo data.
  • Append-only stock ledger: every add, removal, sale and count correction is recorded as a movement. Demo data.
  • Inventory with stock-status filters and per-product approval status from platform moderation. Demo data.
  • Order management across the lifecycle, from new order to ready for pickup and completed. Demo data.
  • PharmaStock checkout splits one cart into a separate order for each pharmacy. Demo data.
On this page

This is the pharmacy side of Simple Green Solutions, the multi-tenant healthcare platform I led. It shares that platform's accounts, organizations and permissions, and this page covers what pharmacies, their customers and the platform operator get from it.

The Problem

An independent pharmacy has to do three jobs at once: keep its shelves right, sell to patients, and stay trustworthy for the doctors who send patients its way. The usual tools split those jobs apart. Stock lives in a spreadsheet or a desktop program, online orders (if there are any) come in by phone or message, and a doctor writing a prescription has no idea which pharmacy actually has the medicine.

Putting pharmacies onto a shared healthcare platform raised harder requirements than a single-shop stock system ever faces:

  • Stock that two people can change at once. Staff receive deliveries and write off damaged boxes while customers check out online. The classic "read the quantity, subtract, save it back" quietly loses updates and oversells.
  • A history you can audit. When the shelf says 6 and the screen says 9, someone has to be able to see every change that led there, who made it and why.
  • One storefront, many pharmacies. A patient's cart can hold medicines from several pharmacies, and each pharmacy must see only its own orders and stock.
  • Regulated products need a gatekeeper. A new pharmacy, and every product it lists, has to be checked before patients can see it.
  • Doctors should prescribe what really exists. Prescriptions should come from medicines actually stocked on the platform, without tying the patient to one shop.

What I Built

A complete pharmacy module inside the platform, roughly 12,600 lines of TypeScript across 19 pages, built with Next.js 16 (App Router, Server Components and Server Actions), React 19 and MongoDB. It has four parts: a back office for each pharmacy, a public storefront called PharmaStock, the operator's approval tools, and the link that lets doctors prescribe from live stock.

An append-only stock ledger

The decision everything else rests on: a stock item has no quantity field. Its quantity is the sum of an immutable ledger of movements, each one an initial balance, an add, a remove, a sold or an adjustment, recording who made it, when, and an optional note.

  • Every change is a new row, so two staff members adjusting the same item at the same moment can never overwrite each other
  • Corrections are new movements, never edits, so the history is complete and tamper-evident
  • Stock status (in stock, low, critical, not available) is derived when it is read from the ledger sum and each item's own thresholds, so a badge can never disagree with the number it describes
  • Indexes keep the sum to a single pass, which is a small read cost for a large gain in correctness

Pharmacy back office

  • Dashboard: products, monthly revenue, orders and low-stock counts, a six-month revenue trend, stock by category and recent activity
  • Inventory: every product with price, category, quantity, value and approval status, filterable by stock state and searchable, plus a full product record:
    • SKU, unit type, manufacturer and expiry date
    • dosage, active ingredient and country of origin
    • warnings, contraindications and storage restrictions
    • low and critical thresholds, a maximum level, and images
  • Stock management: add or remove stock for many items in one go, with an optional note on each line and the full movement history per item. A bulk adjustment works out the net change per item across the whole batch before checking it, so a batch of −3 and −2 against a balance of 4 is rejected as a whole instead of half applied. Accepted batches are written in a single database transaction.
  • Orders: each order moves through new, confirmed, ready for pickup and completed (or cancelled), with counts and filters per status. Confirming an order and marking it ready emails the customer automatically. Email is best effort, so a mail failure never blocks the status change.
  • Analytics: revenue and order trends, sales by category and how products are spread across categories

PharmaStock: one storefront across pharmacies

A public catalog of every approved product from every approved pharmacy. It has search, category and price filters, and an infinitely scrolling product grid. Each product page shows its dosage, ingredients, warnings and contraindications, and each pharmacy has a public profile page. The cart is kept in the browser, so a guest's cart survives signing in partway through checkout.

Checkout that cannot oversell

A cart that spans several pharmacies is split into one order per pharmacy, each with its own subtotal, tax and total, and the whole checkout commits in one MongoDB transaction:

  • Stock is checked first, and a shortfall comes back as a plain message ("Paracetamol only has 3 left in stock")
  • Inside the transaction the ledger sum is calculated again, which closes the gap where another customer buys the last units between the check and the write
  • Every order and every "sold" movement is written together, so it is all or nothing across all pharmacies

Line items and customer details are copied onto the order, so a later price change or profile edit never rewrites order history. Delivery details are already stored on every order ahead of the delivery feature, so it can be switched on without reshaping live data.

Approval before anything goes public

  • Pharmacy onboarding: a new pharmacy submits its details and waits as pending until the platform operator reviews it, moves it under review, and approves or rejects it. The pharmacy's own screens check its approval status live, so a suspension takes effect on the next page load.
  • Product moderation: every new product starts as pending. The operator allows or rejects it, with a required reason shown back to the pharmacy, either one by one or in bulk. Trusted pharmacies can be switched to auto-approve. Only allowed products reach patients and doctors, while the pharmacy always sees its full list.

Prescribing from real stock

On the clinical side, the doctor's medicine picker is fed by live, approved pharmacy stock. It is de-duplicated by name and dosage, so a drug stocked by five pharmacies appears once, while different strengths stay separate. A prescription names a medicine, not a shop, so the patient is free to buy it anywhere on PharmaStock.


Outcomes

  • Overselling and lost stock updates are prevented by design. The ledger removes the overwrite race, and recalculating stock inside the checkout transaction removes the race between customers. Nothing depends on retries or luck.
  • Every unit has a history. Each change in stock can be traced to the person who made it and when, with an optional note explaining it, which is what an audit or a stock dispute needs.
  • Status that never goes stale. In-stock, low and critical are worked out from the real quantity every time, never stored and left to drift.
  • One checkout across many pharmacies. Patients buy from several shops in one go, and each pharmacy receives only its own order.
  • Nothing reaches patients unchecked. Pharmacies and their products are approved by the operator first, with reasons on every rejection and auto-approve for trusted shops.
  • Built on the platform, not bolted on. The whole pharmacy business fitted into the platform's existing identity and permission model with no changes to its core.
All projects

Have a project in mind?

Whether it's an MVP, a dashboard, or a rescue mission on an existing codebase — let's talk about it.

Prefer to talk first? Book a free 30-min call (opens in a new tab)