PHARMACY PLATFORM
SihaRx
SihaRx connects inventory, purchasing, sales, and customer balances in one pharmacy workspace.
From receiving stock
to recording a sale.
SihaRx brings the work around the pharmacy counter into one application: receiving deliveries, managing product batches, recording sales and payments, and following outstanding customer balances.
- OrderSupplier orders and line-level costs
- ReceiveDelivered quantities and batch details
- StockLots, expiry dates, and movements
- SellCheckout, payments, and balances
My engineering
contribution
My contributions span the React interface, server-side validation, database operations, and regression tests. I build and refine the workflows that connect stock, sales, purchasing, and customer balances.
THE SYSTEM
BEHIND THE WORKFLOW.
A web interface backed by authenticated application services and a shared PostgreSQL data layer.
- Interface
Product workflows, responsive layouts, and client state.
Next.js · React · TypeScript - Application
Request validation, permission checks, and business operations.
Server routes · Service layer - Data
Persistent records, Postgres functions, and Row Level Security (RLS) policies.
PostgreSQL
- Identity & access
- Authentication, membership checks, and role-aware workflows.
- Data integrity
- Database validation, related-record updates, and audit history.
Engineering decisions
Tenant boundaries
Keeping pharmacy data separate.
Each pharmacy’s records stay separate within one shared application.
- Problem
- The data model supports separate pharmacies within a shared application and database.
- Constraint
- Signing in must not grant access to another pharmacy’s records.
- Approach
- Membership and permission checks in application workflows are paired with Row Level Security (RLS) policies in PostgreSQL.
- Why it matters
- Tenant ownership becomes an explicit part of the data model and the request boundary.
Transactional workflows
A sale changes more than a total.
recordedStock
adjustedPayment
linked
- Problem
- Recording a sale also affects stock, payment information, and outstanding balances.
- Constraint
- Related records need to agree when a request succeeds, fails, or is retried.
- Approach
- Postgres functions coordinate related writes and calculate sale totals. Idempotency keys support retry handling, while audit entries retain the event’s context.
- Why it matters
- The sale record can stay aligned with its stock and payment effects.
Ordering & receiving
A delivery can arrive in parts.
- Problem
- An order may be fulfilled across several deliveries, with costs and batch details captured as stock arrives.
- Constraint
- Receiving part of an order must preserve what is still outstanding.
- Approach
- The receiving workflow validates remaining quantities, records costs, and updates batch stock alongside order progress.
- Why it matters
- Partial deliveries remain linked to the order while outstanding quantities stay visible.
Ordered quantities
and agreed costs
Received stock recorded.
Outstanding lines remain.
All order lines
accounted for
The product surfaces
- At the counter
- Product search, a working cart, customer selection, and payment flows, with dedicated mobile controls.
- Behind the shelf
- Stock and batch views, expiry information, supplier ordering, receiving deliveries, and movement history.
- After the sale
- Customer balances, payment collection, and reports that connect back to recorded activity.
Workflow diagrams based on the application; its screens are private.
Built with
The tools behind the application.
- Interface
- Next.js, React, TypeScript
- State & styling
- Zustand, Tailwind CSS
- Database
- PostgreSQL
- Verification
- Vitest, Testing Library, database integration tests
Testing the transitions
Unit and component tests cover input handling and interface state. Database integration tests exercise tenant separation, sale calculations, receiving, retries, and rejected operations.