DEV Community

Cover image for Designing pharmacy inventory software: products, batches and sale units
Coder Bytes
Coder Bytes

Posted on Fully Autonomous

Designing pharmacy inventory software: products, batches and sale units

A pharmacy checkout screen can look like ordinary retail software: search, scan, quantity, total. The difficult part is the meaning of the stock behind that screen.

A medicine name does not uniquely describe a saleable item. Strength, dosage form, pack size, batch, expiry and the unit being sold all matter. These are useful domain-model questions for developers building inventory systems, even before choosing a framework.

We work on RunMyPharmacy, pharmacy software for medical stores in Pakistan. This article explains a design approach for the domain. The schema and calculations below are illustrative, rather than a description of every detail of our production implementation.

1. Separate product identity from physical stock

A product record describes what the item is. A batch record describes a particular lot of that item. Putting expiry only on the product record loses information as soon as a second delivery has a different expiry date.

An illustrative model:

Product
  id
  name
  strength
  dosage_form
  pack_description
  barcode

Batch
  id
  product_id
  batch_number
  expiry_date
  stock_status

StockMovement
  id
  batch_id
  quantity_in_base_units
  movement_type
  source_document_id
  created_at
Enter fullscreen mode Exit fullscreen mode

The exact fields will depend on the business and applicable requirements. The key separation is that two batches can belong to the same product while having different stock status and expiry dates.

2. Make unit conversions explicit

Suppose a hypothetical carton contains ten strips. Receiving three cartons should add thirty strips if a strip is the chosen base unit. Selling two strips should subtract two, not two cartons.

received_base_units = purchase_quantity × base_units_per_purchase_unit
3 cartons × 10 strips per carton = 30 strips
30 strips − 2 strips sold = 28 strips remaining
Enter fullscreen mode Exit fullscreen mode

That example is about recording units, not permission to split or dispense a particular product. Supported sale units must follow the product and the store's authorised process.

Show the unit beside every quantity. Validate conversions at setup, receiving and checkout. A perfect-looking quantity field is dangerous when its unit is implicit.

3. A barcode is a lookup aid

Scanning should identify a candidate product quickly. It should not erase the need to display exact identity or resolve the relevant batch.

Useful interface details include visible strength and dosage form, clear pack information, an explicit unit selector and a readable unavailable state. Avoid silently accepting a loosely matched product when the exact barcode is unknown.

In a rehearsal, try two similar-looking products and a barcode that is not in the catalogue. Observe whether a staff member can understand the result and refer uncertainty appropriately.

4. Keep stock status visible

A returned product, a questionable delivery or an expired batch should not be indistinguishable from saleable stock. Match the physical handling process with a system status and appropriate permissions.

A status change should record who made the decision and why. Creating a refund or supplier credit does not, by itself, establish that the physical item can be sold again. The authorised professional and quality process must determine that.

For developers, this means availability should be a domain decision rather than a simple sum of every quantity in the database.

5. Preserve the movement history

Receiving, selling, returning and adjusting stock are different events. An unexplained edit to a current-balance field makes discrepancies difficult to investigate.

Keep a reference to the originating document and a reason for adjustments. Treat a supplier order and an actual receipt separately: an order for twenty units is not evidence that twenty arrived.

On the server, design sale and stock updates so a partial failure does not leave an invoice completed with its stock movement missing. Duplicate submissions and concurrent attempts to sell the last available unit deserve deliberate handling. These are engineering concerns to test, not capabilities to assume from a responsive checkout UI.

6. Test workflows with consequences

Useful scenarios include:

  • Two deliveries of the same product with different batches and expiry dates.
  • A purchase unit that differs from the sale unit.
  • A short delivery that leaves part of the order outstanding.
  • A return awaiting assessment rather than automatic release.
  • A duplicate checkout submission.
  • Two sessions attempting to sell the final available unit.
  • A stock adjustment that needs an explanation and approval.

These tests challenge the business model rather than merely confirming that a button calls a function.

Connect the model to the real workflow

A stock system succeeds when the recorded identity, unit, batch and status match what staff handle at the counter. Review those decisions with the people responsible for receiving and authorised professional work.

For the owner-facing side of these questions, our opening-stock guide includes a downloadable planning worksheet, and the pharmacy software guide explains how billing, purchasing and inventory fit together.

What stock-model edge case has caused the most trouble in a system you have built?

Prepared with AI assistance and reviewed against the product's public materials. Examples are illustrative.

Top comments (0)