التكامل متقدم ⏱ 8 ساعات الدورة 14 🏥 NPHIES Ready

التكامل مع HL7 و FHIR

HL7 & FHIR Integration with NPHIES

🎯 أهداف التعلم

1فهم بروتوكول HL7v2 و معيار FHIR R4
2إنشاء وتحليل موارد FHIR (Patient, Observation, Claim)
3دمج NPHIES مع IRIS for Health
4تحويل رسائل HL7 إلى FHIR والعكس
5بناء FHIR Server على IRIS
6تطبيق الامتثال لمعايير NPHIES السعودية

01 مقدمة في HL7

HL7 (Health Level Seven) هو المعيار الأكثر استخداماً لتبادل المعلومات الصحية. يدعم IRIS HL7v2 و HL7v3 و FHIR.

هيكل رسالة HL7v2

تتكون رسالة HL7v2 من.segments (أجزاء)، كل segment يبدأ بـ 3 أحرف مميزة:

// MSH - Message Header
// PID - Patient Identification
// PV1 - Patient Visit
// OBR - Observation Request
// OBX - Observation Result

// مثال: رسالة ADT^A01 (Admission)
Set msg = "MSH|^~\&|MyApp|Hospital|HIS|Receiver|20260626||ADT^A01|MSG001|P|2.5"
Set msg = msg _ "|PID||12345||محمد^أحمد||19900115|M|||الرياض^^|||966|||"
Set msg = msg _ "|PV1||I|ICU^01^01||||||||||||||||||||||||||||||||||||||||||"

قراءة رسالة HL7 في IRIS

ClassMethod ParseHL7(msgString As %String) {
  Set hl7 = ##class(EnsLib.HL7.Message).%New()
  Do hl7.ImportFromString(msgString)
  
  Write "نوع الرسالة: ", hl7.GetValueAt("MSH:9.1"), !
  Write "اسم المريض: ", hl7.GetValueAt("PID:5.1"), !
  Write "رقم المريض: ", hl7.GetValueAt("PID:3.1"), !
  Write "تاريخ الميلاد: ", hl7.GetValueAt("PID:7"), !
  Write "الجنس: ", hl7.GetValueAt("PID:8"), !
  
  Return hl7
}

02 موارد FHIR الأساسية

FHIR (Fast Healthcare Interoperability Resources) هو المعيار الحديث لتبادل البيانات الصحية باستخدام RESTful APIs و JSON/XML.

الموارد الأساسية في NPHIES

  • Patient: بيانات المريض (الاسم، الرقم الوطني، تاريخ الميلاد)
  • Observation: نتائج المختبر والعلامات الحيوية
  • Encounter: زيارة المريض (دخول، خروج)
  • Claim: مطالبة التأمين
  • Coverage: التغطية التأمينية
// إنشاء مورد FHIR Patient
Set patient = {
  "resourceType": "Patient",
  "identifier": [{
    "system": "https://nphies.sa/identifier/national-id",
    "value": "1234567890"
  }],
  "name": [{
    "use": "official",
    "family": "العلي",
    "given": ["محمد", "أحمد"]
  }],
  "gender": "male",
  "birthDate": "1990-01-15",
  "address": [{
    "city": "الرياض",
    "country": "SA"
  }]
}

03 مورد Patient — تعمق

مورد Patient هو أساس كل سجل صحي. في NPHIES، يجب تضمين الرقم الوطني السعودي.

// إنشاء سجل مريض متوافق مع NPHIES
ClassMethod CreateNPHIESPatient(nationalId, familyName, givenName, gender, dob) As %DynamicObject {
  Set patient = {}
  Set patient.resourceType = "Patient"
  
  // المعرّف الوطني السعودي
  Set identifier = {}
  Set identifier.system = "https://nphies.sa/identifier/national-id"
  Set identifier.value = nationalId
  Set patient.identifier = [identifier]
  
  // الاسم (ثنائي اللغة)
  Set name = {}
  Set name.use = "official"
  Set name.family = familyName
  Set name.given = [givenName]
  Set patient.name = [name]
  
  // معلومات أساسية
  Set patient.gender = gender
  Set patient.birthDate = dob
  
  // حفظ في IRIS
  Set sc = ##class(HS.FHIR.Server.Storage.Json.Interactions).Create("Patient", patient, .id)
  If $$$ISOK(sc) {
    Write "تم إنشاء المريض: ", id, !
  }
  Return patient
}

04 مورد Observation — المختبر والعلامات الحيوية

مورد Observation يمثل نتائج المختبر والعلامات الحيوية. يجب ربطه بكود LOINC.

