A cloud-ready, single-hospital Hospital Management System built with Flask, SQLAlchemy, and server-rendered HTML/CSS. Covers all 10 core MVP modules from the requirements: Authentication, Reception, EMR, Doctor, Nurse, Laboratory, Pharmacy, Billing, HR, and Inventory — plus admin tooling (users, beds, audit log) and a basic Analytics dashboard.
pip install -r requirements.txt
python3 seed.py # creates database tables + a Super Admin account + sample beds/inventory
python3 app.py # runs on http://localhost:5000Default Super Admin login:
- Email:
admin@medicore.ng - Password:
admin123
Change this password immediately after first login (Change Password link in the sidebar), and use the HR module (or Admin → Manage Users) to create real staff accounts for each role.
app.py— Flask app factory, blueprint registrationconfig.py— configuration (defaults to local SQLite; setDATABASE_URLenv var for Postgres/MySQL in production)extensions.py— shareddb(SQLAlchemy) andlogin_manager(Flask-Login) instancesmodels/— all database models, split by domain:user.py—User, roles,AuditLogpatient.py—Patient,Appointment,Encounter(the consultation hub),VitalSign,NurseNote,Admission,Bedclinical.py—LabRequest,Prescription,InventoryItem,StockMovementbilling.py—Bill,Payment,Employee,LeaveRequest,Attendance
routes/— one blueprint per module (auth,dashboard,reception,doctor,nurse,lab,pharmacy,billing,hr,inventory,admin,analytics)templates/— Jinja2 templates, organized to mirror the routesstatic/css/style.css— the full design system (deep teal / warm paper / amber alert palette)utils/access.py—@roles_required(...)decorator and ID-generation helpers
This is the piece the original spec emphasized: doctor actions automatically route to other departments.
- Receptionist registers a patient → gets a unique Hospital ID (
HMS-2026-0001) → schedules an appointment → checks them into the queue. - Doctor sees them on the dashboard, opens a Consultation (
Encounter), records symptoms/diagnosis/notes. - From that same consultation screen, the doctor can:
- Request a lab test → instantly appears on the Laboratory Dashboard as "Pending."
- Write a prescription → instantly appears on the Pharmacy Dashboard as "Pending."
- Recommend admission, refer to another doctor, or schedule a follow-up.
- Lab scientist assigns themselves, uploads a result (text + optional PDF) → marks completed → the requesting doctor can see it immediately in the patient's EMR.
- Pharmacist dispenses the prescription → inventory is automatically decremented via a
StockMovementrecord, and a dispensing label can be printed. - Nurse can record vitals (visible to doctors immediately) and mark dispensed medications as administered.
- Cashier generates a bill (consultation + lab + drug + admission + procedure fees), receives payment (cash/POS/bank transfer), and prints a receipt.
- Every one of these actions writes to the Audit Log (who, what, when) — visible to Admins.
Each role only sees its own dashboard and permitted actions (enforced server-side via @roles_required on every route, not just hidden in the UI). Roles: Super Admin, Hospital Administrator, Receptionist, Doctor, Nurse, Laboratory Scientist, Pharmacist, Cashier/Billing Officer, HR Manager, Store/Inventory Officer.
- Single hospital / single tenant for now — models are structured so a
hospital_idforeign key could be added to every table later for true multi-tenancy without a rewrite. - No patient portal, telemedicine, SMS/WhatsApp notifications — explicitly out of scope for this MVP per the requirements doc.
- Password reset is a stub (tells the user to contact their Hospital Administrator) rather than sending real emails — wire up Flask-Mail or a transactional email provider for production.
- Diagnosis "most common diseases" analytics groups on free-text diagnosis strings; for real trend analysis, consider constraining diagnosis entry to an ICD-10-lite pick list.
- File uploads (patient photos, lab PDF reports) are stored on local disk under
static/uploads/— swap for S3-compatible object storage before production deployment.
- Add a
Hospitalmodel +hospital_idFK across tables for multi-tenancy. - Swap SQLite for Postgres (
DATABASE_URLenv var already supported). - Add Flask-Mail (or Termii/Africa's Talking for SMS) for real password resets and notifications.
- Add automated tests (the workflow above was manually verified via Flask's test client during build — worth formalizing into
pytest). - Containerize (Dockerfile) and put behind Gunicorn + Nginx for deployment.