HEALTHCARE AIHospital Pharmacy & Clinical InventorySolo Build

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.

1. Requirements→2. User Needs→3. Architecture→4. Development→5. Testing→6. Deployment

Project Snapshot

The problem, the users and the approach at a glance

Executive Summary
01. The Problem

Hospitals often charge patients for what was issued, not what was used. Returns rarely reach stock again, and expiring medicines are found too late.

02. Target Users

Pharmacists, store and procurement staff, OT and department nurses, billing staff, and hospital administrators or auditors.

03. Core Insight

“Issued” is not “consumed”. Once quantities are split into consumed, returned, wasted and unresolved, correct billing and stock follow naturally.

04. The Solution

A ledger-based pharmacy system with FEFO, GRN-controlled receipts, consumption reconciliation and tariff-driven patient billing.

05. AI Layer

RxPulse Assist: a Microsoft Agent Framework copilot with vector RAG over SOPs, tariffs and package rules, and human-confirmed actions.

06. Security

Microsoft Entra ID / MSAL sign-in with role-based access, and an audit trail for inventory, billing and AI-assisted actions.

01 / Purpose

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.

4Quantity states per issue
FEFOFirst-expiry, first-out
7Alert families
6Step role-based journey
🧾Billing on Issue, Not Use

Ten pairs of gloves go to the OT and the patient pays for ten, even though two came back unused.

↩️Returns That Vanish

Unused items returned from departments are not inspected, restocked or credited back on the patient's bill.

⏳Expiry Waste

Without FEFO, newer batches get issued first while older stock silently expires on the shelf.

📦Broken Procurement Trail

Stock enters without a clear link to a purchase order or goods receipt, so batch and supplier history is lost.

📚Policy Locked in Documents

Tariffs, package rules and SOPs live in files that staff can't query while standing at the counter.

🔍No Audit Trail

When stock doesn't match, nobody can reconstruct who issued, consumed, returned or wrote off what.

The mission

“A patient should pay for exactly what was used on them, and every unit in the hospital should have a story you can trace.”

02 / Step 1 — Requirement Gathering

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.

🗺️STEP 1

Workflow Mapping

Traced the full chain: Purchase Order → GRN → Inventory → Issue → Consumption → Bill → Audit.

🧤STEP 2

Scenario Walkthroughs

Walked real edge cases: partial OT usage, damaged returns, near-expiry batches and unreconciled issues.

📑STEP 3

Policy & Document Audit

Listed the policies, SOPs, tariffs and billing/package rules that decisions depend on, as inputs for the AI copilot.

🎯STEP 4

Success Criteria First

Defined measurable success criteria (inventory, expiry, billing and return accuracy) before designing anything.

Who I Was Building For

STAKEHOLDERPAIN POINTWHAT THEY NEED FROM THE SYSTEM
Pharmacist / StoreCan'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.
ProcurementReceipts 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 NurseBulk issues to procedures are never reconciled afterwards.A simple way to record consumed, returned and wasted quantities per issue.
Billing StaffPatient bills don't reflect returns or package/tariff rules.Patient-based sales showing the full item timeline, tariff pricing and printable bills.
Admin / AuditorDiscrepancies can't be explained after the fact.An immutable transaction history, approvals, alerts and an audit of AI-assisted actions.
Functional · Inventory
  • ✓Item master: medicines + hospital supplies
  • ✓Batch / lot / expiry / serial / location
  • ✓FEFO for expiry-sensitive stock
  • ✓Adjustments, transfers, wastage, expired
Functional · Procurement
  • ✓Supplier purchase orders
  • ✓Rates, taxes, expected delivery, status
  • ✓GRN receipt capturing batch & expiry
  • ✓Stock updates only via receipts
Functional · Sales & Billing
  • ✓Search patient & encounter
  • ✓Tariff, pricing & package rules
  • ✓Return reversals on the patient account
  • ✓Generate and print the bill from the Sales tab
Functional · Department / OT
  • ✓Issue to patient, department or procedure
  • ✓Issued = Consumed + Returned + Wasted + Unresolved
  • ✓Restock only eligible returns
  • ✓Flag unreconciled issues
Functional · AI Copilot
  • ✓Conversations + history retrieval
  • ✓Vector RAG over policies, SOPs and tariffs
  • ✓Answers grounded in live system data
  • ✓Human confirmation for sensitive writes
Functional · Alerts
  • ✓Low / critical stock
  • ✓Near-expiry & expired stock
  • ✓PO / receipt exceptions
  • ✓Consumed-not-billed & returned-still-billed
Non-functional requirements (the constraints that shaped the architecture)

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.

03 / Step 2 — What to Give the User

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.

What I heard

“Patients are billed for what we issued, not what they used.”

What it really means

Billing must be driven by consumption, not by stock movement.

What I built

A 4-state consumption ledger. The charge is consumed quantity × applicable tariff.

What I heard

