All features Pharmacy
Pharmacy

Pharmacy management — technical details

The pharmacy is a standalone sub-application (at /pharmacy/) with its own login, database schema (database_pharmacy.sql), and RBAC layer, sharing only the patients and prescriptions tables with the main app. It can be installed independently or alongside the main app.

FEFO dispense logic India Pharmacy Act NDPS Act GST (HSN codes) Shiprocket API

Drug master & stock

Drug master

pharm_drug_master stores the canonical drug catalog: generic name, brand name, form (tablet/capsule/liquid/injection), strength, unit, HSN code for GST, and a controlled_substance flag. The catalog is shared across all pharmacists in the clinic.

Stock batches

pharm_stock_batches tracks inventory at the batch/lot level: batch number, expiry date, purchase price, MRP, and quantity remaining. Multiple batches per drug can exist simultaneously; dispense logic uses FEFO (First Expiry, First Out) by default.

Adjustments

pharm_stock_adjustments records every manual stock change (reason, quantity delta, user, timestamp) — required for audit trails and to reconcile physical stock counts against the system.

Expiry alerts

The pharmacy cron job (pharmacy/api/cron.php) scans pharm_stock_batches daily and raises notifications for batches expiring within the configured lead time (default 30 days). Notifications go to pharmacist accounts via the notification_queue.

Dispensing

Dispense queue

pharm_dispense_queue holds pending dispense requests linked to prescription IDs. pharmacy/pages/queue.php is the main pharmacist workstation view — it shows all pending items, lets the pharmacist confirm quantities, and records the dispense in pharm_dispense_items.

Drug-drug interaction check

pharm_drug_interactions stores known DDI pairs (drug_a_id, drug_b_id, severity, description). Before dispensing, the system cross-checks all drugs being dispensed against all active medications in the patient's record (medications table) and raises a warning for any severity level — the pharmacist must acknowledge before proceeding.

Returns & refunds

pharm_returns + pharm_return_items + pharmacy/api/returns.php: a return can be against a dispense (full or partial) or an external prescription. Approved returns credit the patient's account or trigger a cash refund, logged in pharm_payment_log.

External prescriptions

pharm_external_prescriptions + pharm_ext_rx_items: prescriptions written by outside doctors (scanned or manually entered) can be received and dispensed via pharmacy/pages/external_prescriptions.php. A printable receipt is generated via pharmacy/pages/print_ext_rx.php.

Cash shifts

pharm_cash_shifts mirrors the main app's cash shift concept for the pharmacy — shift open/close with cash-in-hand count, auto-reconciled against pharm_payment_log totals for the shift period.

Controlled substances

Register

pharm_controlled_register is a dedicated table with one row per controlled-substance dispense: drug, batch, quantity, patient, prescriber, date, and a remarks field. pharmacy/pages/controlled_register.php renders the register in the format required by India's Pharmacy Act for narcotics and Schedule H1 drugs.

NDPS integration

For de-addiction facilities, IPD-level NDPS register entries (ipd_ndps_register) are separate from the pharmacy-level controlled register, reflecting that OST dispensing in a de-addiction ward follows NDPS Act regulations rather than standard Pharmacy Act requirements.

Procurement

Suppliers

pharm_suppliers stores supplier name, GST number, contact, and payment terms. pharm_purchase_orders + pharm_po_items model purchase orders with line-item detail, expected delivery date, and received-quantity tracking.

Goods receipt

Receiving a PO auto-creates stock batch entries in pharm_stock_batches. The PO status transitions from draft → sent → partial → received, with each received line updating stock.

Online orders & store integration

Store bridge

pharmacy/pages/store_bridge.php (and includes/pharmacy_store.php) links pharmacy stock to the patient-facing store. When a patient orders a product that maps to a drug in pharm_drug_master, a dispense queue entry is automatically created when the store order is confirmed.

Shipping

Shipping is handled via the Shiprocket API (includes/shiprocket.php). When a store order requires physical delivery, a shipment is created in Shiprocket, and tracking updates are received via api/shiprocket_webhook.php and reflected on the store order.

Pharmacy billing

pharmacy/api/billing.php generates pharmacy invoices that can be standalone (walk-in customer) or linked to the main app's invoice (IPD/OPD patient). The pharmacy billing migration (includes/pharm_billing_migration.php) handles schema version upgrades.

Ready to see it in action?

The demo has real sample data — appointments, patients, prescriptions — so you can explore freely.

Try the demo ← All features