RxPulse
Every unit, from purchase order to patient bill: reconciled, billed correctly and audited.
A case study on how I designed and built an intelligent hospital pharmacy system. It covers procurement, FEFO inventory, department and OT consumption, patient billing and returns, plus RxPulse Assist, an AI copilot that answers from hospital policy and never changes a record without a human saying yes.
Project Snapshot
The problem, the users and the approach at a glance
Hospitals often charge patients for what was issued, not what was used. Returns rarely reach stock again, and expiring medicines are found too late.
Pharmacists, store and procurement staff, OT and department nurses, billing staff, and hospital administrators or auditors.
“Issued” is not “consumed”. Once quantities are split into consumed, returned, wasted and unresolved, correct billing and stock follow naturally.
A ledger-based pharmacy system with FEFO, GRN-controlled receipts, consumption reconciliation and tariff-driven patient billing.
RxPulse Assist: a Microsoft Agent Framework copilot with vector RAG over SOPs, tariffs and package rules, and human-confirmed actions.
Microsoft Entra ID / MSAL sign-in with role-based access, and an audit trail for inventory, billing and AI-assisted actions.
Why I Built RxPulse
A hospital pharmacy is a money-and-safety system disguised as a stock register. Medicines and supplies such as gloves, syringes, dressings, procedure kits and implants move constantly between the pharmacy, wards, OTs and patients. Wherever that movement isn't tracked precisely, patients get over-billed, stock goes missing and expiring items go to waste.
Ten pairs of gloves go to the OT and the patient pays for ten, even though two came back unused.
Unused items returned from departments are not inspected, restocked or credited back on the patient's bill.
Without FEFO, newer batches get issued first while older stock silently expires on the shelf.
Stock enters without a clear link to a purchase order or goods receipt, so batch and supplier history is lost.
Tariffs, package rules and SOPs live in files that staff can't query while standing at the counter.
When stock doesn't match, nobody can reconstruct who issued, consumed, returned or wrote off what.
“A patient should pay for exactly what was used on them, and every unit in the hospital should have a story you can trace.”
Understanding the Problem Before Writing Code
Before designing anything, I mapped how material and money actually flow through a hospital pharmacy, then wrote requirements and success criteria for each area. Measurable success criteria came first, so every later design and test decision had something to be checked against.
Workflow Mapping
Traced the full chain: Purchase Order → GRN → Inventory → Issue → Consumption → Bill → Audit.
Scenario Walkthroughs
Walked real edge cases: partial OT usage, damaged returns, near-expiry batches and unreconciled issues.
Policy & Document Audit
Listed the policies, SOPs, tariffs and billing/package rules that decisions depend on, as inputs for the AI copilot.
Success Criteria First
Defined measurable success criteria (inventory, expiry, billing and return accuracy) before designing anything.
Who I Was Building For
| STAKEHOLDER | PAIN POINT | WHAT THEY NEED FROM THE SYSTEM |
|---|---|---|
| Pharmacist / Store | Can't see live stock, batches or what's about to expire. | Real-time stock by location, batch/lot/expiry, FEFO issue and near-expiry alerts. |
| Procurement | Receipts aren't tied to purchase orders; quantities and rates drift. | PO lifecycle and GRN receipts that are the only way stock enters inventory. |
| OT / Department Nurse | Bulk issues to procedures are never reconciled afterwards. | A simple way to record consumed, returned and wasted quantities per issue. |
| Billing Staff | Patient bills don't reflect returns or package/tariff rules. | Patient-based sales showing the full item timeline, tariff pricing and printable bills. |
| Admin / Auditor | Discrepancies can't be explained after the fact. | An immutable transaction history, approvals, alerts and an audit of AI-assisted actions. |
- ✓Item master: medicines + hospital supplies
- ✓Batch / lot / expiry / serial / location
- ✓FEFO for expiry-sensitive stock
- ✓Adjustments, transfers, wastage, expired
- ✓Supplier purchase orders
- ✓Rates, taxes, expected delivery, status
- ✓GRN receipt capturing batch & expiry
- ✓Stock updates only via receipts
- ✓Search patient & encounter
- ✓Tariff, pricing & package rules
- ✓Return reversals on the patient account
- ✓Generate and print the bill from the Sales tab
- ✓Issue to patient, department or procedure
- ✓Issued = Consumed + Returned + Wasted + Unresolved
- ✓Restock only eligible returns
- ✓Flag unreconciled issues
- ✓Conversations + history retrieval
- ✓Vector RAG over policies, SOPs and tariffs
- ✓Answers grounded in live system data
- ✓Human confirmation for sensitive writes
- ✓Low / critical stock
- ✓Near-expiry & expired stock
- ✓PO / receipt exceptions
- ✓Consumed-not-billed & returned-still-billed
Auditability
Every stock, billing and AI-assisted action is recorded with who, what and when.
Configurability
Tariff, billing, return and policy rules change per hospital without changing the core UX.
Role-based access
Staff only see the modules relevant to their responsibilities.
Safety of AI actions
The copilot may propose, but a human must confirm anything that writes data.
Traceability
Any unit can be traced from PO and receipt, through issue and consumption, to the bill.
Usability
Issue, reconciliation and billing workflows are quick enough to use at a busy counter.
Translating Requirements Into Product Decisions
Requirements tell you what the system must do. I still had to decide what to actually put in front of each user, so I turned each complaint into the underlying need and then into a concrete product decision.
“Patients are billed for what we issued, not what they used.”
Billing must be driven by consumption, not by stock movement.
A 4-state consumption ledger. The charge is consumed quantity × applicable tariff.
“Returned gloves never make it back to the shelf.”
Returns need inspection, restocking and a matching bill credit.
A return workflow that restores only eligible stock and automatically reverses the patient charge.
“We keep finding expired vials.”
Picking must be expiry-aware, and risk must be visible early.
FEFO batch allocation plus near-expiry and expired-stock alerts.
“Where did this batch even come from?”
Stock needs a single, controlled way in.
Inventory only changes through GRN receipts that capture batch, expiry and supplier.
“What's the package rule for this procedure again?”
Policy answers are needed at the counter, grounded in the hospital's own documents.
RxPulse Assist with vector RAG over SOPs, tariffs and billing/package rules.
“I don't want an AI changing records on its own.”
AI should assist, never act unilaterally.
Action proposals with human confirmation, and every AI-assisted action written to the audit log.
The User Journey I Designed For
Sign in
Microsoft Entra ID / MSAL authentication decides the user's role.
Role dashboard
Inventory, procurement, consumption, billing and alerts relevant to that role.
Receive & manage stock
Purchase orders, GRN receipts and inventory transactions.
Issue & reconcile
Issue to patients, departments or OT, then record consumed, returned and wasted quantities.
Bill the patient
Review charges on the Sales tab and print the final patient bill.
Ask RxPulse Assist
Query operational data and hospital policy in plain language.
Scope decision: No patient-facing portal. All patient transactions are handled by staff through the Sales tab, which kept the first release focused on internal accuracy.
How the Architecture Was Designed, Step by Step
I designed the architecture as a series of decisions, each answering one question the requirements raised. The order mattered: I modelled the data first, then the rules, then the AI.
How do we make every stock number explainable?
Never edit stock counts directly. Every receipt, issue, consumption, return, wastage, transfer and adjustment is a ledger entry, and stock is derived from the ledger.
Auditability comes built in, and any discrepancy can be replayed transaction by transaction.
How do we stop billing on issue?
Every issue must balance: Issued = Consumed + Returned + Wasted + Unresolved. Anything still unresolved is flagged for follow-up.
It turns a vague process ("reconcile later") into a rule the system can check.
Where should patient charges come from?
Billing reads only consumed quantities × tariff or package rule. An accepted return creates a billing credit.
Inventory and billing stay decoupled but can never disagree.
Every hospital's tariffs and workflows differ. How do we avoid forks?
Tariff, pricing, package, return and role policies live in a configuration layer, not in code.
Hospital-specific workflows can change without changing the core user experience.
Who can see and do what?
Microsoft Entra ID / MSAL for sign-in, with role-based access to modules.
Uses the hospital's existing identity provider and keeps permissions consistent.
How can AI help without becoming a liability?
A Microsoft Agent Framework agent behind Flask chat APIs. It reads data through tools, answers policy questions via vector RAG, and can only write through proposals that a human confirms.
It gives staff natural-language help while keeping humans accountable for every change.
How do problems surface before they cost money?
Alert rules run over ledger and billing state: stock levels, expiry, PO exceptions, unreconciled issues and billing mismatches.
Alerts reflect the same source of truth as everything else.
Layered System Architecture
Presentation
Role-based operational UI
Identity & Access
Who you are, what you can do
Application APIs (Flask)
Business rules & transactions
AI Copilot
Assist, retrieve, propose
Data
Single source of truth
Core Transaction Flow
How the Core Mechanics Work
The three mechanisms that make RxPulse trustworthy: consumption reconciliation, return handling and the guarded AI copilot.
Consumption Reconciliation — Worked Example
10 pairs of gloves
Issued to the OT against the patient's procedure.
8 pairs
Recorded as used; these become billable.
2 pairs
Inspected, found acceptable and restored to pharmacy inventory.
0 pairs
Any wastage is recorded separately, with a reason and approval where needed.
0 pairs
Anything not yet accounted for is flagged for follow-up.
8 × tariff
The bill reflects actual consumption, not the issued quantity.
Scenario → System Action
| Scenario | System action |
|---|---|
| Items issued to dept / OT | Record issue quantity against the department, patient/encounter or procedure. |
| Items consumed | Record actual consumed quantity and make it eligible for patient billing. |
| Items returned | Record the return, inspect condition, restore only eligible stock, and credit the bill. |
| Items wasted / damaged | Record wastage separately with a reason, and approval where required. |
| Unreconciled issue | Flag pending consumption/return reconciliation for follow-up. |
RxPulse Assist — Guarded Copilot Flow
Alerts & Notifications
| Alert | Triggered when |
|---|---|
| Low / critical stock | Available quantity falls below configured thresholds. |
| Near-expiry / expired | A batch approaches or passes its expiry date. |
| PO / receipt exceptions | Purchase orders or receipts are pending or don't match. |
| Unreconciled consumption | Department/OT issues still have unresolved quantities. |
| Stock discrepancy | Unusual inventory movement or mismatched counts. |
| Billing discrepancy | Consumed-but-not-billed, or returned-but-still-billed items. |
| System / integration | Critical system or integration failures. |
Tech Stack & Why Each Piece Was Chosen
Python · Flask
Lightweight REST and chat/agent APIs for the procurement, inventory, sales and copilot modules.
Microsoft Agent Framework SDK
Structured agents with tools, conversation state and controlled actions.
Vector RAG
Grounds answers in the hospital's own policies, SOPs, tariffs and package rules.
Microsoft Entra ID · MSAL
Enterprise sign-in and role-based access through the hospital's existing identity provider.
Relational transaction ledger
ACID transactions for stock movements, bills and audit history.
Role-based web UI
One operational interface with modules shown according to role.
Building It Phase by Phase
I built RxPulse in vertical slices, each one usable end to end, following the order of the transaction flow so every new module had real data from the previous one.
- 1
Foundation: item master & ledger
Goal: A trustworthy source of truth for stock.
- •Item master for medicines and hospital supplies
- •Batch / lot / expiry / serial / location model
- •Append-only inventory transaction ledger
Output: Stock that can be explained from its transaction history.
- 2
Procurement & receipts
Goal: Controlled entry of stock.
- •Supplier purchase orders with status
- •GRN receipts capturing batch and expiry
- •Inventory updates only via receipts
Output: Every unit traceable back to a PO and receipt.
- 3
Issue & consumption reconciliation
Goal: Know what was really used.
- •Issue to patient, department or OT/procedure
- •Consumed / returned / wasted / unresolved capture
- •FEFO allocation for expiry-sensitive items
Output: Issues that must balance under the consumption rule.
- 4
Patient sales & billing
Goal: Bills that match consumption.
- •Patient and encounter search
- •Tariff, pricing and package rules
- •Return credits and printable bills from the Sales tab
Output: Accurate, printable patient bills with a full item timeline.
- 5
Alerts & role dashboards
Goal: Surface problems early.
- •Stock, expiry, PO and reconciliation alerts
- •Billing discrepancy detection
- •Role-specific dashboards
Output: Each role sees its own risks as soon as they appear.
- 6
RxPulse Assist copilot
Goal: Natural-language help that stays safe.
- •Flask chat APIs with conversation history
- •Vector RAG over policies, SOPs and tariffs
- •Data tools + action proposals with human confirmation
Output: A copilot grounded in hospital data and policy that can't write unilaterally.
- 7
Identity, roles & audit hardening
Goal: Production-grade access control.
- •Entra ID / MSAL sign-in
- •Role-based module access
- •Audit trail across inventory, billing and AI actions
Output: A secure, auditable system ready for staff.
How I Verified It Works
Every test traced back to a success criterion defined during requirement gathering. The focus was on the rules that affect money and patient safety.
Ledger & inventory rules
Stock must always be explainable by its transactions.
- ✓Stock balance equals the sum of ledger movements
- ✓FEFO picks the earliest-expiring eligible batch
- ✓Expired stock is never issued
- ✓Stock only enters through GRN receipts
Consumption & returns
Every issue has to balance under the consumption rule.
- ✓Issued = Consumed + Returned + Wasted + Unresolved holds for every issue
- ✓Only eligible returns are restocked
- ✓Unresolved quantities raise reconciliation alerts
Billing accuracy
Patient charges must equal actual consumption.
- ✓Charge = consumed quantity × applicable tariff/package rule
- ✓Accepted returns reverse the matching charge
- ✓Consumed-not-billed and returned-still-billed cases trigger alerts
AI copilot safety
The copilot has to be useful without being able to cause harm.
- ✓Policy answers are grounded in retrieved documents
- ✓No write executes without human confirmation
- ✓Every AI-assisted action appears in the audit log
- ✓Users only reach data their role allows
Success Criteria → How Each Was Verified
| CRITERION | VERIFIED BY |
|---|---|
| Inventory accuracy | Replaying ledger transactions against displayed stock. |
| Expiry control | Multi-batch issue scenarios checking FEFO order and expiry alerts. |
| Procurement traceability | Tracing received stock back to its PO and GRN. |
| Consumption accuracy | The OT gloves scenario (10 issued → 8 consumed, 2 returned). |
| Billing accuracy | Comparing bill totals to consumed × tariff, including return credits. |
| Policy compliance | Checking copilot answers against the source policy/tariff documents. |
| Auditability | Confirming inventory, billing and AI actions each leave an audit record. |
Shipping It
Deployment was mostly configuration. Because hospital rules are data rather than code, going live meant setting up identity, data and documents rather than changing the application.
Register the app in Entra ID
Set up the client and tenant, redirect URIs and role assignments for MSAL sign-in.
Provision the database
Create the ledger schema and load the item master, suppliers and locations.
Load hospital rules
Configure tariffs, package rules, return policies and alert thresholds.
Index policy documents
Embed SOPs, tariffs and billing rules into the vector store for RxPulse Assist.
Deploy APIs & UI
Ship the Flask APIs and web interface with environment-based configuration and secrets.
Smoke-test every role
Run the 6-step journey (sign-in to copilot) for each role before handing over.
Development
Local Flask APIs with sample hospital data and a small policy corpus for fast iteration.
Staging / Demo
Full configuration with Entra ID sign-in, realistic item master and end-to-end scenarios.
What I Learned & What's Next
Model the quantities that affect money explicitly.
Splitting “issued” into consumed, returned, wasted and unresolved fixed billing, stock and auditing in one move.
A ledger beats a counter.
Deriving stock from transactions made every number explainable and every bug reproducible.
Configuration over customisation.
Keeping tariffs and policies as data means one codebase can serve hospitals with different rules.
In regulated domains, AI proposes and humans decide.
Confirmation plus an audit trail is what makes an AI copilot acceptable where money and patients are involved.
RAG turns SOPs into usable knowledge.
Policies that sat unread in documents became answers staff can get in seconds.
Say no to scope deliberately.
Leaving out a patient portal kept the first release focused on the accuracy problems that mattered most.