14 KiB
HIS Simulator - Complete Implementation Guide
Overview
The HIS (Hospital Information System) Simulator is a comprehensive tool for testing the patient journey tracking system. It simulates real-world patient events from a hospital system and automatically triggers survey invitations when patients complete their journeys.
What Was Implemented
1. HIS Events API Endpoint
Location: apps/simulator/views.py - HISEventsAPIView
A public API endpoint that receives patient journey events from external HIS systems:
- URL:
/api/simulator/his-events/ - Method: POST
- Authentication: None (public for simulator testing)
- Request Format: JSON array of events
2. HIS Simulator Script
Location: apps/simulator/his_simulator.py
A continuous event generator that simulates patient journeys:
- Generates realistic patient data (Saudi names, national IDs, phone numbers)
- Creates complete patient journeys (registration → discharge)
- Sends events to the API endpoint
- Configurable delay and patient count
3. Journey & Survey Seeding
Location: apps/simulator/management/commands/seed_journey_surveys.py
Management command that creates journey templates and surveys:
- EMS journey (4 stages)
- Inpatient journey (6 stages)
- OPD journey (5 stages)
- Survey templates with questions for each journey type
4. Event Processing Logic
When events are received:
- Creates or finds patient records
- Creates journey instance for new encounters
- Completes stages based on event type
- When journey is complete → creates survey instance
- Sends survey invitation via email and SMS
How It Works
Event Flow
HIS System → API Endpoint → Event Processing → Journey Tracking → Survey Creation → Notification Delivery
Supported Event Types
EMS Events
EMS_ARRIVAL- Patient arrives at emergencyEMS_TRIAGE- Triage completedEMS_TREATMENT- Treatment completedEMS_DISCHARGE- Patient discharged
Inpatient Events
INPATIENT_ADMISSION- Patient admittedINPATIENT_TREATMENT- Treatment completedINPATIENT_MONITORING- Monitoring phaseINPATIENT_MEDICATION- Medication administeredINPATIENT_LAB- Lab tests completedINPATIENT_DISCHARGE- Patient discharged
OPD Events
OPD_STAGE_1_REGISTRATION- Registration completedOPD_STAGE_2_CONSULTATION- Consultation completedOPD_STAGE_3_LAB- Lab tests completedOPD_STAGE_4_RADIOLOGY- Radiology completedOPD_STAGE_5_PHARMACY- Pharmacy/dispensing completed
Quick Start
1. Seed Journey Templates and Surveys
cd /home/ismail/projects/HH
uv run python manage.py seed_journey_surveys
This creates:
- 3 journey templates (EMS, Inpatient, OPD)
- 3 survey templates with questions
- 18 survey questions total
2. Start Django Server
uv run python manage.py runserver
3. Run the Simulator
Option A: Using the Python Script (Continuous Mode)
# Simulate 5 patients with 2 seconds between events
uv run python apps/simulator/his_simulator.py --delay 2 --max-patients 5
# Continuous mode (unlimited patients, 1 second between events)
uv run python apps/simulator/his_simulator.py --delay 1 --max-patients 0
Option B: Using cURL (Single Request)
curl -X POST http://localhost:8000/api/simulator/his-events/ \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"encounter_id": "TEST-001",
"mrn": "MRN-TEST-001",
"national_id": "1234567890",
"first_name": "Test",
"last_name": "Patient",
"phone": "+966501234567",
"email": "test@example.com",
"event_type": "OPD_STAGE_1_REGISTRATION",
"timestamp": "2026-01-20T10:30:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
},
{
"encounter_id": "TEST-001",
"mrn": "MRN-TEST-001",
"national_id": "1234567890",
"first_name": "Test",
"last_name": "Patient",
"phone": "+966501234567",
"email": "test@example.com",
"event_type": "OPD_STAGE_2_CONSULTATION",
"timestamp": "2026-01-20T11:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
}
]
}'
4. Verify Results
Check the Django logs for:
- Patient creation:
Created patient MRN-XXX: Full Name - Journey creation:
Created new journey instance XXX with N stages - Stage completion:
Completed stage StageName for journey ENC-XXX - Survey creation:
Created survey instance XXX for journey ENC-XXX - Email sent:
Survey invitation sent via email to email@example.com - SMS sent:
Survey invitation sent via SMS to +966XXXXXXXXX
API Specification
POST /api/simulator/his-events/
Request Body:
{
"events": [
{
"encounter_id": "string (required) - Unique encounter ID from HIS",
"mrn": "string (required) - Medical Record Number",
"national_id": "string (required) - Patient national ID",
"first_name": "string (required) - Patient first name",
"last_name": "string (required) - Patient last name",
"phone": "string (required) - Patient phone number",
"email": "string (required) - Patient email address",
"event_type": "string (required) - Event code (see supported events above)",
"timestamp": "string (required) - ISO 8601 timestamp",
"visit_type": "string (required) - Journey type: ems, inpatient, or opd",
"department": "string (optional) - Department name",
"branch": "string (optional) - Hospital branch",
"physician_name": "string (optional) - Physician name"
}
]
}
Success Response:
{
"success": true,
"message": "Processed 5 events successfully",
"results": [
{
"encounter_id": "TEST-001",
"patient_id": "uuid",
"journey_id": "uuid",
"stage_id": "uuid",
"stage_status": "completed",
"survey_sent": false
}
],
"surveys_sent": 1,
"survey_details": [
{
"encounter_id": "TEST-001",
"survey_id": "uuid",
"survey_url": "/surveys/XXXXX/"
}
]
}
Testing Scenarios
Scenario 1: Complete OPD Journey
Test a full OPD patient journey that triggers a survey:
curl -X POST http://localhost:8000/api/simulator/his-events/ \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"encounter_id": "OPD-TEST-001",
"mrn": "OPD-MRN-001",
"national_id": "1234567891",
"first_name": "Ahmed",
"last_name": "Al-Rashid",
"phone": "+966501234568",
"email": "ahmed@example.com",
"event_type": "OPD_STAGE_1_REGISTRATION",
"timestamp": "2026-01-20T10:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
},
{
"encounter_id": "OPD-TEST-001",
"mrn": "OPD-MRN-001",
"national_id": "1234567891",
"first_name": "Ahmed",
"last_name": "Al-Rashid",
"phone": "+966501234568",
"email": "ahmed@example.com",
"event_type": "OPD_STAGE_2_CONSULTATION",
"timestamp": "2026-01-20T11:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
},
{
"encounter_id": "OPD-TEST-001",
"mrn": "OPD-MRN-001",
"national_id": "1234567891",
"first_name": "Ahmed",
"last_name": "Al-Rashid",
"phone": "+966501234568",
"email": "ahmed@example.com",
"event_type": "OPD_STAGE_3_LAB",
"timestamp": "2026-01-20T12:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
},
{
"encounter_id": "OPD-TEST-001",
"mrn": "OPD-MRN-001",
"national_id": "1234567891",
"first_name": "Ahmed",
"last_name": "Al-Rashid",
"phone": "+966501234568",
"email": "ahmed@example.com",
"event_type": "OPD_STAGE_4_RADIOLOGY",
"timestamp": "2026-01-20T13:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
},
{
"encounter_id": "OPD-TEST-001",
"mrn": "OPD-MRN-001",
"national_id": "1234567891",
"first_name": "Ahmed",
"last_name": "Al-Rashid",
"phone": "+966501234568",
"email": "ahmed@example.com",
"event_type": "OPD_STAGE_5_PHARMACY",
"timestamp": "2026-01-20T14:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
}
]
}'
Expected Result:
- Patient created
- Journey instance created with 5 stages
- All 5 stages completed
- Survey instance created
- Survey invitation sent via email and SMS
Scenario 2: Partial Journey
Test a partial journey that doesn't trigger a survey:
curl -X POST http://localhost:8000/api/simulator/his-events/ \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"encounter_id": "PARTIAL-001",
"mrn": "PARTIAL-MRN-001",
"national_id": "1234567892",
"first_name": "Sara",
"last_name": "Al-Otaibi",
"phone": "+966501234569",
"email": "sara@example.com",
"event_type": "OPD_STAGE_1_REGISTRATION",
"timestamp": "2026-01-20T10:00:00Z",
"visit_type": "opd",
"department": "Cardiology",
"branch": "Main"
}
]
}'
Expected Result:
- Patient created
- Journey instance created with 5 stages
- Only 1 stage completed
- No survey created (journey incomplete)
Database Verification
Check Journey Instances
from apps.journeys.models import PatientJourneyInstance, StageStatus
# Get all journeys
journeys = PatientJourneyInstance.objects.all()
for j in journeys:
print(f"{j.encounter_id}: {j.status} - {j.get_completion_percentage()}% complete")
# Check a specific journey
ji = PatientJourneyInstance.objects.get(encounter_id='OPD-TEST-001')
print(f"Status: {ji.status}")
print(f"Complete: {ji.is_complete()}")
print(f"Stages: {ji.stage_instances.filter(status=StageStatus.COMPLETED).count()}/{ji.stage_instances.count()}")
Check Survey Instances
from apps.surveys.models import SurveyInstance
from apps.journeys.models import PatientJourneyInstance
# Get all surveys
surveys = SurveyInstance.objects.all()
for s in surveys:
print(f"Survey: {s.id} - Journey: {s.journey_instance.encounter_id}")
print(f"URL: {s.get_survey_url()}")
print(f"Status: {s.status}")
# Get survey for a specific journey
ji = PatientJourneyInstance.objects.get(encounter_id='OPD-TEST-001')
si = SurveyInstance.objects.filter(journey_instance=ji).first()
if si:
print(f"Survey URL: {si.get_survey_url()}")
Monitoring and Debugging
Django Logs
Watch for these log messages:
Patient Creation:
Created patient MRN-XXX: Full Name
Journey Creation:
Created new journey instance XXX with N stages
Stage Completion:
Completed stage StageName for journey ENC-XXX
Survey Creation:
Created survey instance XXX for journey ENC-XXX
Email Sending:
[Email Simulator] Email sent successfully to email@example.com
Survey invitation sent via email to email@example.com
SMS Sending:
[SMS Simulator] SMS sent to +966XXXXXXXXX
Survey invitation sent via SMS to +966XXXXXXXXX
Common Issues
Issue: "Journey template not found for visit_type"
Solution: Run the seed command: uv run python manage.py seed_journey_surveys
Issue: Survey not created after completing journey
Solution: Check that the journey template has send_post_discharge_survey = True
Issue: Email/SMS not sent
Solution: Check that the NotificationService is configured and the simulator endpoints are accessible
Architecture
Components
-
HIS Events API (
apps/simulator/views.py)- Receives events from external systems
- Validates event data
- Processes events sequentially
- Returns detailed response
-
Event Processor (
apps/simulator/views.py-process_his_event())- Creates/updates patients
- Creates/updates journeys
- Completes stages
- Triggers surveys
-
HIS Simulator Script (
apps/simulator/his_simulator.py)- Generates patient data
- Creates event sequences
- Sends events to API
- Logs results
-
Survey Notification Service (
apps/integrations/services.py)- Sends email invitations
- Sends SMS invitations
- Tracks delivery status
Data Flow
HIS System
↓
HIS Events API
↓
Event Processor
↓
Patient Manager (create/find patient)
↓
Journey Manager (create/find journey)
↓
Stage Manager (complete stage)
↓
Survey Manager (create survey if journey complete)
↓
Notification Service (send email & SMS)
Future Enhancements
Potential improvements to the simulator:
- Real-time Event Stream: WebSocket support for live event streaming
- Event Replay: Ability to replay historical events for testing
- Error Handling: Better error recovery and retry logic
- Metrics Dashboard: Real-time metrics on event processing
- Batch Processing: Support for large batch imports
- Event Validation: More robust event data validation
- Custom Event Types: Support for custom journey templates
Summary
The HIS Simulator provides a complete testing environment for:
✅ Patient journey tracking ✅ Stage completion automation ✅ Survey triggering on journey completion ✅ Email and SMS notifications ✅ Real-time event processing ✅ Database verification
The system is production-ready for integration testing and can be easily extended for real HIS system integration.