Pharmacy
Dedicated Pharmacy POS — /Pharma/PharmacyPOS
Pharmacies have their OWN POS surface, visually + functionally distinct from Retail / Hospitality / Kiosk. Health-green branding, 3-column layout with Patient panel · Cart · Rx panel, and Shelf · Batch · Expiry as first-class columns on every cart line.
- Set the terminal type: /POS/POSTerminal edit terminal Terminal Type = Pharmacy POS Save.
- Download the launcher .bat (purple button on the terminal card) and drop on the cashier PC's Desktop.
- Double-click the .bat the Launch endpoint sees TerminalType='Pharma' and 302s to
/Pharma/PharmacyPOSin full-screen kiosk mode.
/Pharma/PharmacyPOS directly in a browser (needs auth + store's PharmacyMode=1).Overlay on Retail POS (legacy fallback)
A pharmacy sells prescription drugs AND everyday goods (toothpaste, Maggi, beauty products) in the SAME bill. Solvexa handles this as an overlay on the standard Retail POS — no separate pharmacy POS surface. The retail cart, tender, receipt, GRN, transfer, return — all unchanged.
What the pharma overlay adds (only at stores with Pharmacy Mode on):
- FEFO batch picker — pops when a pharma-flagged item is added. Sorted by earliest expiry. Cashier taps to select.
- Upload Rx button — floats bottom-right. Camera or file upload server OCRs matched drugs shown with 1-tap "Add to cart".
- Rx Sale linkage — Rx auto-links to the resulting bill. Receipt footer prints Rx number.
- Expiry warnings — near-expiry batches show red badges in the picker.
- Return restocks the batch — refund puts qty back on the exact batch it came from.
Setup checklist
- Turn on Pharmacy Mode on the store — see below
- Flag the drug items with pharma fields — see below
- Get batches in — GRN with Batch # + Expiry, OR manual add at /Pharma/Batches
- Ring a sale at Retail POS — batch picker pops for pharma items, Upload Rx button appears bottom-right
Store: Pharmacy Mode toggle
Pharmacy Mode is a per-store flag. Turn it on for the stores that dispense drugs; leave it off for pure-retail stores.
- Go to /Stores/StoreList click the store you want as a pharmacy
- Scroll to the toggles row (below Manager/Phone)
- Toggle Pharmacy? to Yes
- Save
Drug master — Item form's Pharma tab
Every drug is a standard Item. The pharma-specific fields live on a dedicated Pharma tab on the item form.
- /Items/ItemForm open the item (or + New)
- Click the Pharma tab (between "More" and "Dimensions")
- Toggle Requires prescription — warns cashier + suggests Rx upload when this item is added
- Toggle Is Schedule H — the KEY flag. Enables the FEFO batch picker for this item.
- Pick Schedule class — H, H1, X, G, K, or blank for OTC
- Fill Generic name (Paracetamol), Manufacturer (GSK / Cipla), Pack size (10 tabs / 30ml syrup)
- Set Min expiry days — batches expiring within this window show a red warning in the picker (default 30)
- Save
/Pharma/Batches admin page
All PharmaBatchLot rows in one place. Filter, add manually, deactivate.
- Filters: Item search · Batch # search · Expires within 30/60/90 days or Already expired · Active/Inactive
- Columns: Item · Batch # · Mfg · Expiry (with days-remaining badge — red if ≤ 30) · Received · Sold · Remaining · MRP · Active
- + Manual Batch: for opening balances or one-off adjustments. Item code, Batch #, Mfg date, Expiry, Qty, MRP Save. If (Item + Batch #) already exists, qty is ADDED (upsert).
- Deactivate: batch disappears from the POS FEFO picker. Data is preserved for audit. Use for expired or bad batches you want frozen.
Batch picker — qty-aware + multi-batch split
When a cashier adds a pharma-flagged item, a picker modal pops with a Requested vs Total Available banner. Every batch shows a status pill:
- SUFFICIENT — batch alone covers the request
- TAKE N — PICK MORE — partial fulfilment; taking this batch reopens the picker for the leftover
- EMPTY — greyed out, cannot click
All batches sorted FEFO (earliest expiry at top). Near-expiry rows show a red badge (within Item.MinExpiryDays).
Multi-batch split (need 15, batches have 5 + 8 + 10)
- Pick batch A (5 left) cart gets a line for 5 units stamped with batch A
- Toast: "Took 5 from A. 10 more needed — pick another batch."
- Picker re-opens automatically with batch A hidden + Requested = 10
- Pick batch B (8 left) line for 8 units with batch B toast for 2 more needed
- Pick batch C (10 left) line for 2 units with batch C
Result: 3 cart lines for the same item, each with its own batch stamp. Perfectly auditable at Refund + EOD reporting.
Upload Rx (prescription) + OCR
Purple Upload Rx button floats bottom-right of POS. Tap it to attach a prescription to the current bill.
- Tap Upload Rx phone camera or file picker (JPG / PNG / WebP / PDF)
- Server receives image compresses to ~250 KB JPEG (max 1600px) stores at
App_Data/Prescriptions/<CompanyID>/<yyyyMM>/<id>.jpg - Server runs OCR (Tesseract LLM extract) returns list of drugs with name, strength, dosage, duration, qty
- Modal opens: Rx image on left, extracted drugs on right with 1-tap "Add to cart" against matching items
- Tap the buttons for the drugs you want to dispense — each add triggers the FEFO batch picker
- On tender complete, the Rx auto-links to the bill (
POSTransaction.RxID+PharmaPrescription.LinkedBillID+ Status="Filled") - Receipt footer prints "Rx: RX-2026-00042"
?handler=RxFile which enforces same-tenant CompanyID. Cross-tenant leak-proof.Item flag: Allow Negative-Stock Sales
Every Item has a toggle (Item form Flags Allow Negative-Stock Sales). Default OFF — POS refuses any sale that would drive stock at this store below zero.
Item PARA500 has only 3 in stock at this store; line needs 15. Reduce line qty, receive stock, or tick the item's "Allow negative-stock sales" option. — Sale rolls back cleanly.Tick ON per-item for services, made-to-order items, back-orders where you accept payment before receiving stock, or composite items that unpack via BOM at EOD.
Pre-tender validation — catches batch errors before Pay
The moment you tap PAY on a bill with any pharma line, the browser calls ?handler=ValidatePharmaLines. Server re-checks every batch stamp against live PharmaBatchLot state (exists, active, not expired, correct item, enough qty). If ANY issue big alert dialog listing each bad line + fix hint. Tender modal never opens. Non-pharma sales skip this round trip.
Doctor/Patient auto-detect from master
When you upload the same Rx a second time, the modal shows a green pill instead of a checkbox:
- Doctor already in master (auto-linked) — server matched OCR name against PharmaDoctor. Stored master row prefills Reg No + Qualification (in case OCR misread). Rx auto-links on Done.
- Save doctor to master (next Rx auto-fills) — shown only when the doctor is NEW.
Same behavior for Patient (matches on PatientName + Phone).
Shelves + racks (schema ready, admin UI Slice C)
Migration 502 shipped foundations: PharmaShelf (shelf/rack master per store), PharmaItemShelf (multi-shelf per item, one primary), GRNLine.ShelfID (receiving records shelf). Pharmacy POS already displays the primary shelf in the SHELF cart column when set. Coming in Slice C: /Pharma/Shelves admin, item form assignment, /Pharma/Receive with mandatory shelf, "Where is X?" lookup.
Schedule-H drugs (prescription required)
Indian law: Schedule H drugs (most antibiotics, sedatives, opioids) can only be sold against a valid prescription.
- Set the item's Schedule class = H / H1 / X on the Pharma tab
- Cashier prompted to Upload Rx when adding (via the Requires Prescription flag)
- Rx is stored + linked to the bill for 2-year audit retention
Prescription (Rx) capture
- At POS, before scanning: Rx button (or auto-prompted for Schedule H)
- Enter: Doctor Name + Doctor Registration No (validated against your Doctor Master)
- Optional: Photo of the paper Rx (uses tablet camera). Stored as attachment.
- Enter Patient Name + Patient Phone (for future refill reminders)
- Rx auto-attaches to the bill. Every sale line tagged with Rx ID.
Batch + expiry (FEFO)
Same drug arrives in multiple batches (different mfg + expiry). POS auto-picks the batch expiring first (FEFO = First-Expiring-First-Out).
- GRN captures batch no + expiry per line
- POS scan: instant FEFO pick. Cashier sees "Batch B-2026-04, Exp 08/2027"
- Manual override: cashier can pick a different batch (e.g. customer prefers newer batch)
- Expiry Report: Reports Expiry. Groups: This Month / Next 30/60/90 days. Alerts you 6 months out for slow-moving stock.
Generic substitutes (offer cheaper alternative)
Doctor prescribed Crocin (branded). Cashier can offer patient the generic Paracetamol (₹15 vs ₹35) — legal and encouraged.
- Setup: on Item form, expand Substitutes add generic + branded siblings sharing same composition
- At POS, scanning any variant shows a Substitute button with cheaper options + savings
- If patient accepts substitute, cashier taps it — replaces original line in cart
- Rx record still valid (composition matches)
Ring up a pharma sale
Same POS as retail — /POS/POSScreen. The overlay adds the batch picker and Upload Rx button; everything else is identical.
- Open /POS/POSScreen (or double-click the .bat launcher on the pharmacy terminal)
- Swipe / PIN in as cashier
- (Optional) Tap Upload Rx phone camera OCR 1-tap add drugs
- Or scan/type items directly. Pharma items trigger the FEFO batch picker; non-pharma items add straight to cart.
- Mix in everyday items (toothpaste, biscuits) — same cart, same tender
- Tap Tender pick payment mode Complete
- Receipt prints — footer shows Rx number if one was uploaded
Insurance / TPA (Third-Party Administrator) claims
Corporate customers, mediclaim policies — patient shows the card, shop bills to the insurance company.
- Setup insurers: Pharma Insurance Setup + New. TPA name, code, discount % if applicable, GL account
- At POS, after scanning: tap TPA Claim
- Enter: TPA, Patient Policy No, Auth Code (pre-authorized by insurer), Approved Amount
- Split: Patient pays co-pay (₹100 out of ₹500). Insurer pays balance (₹400).
- Bill printed with both split. Insurer receivable posts as AR to that TPA account.
- Claim aging: Pharma TPA Aging. Follow up if unpaid > 30 days.
Returns — auto-restock to the same batch
- Customer return: POS Sales Return scan receipt tick items post. Refund cash or credit.
- Pharma-line refund restocks the EXACT batch it came from — the return reads the original line's
BatchLotIDand decrementsPharmaBatchLot.QtySold, effectively putting qty back on the same batch. FEFO stays accurate. - Non-pharma-line refund — same as retail today (no batch, no change).
- Expiry write-off: Stocks Item Journal pick items Type = Negative Reason = Expired. Loss GL account debited (default 5300). Deactivate the batch at /Pharma/Batches so it disappears from POS picker.
- Vendor return of expiring stock: some manufacturers accept returns 60 days before expiry. Purchase Returns + New Reason = Expiring soon. Debit Note issued.