“Returned gloves never make it back to the shelf.”

What it really means

Returns need inspection, restocking and a matching bill credit.

What I built

A return workflow that restores only eligible stock and automatically reverses the patient charge.

What I heard

“We keep finding expired vials.”

What it really means

Picking must be expiry-aware, and risk must be visible early.

What I built

FEFO batch allocation plus near-expiry and expired-stock alerts.

What I heard

“Where did this batch even come from?”

What it really means

Stock needs a single, controlled way in.

What I built

Inventory only changes through GRN receipts that capture batch, expiry and supplier.

What I heard

“What's the package rule for this procedure again?”

What it really means

Policy answers are needed at the counter, grounded in the hospital's own documents.

What I built

RxPulse Assist with vector RAG over SOPs, tariffs and billing/package rules.

What I heard

“I don't want an AI changing records on its own.”

What it really means

AI should assist, never act unilaterally.

What I built

Action proposals with human confirmation, and every AI-assisted action written to the audit log.

The User Journey I Designed For

1

Sign in

Microsoft Entra ID / MSAL authentication decides the user's role.

2

Role dashboard

Inventory, procurement, consumption, billing and alerts relevant to that role.

3

Receive & manage stock

Purchase orders, GRN receipts and inventory transactions.

4

Issue & reconcile

Issue to patients, departments or OT, then record consumed, returned and wasted quantities.

5

Bill the patient

Review charges on the Sales tab and print the final patient bill.

6

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.

04 / Step 3 — Designing the Architecture

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.

DESIGN STEP 01Model inventory as a transaction ledger
THE QUESTION

How do we make every stock number explainable?

THE DECISION

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.

WHY

Auditability comes built in, and any discrepancy can be replayed transaction by transaction.

DESIGN STEP 02Encode the consumption rule
THE QUESTION

How do we stop billing on issue?

THE DECISION

Every issue must balance: Issued = Consumed + Returned + Wasted + Unresolved. Anything still unresolved is flagged for follow-up.

WHY

It turns a vague process ("reconcile later") into a rule the system can check.

DESIGN STEP 03Link billing to consumption events
THE QUESTION

Where should patient charges come from?

THE DECISION

Billing reads only consumed quantities × tariff or package rule. An accepted return creates a billing credit.

WHY

Inventory and billing stay decoupled but can never disagree.

DESIGN STEP 04Make rules configurable
THE QUESTION

Every hospital's tariffs and workflows differ. How do we avoid forks?

THE DECISION

Tariff, pricing, package, return and role policies live in a configuration layer, not in code.

WHY

Hospital-specific workflows can change without changing the core user experience.

DESIGN STEP 05Put identity at the edge
THE QUESTION

Who can see and do what?

THE DECISION

Microsoft Entra ID / MSAL for sign-in, with role-based access to modules.

WHY

Uses the hospital's existing identity provider and keeps permissions consistent.

DESIGN STEP 06Add the AI as a controlled layer
THE QUESTION

How can AI help without becoming a liability?

THE DECISION

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.

WHY

It gives staff natural-language help while keeping humans accountable for every change.

DESIGN STEP 07Derive alerts from ledger state
THE QUESTION

How do problems surface before they cost money?

THE DECISION

Alert rules run over ledger and billing state: stock levels, expiry, PO exceptions, unreconciled issues and billing mismatches.

WHY

Alerts reflect the same source of truth as everything else.

Layered System Architecture

Final Topology
Layer 1

Presentation

Role-based operational UI

DashboardInventoryProcurementIssue & ConsumptionSales & BillingRxPulse Assist chat
Layer 2

Identity & Access

Who you are, what you can do

Microsoft Entra IDMSAL sign-inRole-based module access
Layer 3

Application APIs (Flask)

Business rules & transactions

Procurement & GRNInventory ledgerIssue & reconciliationSales & billingAlertsChat / agent APIs
Layer 4

AI Copilot

Assist, retrieve, propose

Microsoft Agent Framework SDKVector RAG (policies, SOPs, tariffs)Data toolsAction proposals + confirmationConversation history
Layer 5

Data

Single source of truth

Item masterBatches / lots / expiryTransaction ledgerPatients & encountersBills & creditsAudit log
How it works:Each layer has one responsibility and talks only to the layer next to it, which keeps the system testable and replaceable piece by piece.

Core Transaction Flow

End-to-End
Purchase OrderSupplier, qty, rate, tax
↓
GRN / ReceiptBatch, lot, expiry captured
↓
Pharmacy InventoryFEFO, by location
↓
IssuePatient / Dept / OT
↓
Reconcile
ConsumedReturnedWasted
↓
Patient BillConsumed × tariff
↓
AuditEvery step logged
How it works:Stock enters only through a goods receipt, leaves only through a tracked issue, and reaches the patient's bill only once it's confirmed as consumed.
05 / Under the Hood

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

The Core Rule
Issued

