Everything that has shipped
Dated catalogue of HMS Light capabilities — from the 18 June 2026 foundation through each clinical, billing, and platform release.
Scan to build an invoice: products, services, patients and visit scripts
On the invoice screen one scan box accepts whatever the cashier scans: a product or service barcode adds it to the bill at its normal price, and a patient MR card or a visit script number picks the patient and pulls the visit's unbilled services and medicines - the same quoted lines as choosing the session by hand.
- Scan a product or service barcode to add a line at its list price; scanning the same one again raises the quantity, and a barcode shared by more than one product or service asks which one rather than guessing
- Scan a patient MR card or QR to pick the patient, or a visit script number (DSN) to pick the patient and pull that visit's unbilled services and medicines in one step; inactive products or services and unknown codes get a clear message
- A service or medicine that came from the visit is never added a second time by a scan, its quantity cannot be raised above what was booked, and its price stays at the quoted price even if the screen is tampered with - so the bill always equals the quote
- Services now carry an optional barcode on the service form; who can scan what follows the cashier's existing permissions
- The scan is recognised on the server only, so every screen agrees on what a code means, and an automated check fails the build if a second barcode lookup or scan classifier appears
Bill a whole OPD visit from its consultation session, on one editable invoice
On the invoice screen, once a patient is chosen you can pick one of their consultation sessions and the services and medicines the doctor ordered are added to the bill at the quoted price - no re-keying. The invoice stays the one editable bill: you can change quantities, add your own lines, save a draft and post it with the normal payment flow.
- A "Bill from session" control appears beside the patient (for users who can read OPD and create invoices) and lists that patient's sessions with how many services and medicines are still unbilled
- Choosing a session appends its unbilled services and prescribed medicines to the invoice - lines you already typed are never overwritten, and choosing the same session again never adds anything twice
- A "Not added" list shows what was left out and why - already billed (with the invoice number), on another draft, already dispensed, a cancelled script, or a medicine that still needs a stock product - and the consultation fee is only shown as a note because it is billed separately
- Prices, medicine quantities (what is still owed), the dispensing store and lot are quoted by the server, never recomputed on screen, and the invoice is linked to the visit so the services and medicines read as billed everywhere after it posts - on the session, the pharmacy counter and the encounter bill
- Controlled medicines keep the legal capture: save the draft, then post it with the witness, collector and prescriber details; changing the patient asks first and removes only the lines pulled from the previous patient's session
Pharmacy dispensing at a scan-driven counter
Prescriptions are now dispensed by the pharmacist, not billed from the doctor's screen. Every signed prescription gets a scannable script number; the pharmacist scans or types it, sees what is still owed, checks the safety findings, dispenses what is in stock, collects payment and hands the medicines over — with stock, the invoice and the doctor's prescription status always in agreement.
- Each signed prescription carries a script number (DSN) printed as a barcode and QR; a keyboard-wedge scanner just types it into the new Dispense Counter, which also finds scripts by patient name or MR number and lists everything awaiting dispensing, oldest first
- Medicines are dispensed per loose unit (tablet, capsule, mL) from stock held in packs, priced per unit, with the correct fraction of a pack taken from stock and the right cost booked
- Partial fills for short supply: dispense what you have from a chosen store and lot (earliest expiry first, or pick a lot); only what is handed over is billed and taken from stock, the rest stays visibly owed and can be dispensed later
- Medication-safety findings (interactions, allergies, duplicates) are shown before dispensing, with a recorded reason required to override a major finding; a held invoice shows exactly why it is held
- Payment is collected at the counter through the normal payment flow (cash, card, bank, online, insurance co-pay), the medicines are then marked handed over with who and when, and the patient's balance matches the books
- Double-clicks and two counters working the same script can never dispense a medicine twice; the doctor's prescription list shows live status (not dispensed, in progress, partly dispensed, dispensed) after any refresh
- Generic prescriptions are dispensable: the pharmacist picks an in-stock product with the same ingredient, and can substitute another same-ingredient product with a recorded reason — never a different ingredient, and never when the prescriber marked the medicine do-not-substitute; the barcode check, price and stock follow the product actually dispensed
- Controlled drugs at the counter capture the legal controls: a second-pharmacist witness (never the dispenser), the collector's name and ID (stored encrypted, shown masked), the prescriber registration, and a per-item maximum quantity per dispense that only a pharmacist with override rights can exceed with a reason — all written to the controlled-drug register, whose columns follow a per-tenant layout (generic, DRAP or MOHAP/DHA; the DRAP and MOHAP/DHA layouts are UNVERIFIED working approximations and must be confirmed with legal/compliance before use in an inspection)
- A per-tenant setting chooses a one-step counter (pharmacist collects and hands over) or the two-step flow (pharmacist fills, cashier settles) — the same ledger either way
- The item form has a Dispensing tab where a medicine is set up for loose-unit sale: a dispense unit chosen from a fixed list, units per pack, an optional price per unit and — for a controlled drug — the maximum per dispense (capped at 100 loose units, or one pack for a liquid); stock quantities now show down to a ten-thousandth of a pack, so a single tablet of a large pack no longer reads as zero
- The counter shows each substitute's current stock in the product picker, a controlled drug's maximum per dispense holds even when two counters dispense at the same moment, a line started in tablets cannot be finished in whole packs, and a branded A4 or thermal receipt opens after payment and can be reprinted for the money taken on the script
- The product barcode on file is no longer sent to the screen: the scan is checked on the server and the counter only shows the verdict
"What's included" on every price
Pricing is no longer a number with no detail. Each plan, add-on, and bundle now shows exactly what it includes — the modules you get and the limits (users, patients, items, stores) — the same way on the public pricing page, the registration showcase, and inside the app, so there is one honest list that cannot drift between surfaces.
- A shared "what's included" panel renders modules (by friendly name) and quota limits on /pricing, the registration showcase, the tenant subscription panel, and the platform catalogue — built by one owner so every surface agrees
- Bundles list the specific suites they actually sell (explicit membership), not everything that happens to share a permission; quantity add-ons show their per-unit top-up
- Public surfaces show the included modules and limits without ever exposing raw internal permission keys
- Add-ons that rely on an outside provider (SMS/WhatsApp, e-mail, e-invoicing, AI, connected devices, insurance clearing-house) now carry a clear "billed separately by <vendor>; our price covers the integration only" note with the real vendor name, on every price surface and the Integrations hub
Trial countdown and in-app billing notice
Every workspace now starts on a 30-day full-access trial and sees exactly where it stands — days left, payment due, or read-only — in a non-blocking in-app banner, with a one-tap WhatsApp link to the provider to clear a bill. No one is surprised by a lockout mid-shift anymore.
- Dashboard banner for all staff: trial countdown (amber in the final 3 days), amber "payment pending" during the grace period, and a red read-only notice when access is restricted — dismissible for info, persistent for urgent states
- A "Contact us on WhatsApp" button prefilled with the workspace and latest invoice reference, pointed at the provider's own contact number (never a hospital's patient-payment number)
- The amount due is shown only to staff who can read billing (subscription:read); everyone else sees the state and deadline without figures; a blocked write surfaces the banner instead of a raw error
Support-access transparency and PHI consent
Tenants can now see exactly when platform support opened their workspace, why, and what was attempted — and they choose whether support can see patient data at all. Support sessions are read-only, time-limited, and attributed to the real operator in the tenant's own tamper-evident audit.
- Settings → Support access log (gated on audit:read) lists every impersonation start, stop, and blocked write with the operator, reason, and time, from the tenant's own hash-chained audit trail
- Patient data is off-limits to support by default; a tenant-owned "Allow support access to patient data" consent toggle must be turned on before any PHI module is visible, and then only read-only
- Impersonation is server-enforced read-only (writes 403 even outside the browser), capped at 30 minutes with a mandatory reason, and the in-app banner shows that reason plus remaining time
Send a ward procedure order to theatre
A ward-booked procedure order can escalate straight into an OT case from the IPD Procedures tab, carrying the patient, admission, service, and clinical indication into the existing Surgery booking dialog — no re-keying, and the order is linked back to the case so it never orphans.
- "Send to theatre" row action on eligible procedure orders (gated on surgery:create, hidden not disabled), reusing the existing /surgery booking deep-link with service, procedure name, and indication pre-filled
- The surgeon still picks theatre and time — no auto-scheduling; the ward order is left untouched (no status flip)
- ClinicalOrder.resultRefType='surgery'/resultRefId is the single link owner; the back-stamp is idempotent (one order → at most one case, second escalation returns 409), and the row then shows "OT case scheduled — view"
Clinical safety UX — eMAR, pharmacy, labs, and boards
Bedside and consult surfaces harden BCMA and pharmacist verification, surface allergies and lab intervals at a glance, and tighten ED staffing and OPD BMI feedback without new parallel safety engines.
- eMAR BCMA hard-stop on Given mismatch, verify-before-administer parity when the tenant toggle is on, and Administer dialog Scan & verify / Details tabs
- OPD consult PatientContextRail; Verification Queue Verify/Reject shows dose, route, frequency, and prescribe-time safety alerts
- Admission Results projects gender/age effectiveReferenceRange; ward/ICU/IPD chips show allergen names; ED ESI 1–2 unassigned attending breach badge; shared FE vitals BMI helper
Walk-in service booking charge and payment
Lab and radiology clerks can Save a walk-in booking unbilled or Post & collect cash, card, bank, online, credit, insurance, or split tenders, and Bill later on an existing standalone order — one invoice to Service Income.
- Save booking posts no journal; omitted collectFee is never auto-cash
- Post & collect and Bill later share collectBookingFee through PaymentService; revenue is Service Income 4003
- Encounter-linked orders stay deferred; a second Bill or an encounter charge is rejected
Lab worklist and radiology New study stay on one booking
Service Bookings is the LIS specimen bench for lab orders only. Walk-in imaging is booked from Radiology New study on the same ServiceBooking create — not a second booking module.
- Lab list, stage KPIs, barcode scan, and Unmatched rematch request serviceType=lab so X-ray never shares Awaited tiles
- Omitted GET /service-bookings still returns all types so commissions keep mixed sources
- Radiology header New study uses the shared create dialog with an imaging picker
Surgery Complete opens the missing step
When an in-progress OT case cannot Complete, the listing hides Complete and promotes Bill, Materials, Checklist, or Case timeline so staff open the existing owner instead of a dead-end toast.
- First-blocker order from the shared completeBlocker helper: closure, Sign Out, procedure fee, priced consumables
- Billed badge counts unbilled priced consumables as well as the procedure fee
- Time Out missing consent or site-mark and Sign Out count gates hide Complete phase and open Readiness or Counts
Service Bookings list polish and lab-tab tours
Lab receptionists clear active worklist filters in one control, see the referring doctor on the Bookings table, and the Tutorial covers QC, Rules, Unmatched, and Criticals with permission-gated steps.
- Filter row meets T-1239: scan hint sits under search, not on the controls baseline
- Clear filters resets search, status, sample stage (including worklist tiles), and page
- Referring-doctor column from existing referringDoctorName; service type stays visible; collected time stays on detail only
QC and rules workbench scoped to one analyte
LIS techs pick an analyte before Levey–Jennings and QC runs, see control names and timestamps from the run DTO, and supervisors can enable or disable autoverify, reflex, delta, and critical rules without a builder.
- QC tab requires an analyte; runs and the chart never mix parameters
- Run and level rows project material and parameter names; warning vs rejected use distinct badges
- Rules list shows service/parameter scope; enable/disable uses the existing PATCH only
Lab attention queues: safe criticals ack and true TAT breaches
LIS techs acknowledge each critical on its own read-back dialog, and the TAT badge counts bookings that missed their target — not every completed assay. Unmatched reasons are translated; exceptions show accession and open the booking.
- Criticals tab uses LabCriticalAckDialog only; badge is unacked notifications, not leftover criticalFlag bookings
- Worklist TAT badge, TAT tab, and lab TAT report share isLabTatBreached over the same 30-day window
- Unmatched reasons i18n plus a truncated analyser snippet; Exceptions show accession and Open booking
Dietary plans in IPD nav and diet-only charges
The dietary-plans register is a first-class Inpatient & Theatre item. Diet plans bill only dietary-type catalogue services; lab, consult, and other types stay off the picker and the charge API.
- Dietary plans nav at /dietary (dietary:read), immediately above Kitchen worklist
- Catalogue Service.serviceType includes dietary; Services can create and filter them
- Create and bill-later pickers list dietary services only; charge rejects a non-dietary serviceId
Item pickers show catalogue type
Every catalogue item dropdown names the type — Medicine, Consumable, Supply, or Equipment — next to the item, so mixed lists are distinguishable at pick time.
- Shared picker label: name, optional code, then type from Items kinds
- Invoice, inventory, indent, procurement, OT, CSSD, and medicine search rows
- Type is searchable in the combobox
Record incision from WHO Sign Out
Sign Out stays blocked until knife-to-skin is recorded. The safety checklist now offers Record incision (or Case timeline) instead of a failed Complete.
- Sign Out pause explains the incision gate and hides Complete until knife-to-skin exists
- Record incision uses the same case-timeline milestone (current time; Time Out and anaesthesia start required)
- In-progress cases without incision show Case timeline as a labeled row action
Type-specific collect→receive stability
Each sample type carries its own pre-analytical integrity window on the bookings worklist, specimen bench, and Exceptions tab. Overdue receive and start-processing warn before proceeding; reject can pre-fill delayed.
- Type-specific stability minutes with tenant SLA fallback; 0 disables the clock
- Remaining minutes and near/overdue badges on bookings rows and custody hints
- near_expiry exception kind; overdue receive warn-only ConfirmDialog
Sample-type storage temp and blood batch windows
Each sample type carries a derived storage temperature; blood-family draws show the next :00/:30 chemistry batch in clinic time. Missed-batch and wrong-storage breaches surface on the existing specimen-exceptions worklist.
- Storage temp derived from sample type (ambient / refrigerated / frozen)
- Blood, serum, and plasma project next half-hour batch after collection
- Exceptions tab adds missed-batch and wrong-storage kinds with clear labels
Specimen tube labels at 50×25 mm
Phlebotomy prints direct-thermal tube stickers sized for 50×25 mm stock. The lab worklist can reprint the same Code-128 labels after collection without reopening the specimen bench.
- Collect opens browser print at 50×25 mm label geometry (not ID-1 card)
- Code-128 still encodes the SP- container barcode assigned at collection
- Print labels row action on the bookings worklist for collected samples
Admission amount due display SSOT
IPD overview, billing KPIs, discharge wizard, and interim print now separate running-bill charge totals from patient-facing amount due (unpaid admission fee invoice plus ward residual). Dual ledgers unchanged — display only.
- Overview card headline shows amountDue; running bill total stays secondary
- Billing tab KPI labels Amount due vs running bill total; fee chip stays off the folio
- Discharge wizard uses accrued room from charge lines and stay amountDue — not room rent × nights
- Interim print footer shows running bill balance, not amount due
Consumables stay on Items, not a menu row
Pharmacy Products no longer lists Consumables beside Items. Consumables remain an item type: filter them on Items, or open /items?kind=consumable.
- Removed the Products → Consumables sidebar duplicate of the Items list
- Items type filter (Medicines / Consumables / Supplies / Equipment) stays the finder
- Demo consumable seed unchanged
Consumables catalogue discoverability
Demo tenant seeds common ward and OT supplies as Item.kind=consumable in the main pharmacy store. Staff find them with the Items type filter (not a second Products menu).
- Items page kind filter syncs with the ?kind= URL parameter
- Demo seed includes gauze, syringes, cannulae, sutures, gloves and IV sets as consumables
Admit from Ward Board Available tab
Ward clerks admit directly from the Available beds list with the bed preselected. Cleaning rows explain that EVS must finish first and link to the Housekeeping worklist — no Admit until the bed is census-available.
- Admit row action on census-available beds (ipd:create)
- Admission intake opens with room and bed preselected
- Cleaning rows show EVS copy and a Housekeeping tab link; discharge still routes beds through markForCleaning
Bed types and properties on every bed surface
Facility staff record frame type (including labour, recliner, crib, orthopedic, psychiatric, electric) and see type, isolation, gender, anti-bedsore overlay, and care level on every bed picker, ward tile, Available row, and ICU census.
- Bed type enum on Beds manager (13 frame classes; ICU stays careLevel)
- Anti-bedsore boolean overlay — not a type and not Braden
- Shared picker label plus property chips on intake, transfer, escalation, ward board, Available, ICU census, and beds manager
Building master on Room
Facility admins maintain campus buildings on the Rooms page and assign every room to a building. The ward board groups census and available beds by building then floor.
- Buildings tab on /rooms with CRUD reusing rooms permissions
- Required building picker on room create/edit; Main seeded per tenant
- Ward board census and Available tabs group by building name then floor
Appointment series and cancellation waitlist
Front desk books a repeating course as linked visits in one action. Cancelling one occurrence leaves the rest. A cancelled or no-show slot offers the next waitlisted patient for that doctor or department.
- Book daily, weekly, biweekly or monthly series with a visit count or end date
- Series badge on the appointments list; cancel remaining scheduled visits without a parallel series status
- Waitlist listing at /appointments/waitlist; cancel and no-show surface the next candidate
Kitchen tray worklist by ward and meal
Ward kitchen sees today's diet orders grouped by ward for breakfast, lunch, or dinner and marks each tray delivered or refused. NPO and allergy flags come from the diet-order safety owner. Status shows on the IPD chart and Patient-360.
- New /dietary/kitchen listing with meal tabs (one listing per view)
- Delivered blocked for NPO and same-day OT feeding diets; refused always available
- dietary:kitchen permission ships with the screen; IPD chart diet badge / Overview card / Kitchen diet action; tray status on Patient-360 dietary rows
Dietary NPO and allergy safety flags
Diet orders now use a structured type. NPO versus same-day theatre and food-allergy warnings from the patient allergy list are flagged on the order screen and the day's list. Charge posting is unchanged.
- Structured diet types (NPO, fasting, regular, therapeutic categories) on the nutrition plan dialog
- Same-day OT booking flags NPO as expected and blocks a feeding tray
- Allergy warnings read PatientAllergy — the same list Patient-360 shows
IPD discharge disposition and in-hospital death register
Discharging an inpatient stay now requires a structured outcome shared with ED (routine, referred, transferred, LAMA, DAMA, deceased). Death captures time, certifying clinician, MLC, and body release. LAMA/DAMA uses the existing admission consent ledger.
- Disposition is required on PATCH /admissions/:id/discharge; deceased opens death-register fields
- LAMA/DAMA blocked until a signed AMA consent exists on POST /admissions/:id/consents
- IPD reports Registers tab shows mortality/outcome counts by disposition for a date range
Ward Board housekeeping worklist
EVS can assign, start, and complete bed-turnaround tasks from Ward Board ?tab=housekeeping. Age is shown from createdAt. Completing a row or Mark cleaned on a cleaning tile uses the same HousekeepingTask PATCH.
- Third ward tab lists open HousekeepingTask rows (room/bed, kind, status, age, assignee)
- Assign via StaffCombobox; start and complete from row actions; bed returns to available in the same complete transaction
- Assignee is a User FK with a flat assignedToName on the existing housekeeping DTO
Invoice lot on purchase, sale, and print
Medicines default to batch tracking. Purchase invoices capture lot and expiry; sales consume FEFO and stamp the lot onto the line so detail, A4, and thermal receipts show it under the description.
- New medicines default tracksBatches on (supply/equipment still forced off)
- Composer copies the header store onto the line so Auto (FEFO) shows without a second pick
- Posted GET detail + A4 + thermal show lot and expiry as a sub-line
UI/UX audit — structured pickers, Arabic/Urdu sweep, i18n ratchet
Comprehensive UI/UX audit batch: identity comboboxes replace free-text clinical fields; CSSD and quality wired to structured FK pickers; reports, commissions, contracts, bank, installments, tax, care-packages, platform admin, and compliance pages fully localized (en/ar/ur); literal baseline ratchet guard prevents new hardcoded UI prose.
- Shared DepartmentCombobox, StaffCombobox, AssetCombobox for department, clinical staff, and biomedical assets
- CSSD Record load dialog tabbed with department/operator/sterilizer pickers; quality incidents use reporter StaffCombobox
- Referrals catalog enums and structured pickers; six clinical dialogs i18n'd
- All financial reports localized (phase A + B) via docs locale and ReportShell chrome
- Commissions, doctor contracts, bank accounts, installments, tax, and care packages use billing namespace (en/ar/ur)
- Platform admin, SalaryDialog HR tour, governance, HIE, privacy consent, and breach incident pages localized
- i18n literal baseline budget guard wired into audit:integration — ceiling ratcheted 4260→2230
Phase 100 production readiness — POS, specialty templates, balance hints, ZATCA
Pharmacy quick-sale POS preset, specialty encounter templates for oncology/IVF/dialysis/anaesthesia, live A/R on register list filters, admin listing row-action consistency, ZATCA e-invoice transport, and combobox polish for small tenants.
- Invoice New sale / ?quickSale=1 opens items-first POS composer (no hold/draft, Post primary)
- SPECIALTY_TYPES + seeded encounter templates; registers stay SSOT for cycles/sessions
- PatientBalanceStrip on specialty register list patient filters with Pay outstanding
- TableRowActions + i18n on Governance, HIE, DSR, Feedback, and 18 HR/settings listings
- ZATCA FATOORA transport (UBL + TLV QR + clearance/reporting API; PCSID pasted externally)
- SimpleCombobox single-option panel layout polish
Counterparty balance on every patient and vendor picker
Selecting a patient or vendor on billing and clinical forms now shows live A/R or A/P balance from the ledger, with Pay outstanding or Record payment when money is owed — plus stable deep-links from the accounting ledger into invoice and bill detail.
- PatientBalanceStrip / VendorBalanceStrip on appointments, OPD, lab bookings, admissions, invoices, claims, specialty registers, procurement, and payables
- Pay outstanding opens the same multi-invoice collection dialog as Patient 360 Billing
- Vendor balance links to Payables filtered by supplier
- useDeepLinkOpen fixes dialog flash-then-dismiss on ?open= deep links
- Completed appointments show View consultation (eye) instead of Open consultation
Front desk allergy and ABO badges
Appointments and Queue desk rows show read-only allergy indicators and blood group when known on the patient chart — so reception sees hazards before check-in or call-next, without a desk allergy editor.
- Appointment list/detail and queue ticket patient refs project bloodGroup, NKA flag, and allergy counts
- Shared ClinicalSafetyBadges on Appointments and Queue (absent when unknown; no invented NKA)
- Visit-status and payment gates unchanged
Nursing station blood request and bedside transfusion
Ward nurses can request blood and run bedside transfusion from Nursing Station patient cards — the same sheets and safety gates as the IPD chart and ED, without a parallel transfuse path.
- Request blood and Transfuse icons on nursing-station patient cards (permission-gated)
- Reuses BloodRequestSheet and BedsideTransfusionSheet (SHOT bedside chain)
- Blood Bank worklist and chart stay aligned after refresh
Ward transfer placement override
Ward-board TransferDialog explains isolation, gender-policy, and ICU bed mismatches before submit and requires an audited placementOverrideReason — the same override path as intake and care-level escalation.
- Available-bed picker projects genderPolicy and isIsolation for explainable gates
- Override reason required when placement rules fail; stored on transfer history
- Backend assertPlacement rules unchanged; occupancy still censusBedStatus
Ward board and ICU census safety badges
Occupied ward-board tiles, the patient peek sheet, and the ICU census widget show allergy, ABO, isolation, open blood requests, and due-dose pressure — the same clinical safety strip already used on the ED board.
- Ward board / ICU census API projects blood group, allergy counts, isolation, open blood requests, and due doses
- Shared ClinicalSafetyBadges on bed tiles, peek, and ICU census
- Occupancy still uses censusBedStatus (no second occupancy owner)
CSSD sterilization loads pagination and KPIs
CSSD operational desk shows paginated sterilization cycles with date filters and a KPI strip for total cycles, pass rate, active released loads, and recalls.
- Paginated sterilization cycle listing with date range
- GET /sterilization-cycles/kpis
- KPI strip and pagination on CSSD page
Patient 360 transfusion history
Patient charts show transfusion history with unit details, reactions flagged, and links to the blood bank module.
- GET /patients/:id/transfusions
- Transfusion history card on Patient 360 overview
- Reaction status badges and blood bank deep-link
Blood bank inventory KPIs and pagination
The blood bank units table is paginated with an inventory KPI strip — available units, expiring within 7 days, reserved, and issued today.
- Paginated GET /blood-units
- Inventory summary endpoint for KPI tiles
- Expiring-soon units highlighted in the table
Blood bank donor lookback and unit traceback
Haemovigilance lookback lists every unit and recipient when donor screening fails; unit traceback shows donor and sibling units. Bank broadcast and treating-clinician inbox alerts fire for affected recipients.
- Donor row Lookback dialog with units and transfusion recipients
- Alert banner when donor screening is failed post-issue
- GET donor lookback and unit traceback endpoints
Donor lookback notifies treating clinicians of recipients
When donor screening fails with issued or transfused units, the blood bank desk still gets the lookback broadcast, and each affected recipient's admitting doctor (and today's assigned nurse, when admitted) receives a targeted critical inbox alert linking to the admission chart — not the donors tab.
- Active admission doctor preferred; else most recent admission with doctor
- Today's NursePatientAssignment nurse on active stays only (one nurse, deduped)
- Clinician link opens /admissions/<id>; no patient-portal panic messaging
Emergency Department operational KPI strip
The ED register shows live door-to-disposition metrics — active census, acuity mix, LAMA/DAMA rate — filtered by the same date range as the visit table.
- GET /emergency-visits/kpis with date-range filter
- KPI auto-fit strip above the ED visit table
- Arrival date From/To filters drive both table and KPIs
ED attending doctor is a real user FK
Emergency visits now pick the attending doctor from staff directory; the visit stores attendingDoctorId for my-ED-list scoping while keeping the display name on the row.
- Doctor SimpleCombobox on the ED visit dialog
- attendingDoctorId FK with display-name cache on EmergencyVisit
- Doctor data-scope filters ED list/board by attending doctor
Emergency triage vitals are structured with auto NEWS2
ED visit triage now captures BP, HR, RR, SpO₂, temperature and GCS as structured readings that flow into the patient vitals chart and compute NEWS2 automatically — legacy free-text visits still display.
- Clinical tab replaces the single vitals text box with structured fields plus notes
- Structured readings post to PatientVital via VitalsService for Patient 360 charts
- NEWS2 score auto-calculated on save and previewed while entering vitals
Emergency admitted visits now link to inpatient stays
When an ED visit closes with disposition Admitted, the IPD admission intake opens inline and stamps a two-way link — the ED register and Patient 360 show the connected ward chart instead of a dead-end closed visit.
- Choosing Admitted in the ED visit dialog opens the bed/ward intake wizard with ED context
- Emergency listing shows Admit pending, Admit to IPD, and a green IPD deep-link after linkage
- IPD chart header and Patient 360 procedures tab surface the ED → ward chain
Appointment list and consultation share one visit status
After check-in, start consultation, complete, or cancel, the appointments listing and the consultation dialog now read the same server-owned visit status — a full refresh no longer shows checked-in on the list while the session still says scheduled.
- Visit status is projected from the same SSOT the queue and consultation use
- Appointments list badges match the consultation dialog after refresh
- Cancel routes through visit-payment SSOT so billing and status stay aligned
Insurance claims now track clearinghouse transport status
Submitted claims show whether the 837 is queued, transmitting, accepted, or failed at the clearinghouse — with a retry action on failure, the same transport pattern as e-invoice authority transmission.
- Claims listing and detail show transportStatus (pending → transmitting → submitted / failed)
- Configure clearinghouse credentials in Settings → Integrations
- Retry re-queues failed EDI transmission without duplicating the claim row
Structured crossmatch before blood issue
Blood units now require a recorded crossmatch result compatible with the patient before issue — ABO/Rh remain the first gate, but transfusion safety also stores the formal crossmatch outcome instead of free text on the unit.
- Crossmatch workflow on /blood-bank before Issue is enabled
- Issue is blocked when the latest crossmatch is incompatible or missing
- Existing unit inventory and screening flows are unchanged
Radiology critical findings use the shared critical-result loop
Signing a radiology report with a critical finding no longer opens a one-off dialog — it feeds the same critical-result acknowledgement workflow used elsewhere, so ordering clinicians see one inbox and one ack trail.
- Critical flag on radiology sign routes through the shared critical-result service
- Ordering clinician must acknowledge from the critical inbox
- IPD and OPD Results tabs update when the report is signed
RIS worklist acknowledges critical imaging findings (LIS parity)
Radiologists and ordering clinicians can acknowledge unacked critical imaging findings on the radiology worklist and report dialog using the same LabCriticalAckDialog and lab-critical:ack permission as the LIS — no second critical store.
- Worklist rows and report dialog surface Acknowledge when a CriticalResultNotification is pending
- Ack uses the existing service-bookings critical-ack API; LIS and session banners agree after refresh
- Without lab-critical:ack the action is hidden and the report dialog shows explainable forbidden copy
FHIR DiagnosticReport and ServiceRequest from live clinical data
Interoperability export now includes FHIR R4 DiagnosticReport (validated lab and radiology results) and ServiceRequest (CPOE orders) — facades over existing ServiceBooking and CPOE rows, not a second data store.
- GET /fhir/DiagnosticReport?patient=… returns validated booking results
- GET /fhir/ServiceRequest?patient=… returns CPOE orders with date search
- Capability statement updated; mappers read the same rows as LIMS and order worklist
Biomedical PM schedules auto-create maintenance work orders
When a device passes its next preventive-maintenance due date, the system creates a scheduled maintenance log automatically — overdue PMs appear in the assets summary and listing filter instead of relying on manual entry alone.
- Nightly job scans PM schedules and creates scheduled maintenance logs on due date
- Assets summary shows overdue PM count; listing filter for due/overdue PM
- Manual corrective maintenance logs remain for ad-hoc work
E-invoices now transmit to FBR for a real IRN
Submitting a sale invoice queues async transmission to the tax authority (FBR PRAL by default). The system no longer fabricates a local IRN — status stays Transmitting until FBR returns invoiceNumber and QR data, or Failed with a retry action.
- Configure seller NTN and FBR bearer token in Settings → Integrations → e-Invoice
- Submit sets pending_transmission; BullMQ posts to FBR and stores the authority-issued IRN
- Failed transmissions show the error and a Retry action on the e-Invoice listing
Sign-in showcase now includes formulary, floor-stock indents and asset custody
The login and registration capability cards match what the product actually ships: a Formulary & Drug Knowledge card (curation plus CSV/JSON import), inventory copy for item types, department stores, fill-to targets and Stock Indents, and biomedical location/custody on the existing equipment register.
- New Formulary & Drug Knowledge card on the public showcase
- Stock, Batches & Floor Indents describes item types, department stores and non-billable ward indents
- Biomedical Assets describes department/room/custodian assignment and the movement timeline
Biomedical equipment now tracks department, room and custodian
Each device on the biomedical register can be assigned to a department, room and staff custodian. Assign / Transfer records a movement timeline so you can see where a ventilator has been — without a second listing or new in-use status. Sending it to maintenance still uses the existing service log.
- Department (and status) filters on the existing /assets register — no second page
- One Assign / Transfer dialog writes location, custodian and a movement ledger row together
- Asset detail shows a movement timeline; surgical case reservations are unchanged
Wards can indent floor stock from central pharmacy
A ward or OT raises a Stock Indent to a department store; pharmacy approves and issues it as a normal stock transfer — no patient invoice and no accounting journal. The ward can then mark the delivery received. After issue, using a consumable on that ward prefers the department store.
- Pharmacy → Stock Indents with My indents and Issue queue tabs (one listing each)
- Draft → submitted → approved → issued (or cancelled); receive is an acknowledgement only
- Issue creates a Stock Transfer into the department store and does not post a journal
Stores can belong to a department, with a fill-to target beside par min
Each inventory store can optionally be linked to the department it serves, and each store-item now has a fill-to target next to the existing par minimum. Par Level Alerts still fire only when on-hand drops below the minimum — the target is for replenishment planning, not a second alert.
- Store form includes an optional Department picker; the store list can be filtered by department
- Par Alerts “Set par” dialog edits both the minimum and the fill-to target
- Alerts remain min-breach only — stock below target but at or above par does not appear
Inventory items now have a type, with fields to match
Every stock item is now classified as a Medicine, Consumable, Supply or Equipment, and the item form adapts to the type you pick — only medicines show drug codes (RxNorm/NDC), coded clinical-drug identity and controlled/high-alert safety, while consumables/supplies/equipment (OT, CSSD and general-store stock) get a cleaner, relevant form. Medicine items also show whether their safety checks are active, with a link to map them in the Formulary.
- Item type selector (Medicine / Consumable / Supply / Equipment) drives which fields appear
- Medicine-only fields (RxNorm/NDC, controlled, high-alert, coded identity) hidden for non-medicine items
- Read-only coded-identity badge on medicines: 'safety checks active' vs 'not yet coded', linking to the Formulary
- Type badge and a type filter on the item list, so non-medicine stock (OT/CSSD/general) is easy to find and purchase
Explore every capability from the sign-in page
The feature showcase on the login and registration pages is now interactive: each capability is a tappable card that opens a focused detail modal explaining what the module is, why it matters, how it threads through the rest of the system (as a step-by-step flow) and the concrete benefits it delivers — presented as three short tabs, never a long scroll. The list was also de-duplicated so each capability appears exactly once.
- Every capability card opens a tabbed detail modal (Overview · How it works · Benefits)
- Each module documents what it is, why it matters, an integration flow and its benefits
- Removed duplicate cards caused by live add-on keys aliasing curated capabilities (Emergency, Operation Theatre, Blood Bank, CSSD, Governance)
- Newly surfaced capabilities folded into the showcase: ICU Care, AI Appointment Chatbot, LIMS, Patient Feedback, HR & Payroll and Recruitment
Dead letter queue for failed background jobs
Platform super-admins can see BullMQ jobs that exhausted all retries, inspect the error, and replay them from a dedicated screen — with Prometheus depth and enqueue-failure counters for alerting.
- New Platform → Dead letter queue listing with status, queue and tenant filters
- Replay re-enqueues the stored payload and records who replayed it
- Duplicate device-ingest work is idempotent; hms_bullmq_dlq_depth gauge tracks pending DLQ rows
Bulk formulary import from CSV or JSON
Pharmacists can upload or paste a CSV or JSON of substances and clinical drugs on the Formulary Stewardship tab. Re-importing the same RxNorm, UNII or name updates in place instead of duplicating rows.
- POST /formulary/import is audited and gated on formulary:create
- Stewardship-tab upload (no second page); helper text sits under the toolbar, not on the control row
- Per-row validation for missing names, unresolved ingredients, and invalid UCUM strength units
Pharmacy formulary curation and an all-medicine coded catalogue
Pharmacists get a dedicated Formulary screen to curate substances and clinical drugs, map stock products to coded drugs, and clear the unmapped queue — and every medicine in the catalogue now ships pre-coded, so that importing the medicine catalogue brings interaction, duplicate-therapy and allergy checking with it rather than needing each drug hand-coded first.
- Formulary screen with Substances, Clinical drugs and Stewardship tabs, gated on its own formulary permissions
- All ~10K medicines in the item-template catalogue carry coded identity (ingredient RxNorm, cross-reactivity class, dose form)
- Importing a medicine now creates its coded clinical drug automatically, so safety checks work on imported items with no manual mapping
- Curated conflict reference seeded on install: interactions, dose ceilings, paediatric/renal dosing and pregnancy/disease/age contraindications
Inpatient chart no longer repeats the patient header
The layout patient rail already shows name, allergies, stay status and balance. The IPD chart page now only adds stay facts (room, doctor, day count, checklist) plus IPD-only safety chips.
- Name, MRN and Penicillin (or other allergens) appear once, in the rail
- Admission number, room/bed and attending stay on the page title line
- Fall risk, NEWS2 and due doses remain on the IPD safety strip
One vitals record for OPD, IPD, ED, and FHIR
Blood pressure, pulse, temperature and the rest of the chart vitals live on PatientVital. Encounter columns stay as a cache, emergency free-text is saved as a note on that same record, and FHIR export reads the canonical row instead of session columns.
- OPD encounter GET overlays vitals from PatientVital when a row exists
- Emergency visit vitals string write-through as a note-only PatientVital
- FHIR Observations and ORU export prefer PatientVital; session columns are fallback only
Restricted and VIP charts need extra permission or emergency access
Psychiatry and VIP records stay on the patient list but the chart, EHR, vitals and context rail stay locked until the caller has the matching attribute permission or records a 4-hour audited break-glass reason.
- Restricted charts open for psychiatry readers; VIP charts need VIP-read
- Emergency access is audited and expires after four hours
- Unmasking contact details is still a separate permission from opening the chart
72-hour National Commission breach clock
Personal-data breaches now track the Pakistan PDPB 2025 72-hour notice to the National Commission on the same register as GDPR, and a tenant whose data region is not Pakistan must name a transfer safeguard on every cross-border processing activity.
- Breach register shows a live 72-hour clock computed by the server (not the browser)
- Notify records the National Commission as the supervisory authority
- RoPA blocks a cross-border transfer with no named safeguard; data-residency region flags non-PK hosting
Clinical AI stays decision-support, not diagnosis
The appointment chatbot cannot be configured to give medical advice. Clinical questions are refused and handed to a human, and any future clinical-AI feature needs a recorded SaMD determination before it can ship.
- Booking assistant is logistics-only (book / reschedule / cancel)
- Human-in-the-loop rules are appended to every chatbot prompt and cannot be turned off
- Note-copilot and medication-reconciliation assist remain blocked until registered as devices
Coded route, unit and override reasons
Prescribing no longer asks for free-text route, dose unit or safety-override reason. Clinicians pick from coded lists (SNOMED routes, UCUM units, and a closed override-reason set) so orders stay consistent and auditable.
- Route and dose-unit pickers on OPD, IPD, order sets, the medication list and immunisation
- Safety alerts require a coded override reason (Other still allows a short note)
- Older free-text values still display and remain editable
Patient snapshot stays as you move around
The patient snapshot bar now lives in the app chrome, so identity, allergies, the active encounter, medications and balance stay visible when you leave the record for the queue, an admission chart, a consultation or billing.
- One current-patient store; the bar is mounted once in the layout, not copied onto each page
- Opening a record, IPD chart, consultation or a patientId link sets the current patient
- The snapshot survives navigation until another patient is selected
Patient snapshot rail
A single at-a-glance patient bar shows identity, allergies (flagging critical ones), the active admission or consultation, active-medication count and outstanding balance — loaded in one request at the top of the patient record.
- One consolidated read for the whole snapshot instead of piecemeal fetches
- Allergies show No-Known-Allergies, and highlight severe/anaphylaxis in red
- Balance comes from the same billing figure used everywhere else
Coded drug-allergy picker
Drug allergies can now be recorded from a coded substance list instead of free text, so allergy alerts catch the drug even when the prescribed brand name looks nothing like the allergen, and warn on same-class agents.
- Allergen field for drug allergies is a searchable coded substance picker (free text still allowed)
- Allergy checks match by substance and cross-reactivity class, not just by name
- Existing free-text allergies keep working via name resolution
Configure secure file storage from the admin console
Super-admins can now point the platform at their S3/MinIO object storage for PHI files (attachments, consents, imaging) from a settings page, instead of editing environment variables — keys are stored encrypted and take effect immediately.
- New Platform → File Storage page: endpoint, bucket, region, path-style, max size and credentials
- Access/secret keys are write-only and encrypted at rest; never returned to the browser
- Saving reconfigures the live storage client with no redeploy; falls back to env config when unset
Closed-period posting override
A voucher dated inside a closed accounting period is now blocked with a clear warning; users with the new override permission can still post it by giving a reason, which is recorded on the voucher for audit.
- General voucher warns when the chosen date is in a closed period
- Authorised users post into a closed period with a required reason (recorded on the entry)
- Users without the override permission are blocked and guided to a valid date
Early-warning escalation on the ward
Inpatient NEWS2 readings now drive a graded response: a single severely-abnormal vital raises a nurse-review alert even when the total is low, higher scores page the clinician, and observation frequency tightens automatically as a patient deteriorates.
- Nurse-review alert for a single red parameter (previously only total scores of 5+ alerted)
- Clinician paged for medium and high scores
- Observation cadence auto-tightens (to 30/60/240 min) on deterioration and feeds the overdue-vitals sweep
Auto-maintained problem list
Diagnoses recorded during a visit or admission now flow automatically into the patient's longitudinal problem list (deduplicated by code), so the active problem list stays current without separate data entry and feeds contraindication checking.
- Recording a diagnosis promotes it to the problem list with its ICD code and the source encounter
- Duplicate diagnoses across visits do not create duplicate problems
- Problems carry SNOMED alongside ICD for interoperability
Contraindication alerts at prescribing
Prescribing now warns on drugs contraindicated for the patient's state — active pregnancy, a recorded disease (by diagnosis code), or age — alongside the existing allergy, interaction and dose checks.
- Pregnancy contraindications triggered by an active pregnancy episode
- Disease contraindications matched against the patient's recorded diagnosis codes
- Age-based contraindications (too young / too old) from the patient's date of birth
Age- and weight-based dose checking
Dose alerts can now use the patient's age and recorded weight — flagging paediatric mg/kg overages, per-band ceilings, excess frequency or course length, and renal dose adjustments — instead of a single flat adult maximum.
- Weight-based (mg/kg) single and daily ceilings using the latest recorded weight
- Age-band rules (paediatric / adult / geriatric) with frequency and duration bounds
- Renal (eGFR) and hepatic adjustment flags, with the flat adult ceiling kept as a fallback
Ingredient-level medication safety checking
Interaction, allergy, and duplicate-therapy checks now match on the drug's active ingredient and class — not just its typed name — so a brand name is caught against an ingredient rule, and a penicillin allergy warns on other beta-lactams.
- Drug interactions match at ingredient (RxNorm) and ATC-class level, with source/evidence shown on the alert
- Drug-allergy checks add class cross-reactivity (e.g. penicillins, sulfonamides)
- Duplicate-therapy detection catches the same ingredient across different brands on an encounter
Coded drug prescribing
Prescribers can now pick a coded clinical drug (by ingredient, brand, or ATC) in OPD and IPD prescribing, not just free text — the coded reference is what makes ingredient-level interaction, allergy, and duplicate-therapy checking accurate.
- Structured medicine formulary: substances, clinical drugs with strength/dose-form/route/ATC, and product mapping
- Medicine picker offers coded formulary drugs alongside stock items, with a free-text fallback
- Prescriptions store the coded drug (derived from the chosen product or picked directly) across OPD and IPD
Price calculator on sign-in and pricing
Visitors on login, register, and /pricing pick a base plan and add-ons and see an estimated monthly total in their local currency, instead of a static starting-from price.
- Login and register left pane: collapsible calculator on small screens, open on desktop
- Same estimator on the public pricing page so the quote math has one owner
- Country-resolved prices from the existing public pricing API
Notifications open the record and fill names
In-app, SMS, email, and WhatsApp fallbacks no longer show leftover {admissionNumber} or {claimNumber}. Clicking a notification opens that admission, claim, appointment, invoice, or portal stay.
- Mustache {{var}} templates interpolate through one renderer after i18n lookup
- Staff bell and inbox go to the record, not the listing
- Patient portal messages open the matching stay or appointment
Split tenders and zero-due discharge
IPD discharge no longer asks for a payment when the bill is already clear. Everywhere money is taken from a patient, one PaymentMethodSelect can combine cash, card, credit, and insurance; each line posts a balanced journal through PaymentService.
- Zero outstanding: discharge from the clinical-ready step with no settle screen
- Add several tenders on one collection so they add up to the amount due
- Queue, pay-outstanding, appointment collect, invoices, IPD, registration, OPD, installments, and care packages use the same widget
- One insurance payer per collection; combine with cash, card, bank, or credit
Long screens split into tabs
IPD reports, the account ledger, IPD clinical and orders, surgery record/counts/materials, the platform subscription dialog, and specialty registers no longer stack four or more sections past one viewport.
- IPD dashboard: Overview / Live lists / Registers
- Surgery case: Case / Theatre / Operative note / Post-op, with Save in the footer
- Specialty records: Visit / Clinical / Plan
Discharge without scrolling the bill
The IPD billing tab is the running bill only. Discharge is a two-step dialog: remaining clinical blockers, then settle. Every clearance gate still runs on the server.
- Discharge button on the billing header, with a count of open clinical items
- Step 1 shows only unmet checks; passed items sit under Already clear
- Step 2 settles and discharges in the dialog footer — same PaymentService path
Discharge summary finalize after the stay ends
Staff draft the summary while the patient is still admitted, finalize only after discharge, and can revert a mistaken finalize so care and clearance can continue.
- Finalize is refused until the admission status is discharged
- Revert finalize returns the summary to draft (same discharge permission)
- A mistaken early finalize no longer locks charges, orders, or discharge
LIMS owns where the sample is
Specimen custody — stage, location, and a misplaced-sample exceptions board — on Service Bookings. The order worklist stays on the booking; the tube has its own timeline.
- Scan at every handoff writes an immutable custody event with location
- Exceptions tab for overdue-in-transit, stalled-in-lab, missing, and wrong-station tubes
- Barcode find shows last known location and the full timeline
- Coded reject and recollect, send-out, dispose, start processing, OT→lab handoff, AP recut
- Arabic and Urdu labels for sample stage, specimen status, and custody events (T-1212)
- App-wide status, kind, and channel codes use shared translations (T-1213)
Public feature timeline
A dated, public catalogue of what has shipped — kept in lock-step with the feature-set backlog so new work appears here in the same task.
- Public /features page with year filter and search
- robots.txt, sitemap.xml, and prerendered HTML so Google can crawl /features without signing in
- Machine-readable SSOT at docs/feature-timeline.json
- CI guard plus G-02 close-out so agents append every future ship
Must-have clinical depth on existing owners
Terminology, hosted DICOM, BCMA five-rights, voice adapters, and transfusion reactions — shipped on the screens that already own the work, not as parallel LIMS/RIS products.
- SNOMED/LOINC/ICD terminology store, CodePicker, and FHIR $lookup
- Hosted DICOM STOW/WADO with in-app study viewer (external OHIF remains default)
- eMAR barcode five-rights (wristband + drug scan) with witnessed override
- Twilio/Vonage/Plivo/Amazon Connect voice adapters on Integrations Verify
- Transfusion vitals, ABO re-check, and reaction reporting on BloodTransfusion
LIMS depth and one listing per view
Microbiology, pathology, CPOE, and radiology benches stay on Services and Radiology — with page-level tabs so staff never scroll past a second workbench.
- Microbiology culture/sensitivity and pathology gross/microscopy on the lab bench
- CPOE clinical decision support and order-set depth on the existing worklist
- Radiology structured reporting and study worklist UX
- Enterprise IA: one primary listing per view (tabs, not stacked tables)
OpenAPI as the frontend contract
Every migrated module’s React client is generated from the backend OpenAPI spec, so request/response shapes cannot drift between Nest DTOs and the UI.
- Orval-generated hooks from backend/openapi.json
- Response DTOs required on every migrated route
- CI drift guards (openapi-response-types, openapi-check)
Connected devices and remote monitoring
Wearables and clinic Bluetooth vitals ingest as patient-generated data, reviewed by staff before they become chart vitals, with RPM plans and threshold alerts.
- Withings, Dexcom, and generic OAuth device connect
- Staff review queue and promote-to-vital gate
- Doctor-ordered RPM plans with threshold alerts
- Web Bluetooth capture for clinic vitals
- Patient portal “My devices” with consent
Inpatient chart, CPOE, and eMAR
The admission becomes a full chart workspace: NEWS2 vitals, unified clinical orders, dose administration with witness, nursing station, and automated room-rent.
- Admission event spine, bed lifecycle, and transfer history
- Admission-linked vitals with NEWS2 alerts
- Unified CPOE ClinicalOrder with fulfilment billing
- eMAR dose engine with witness, charge, and stock
- Nurse station, I/O, fluid restriction, and room-rent accrual
HR, attendance, and payroll
Workforce lives in the same tenant as clinical work: attendance, leave, salary structures, and payroll that posts a balanced journal.
- Attendance and timesheets
- Leave management
- Salary structures and statutory configuration
- Payroll run engine with balanced accounting
- Disbursement, remittance, and staff loans
Patient feedback and service recovery
Branded public surveys, automated dispatch after visits, scoring, and a staff call-task queue so complaints close the loop.
- Survey templates and trigger engine
- Public branded survey form with scoring
- Delivery plus staff call-task queue
- Closed-loop service recovery and analytics
One person, one identity
National-ID and phone reconciliation on create, so the same human is not registered twice under slightly different names.
- Additive person-identity links
- IdentityService reconcile-on-create (national-ID → phone, never name alone)
- Merge review for suspected duplicates
CPOE and radiology RIS
Server-enforced clinical decision support at order entry, plus structured radiology reporting and a PACS viewer deep-link.
- CDSS at order entry and a unified order console
- RIS structured reporting and modality worklist
- PACS viewer deep-link (external OHIF)
Patient portal
Patients see their own appointments, invoices, and payment plans without a staff login — conflict-aware booking and printable receipts included.
- Appointment requests with free-slot / conflict feedback
- Personal agenda and calendar
- Invoice breakdown, insurance split, and printable receipt
- Payment-plan schedule and progress
Email and WhatsApp messaging
Per-tenant templates, channels, and a delivery log so appointment and result notifications leave through one owned path.
- Per-tenant Email and WhatsApp templates
- Channel configuration and delivery log
Emergency, theatre, blood bank, and CSSD
Triage, OT scheduling, blood-unit issue, and sterilization release — the first specialty and peri-operative modules on the same ledger as OPD/IPD.
- Emergency triage and disposition
- OT scheduling and operative note
- Blood-unit inventory, screening, and issue
- CSSD sterilization load log and release control
- Pharmacy inter-store transfers and reorder suggestions
Admissions, POS billing, and insurance at sale
Inpatient encounters with a running charge ledger, plus a pharmacy/retail POS composer that posts pay-and-post into the same double-entry engine.
- Tabbed admission encounter with clinical parity from OPD
- Running charge ledger and partial payments against the admission bill
- POS composer with store/batch, scan-to-add, draft + post
- Printable A4 invoice and 80 mm receipt with barcode
- Insurance payer split at point of sale
Batch, expiry, and FEFO
Lots are first-class: invoice lines pick a batch, stock issues FEFO, and near-expiry write-off posts to the ledger.
- Batch-aware stock movements with FEFO
- Expiry write-off and near-expiry dashboard
- Batch and expiry on invoice lines
FHIR export, trust page, and audit chain
Read-only FHIR R4 Patient $everything, a public Trust & Compliance page, data-subject rights, and a hash-chained audit log.
- FHIR R4 Patient $everything bundle
- Public /trust page and auth-screen trust badges
- SAR / portability export and data-subject register
- Read-access logging and tamper-evident audit hash chain
Unified patient queue and display board
Appointments and walk-in sessions share one token line per doctor/department/day, with a waiting-room board and realtime call/recall.
- QueueTicket console: call, recall, skip, serve, transfer
- Read-only waiting-room display board (zones / counters)
- Realtime announcements, priority, and wait-time analytics
- Auto-start consultation and fee capture on call/serve
Perpetual stock and inventory ledger
Every stock movement posts COGS/inventory journals; adjustments and wastage are first-class endpoints, not spreadsheet afterthoughts.
- Perpetual stock engine with COGS posting
- Stock adjustment / wastage with movement ledger
OPD vitals, notes, and prescription pad
The diagnostic session becomes a paper-like Rx pad with vitals, clinical notes, follow-up, and a printable completion flow.
- Vitals, clinical notes, and follow-up on the session
- Plain-language Rx dosing and item-catalogue lines
- Session completion and reusable print scoping
Registration cards and registration fees
Printable scannable MR cards, scan-back lookup on return visits, and a configurable registration fee posted to the ledger.
- Printable ID-1 registration card (QR + Code-128)
- Scan-card return-visit lookup
- Configurable registration fee journal
Platform foundation
Multi-tenant identity, masters, patients, OPD, appointments, EHR, inventory, and a double-entry chart of accounts — the day HMS Light became a product rather than a scaffold.
- Users, roles, RBAC, and per-tenant isolation (isTest)
- Patient registration with auto MR# and charity/zakat
- Diagnostic sessions, symptom/diagnosis libraries, prescriptions
- Appointment scheduling
- Longitudinal EHR with ICD-10 coding
- Stores, generics, and item catalogue
- Chart of accounts, general voucher, and per-account ledger