Ali2206 commited on
Commit
1424ea9
·
1 Parent(s): c4f38f8

device token

Browse files
Files changed (2) hide show
  1. api/routes/patients.py +131 -63
  2. models/schemas.py +1 -1
api/routes/patients.py CHANGED
@@ -491,83 +491,137 @@ async def import_patients(
491
  async def import_ehr_patients(
492
  ehr_data: List[dict],
493
  ehr_system: str = Query(..., description="Name of the EHR system"),
494
- current_user: dict = Depends(get_current_user),
495
- db_client: AsyncIOMotorClient = Depends(lambda: db)
496
  ):
497
- """Import patients from external EHR system"""
 
 
498
  logger.info(f"Importing {len(ehr_data)} patients from EHR system: {ehr_system}")
499
 
500
  if not any(role in current_user.get('roles', []) for role in ['admin', 'doctor']):
501
  logger.warning(f"Unauthorized EHR import attempt by {current_user.get('email')}")
502
  raise HTTPException(
503
  status_code=status.HTTP_403_FORBIDDEN,
504
- detail="Only administrators and doctors can import EHR patients"
505
  )
506
 
507
  try:
 
 
508
  imported_patients = []
509
  skipped_patients = []
 
510
 
511
  for patient_data in ehr_data:
512
- # Check if patient already exists by multiple criteria
513
- existing_patient = await patients_collection.find_one({
514
- "$or": [
515
- {"ehr_id": patient_data.get("ehr_id"), "ehr_system": ehr_system},
516
- {"full_name": patient_data.get("full_name"), "date_of_birth": patient_data.get("date_of_birth")},
517
- {"national_id": patient_data.get("national_id")} if patient_data.get("national_id") else {}
518
- ]
519
- })
520
-
521
- if existing_patient:
522
- skipped_patients.append(patient_data.get("full_name", "Unknown"))
523
- logger.info(f"Patient {patient_data.get('full_name', 'Unknown')} already exists, skipping...")
524
- continue
525
-
526
- # Prepare patient document for EHR import
527
- patient_doc = {
528
- "full_name": patient_data.get("full_name"),
529
- "date_of_birth": patient_data.get("date_of_birth"),
530
- "gender": patient_data.get("gender"),
531
- "address": patient_data.get("address"),
532
- "national_id": patient_data.get("national_id"),
533
- "blood_type": patient_data.get("blood_type"),
534
- "allergies": patient_data.get("allergies", []),
535
- "chronic_conditions": patient_data.get("chronic_conditions", []),
536
- "medications": patient_data.get("medications", []),
537
- "emergency_contact_name": patient_data.get("emergency_contact_name"),
538
- "emergency_contact_phone": patient_data.get("emergency_contact_phone"),
539
- "insurance_provider": patient_data.get("insurance_provider"),
540
- "insurance_policy_number": patient_data.get("insurance_policy_number"),
541
- "contact": patient_data.get("contact"),
542
- "source": "ehr",
543
- "ehr_id": patient_data.get("ehr_id"),
544
- "ehr_system": ehr_system,
545
- "status": "active",
546
- "registration_date": datetime.now(),
547
- "created_by": current_user.get('email'),
548
- "created_at": datetime.now(),
549
- "updated_at": datetime.now()
550
- }
551
-
552
- # Insert patient
553
- result = await patients_collection.insert_one(patient_doc)
554
- imported_patients.append(patient_data.get("full_name", "Unknown"))
555
-
556
- logger.info(f"Successfully imported {len(imported_patients)} patients, skipped {len(skipped_patients)}")
 
 
 
 
 
 
 
 
557
 
558
  return {
559
- "message": f"Successfully imported {len(imported_patients)} patients from {ehr_system}",
560
- "imported_count": len(imported_patients),
561
- "skipped_count": len(skipped_patients),
 
562
  "imported_patients": imported_patients,
563
- "skipped_patients": skipped_patients
 
 
564
  }
565
 
566
  except Exception as e:
567
- logger.error(f"Error importing EHR patients: {str(e)}")
568
  raise HTTPException(
569
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
570
- detail=f"Error importing EHR patients: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
  )
572
 
573
  @router.get("/patients/sources", response_model=List[dict])
@@ -704,18 +758,32 @@ async def get_patients(
704
  # Add assigned doctor name
705
  patient["assigned_doctor_name"] = assigned_doctor_name
706
 
 
 
 
 
707
  processed_patients.append(patient)
708
 
709
  logger.info(f"✅ Returning {len(processed_patients)} processed patients")
710
 
711
- return PatientListResponse(
712
- patients=processed_patients,
713
- total=total,
714
- page=page,
715
- limit=limit,
716
- source_filter=source,
717
- status_filter=patient_status
718
- )
 
 
 
 
 
 
 
 
 
 
719
 
720
  except Exception as e:
721
  logger.error(f"❌ Error fetching patients: {str(e)}")
 
491
  async def import_ehr_patients(
492
  ehr_data: List[dict],
493
  ehr_system: str = Query(..., description="Name of the EHR system"),
494
+ current_user: dict = Depends(get_current_user)
 
495
  ):
496
+ """
497
+ Import patients from external EHR system
498
+ """
499
  logger.info(f"Importing {len(ehr_data)} patients from EHR system: {ehr_system}")
500
 
501
  if not any(role in current_user.get('roles', []) for role in ['admin', 'doctor']):
502
  logger.warning(f"Unauthorized EHR import attempt by {current_user.get('email')}")
503
  raise HTTPException(
504
  status_code=status.HTTP_403_FORBIDDEN,
505
+ detail="Only administrators and doctors can import patients"
506
  )
507
 
508
  try:
509
+ imported_count = 0
510
+ skipped_count = 0
511
  imported_patients = []
512
  skipped_patients = []
513
+ errors = []
514
 
515
  for patient_data in ehr_data:
516
+ try:
517
+ # Validate required fields
518
+ if not patient_data.get('ehr_id') or not patient_data.get('full_name'):
519
+ errors.append(f"Patient missing required fields (ehr_id, full_name): {patient_data.get('full_name', 'Unknown')}")
520
+ continue
521
+
522
+ # Check for existing patient by EHR ID and system
523
+ existing_patient = await patients_collection.find_one({
524
+ "ehr_id": patient_data['ehr_id'],
525
+ "ehr_system": ehr_system
526
+ })
527
+
528
+ if existing_patient:
529
+ skipped_count += 1
530
+ skipped_patients.append(patient_data['full_name'])
531
+ continue
532
+
533
+ # Prepare patient document
534
+ patient_doc = {
535
+ "fhir_id": str(uuid.uuid4()),
536
+ "full_name": patient_data['full_name'],
537
+ "date_of_birth": patient_data.get('date_of_birth', ''),
538
+ "gender": patient_data.get('gender', 'unknown'),
539
+ "address": patient_data.get('address', ''),
540
+ "national_id": patient_data.get('national_id', ''),
541
+ "blood_type": patient_data.get('blood_type', ''),
542
+ "allergies": patient_data.get('allergies', []),
543
+ "chronic_conditions": patient_data.get('chronic_conditions', []),
544
+ "medications": patient_data.get('medications', []),
545
+ "emergency_contact_name": patient_data.get('emergency_contact_name', ''),
546
+ "emergency_contact_phone": patient_data.get('emergency_contact_phone', ''),
547
+ "insurance_provider": patient_data.get('insurance_provider', ''),
548
+ "insurance_policy_number": patient_data.get('insurance_policy_number', ''),
549
+ "source": "ehr_import",
550
+ "ehr_id": patient_data['ehr_id'],
551
+ "ehr_system": ehr_system,
552
+ "status": "active",
553
+ "created_by": current_user.get('email'),
554
+ "created_at": datetime.utcnow().isoformat(),
555
+ "updated_at": datetime.utcnow().isoformat()
556
+ }
557
+
558
+ # Insert patient
559
+ result = await patients_collection.insert_one(patient_doc)
560
+ imported_count += 1
561
+ imported_patients.append(patient_data['full_name'])
562
+
563
+ logger.info(f"Imported patient {patient_data['full_name']} with EHR ID {patient_data['ehr_id']}")
564
+
565
+ except Exception as e:
566
+ error_msg = f"Error importing patient {patient_data.get('full_name', 'Unknown')}: {str(e)}"
567
+ errors.append(error_msg)
568
+ logger.error(error_msg)
569
 
570
  return {
571
+ "message": f"Import completed: {imported_count} imported, {skipped_count} skipped, {len(errors)} errors",
572
+ "imported_count": imported_count,
573
+ "skipped_count": skipped_count,
574
+ "error_count": len(errors),
575
  "imported_patients": imported_patients,
576
+ "skipped_patients": skipped_patients,
577
+ "errors": errors,
578
+ "ehr_system": ehr_system
579
  }
580
 
581
  except Exception as e:
582
+ logger.error(f"Failed to import EHR patients: {str(e)}")
583
  raise HTTPException(
584
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
585
+ detail=f"Failed to import EHR patients: {str(e)}"
586
+ )
587
+
588
+ @router.post("/patients/import-hapi-fhir", status_code=status.HTTP_201_CREATED)
589
+ async def import_hapi_fhir_patients(
590
+ limit: int = Query(20, ge=1, le=100, description="Number of patients to import"),
591
+ current_user: dict = Depends(get_current_user)
592
+ ):
593
+ """
594
+ Import patients from HAPI FHIR Test Server
595
+ """
596
+ logger.info(f"Importing {limit} patients from HAPI FHIR by user {current_user.get('email')}")
597
+
598
+ if not any(role in current_user.get('roles', []) for role in ['admin', 'doctor']):
599
+ logger.warning(f"Unauthorized HAPI FHIR import attempt by {current_user.get('email')}")
600
+ raise HTTPException(
601
+ status_code=status.HTTP_403_FORBIDDEN,
602
+ detail="Only administrators and doctors can import patients"
603
+ )
604
+
605
+ try:
606
+ service = HAPIFHIRIntegrationService()
607
+ result = await service.import_patients_from_hapi(limit=limit)
608
+
609
+ return {
610
+ "message": f"Successfully imported {result.get('imported_count', 0)} patients from HAPI FHIR",
611
+ "imported_count": result.get('imported_count', 0),
612
+ "skipped_count": result.get('skipped_count', 0),
613
+ "error_count": result.get('error_count', 0),
614
+ "imported_patients": result.get('imported_patients', []),
615
+ "skipped_patients": result.get('skipped_patients', []),
616
+ "errors": result.get('errors', []),
617
+ "source": "hapi_fhir"
618
+ }
619
+
620
+ except Exception as e:
621
+ logger.error(f"Failed to import HAPI FHIR patients: {str(e)}")
622
+ raise HTTPException(
623
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
624
+ detail=f"Failed to import HAPI FHIR patients: {str(e)}"
625
  )
626
 
627
  @router.get("/patients/sources", response_model=List[dict])
 
758
  # Add assigned doctor name
759
  patient["assigned_doctor_name"] = assigned_doctor_name
760
 
761
+ # Clean date_of_birth field - convert empty strings to None
762
+ if patient.get("date_of_birth") == "":
763
+ patient["date_of_birth"] = None
764
+
765
  processed_patients.append(patient)
766
 
767
  logger.info(f"✅ Returning {len(processed_patients)} processed patients")
768
 
769
+ try:
770
+ return PatientListResponse(
771
+ patients=processed_patients,
772
+ total=total,
773
+ page=page,
774
+ limit=limit,
775
+ source_filter=source,
776
+ status_filter=patient_status
777
+ )
778
+ except Exception as validation_error:
779
+ logger.error(f"❌ Validation error for PatientListResponse: {str(validation_error)}")
780
+ # Log the problematic data for debugging
781
+ for i, patient in enumerate(processed_patients):
782
+ logger.error(f"Patient {i}: {patient.get('full_name', 'Unknown')} - date_of_birth: '{patient.get('date_of_birth')}'")
783
+ raise HTTPException(
784
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
785
+ detail=f"Data validation error: {str(validation_error)}"
786
+ )
787
 
788
  except Exception as e:
789
  logger.error(f"❌ Error fetching patients: {str(e)}")
models/schemas.py CHANGED
@@ -140,7 +140,7 @@ class PatientUpdate(BaseModel):
140
  class PatientResponse(BaseModel):
141
  id: str
142
  full_name: str
143
- date_of_birth: date
144
  gender: str
145
  notes: Optional[Union[str, List[dict]]] = [] # Can be string or list of dicts
146
  address: Optional[str] = None
 
140
  class PatientResponse(BaseModel):
141
  id: str
142
  full_name: str
143
+ date_of_birth: Optional[date] = None
144
  gender: str
145
  notes: Optional[Union[str, List[dict]]] = [] # Can be string or list of dicts
146
  address: Optional[str] = None