10 pairs of gloves

Issued to the OT against the patient's procedure.

Consumed

8 pairs

Recorded as used; these become billable.

Returned

2 pairs

Inspected, found acceptable and restored to pharmacy inventory.

Wasted

0 pairs

Any wastage is recorded separately, with a reason and approval where needed.

Unresolved

0 pairs

Anything not yet accounted for is flagged for follow-up.

Patient Charge

8 × tariff

The bill reflects actual consumption, not the issued quantity.

How it works:Ten pairs of gloves go to the OT. Eight are used and two come back in good condition, so the patient pays for eight and two go back on the shelf.

Scenario → System Action

Business Rules
ScenarioSystem action
Items issued to dept / OTRecord issue quantity against the department, patient/encounter or procedure.
Items consumedRecord actual consumed quantity and make it eligible for patient billing.
Items returnedRecord the return, inspect condition, restore only eligible stock, and credit the bill.
Items wasted / damagedRecord wastage separately with a reason, and approval where required.
Unreconciled issueFlag pending consumption/return reconciliation for follow-up.
How it works:Each real-world event maps to exactly one system behaviour, which keeps the ledger consistent.

RxPulse Assist — Guarded Copilot Flow

AI Safety
Staff question“Near-expiry insulin in Ward 3?”
↓
Flask chat APIConversation + history
↓
Agent (MS Agent Framework)
RAG: SOPs & tariffsTools: live stock & bills
↓
Grounded answerWith policy references
↓
Write intent?→ Action proposal
↓
Human confirmsThen executes
↓
Audit logAI action recorded
How it works:Read-only questions are answered straight away. Anything that would change data becomes a proposal that a staff member must confirm, and it is written to the audit log either way.

Alerts & Notifications

Proactive Signals
AlertTriggered when
Low / critical stockAvailable quantity falls below configured thresholds.
Near-expiry / expiredA batch approaches or passes its expiry date.
PO / receipt exceptionsPurchase orders or receipts are pending or don't match.
Unreconciled consumptionDepartment/OT issues still have unresolved quantities.
Stock discrepancyUnusual inventory movement or mismatched counts.
Billing discrepancyConsumed-but-not-billed, or returned-but-still-billed items.
System / integrationCritical system or integration failures.
How it works:All alerts are computed from the same ledger and billing state the rest of the system uses.
06 / Technology

Tech Stack & Why Each Piece Was Chosen

Backend APIs

Python · Flask

Lightweight REST and chat/agent APIs for the procurement, inventory, sales and copilot modules.

AI Agent

Microsoft Agent Framework SDK

Structured agents with tools, conversation state and controlled actions.

Retrieval

Vector RAG

Grounds answers in the hospital's own policies, SOPs, tariffs and package rules.

Identity

Microsoft Entra ID · MSAL

Enterprise sign-in and role-based access through the hospital's existing identity provider.

Data

Relational transaction ledger

ACID transactions for stock movements, bills and audit history.

Frontend

Role-based web UI

One operational interface with modules shown according to role.

07 / Step 4 — Development

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

08 / Step 5 — Testing

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

CRITERIONVERIFIED BY
Inventory accuracyReplaying ledger transactions against displayed stock.
Expiry controlMulti-batch issue scenarios checking FEFO order and expiry alerts.
Procurement traceabilityTracing received stock back to its PO and GRN.
Consumption accuracyThe OT gloves scenario (10 issued → 8 consumed, 2 returned).
Billing accuracyComparing bill totals to consumed × tariff, including return credits.
Policy complianceChecking copilot answers against the source policy/tariff documents.
AuditabilityConfirming inventory, billing and AI actions each leave an audit record.
09 / Step 6 — Deployment

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.

STEP 1

Register the app in Entra ID

Set up the client and tenant, redirect URIs and role assignments for MSAL sign-in.

STEP 2

Provision the database

Create the ledger schema and load the item master, suppliers and locations.

STEP 3

Load hospital rules

Configure tariffs, package rules, return policies and alert thresholds.

STEP 4

Index policy documents

Embed SOPs, tariffs and billing rules into the vector store for RxPulse Assist.

STEP 5

Deploy APIs & UI

Ship the Flask APIs and web interface with environment-based configuration and secrets.

STEP 6

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.

10 / Retrospective

What I Learned & What's Next

01

Model the quantities that affect money explicitly.

Splitting “issued” into consumed, returned, wasted and unresolved fixed billing, stock and auditing in one move.

02

A ledger beats a counter.

Deriving stock from transactions made every number explainable and every bug reproducible.

03

Configuration over customisation.

Keeping tariffs and policies as data means one codebase can serve hospitals with different rules.

04

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.

05

RAG turns SOPs into usable knowledge.

Policies that sat unread in documents became answers staff can get in seconds.

06

Say no to scope deliberately.

Leaving out a patient portal kept the first release focused on the accuracy problems that mattered most.