// إنشاء نتيجة مختبر
ClassMethod CreateLabResult(patientId, loincCode, value, unit) As %DynamicObject {
  Set obs = {}
  Set obs.resourceType = "Observation"
  Set obs.status = "final"
  
  // نوع الفحص (LOINC)
  Set obs.code = {
    "coding": [{
      "system": "http://loinc.org",
      "code": (loincCode),
      "display": (..GetLOINCDisplay(loincCode))
    }]
  }
  
  // المريض
  Set obs.subject = {"reference": ("Patient/" _ patientId)}
  
  // النتيجة
  Set obs.valueQuantity = {
    "value": (value),
    "unit": (unit),
    "system": "http://unitsofmeasure.org"
  }
  
  // نطاق مرجعي
  Set obs.referenceRange = [{
    "low": {"value": 0, "unit": unit},
    "high": {"value": 100, "unit": unit}
  }]
  
  Return obs
}

// أكواد LOINC شائعة في NPHIES
// 2345-7: Glucose (Blood)
// 2093-3: Cholesterol (Total)
// 718-7: Hemoglobin
// 2160-0: Creatinine

05 تكامل NPHIES — المطالبات التأمينية

NPHIES (National Platform for Health Information Exchange) هو المنصة الوطنية السعودية لتبادل المعلومات الصحية. يتطلب التزام صارم بمعدل FHIR.

// تحويل مطالبة NPHIES إلى FHIR Claim
ClassMethod ConvertNPHIESClaimToFHIR(claimJSON) As %DynamicObject {
  Set fhirClaim = {}
  Set fhirClaim.resourceType = "Claim"
  
  // نوع المطالبة
  Set fhirClaim.type = {
    "coding": [{
      "system": "http://terminology.hl7.org/CodeSystem/claim-type",
      "code": claimJSON.claimType
    }]
  }
  
  // المريض
  Set fhirClaim.patient = {
    "reference": ("Patient/" _ claimJSON.patientID),
    "identifier": {
      "system": "https://nphies.sa/identifier/patient",
      "value": claimJSON.nationalID
    }
  }
  
  // فترة الخدمة
  Set fhirClaim.billablePeriod = {
    "start": claimJSON.serviceStartDate,
    "end": claimJSON.serviceEndDate
  }
  
  // مقدم الخدمة
  Set fhirClaim.provider = {
    "reference": ("Organization/" _ claimJSON.providerID),
    "identifier": {
      "system": "https://nphies.sa/identifier/provider",
      "value": claimJSON.providerLicense
    }
  }
  
  // شركة التأمين
  Set fhirClaim.insurer = {
    "reference": ("Organization/" _ claimJSON.insurerID),
    "identifier": {
      "system": "https://nphies.sa/identifier/insurer",
      "value": claimJSON.insurerCode
    }
  }
  
  // بنود المطالبة
  Set fhirClaim.item = []
  Set items = claimJSON.items.%GetIterator()
  While items.%GetNext(.key, .item) {
    Do fhirClaim.item.%Push({
      "sequence": (key + 1),
      "productOrService": {
        "coding": [{
          "system": "http://nphies.sa/terminology/CodeSystem/drug-code",
          "code": item.code
        }]
      },
      "unitPrice": {"value": item.price, "currency": "SAR"},
      "quantity": {"value": item.quantity}
    })
  }
  
  Return fhirClaim
}

🔗 الربط مع ClaimLinc: يستخدم ClaimLinc من BrainSAIT هذا التحويل مباشرة لمعالجة المطالبات التأمينية.

06 تحويل HL7 إلى FHIR

تحويل رسائل HL7v2 إلى موارد FHIR أمر أساسي للتكامل بين الأنظمة القديمة والحديثة.

// تحويل رسالة ADT^A01 إلى FHIR Encounter
ClassMethod HL7ToFHIR(hl7Msg As EnsLib.HL7.Message) As %DynamicObject {
  Set encounter = {}
  Set encounter.resourceType = "Encounter"
  Set encounter.status = "in-progress"
  
  // نوع الزيارة
  Set encounter.class = {
    "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
    "code": "IMP",
    "display": "Inpatient"
  }
  
  // المريض
  Set patientId = hl7Msg.GetValueAt("PID:3.1")
  Set encounter.subject = {"reference": ("Patient/" _ patientId)}
  
  // تاريخ الدخول
  Set admitDate = hl7Msg.GetValueAt("PV1:44.1")
  Set encounter.period = {"start": (admitDate)}
  
  // القسم
  Set dept = hl7Msg.GetValueAt("PV1:3.1")
  Set encounter.location = [{"location": {"display": dept}}]
  
  Return encounter
}

07 بناء FHIR Server على IRIS

يمكنك بناء FHIR Server كامل على IRIS يدعم REST APIs و OAuth2.

