๐ 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.