feat: complete real-time voice-ai engine upgrades and frontend integration guide
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from typing import Dict, Any, List, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from app.database.models import OnboardingSession, OnboardingState, OnboardingMessage
|
||||
|
||||
|
||||
def export_session_to_fhir_bundle(session_id: str, db: Session) -> Dict[str, Any]:
|
||||
"""
|
||||
Exports a completed or in-progress onboarding session state into standard HL7 FHIR R4 Bundle.
|
||||
Resources Generated:
|
||||
1. Patient (Demographics)
|
||||
2. Encounter (Clinical Intake Session)
|
||||
3. Condition (Symptoms & Past Medical History)
|
||||
4. MedicationStatement (Current Active Medications)
|
||||
5. AllergyIntolerance (Confirmed Allergies)
|
||||
"""
|
||||
sess = db.query(OnboardingSession).filter(OnboardingSession.session_id == session_id).first()
|
||||
if not sess:
|
||||
raise ValueError(f"Session {session_id} not found.")
|
||||
|
||||
state_obj = db.query(OnboardingState).filter(OnboardingState.session_id == session_id).first()
|
||||
state_data = json.loads(state_obj.state_json) if state_obj and state_obj.state_json else {}
|
||||
|
||||
now_iso = datetime.now(timezone.utc).isoformat()
|
||||
patient_ref = f"Patient/{sess.patient_id or 'PAT-UNKNOWN'}"
|
||||
encounter_id = f"enc-{session_id.lower()}"
|
||||
|
||||
entries: List[Dict[str, Any]] = []
|
||||
|
||||
# 1. FHIR Patient Resource
|
||||
patient_resource = {
|
||||
"resourceType": "Patient",
|
||||
"id": sess.patient_id or "PAT-UNKNOWN",
|
||||
"identifier": [{
|
||||
"system": "http://hospital.org/patients",
|
||||
"value": sess.patient_id or "PAT-UNKNOWN"
|
||||
}],
|
||||
"name": [{
|
||||
"text": sess.patient_name or "Patient",
|
||||
"family": (sess.patient_name or "Patient").split()[-1],
|
||||
"given": (sess.patient_name or "Patient").split()[:-1] or [sess.patient_name or "Patient"]
|
||||
}],
|
||||
"gender": sess.gender if sess.gender in ["male", "female", "other"] else "unknown"
|
||||
}
|
||||
entries.append({"resource": patient_resource})
|
||||
|
||||
# 2. FHIR Encounter Resource
|
||||
encounter_resource = {
|
||||
"resourceType": "Encounter",
|
||||
"id": encounter_id,
|
||||
"status": "finished" if sess.status == "completed" else "in-progress",
|
||||
"class": {
|
||||
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
|
||||
"code": "AMB",
|
||||
"display": "ambulatory"
|
||||
},
|
||||
"type": [{
|
||||
"coding": [{
|
||||
"system": "http://snomed.info/sct",
|
||||
"code": "32485007",
|
||||
"display": "Hospital admission intake"
|
||||
}],
|
||||
"text": sess.category_name or "General Intake"
|
||||
}],
|
||||
"subject": {"reference": patient_ref},
|
||||
"period": {
|
||||
"start": sess.created_at.isoformat() if sess.created_at else now_iso
|
||||
}
|
||||
}
|
||||
entries.append({"resource": encounter_resource})
|
||||
|
||||
# 3. FHIR Condition Resources (Symptoms)
|
||||
symptoms = state_data.get("symptoms", [])
|
||||
if isinstance(symptoms, list):
|
||||
for idx, sym in enumerate(symptoms):
|
||||
if isinstance(sym, dict) and sym.get("name"):
|
||||
cond_resource = {
|
||||
"resourceType": "Condition",
|
||||
"id": f"cond-sym-{idx+1}-{uuid4().hex[:4]}",
|
||||
"clinicalStatus": {
|
||||
"coding": [{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
|
||||
"code": "active"
|
||||
}]
|
||||
},
|
||||
"category": [{
|
||||
"coding": [{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/condition-category",
|
||||
"code": "encounter-diagnosis",
|
||||
"display": "Encounter Diagnosis"
|
||||
}]
|
||||
}],
|
||||
"code": {
|
||||
"text": sym["name"]
|
||||
},
|
||||
"subject": {"reference": patient_ref},
|
||||
"encounter": {"reference": f"Encounter/{encounter_id}"},
|
||||
"onsetDateTime": now_iso,
|
||||
"note": [{"text": f"Duration: {sym.get('duration', 'N/A')}, Severity: {sym.get('severity', 'N/A')}"}]
|
||||
}
|
||||
entries.append({"resource": cond_resource})
|
||||
|
||||
# 4. FHIR Condition Resources (Medical History)
|
||||
history = state_data.get("medical_history", [])
|
||||
if isinstance(history, list):
|
||||
for idx, hist in enumerate(history):
|
||||
cond_name = hist.get("condition") if isinstance(hist, dict) else str(hist)
|
||||
if cond_name:
|
||||
cond_resource = {
|
||||
"resourceType": "Condition",
|
||||
"id": f"cond-hist-{idx+1}-{uuid4().hex[:4]}",
|
||||
"clinicalStatus": {
|
||||
"coding": [{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
|
||||
"code": "active"
|
||||
}]
|
||||
},
|
||||
"category": [{
|
||||
"coding": [{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/condition-category",
|
||||
"code": "problem-list-item",
|
||||
"display": "Problem List Item"
|
||||
}]
|
||||
}],
|
||||
"code": {
|
||||
"text": cond_name
|
||||
},
|
||||
"subject": {"reference": patient_ref}
|
||||
}
|
||||
entries.append({"resource": cond_resource})
|
||||
|
||||
# 5. FHIR MedicationStatement Resources
|
||||
medications = state_data.get("medications", [])
|
||||
if isinstance(medications, list):
|
||||
for idx, med in enumerate(medications):
|
||||
med_name = med.get("name") if isinstance(med, dict) else str(med)
|
||||
dosage_str = med.get("dosage", "") if isinstance(med, dict) else ""
|
||||
if med_name:
|
||||
med_resource = {
|
||||
"resourceType": "MedicationStatement",
|
||||
"id": f"med-{idx+1}-{uuid4().hex[:4]}",
|
||||
"status": "active",
|
||||
"medicationCodeableConcept": {
|
||||
"text": med_name
|
||||
},
|
||||
"subject": {"reference": patient_ref},
|
||||
"dosage": [{"text": dosage_str}] if dosage_str else []
|
||||
}
|
||||
entries.append({"resource": med_resource})
|
||||
|
||||
# 6. FHIR AllergyIntolerance Resources
|
||||
allergies = state_data.get("allergies", [])
|
||||
if isinstance(allergies, list):
|
||||
for idx, alg in enumerate(allergies):
|
||||
alg_name = alg.get("name") if isinstance(alg, dict) else str(alg)
|
||||
if alg_name:
|
||||
alg_resource = {
|
||||
"resourceType": "AllergyIntolerance",
|
||||
"id": f"alg-{idx+1}-{uuid4().hex[:4]}",
|
||||
"clinicalStatus": {
|
||||
"coding": [{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical",
|
||||
"code": "active"
|
||||
}]
|
||||
},
|
||||
"code": {
|
||||
"text": alg_name
|
||||
},
|
||||
"patient": {"reference": patient_ref}
|
||||
}
|
||||
entries.append({"resource": alg_resource})
|
||||
|
||||
# Assemble FHIR R4 Bundle
|
||||
fhir_bundle = {
|
||||
"resourceType": "Bundle",
|
||||
"id": f"bundle-{session_id.lower()}",
|
||||
"type": "collection",
|
||||
"timestamp": now_iso,
|
||||
"total": len(entries),
|
||||
"entry": entries
|
||||
}
|
||||
|
||||
return fhir_bundle
|
||||
Reference in New Issue
Block a user