HH/docs/HIS_SIMULATOR_COMPLETE.md
2026-01-24 15:27:30 +03:00

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:

  1. Creates or finds patient records
  2. Creates journey instance for new encounters
  3. Completes stages based on event type
  4. When journey is complete → creates survey instance
  5. 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 emergency
  • EMS_TRIAGE - Triage completed
  • EMS_TREATMENT - Treatment completed
  • EMS_DISCHARGE - Patient discharged

Inpatient Events

  • INPATIENT_ADMISSION - Patient admitted
  • INPATIENT_TREATMENT - Treatment completed
  • INPATIENT_MONITORING - Monitoring phase
  • INPATIENT_MEDICATION - Medication administered
  • INPATIENT_LAB - Lab tests completed
  • INPATIENT_DISCHARGE - Patient discharged

OPD Events

  • OPD_STAGE_1_REGISTRATION - Registration completed
  • OPD_STAGE_2_CONSULTATION - Consultation completed
  • OPD_STAGE_3_LAB - Lab tests completed
  • OPD_STAGE_4_RADIOLOGY - Radiology completed
  • OPD_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

  1. HIS Events API (apps/simulator/views.py)

    • Receives events from external systems
    • Validates event data
    • Processes events sequentially
    • Returns detailed response
  2. Event Processor (apps/simulator/views.py - process_his_event())

    • Creates/updates patients
    • Creates/updates journeys
    • Completes stages
    • Triggers surveys
  3. HIS Simulator Script (apps/simulator/his_simulator.py)

    • Generates patient data
    • Creates event sequences
    • Sends events to API
    • Logs results
  4. 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:

  1. Real-time Event Stream: WebSocket support for live event streaming
  2. Event Replay: Ability to replay historical events for testing
  3. Error Handling: Better error recovery and retry logic
  4. Metrics Dashboard: Real-time metrics on event processing
  5. Batch Processing: Support for large batch imports
  6. Event Validation: More robust event data validation
  7. 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.