# Simplified Survey Integration Documentation ## Overview The PX360 survey system has been simplified to directly deliver surveys based on PatientType without the complexity of journey tracking. This document describes the simplified architecture, data flow, and usage. ## Architecture ### Before (Complex) ``` HIS Data → Patient Journey → Journey Stages → Visit Processing → Stage Completion → Survey Creation → SMS Delivery ``` ### After (Simplified) ``` HIS Data → PatientType Detection → Survey Template Selection → Survey Creation → SMS Delivery ``` ## Key Components ### 1. HIS Adapter (`apps/integrations/services/his_adapter.py`) The HIS Adapter processes real HIS patient data and creates surveys directly. **Main Functions:** - `map_patient_type_to_survey_type()`: Maps HIS PatientType codes to survey types - `get_survey_template()`: Selects appropriate survey template based on PatientType - `create_and_send_survey()`: Creates survey instance and triggers SMS delivery - `process_his_data()`: Main entry point for processing HIS data **PatientType Mapping:** | HIS Code | Survey Type | Description | |----------|-------------|-------------| | "1" | INPATIENT | Inpatient visits | | "2" or "O" | OPD | Outpatient visits | | "3" or "E" | EMS | Emergency visits | | unknown | OPD (default) | Falls back to OPD | ### 2. HIS Simulator (`apps/simulator/his_simulator.py`) The simulator generates realistic HIS patient data with proper PatientType distribution. **PatientType Distribution:** - OPD: 60% (most common) - Inpatient: 30% - EMS: 10% **Usage:** ```bash # Run simulator with default settings (5 patients per minute) python apps/simulator/his_simulator.py # Run simulator with custom settings python apps/simulator/his_simulator.py --url http://localhost:8000/api/simulator/his-patient-data/ --delay 10 --max-patients 50 ``` **Parameters:** - `--url`: API endpoint URL - `--delay`: Delay between patients in seconds - `--max-patients`: Maximum number of patients (0 = infinite) ### 3. Survey Templates Survey templates must be named to match PatientType: - `OPD Survey` or template name containing "OPD" - `INPATIENT Survey` or template name containing "INPATIENT" - `EMS Survey` or template name containing "EMS" **Example Template Creation:** ```python from apps.surveys.models import SurveyTemplate from apps.organizations.models import Hospital hospital = Hospital.objects.get(code="ALH-main") # OPD Survey opd_survey = SurveyTemplate.objects.create( name="OPD Survey", hospital=hospital, description="Outpatient Department Survey", is_active=True, survey_type="patient_satisfaction" ) # Inpatient Survey inpatient_survey = SurveyTemplate.objects.create( name="INPATIENT Survey", hospital=hospital, description="Inpatient Care Survey", is_active=True, survey_type="patient_satisfaction" ) # EMS Survey ems_survey = SurveyTemplate.objects.create( name="EMS Survey", hospital=hospital, description="Emergency Medical Services Survey", is_active=True, survey_type="patient_satisfaction" ) ``` ## Data Flow ### 1. HIS Patient Data Reception The system receives HIS data in this format: ```json { "FetchPatientDataTimeStampList": [{ "PatientID": "123456", "AdmissionID": "ADM-001", "HospitalID": "1", "HospitalName": "Al Hammadi Hospital - Main", "PatientType": "2", "AdmitDate": "05-Jun-2025 11:06", "DischargeDate": "05-Jun-2025 16:30", "PatientName": "Ahmed Al-Saud", "MobileNo": "0512345678", "Email": "ahmed@example.com", "InsuranceCompanyName": "Arabian Shield Cooperative Insurance Company", ... }], "FetchPatientDataTimeStampVisitDataList": [...], "Code": 200, "Status": "Success" } ``` ### 2. Processing Flow ``` 1. Receive HIS patient data ↓ 2. Extract PatientType from data ↓ 3. Check if patient is discharged (DischargeDate present) ↓ 4. Get or create patient record ↓ 5. Select appropriate survey template based on PatientType ↓ 6. Create survey instance with metadata ↓ 7. Send survey via SMS using patient's phone number ↓ 8. Return success/failure status ``` ### 3. Survey Creation When a discharged patient is received: ```python # Survey instance created with: { "survey_template": , "patient": , "hospital": , "status": "PENDING", "delivery_channel": "SMS", "recipient_phone": "0512345678", "recipient_email": "ahmed@example.com", "metadata": { "admission_id": "ADM-001", "patient_type": "2", "hospital_id": "1", "insurance_company": "Arabian Shield Cooperative Insurance Company", "is_vip": false } } ``` ### 4. SMS Delivery The survey is sent via SMS to the patient's phone number: ```python from apps.surveys.services import SurveyDeliveryService delivery_success = SurveyDeliveryService.deliver_survey(survey) ``` **SMS Message Format:** ``` Thank you for visiting Al Hammadi Hospital! Please complete our survey at: [Survey URL] Your feedback helps us improve our services. ``` ## Testing ### Automated Tests Run the test script to verify integration: ```bash python test_simplified_survey_integration.py ``` **Test Coverage:** 1. ✅ OPD patients receive OPD surveys 2. ✅ Inpatient patients receive Inpatient surveys 3. ✅ EMS patients receive EMS surveys 4. ✅ Non-discharged patients don't receive surveys 5. ✅ Alternative PatientType codes (O, E) work correctly 6. ✅ Survey metadata is stored correctly ### Manual Testing **Test 1: OPD Patient Survey** ```python from apps.integrations.services.his_adapter import HISAdapter his_data = { "FetchPatientDataTimeStampList": [{ "PatientID": "TEST-001", "AdmissionID": "ADM-TEST-001", "HospitalName": "Al Hammadi Hospital - Main", "PatientType": "2", # OPD "AdmitDate": "05-Jun-2025 11:06", "DischargeDate": "05-Jun-2025 16:30", "PatientName": "Test Patient", "MobileNo": "0512345678", ... }], "FetchPatientDataTimeStampVisitDataList": [], "Code": 200, "Status": "Success" } result = HISAdapter.process_his_data(his_data) print(f"Success: {result['success']}") print(f"Survey: {result['survey']}") print(f"Survey URL: {result['survey_url']}") ``` **Test 2: Non-Discharged Patient** ```python his_data_no_discharge = { "FetchPatientDataTimeStampList": [{ "PatientID": "TEST-002", "AdmissionID": "ADM-TEST-002", "HospitalName": "Al Hammadi Hospital - Main", "PatientType": "2", "AdmitDate": "05-Jun-2025 11:06", "DischargeDate": None, # Not discharged "PatientName": "Test Patient 2", "MobileNo": "0512345679", ... }], "FetchPatientDataTimeStampVisitDataList": [], "Code": 200, "Status": "Success" } result = HISAdapter.process_his_data(his_data_no_discharge) print(f"Result: {result['message']}") # Expected: "Patient not discharged - no survey sent" ``` ## Configuration ### Required Survey Templates Each hospital must have at least one survey template for each patient type: ```bash # Check existing survey templates python manage.py shell >>> from apps.surveys.models import SurveyTemplate >>> SurveyTemplate.objects.filter(hospital__code="ALH-main").values_list('name', 'is_active') ``` ### SMS Configuration Ensure SMS delivery is configured in `apps/surveys/services.py`: ```python class SurveyDeliveryService: @staticmethod def deliver_survey(survey: SurveyInstance) -> bool: # SMS delivery implementation # Returns True if successful, False otherwise pass ``` ### Logging Enable logging to track survey delivery: ```python import logging logger = logging.getLogger(__name__) logger.info(f"Survey {survey.id} sent to {survey.patient.get_full_name()}") ``` ## Troubleshooting ### Issue: Survey Not Created **Check:** 1. Patient has discharge date 2. Survey template exists for PatientType 3. Hospital is active **Debug:** ```python result = HISAdapter.process_his_data(his_data) print(f"Message: {result['message']}") print(f"Success: {result['success']}") ``` ### Issue: Wrong Survey Type **Check:** 1. Survey template name contains PatientType (OPD, INPATIENT, EMS) 2. Template is active (`is_active=True`) 3. Template belongs to correct hospital ### Issue: SMS Not Delivered **Check:** 1. Patient phone number is valid 2. SMS service is configured 3. Check logs for delivery errors ```python # Check delivery status survey = SurveyInstance.objects.get(id=survey_id) print(f"Status: {survey.status}") print(f"Delivery Channel: {survey.delivery_channel}") ``` ### Issue: Duplicate Surveys The system prevents duplicate surveys for the same admission: ```python # Check if survey already exists existing_survey = SurveyInstance.objects.filter( patient=patient, hospital=hospital, metadata__admission_id="ADM-001" ).first() ``` ## Monitoring ### Key Metrics to Track 1. **Survey Creation Rate**: Surveys created per day 2. **Survey Delivery Rate**: SMS delivery success rate 3. **Survey Response Rate**: Patient response rate 4. **Patient Type Distribution**: OPD/Inpatient/EMS breakdown ### Database Queries ```sql -- Surveys created today SELECT COUNT(*) as total_surveys, COUNT(DISTINCT patient_id) as unique_patients FROM surveys_surveyinstance WHERE DATE(created_at) = CURRENT_DATE; -- Surveys by patient type SELECT JSON_VALUE(metadata, '$.patient_type') as patient_type, COUNT(*) as count FROM surveys_surveyinstance WHERE DATE(created_at) = CURRENT_DATE GROUP BY patient_type; -- Survey delivery status SELECT status, COUNT(*) as count FROM surveys_surveyinstance WHERE DATE(created_at) = CURRENT_DATE GROUP BY status; ``` ## Best Practices 1. **Survey Template Names**: Use clear names containing patient type - ✅ "OPD Survey", "INPATIENT Survey", "EMS Survey" - ❌ "Patient Survey", "Feedback Survey" 2. **Discharge Detection**: Only send surveys after discharge - Always check `DischargeDate` field - Don't send surveys for active admissions 3. **Duplicate Prevention**: Check existing surveys before creating new ones - Use `admission_id` in metadata to prevent duplicates 4. **Metadata Storage**: Store relevant patient information in metadata - PatientType, AdmissionID, InsuranceCompany, VIP status 5. **SMS Delivery**: Use reliable SMS service with retry logic - Handle delivery failures gracefully - Log all delivery attempts ## Migration from Journey-Based System If migrating from the complex journey-based system: 1. **Keep Journey Models**: Don't delete journey models - they may be useful for analytics 2. **Update HIS Adapter**: Use simplified `process_his_data()` method 3. **Remove Journey Creation**: No need to create `PatientJourneyInstance` 4. **Direct Survey Creation**: Create surveys directly based on PatientType 5. **Testing**: Run comprehensive tests to ensure surveys are created correctly ## API Endpoints ### Receive HIS Patient Data **Endpoint:** `POST /api/simulator/his-patient-data/` **Request Body:** ```json { "FetchPatientDataTimeStampList": [{ "PatientID": "123456", "PatientType": "2", "DischargeDate": "05-Jun-2025 16:30", ... }], "FetchPatientDataTimeStampVisitDataList": [], "Code": 200, "Status": "Success" } ``` **Response:** ```json { "success": true, "message": "Patient data processed successfully", "patient": { "id": 1, "name": "Ahmed Al-Saud" }, "survey": { "id": 1, "status": "SENT", "survey_url": "https://example.com/survey/abc123" }, "survey_sent": true } ``` ## Summary The simplified survey integration: ✅ **Direct Survey Delivery**: Surveys created immediately upon discharge ✅ **PatientType-Based**: Correct survey template selected automatically ✅ **SMS Delivery**: Surveys sent via SMS to patient's phone ✅ **Duplicate Prevention**: No duplicate surveys for same admission ✅ **Metadata Tracking**: Patient information stored for analytics ✅ **Easy Testing**: Comprehensive test suite available ✅ **Realistic Simulation**: HIS simulator generates realistic patient data This simplified approach reduces complexity while maintaining all essential functionality for survey delivery based on patient type.