// FHIR REST Endpoint
Class MyApp.FHIR.REST Extends %CSP.REST {
  XData UrlMap {
    
      
      
      
      
    
  }
  
  ClassMethod SearchPatients() As %Status {
    Set params = %request.Data
    Set name = $Get(params("name"))
    
    If name'="" {
      Set sql = "SELECT ID, JSONString FROM HS.FHIR.Storage.Json.Resource " _
                "WHERE ResourceType='Patient' AND JSONString %CONTAINS ?"
      Set rs = ##class(%SQL.Statement).%ExecDirect(, sql, name)
    } Else {
      Set sql = "SELECT ID, JSONString FROM HS.FHIR.Storage.Json.Resource WHERE ResourceType='Patient'"
      Set rs = ##class(%SQL.Statement).%ExecDirect(, sql)
    }
    
    Set bundle = {"resourceType": "Bundle", "type": "searchset", "entry": []}
    While rs.%Next() {
      Do bundle.entry.%Push({"resource": (##class(%DynamicObject).%FromJSON(rs.%Get("JSONString")))})
    }
    
    Write bundle.%ToJSON()
    Return $$$OK
  }
}

08 البحث والفلترة في FHIR

FHIR يدعم بحثاً متقدماً مع معاملات معيارية.

// بحث متقدم في موارد FHIR
ClassMethod SearchWithParams(resourceType, params) As %Status {
  Set sql = "SELECT ID, JSONString FROM HS.FHIR.Storage.Json.Resource WHERE ResourceType = ?"
  Set args = [resourceType]
  
  // إضافة معاملات البحث
  If params.%IsDefined("name") {
    Set sql = sql _ " AND JSONString %CONTAINS ?"
    Do args.%Push(params.name)
  }
  If params.%IsDefined("date") {
    Set sql = sql _ " AND JSONString %CONTAINS ?"
    Do args.%Push(params.date)
  }
  
  // _include: تضمين موارد مرتبطة
  If params.%IsDefined("_include") {
    // مثال: Patient?_include=Observation:patient
    // يُرجع المريض مع نتائج المختبر
  }
  
  Set rs = ##class(%SQL.Statement).%ExecDirect(, sql, args...)
  // ... process results
}

09 قائمة الامتثال لـ NPHIES

لتقديم خدمات عبر NPHIES، يجب الامتثال لمتطلبات صارمة.

متطلبات NPHIES الإلزامية

  • المعرّفات: الرقم الوطني السعودي (10 أرقام) + معرّف مقدم الخدمة
  • اللغة: دعم العربية والإنجليزية (ثنائي اللغة)
  • الأكواد: ICD-10 للتشخيصات، LOINC للمختبرات، SNOMED CT للمفاهيم السريرية
  • التشفير: TLS 1.2+ لجميع الاتصالات
  • التوثيق: OAuth 2.0 مع SMART on FHIR
// التحقق من الامتثال لـ NPHIES
ClassMethod ValidateNPHIESCompliance(resource As %DynamicObject) As %Status {
  Set errors = []
  
  // التحقق من المعرّف الوطني
  If resource.resourceType = "Patient" {
    Set hasNationalId = 0
    Set identifiers = resource.identifier.%GetIterator()
    While identifiers.%GetNext(.key, .id) {
      If id.system = "https://nphies.sa/identifier/national-id" {
        Set hasNationalId = 1
        If $Length(id.value) '= 10 {
          Do errors.%Push("الرقم الوطني يجب أن يكون 10 أرقام")
        }
      }
    }
    If 'hasNationalId {
      Do errors.%Push("الرقم الوطني السعودي مطلوب")
    }
  }
  
  // التحقق من أكواد ICD-10
  If resource.resourceType = "Condition" {
    Set code = resource.code.coding.%Get(0).code
    If '$Match(code, "^[A-Z]\d{2}(\.\d{1,2})?$") {
      Do errors.%Push("كود ICD-10 غير صالح: " _ code)
    }
  }
  
  If errors.%Size() > 0 {
    Write "أخطاء الامتثال:", !
    Set iter = errors.%GetIterator()
    While iter.%GetNext(.key, .err) {
      Write "  ✗ ", err, !
    }
    Return $$$ERROR(5001, "فشل التحقق من الامتثال")
  }
  
  Return $$$OK
}

🔗 الربط مع COMPLIANCELINC: يستخدم COMPLIANCELINC من BrainSAIT هذه القواعد للتحقق التلقائي من الامتثال.

📝 اختبار التحقق

1 ما هو المعيار الحديث لتبادل البيانات الصحية؟
💡 الشرح

FHIR R4 هو المعيار الحديث المعتمد من HL7 لتبادل البيانات الصحية.

2 ما هو النظام المستخدم للرقم الوطني السعودي في FHIR؟
💡 الشرح

يستخدم NPHIES نظام معرّف خاص بالرقم الوطني السعودي.

3 أي مورد FHIR يُستخدم لنتائج المختبر؟
💡 الشرح

مورد Observation يُستخدم لنتائج المختبر والعلامات الحيوية.