Blood-bank operations / 2026
BDRS
A case is more
than its status.
A blood-bank system of record: requests, per-bag crossmatch, issue and outcomes connected in one case workspace.
- Founder contribution
- Product owner · sole developer · QA and release
- Built with
- Laravel 13 · PHP 8.4 · Inertia 3 · React 19 · Tailwind 4 · SQLite
Start with the work.
The original process spanned 12 Excel workbooks and a Word document. Producing the monthly report meant manually transcribing between files; the lifecycle of a request and each blood unit needed a shared record.
Adjie designed and built a domain-led system with one case workstation, separate state machines for service, crossmatch and transfusion, and controlled finalisation. Product decisions, full-stack implementation, testing and release were Adjie’s responsibility, with AI-assisted implementation.
Connected events.
Independent meaning.
Receipt confirmation brings units into inventory; unconfirmed deliveries are not stock.
An explanation of the domain model, not a clinical decision tool.
Make the rules
impossible to miss.
- 01
One case. Separate truths.
Issuing a bag does not mean it was used. A used bag does not imply a recorded transfusion episode. Each event keeps its own meaning.
- 02
Compatibility belongs to the pairing.
Crossmatch is per bag, never a single verdict for the request. An incompatible result leaves the request line short.
- 03
A refusal must be actionable.
Named readiness checks explain what is unresolved and where to resolve it. Warnings remain distinct from blockers.
- 04
Enforce the boundary on the server.
Staff handle daily transactions; administration and correction require the super-admin role. Policies enforce the distinction beyond visible buttons.
Explain what
still needs work.
The readiness surface names the unresolved checks and provides the resolving action. The capture shows a synthetic case, including its actual notification stack.
Finalisation evaluates seven blockers and two warnings; the open-episode check runs again inside the transaction.

Available is not always usable.
Stock is derived by the domain service. The interface keeps availability and expiry visible together.


The same case.
A different layout.
At phone width, the case keeps its actions and context. The public fixture makes the boundary explicit: DEMO patients, DEMO bags and E2E staff.
Domain modelling, traceable corrections and release discipline are part of the product—not work left behind the interface.
The public record.
- Recorded release
- 19 September 2026 · owner UAT passed
- Unit / feature suite
- 2,672 passed · 74 skipped · 3 incomplete
- End-to-end suite
- 44 passed
- Handover
- Operator manual + technical maintenance package
