A full-stack blood donation coordination platform β connecting donors, hospitals, and blood banks through a unified digital system
Digitizes emergency blood request handling, geospatial donor matching, donation eligibility tracking, camp discovery, email notifications, and administrative oversight β eliminating fragmented manual coordination during critical situations.
Manual blood donation coordination between donors, hospitals, and blood banks causes critical delays during emergencies β no unified system, no automated donor matching, no real-time notification, no donation history tracking.
BDMS replaces this fragmented process with a centralised platform. A hospital raises an emergency request; the system instantly runs a geospatial ABO/Rh-compatible donor search, dispatches tokenised email alerts, records donor responses, and tracks the full request lifecycle β all automatically.
See the Testing Report for API validation results.
| Layer | Technology |
|---|---|
| Runtime | Node.js + Express.js (MVC structure) |
| Database | PostgreSQL 16 + PostGIS 3 (geospatial queries) |
| Frontend | HTML / CSS / JavaScript (React dashboards β in progress) |
| Authentication | JWT HS256 (24-hour expiry) + bcrypt password hashing |
| Authorization | middleware/requireRole.js β RBAC enforced on all endpoints |
| Email / OTP | Nodemailer via Gmail App Password / SendGrid SMTP |
| Geospatial | PostGIS ST_DWithin + ST_Distance for proximity matching |
| Schema Management | Incremental SQL migration files under database/ (immutable once committed) |
| Task Tracking | ClickUp |
| UML Diagrams | Draw.io + PlantUML |
| API Testing | Postman |
| Version Control | Git / GitHub |
| IDE | VS Code |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Web Frontend (Browser) β
β Donor Dashboard β Hospital Dashboard β Blood Bank β Admin β
β (HTML/CSS/JS β React dashboards in Sprint 4) β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β HTTPS / JSON
ββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββ
β Node.js + Express REST API β
β (MVC: controllers/ models/ routes/ β
β services/ middleware/ utils/ database/) β
β β
β ββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββ β
β β auth.middle β β requireRole.js β β Global Error β β
β β ware.js β β (RBAC guard) β β Handler β β
β ββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββ β
β β
β Auth β Donor β Hospital β BloodBank β Emergency β Camp β Admin β
ββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β Parameterised queries
ββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β PostgreSQL 16 + PostGIS 3 β
β Users Β· Donors Β· Hospitals Β· BloodBanks Β· EmergencyRequests β
β DonationRecords Β· BloodCamps Β· EmailLog β
β GIST spatial indexes on donor + facility location columns β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββ΄βββββββββββββββββββββ
β Nodemailer / SMTP Gateway β
β (Gmail App Password / SendGrid) β
β OTPs Β· Emergency alerts Β· Deep-links β
βββββββββββββββββββββββββββββββββββββββββββ
RBAC is enforced at the middleware layer via requireRole.js for user/admin routes, while verified hospital access is enforced through hospitalAuth.middleware.js.
| Role | Description | Key Capabilities |
|---|---|---|
user |
Registered platform user | Register, verify OTP, create donor profile, manage donor availability |
admin |
System administrator | Verify hospitals, review camps, access admin routes, manage users |
hospital |
Verified hospital actor via hospital JWT | Create blood requests, rematch donors, view own requests |
blood_bank |
Registered blood bank entity | Registration is implemented; full authenticated blood bank module is still in progress |
- Donor registration with OTP-based email verification (6-digit code, 10-minute TTL via Nodemailer)
- Donor accounts remain inactive until OTP verification succeeds
- Hospital registration with admin verification and separate hospital auth setup/login
- Blood bank registration with pending onboarding status
- JWT login with 24-hour expiry
requireRole.jsmiddleware enforces role separation across all endpoints- All passwords hashed with bcrypt (minimum cost factor 12)
- All database queries use parameterised statements β SQL injection prevented by design
- Verified hospitals only may create emergency requests β enforced via hospital auth middleware
- Blood request lifecycle persisted with
open | matched | fulfilled | cancelled - Geospatial donor matching via PostGIS
ST_DWithinwith ABO/Rh compatibility fromutils/bloodCompat.js, cooldown filtering, availability filtering, andST_Distancesorting - Radius expansion service logic exists for
3 km -> 6 km -> 9 km, but scheduler wiring is still pending - Blood bank emergency notification flow is still pending
- Nodemailer/SMTP email delivery for OTPs, emergency donor alerts, camp status emails, and hospital acceptance notifications
- Emergency donor alert emails include single-use signed deep-links for accept/decline
- Deep-link tokens are stored as hashes only and expire after 2 hours
- Retry logic is implemented with exponential backoff: 5s -> 25s -> 125s
- Delivery state is tracked in both
notificationsandemail_logwithpending | sent | failed - Runtime notification pipeline is email-only; no WhatsApp fallback exists in application code
- Donor receives email with tokenised deep-link; clicks to accept or decline without logging in
- Token authenticated server-side (2-hour TTL, single-use, hash stored only)
- Response recorded against the matched request
- Donor availability is set to
unavailableon acceptance - Hospital notified of donor acceptance via email immediately
- Donor volunteer onboarding validates age, BMI, blood group, and last donation date
- Cooldown eligibility is computed from
last_donation_dateanddeferred_until - Donor profile retrieval and availability updates are implemented
- Full donor profile edit workflow and donation history module are still pending
- Organiser submits camp proposal (name, date, time, venue, geolocation, capacity, organiser contact)
- Admin reviews and approves/rejects; organiser notified via email
- Approved camps listed for donor discovery by proximity and date range
- System does not process on-site registrations or record donations β passive information model only
- Find eligible donors by blood group, proximity, cooldown status, and availability
- GIST spatial indexes are used on user, hospital, blood bank, request, and camp locations
- Dedicated nearby blood bank API is not implemented yet
- Reporting modules are pending implementation
- Admin routes exist for users, hospitals, blood banks, and blood requests
- Hospital verification and blood bank verification endpoints exist
- Broader system configuration and reporting screens are still pending
Managed via incremental SQL migration files under database/. Existing migration files are never modified β all schema changes are new additions only.
Core Tables
Users β base auth, role, activation flags, soft-delete flag
Donors β profile, blood group, cooldown, availability
Hospitals β registration, verification, optional hospital login, soft-delete flag
BloodBanks β registration, verification, optional auth fields, soft-delete flag
Emergency & Matching
EmergencyRequests β blood group, units, hospital, location, radius, status, soft-delete flag
BloodRequestMatches β matched donor records and donor response status
ResponseTokens β hashed single-use donor response tokens (2-hour TTL)
Auth & Notifications
OtpTokens β hashed OTP verification records with expiry and consumption tracking
Notifications β email notification lifecycle records
EmailLog β delivery events, attempts, last attempt time, final status
Camp
BloodCamps β proposals, approval status, location, organiser details
Spatial Indexes
GIST index on Users.location
GIST index on Hospitals.location
GIST index on BloodBanks.location
GIST index on BloodRequests.location
GIST index on BloodCamps.location
Blood Compatibility
utils/bloodCompat.js β ABO/Rh compatibility matrix hardcoded
Routes are mounted directly from index.js. Protected routes require Authorization: Bearer <token>.
| Method | Route | Access | FR |
|---|---|---|---|
POST |
/auth/register |
Public | FR 4.1.1 |
POST |
/auth/login |
Public | FR 4.1.4 |
POST |
/auth/verify-otp |
Public | FR 4.1.1 |
| Method | Route | Access | FR |
|---|---|---|---|
POST |
/blood-banks/register |
Public | FR 4.1.2 |
POST |
/hospitals/register |
Public | FR 4.1.3 |
POST |
/hospitals/login |
Public | FR 4.1.4 |
GET |
/hospitals/pending |
admin |
FR 4.9.2 |
POST |
/hospitals/:id/verify |
admin |
FR 4.9.2 |
POST |
/hospitals/:id/setup-auth |
admin |
FR 4.1.3 |
| Method | Route | Access | FR |
|---|---|---|---|
POST |
/donors/become-volunteer |
Authenticated | FR 4.4.1 |
GET |
/donors/me |
Authenticated | FR 4.4.1 |
PATCH |
/donors/availability |
Authenticated | FR 4.4.2 |
GET |
/donor-requests |
Authenticated | FR 4.2.4 |
POST |
/donor-requests/:matchId/accept |
Authenticated | FR 4.2.4 |
POST |
/donor-requests/:matchId/reject |
Authenticated | FR 4.2.4 |
GET |
/donor-requests/respond/accept?token=... |
Public | FR 4.2.4 |
GET |
/donor-requests/respond/decline?token=... |
Public | FR 4.2.4 |
| Method | Route | Access | FR |
|---|---|---|---|
POST |
/blood-requests |
Verified hospital | FR 4.2.1 |
GET |
/blood-requests/mine |
Verified hospital | FR 4.5.2 |
GET |
/blood-requests/:id |
Verified hospital | FR 4.5.2 |
POST |
/blood-requests/:id/match |
Verified hospital | FR 4.2.2 |
| Method | Route | Access | FR |
|---|---|---|---|
POST |
/camps |
Public | FR 4.3.1 |
POST |
/camps/:id/review |
admin |
FR 4.3.2 |
GET |
/camps/nearby |
Public | FR 4.3.3 |
| Method | Route | Access | FR |
|---|---|---|---|
GET |
/admin/users |
admin |
FR 4.9.3 |
PATCH |
/admin/users/:id/role |
admin |
FR 4.9.3 |
DELETE |
/admin/users/:id |
admin |
FR 4.9.3 |
GET |
/admin/hospitals |
admin |
FR 4.9.2 |
PATCH |
/admin/hospitals/:id/approve |
admin |
FR 4.9.2 |
PATCH |
/admin/hospitals/:id/reject |
admin |
FR 4.9.2 |
DELETE |
/admin/hospitals/:id |
admin |
FR 4.9.2 |
GET |
/admin/blood-banks |
admin |
FR 4.9.2 |
PATCH |
/admin/blood-banks/:id/verify |
admin |
FR 4.9.2 |
DELETE |
/admin/blood-banks/:id |
admin |
FR 4.9.2 |
GET |
/admin/blood-requests |
admin |
FR 4.9.x |
DELETE |
/admin/blood-requests/:id |
admin |
FR 4.9.x |
GET |
/admin/stats |
admin |
FR 4.9.x |
Plan Period: Feb 7 β Apr 30, 2026 Β |Β Current: Mar 18, 2026 β Sprint 3 Complete
Feb 7 β Feb 14, 2026
- Donor registration with email OTP verification (FR 4.1.1)
- Hospital registration with admin verification workflow (FR 4.1.3)
- JWT HS256 login + role-based RBAC middleware (FR 4.1.4)
- PostgreSQL 16 + PostGIS 3 schema with GIST spatial indexes
- Geospatial donor matching engine β
ST_DWithin+ST_Distance+ ABO/Rh compatibility (FR 4.2.2)
Feb 15 β Feb 26, 2026
-
requireRole.jsRBAC middleware enforcing role separation across all endpoints - Emergency request creation and donor matching pipeline (FR 4.2.1, FR 4.2.2)
- Blood compatibility filtering via
utils/bloodCompat.js - 90-day donation cooldown data model and controller enforcement (FR 4.4.1)
- Hospital onboarding β register, pending list, verify, auth setup, hospital login (FR 4.1.3 extended)
- Verified-hospital middleware protecting emergency request endpoints (FR 4.5.1)
Feb 27 β Mar 14, 2026
- Nodemailer/SMTP email notification service with HTML donor alert emails (FR 4.7.1)
- Tokenised deep-link generation (2-hour expiry) for donor accept/decline (FR 4.2.3)
- Retry logic β 3 attempts, exponential back-off (5 s β 25 s β 125 s)
- All delivery events recorded in
email_logtable via migration - Donor accept/decline response flow β token auth, response recorded, hospital notified on acceptance (FR 4.2.4)
- OTP-gated donor account activation before login
- Runtime notification pipeline is email-only
Mar 15 β Mar 31, 2026
- Complete donor dashboard (eligibility, history, accept/decline actions)
- Complete hospital dashboard (request creation, status view, donor responses)
- Request status view (FR 4.5.2)
- Donor profile management β update fields, view history (FR 4.4.2, FR 4.4.3)
- Blood bank registration flow (FR 4.1.2)
Apr 1 β Apr 15, 2026
- Camp proposal submission, admin approval/rejection, organiser notification (FR 4.3.1, FR 4.3.2)
- Camp discovery by donors β proximity + date range search (FR 4.3.3)
- Admin console β verify hospitals/blood banks, manage users, system config (FR 4.9.1β4.9.4)
- Wire dynamic radius expansion service into a scheduler/job runner (FR 4.2.5)
- Nearby blood bank notification on emergency request (FR 4.2.6)
- Password reset via email with single-use 30-minute token (FR 4.1.5)
Apr 16 β Apr 30, 2026
- Donation summary report across date range (FR 4.8.1)
- Emergency response performance report β avg response time, fulfilment count (FR 4.8.2)
- Audit logging
- System-wide testing and bug fixes
- Mark notification as read (FR 4.7.2)
# Clone the repository
git clone https://github.com/RounakChoudhary/Blood-Donation-Management-System.git
cd Blood-Donation-Management-System
# Install dependencies
npm install
# Configure environment variables
# Create .env manually and set:
# DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME
# JWT_SECRET
# SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS
# APP_BASE_URL
# RESPONSE_TOKEN_SECRET (recommended)
# OTP_TTL_MINUTES (optional)
# Run database migrations (incremental SQL files under database/)
# Apply each migration file in order using your PostgreSQL client
# Enable PostGIS extension
psql -d your_db -c "CREATE EXTENSION IF NOT EXISTS postgis;"
# Start development server
node index.jsSee the Testing Report for Postman collection and API validation details.
WhatsApp integration via Twilio was originally planned but removed in SRS v2.2. Nodemailer/SMTP is the only runtime notification channel used by the backend. Because migrations are append-only, historical legacy migration files still document the removed WhatsApp design, but application code no longer uses it.
The system does not process on-site attendee registrations or record donations from camps. It acts purely as an information intermediary β publishing approved camp listings for donor discovery. This avoids out-of-scope complexity (on-site ops, physical donation recording) and keeps the system boundary clean.
All schema changes are applied as new numbered SQL migration files under database/. Existing migration files are never modified. This guarantees version consistency and safe, reversible updates across all deployment environments.
Donor search uses ST_DWithin for radius filtering combined with ABO/Rh compatibility (utils/bloodCompat.js), 90-day cooldown check, and ST_Distance for distance-sorted ranking. GIST spatial indexes are placed on all location columns to meet the 3-second performance requirement for up to 10,000 donors.
Rather than requiring donors to log in to respond to emergency alerts, each email contains a tokenised URL (2-hour TTL). The raw token is signed and only its hash is stored in the database. The server validates the link, records the response, marks the token single-use, and updates donor availability on acceptance.
| Category | Requirement |
|---|---|
| Performance | Emergency donor match + email dispatch within 10 seconds of request creation |
| Performance | ST_DWithin geospatial query within 3 seconds for up to 10,000 donors |
| Performance | User authentication and dashboard load within 2 seconds |
| Performance | API 95th-percentile response under 300 ms at 50 concurrent users |
| Performance | Email SMTP handshake + queue within 2 seconds |
| Security | HTTPS (TLS 1.2 minimum) for all client-server communication |
| Security | bcrypt password hashing with minimum cost factor 12 |
| Security | JWT HS256 tokens stored in env variables; 24-hour expiry |
| Security | SMTP credentials exclusively in .env β never in source code or logs |
| Security | All database queries use parameterised statements β no SQL injection possible |
| Safety | Emergency request creation restricted to verified hospitals only |
| Business Rule | One open request per blood group per hospital at a time |
| Business Rule | 90-day donation cooldown enforced before a donor can be matched again |
| Business Rule | Camps visible to donors only after administrator approval |
| Member | Role |
|---|---|
| Rounak Choudhary | Backend & Database Lead |
| Rahul Bishnoi | Requirements Alpha Manager & Backend |
| Priyam Patel | Work & Team Alpha Manager |
| Teenu Kumari | Customer Alpha Manager |
Branching strategy: feature branches β PR review β merge to main.
MVC directory structure standardised across all team members from Sprint 1.
Software Engineering [CSL 2060] Β Β·Β Group 10 Β·Β Blood Donation Management System Β Β