CH ALIS (R4)
0.3.0 - CI build
CH ALIS (R4), published by ALIS-Connect. This guide is not an authorized publication; it is the continuous build for version 0.3.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/ahdis/ch-alis/ and changes regularly. See the Directory of published versions
Official URL: http://fhir.ch/ig/ch-alis/StructureMap/Alis43ToBundle | Version: 0.3.0 | |||
Draft as of 2024-10-29 | Computable Name: Alis43ToBundle | |||
Copyright/Legal: not-open-source |
Convert ALIS43 XML to a Bundle according to the CH ALIS implmementation guide, 2020-12-03 by Oliver Egger, copyright ahdis ag, Apache License, FHIR: http://hl7.org/fhir/r4/. ISSUE7: what are the URL's oid's we have to define.
/// url = "http://fhir.ch/ig/ch-alis/StructureMap/Alis43ToBundle" /// name = "Alis43ToBundle" /// title = "null" /// status = "draft" // Convert ALIS43 XML to a Bundle according to the CH ALIS implmementation guide, // 2020-12-03 by Oliver Egger, copyright ahdis ag, Apache License, // FHIR: http://hl7.org/fhir/r4/. // ISSUE7: what are the URL's oid's we have to define. conceptmap "serviceMap" { prefix s = "http://fhir.ch/ig/ch-alis" prefix t = "http://hl7.org/fhir" s:TARMED == t:"urn:oid:2.16.756.5.30.1.129.1.4" s:ICD10 == t:"urn:oid:2.16.756.5.30.1.126.3.2" } conceptmap "gender" { prefix s = "http://fhir.ch/ig/ch-alis" prefix t = "http://hl7.org/fhir/ValueSet/administrative-gender" s:M == t:male s:F == t:female } conceptmap "laterality" { prefix s = "http://fhir.ch/ig/ch-alis" prefix t = "http://snomed.info/sct" s:l == t:"7771000" s:r == t:"24028007" s:b == t:"51440002" } uses "http://fhir.ch/ig/ch-alis/StructureDefinition/Header" alias Header as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/Visit" alias Visit as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/Service" alias Service as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/PersonV40" alias PersonV40 as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/ParameterV40" alias ParameterV40 as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/DiagGroup" alias DiagGroup as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/LeistungsschnittstelleProcedure" alias Proc as source uses "http://fhir.ch/ig/ch-alis/StructureDefinition/Diagnosis" alias Diagnosis as source uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as target uses "http://hl7.org/fhir/StructureDefinition/ChargeItem" alias ChargeItem as target uses "http://hl7.org/fhir/StructureDefinition/Extension" alias Extension as target uses "http://hl7.org/fhir/StructureDefinition/MessageHeader" alias MessageHeader as target uses "http://hl7.org/fhir/StructureDefinition/BackboneElement" alias BackboneElement as target uses "http://hl7.org/fhir/StructureDefinition/HumanName" alias HumanName as target uses "http://hl7.org/fhir/StructureDefinition/Condition" alias Condition as target uses "http://hl7.org/fhir/StructureDefinition/Encounter" alias Encounter as target uses "http://hl7.org/fhir/StructureDefinition/Procedure" alias Procedure as target group Alis43ToBundle(source header : Header, target bundle : Bundle) { header -> bundle.meta as meta, meta.profile as profile, profile.value = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-message', bundle.entry as e, e.resource = create('MessageHeader') as messageHeader, messageHeader.id = uuid() as uuid, e.fullUrl = append('urn:uuid:', uuid), bundle.entry as e2, e2.resource = create('Bundle') as transactionBundle, transactionBundle.id = uuid() as uuid2, e2.fullUrl = append('urn:uuid:', uuid2), messageHeader.focus = create('Reference') as reference, reference.type = 'Bundle', reference.reference = append('urn:uuid:', uuid2) then { header then Alis43ToMessageHeader(header, messageHeader) "messageHeader"; header then Alis43ToBundleTransaction(header, transactionBundle) "bundleTransaction"; } "bundle"; header -> bundle.type = 'message' "type"; header.FileCreationDate as fileCreationDate then { fileCreationDate.data as date -> bundle.timestamp = date "date"; }; } group Alis43ToMessageHeader(source header : Header, target messageHeader : MessageHeader) { // ISSUE1: should be link to a MessageDefinition or a code? header -> messageHeader.event = create('uri') as value, value.value = 'http://fhir.ch/ig/ch-alis-43' "eventUri"; // ISSUE2: MessageControlID cannot be id of entry, needs to be either fullUrl oder uuid, need to map this to an identifier header -> messageHeader.source as source then { header.SoftwareReleaseNumber as version -> source.version = (%version.data) "version"; // ISSUE3: " : "urn:SendingApplication:SendingFacility:SendingServiceCode" -> add urn: in example/docu header -> source.endpoint = ('urn:' + %header.SendingApplication.data + ':' + %header.SendingFacility.data + ':' + %header.SendingServiceCode.data) "endpoint"; } "source"; header -> messageHeader.destination as destination then { // ISSUE4: " : "urn:ReceivingApplication, ReceivingFacility, ReceivingServiceCode" -> add urn: in example/docu header -> destination.endpoint = ('urn:' + %header.ReceivingApplication.data + ':' + %header.ReceivingFacility.data + ':' + %header.ReceivingServiceCode.data) "endpoint"; } "destination"; } group Alis43ToBundleTransaction(source header : Header, target transactionBundle : Bundle) { header -> transactionBundle.type = 'transaction' "transaction"; header.Visit as visit then { visit.Service as service -> transactionBundle.entry as e, e.resource = create('ChargeItem') as chargeItem then ServiceToChargeItem(service, visit, chargeItem, e) "ServiceToChargeItem"; }; } group ServiceToChargeItem(source service : Service, source visit : Visit, target chargeItem : ChargeItem, target entry) { service.ItemNumber as itemNumber -> chargeItem.id = (%itemNumber.data.lower()) as uuid, entry.fullUrl = append('urn:uuid:', uuid) "R311LaufnummerItemNumber"; service -> chargeItem.contained = create('Patient') as patient, patient.id = 'pat' as containedid, chargeItem.subject = create('Reference') as ref, ref.reference = ('#' + %containedid) then ServiceToPatient(service, visit, patient) "patient"; visit -> chargeItem.contained = create('Encounter') as encounter, encounter.id = 'enc' as containedid, chargeItem.context = create('Reference') as ref, ref.reference = ('#' + %containedid) then { visit then VisitToEncounter(visit, encounter) "VisitToEncounter"; service.Diagnosis as diag -> chargeItem.contained = create('Condition') as condition, condition.id = uuid() as containedid, encounter.diagnosis as diag, diag.condition = create('Reference') as ref, ref.reference = ('#' + %containedid) then DiagnosisToCondition(diag, condition) "DiagnosisToCondition"; } "encounter"; visit.DiagGroup as diaggroup -> chargeItem.contained = create('Condition') as cond, cond.id = 'cond' as containedid then DiagGroupToCondition(diaggroup, cond) "DiagGroupToCondition"; service where (service.Transaction.exists() = false) -> entry.request as request, request.method = 'POST', request.url = 'ChargeItem' "POSTDEFAULT"; service.Transaction where (service.Transaction = 'insert') -> entry.request as request, request.method = 'POST', request.url = 'ChargeItem' "POST"; service.Transaction where (service.Transaction = 'update') -> entry.request as request, request.method = 'PUT', request.url = 'ChargeItem' "UPDATE"; service.Transaction where (service.Transaction = 'delete') -> entry.request as request, request.method = 'DELETE', request.url = 'ChargeItem' "DELETE"; service.SessionID as sessionID -> chargeItem.extension as extension, extension.url = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-ext-sessionid', extension.value = create('string') as value, value.value = (%sessionID.data) "R32SitzungSessionID"; service.OrderID as orderID -> chargeItem.extension as extension, extension.url = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-ext-orderid', extension.value = create('string') as value, value.value = (%orderID.data) "R33AuftragsnummerOrderID"; service.OrderDate as orderDate -> chargeItem.extension as extension, extension.url = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-ext-orderdate', extension.value = create('dateTime') as value, value.value = (%orderDate.data) "R33AuftragsnummerOrderID"; service.Form as form -> chargeItem.extension as extension, extension.url = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-ext-form', extension.value = create('string') as value, value.value = (%form.data) "R37FormularbezeichnungForm"; service.ParameterV40 as parameterV40 -> chargeItem.extension as extension, extension.url = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-ext-parameterv40' then ParameterV40ToExtension(parameterV40, extension) "R4ParamterV40ParameterV40"; service -> chargeItem.status = 'billable' "billable"; service.RefItemNumber as refItemNumber then { refItemNumber.data as data -> chargeItem.partOf = create('Reference') as ref, ref.reference = ('urn:uuid:' + %data.lower()), ref.type = 'ChargeItem' "R312ReferenzzuHauptleistungRefItemNumber"; }; service.ServiceItem as serviceItem then { serviceItem.data as data -> chargeItem.code = create('CodeableConcept') as cc, cc.coding = create('Coding') as coding, coding.code = data then { service.ServiceType as serviceType then { serviceType.data as data -> coding.system = translate(data, '#serviceMap', 'code') "R35KatalogServiceType"; } "servicType"; } "R36TarifpositionServiceItem"; } "R36Tarifposition"; service.ServiceDate as serviceData -> chargeItem.occurrence = create('dateTime') as occurrence, occurrence.value = (%serviceData.data) "R31LeistungsdatumServiceDate"; service.PersonV40 as personV40 -> chargeItem.performer = create('BackboneElement') as performer then PersonV40ToPerformer(personV40, performer) "R315PersonV40PersonV40"; service.ProviderID as providerID -> chargeItem.performingOrganization = create('Reference') as reference, reference.display = (%providerID.data) "R39ErbringendeOrganizationProviderID"; service.ReferrerID as referrerID -> chargeItem.costCenter = create('Reference') as reference, reference.display = (%referrerID.data) "R34AuftraggebendeKostenstelleReferrerID"; service.Quantity as quantity -> chargeItem.quantity = create('Quantity') as q, q.value as value, value.value = (%quantity.data) "R313AnzahlQuantity"; service.EnteredBy as enteredBy -> chargeItem.enterer = create('Reference') as reference, reference.display = (%enteredBy.data) "R310ErfasserEnteredBy"; service.EnteredDateTime as enteredDateTime -> chargeItem.enteredDate = create('dateTime') as enteredDate, enteredDate.value = (%enteredDateTime.data) "R38ErfassungsdatumEnteredDateTime"; service.PatientContactID as patientContactID then { patientContactID.data as data -> chargeItem.identifier = create('Identifier') as identifier, identifier.value = data "PatientContactID"; } "patientContactID"; service.Costweight as costweight then { costweight.data as data -> chargeItem.factorOverride = data "Costweight"; } "costweight"; service.Procedure as proc -> chargeItem.contained = create('Procedure') as procedure, procedure.id = uuid() as containedid, chargeItem.service = create('Reference') as service, service.reference = ('#' + %containedid) then ServiceProcedureToFhirProcedure(proc, procedure) "ServiceProcedureToFhirProcedure"; } group ServiceProcedureToFhirProcedure(source proc : Proc, target procedure : Procedure) { proc.Identifier as identifier -> procedure.identifier = create('Identifier') as identifier, identifier.value = (%identifier.data) "R314ProzedurIDIdentifier"; proc.Code as chopcode where (%proc.Category.data = 'CHOP_2023') -> procedure.code = create('CodeableConcept') as cc, cc.coding = create('Coding') as coding, coding.code = (%chopcode.data), coding.system = 'https://www.bfs.admin.ch/bfs/statistiche/catalog/chop2023', coding.display = (%proc.Display.data) "R316ProzedurcodeCode"; proc.PerformedDateTime as performedDateTime -> procedure.performed = (%performedDateTime.data) "R317DatumZeitPerformedDateTime"; proc.Laterality as laterality then { laterality.data as v -> procedure.bodySite = create('CodeableConcept') as cc, cc.coding = create('Coding') as coding, coding.code = translate(v, '#laterality', 'code'), coding.system = 'http://snomed.info/sct', coding.display = (%proc.LateralityDisplay.data) "R318SeiteLaterality"; } "laterality"; proc.Performer as performer then { // TODO Perfomer.function performer.Identifier as identifier then { identifier.data as data -> procedure.performer as performer, performer.actor as actor, actor.identifier as identifier, identifier.value = data "identifier"; }; } "performer"; proc -> procedure.subject = create('Reference') as ref, ref.reference = '#pat' "containedpatient"; proc -> procedure.status = 'completed' "status"; } group PersonV40ToPerformer(source personV40 : PersonV40, target performer) { personV40.PersonTyp as personTyp -> performer.function as cc, cc.coding as coding, coding.system as system, system.value = 'http://fhir.ch/ig/ch-alis/CodeSystem/ch-alis-persontyp', coding.code as code, code.value = personTyp "R3152PersonIDPersonID"; personV40.PersonID as personId -> performer.actor = create('Reference') as reference, reference.display = (%personId.data) "R3152PersonIDPersonID"; } group ParameterV40ToExtension(source parameterV40 : ParameterV40, target extension : Extension) { parameterV40.ParamTyp as paramTyp -> extension.extension as extInner then InnerExtensionParamTyp(paramTyp, extInner); parameterV40.ParamValue as paramValue then { paramValue.data as data -> extension.extension as extInner then InnerExtensionParamValue(data, extInner); }; } group InnerExtensionParamTyp(source src, target ext : Extension) { src -> ext.url = 'ParamTyp' "url"; src -> ext.value = create('CodeableConcept') as cc, cc.text as text, text.value = src "string"; } group InnerExtensionParamValue(source src, target ext : Extension) { src -> ext.url = 'ParamValue' "url"; src -> ext.value = create('string') as string, string.value = src "string"; } group ServiceToPatientName(source visit : Visit, target name : HumanName) { visit.PatientName as patientName then { patientName.data as data -> name.family = data "R23PatientNamePatientName"; } "patientName"; visit.PatientGivenName as patientGivenName then { patientGivenName.data as data -> name.given = data "R24PatientVornamePatientGivenName"; } "patientGivenName"; } group ServiceToPatient(source service : Service, source visit : Visit, target patient : Patient) { visit.PatientID as patientID then { patientID.data as patId -> patient.identifier as identifier, identifier.value as value, value.value = patId, identifier.system as idsystem, idsystem.value = 'http://www.example.ch/patienteniddomain', identifier.type as type, type.coding as coding, coding.system as system, system.value = 'http://terminology.hl7.org/CodeSystem/v2-0203', coding.code as code, code.value = 'MR' "R22PatientPIDPatientID"; } "patientID"; // <!-- 2.2 Patient.PID (PatientID) --> // <identifier> // <type> // <coding> // <system value="http://terminology.hl7.org/CodeSystem/v2-0203" /> // <code value="MR" /> // <display value="Medical record number"/> // </coding> // </type> // ISSUE8: what do with system value // <system value="http://www.example.ch/patienteniddomain"/> // <value value="Patienten-ID"/> // </identifier>// visit where (visit.PatientName or visit.PatientGivenName) -> patient.name as name then ServiceToPatientName(visit, name) "ServiceToPatient"; visit.PatientGender as gender then { gender.data as v -> patient.gender = translate(v, '#gender', 'code') "gender"; } "R26PatientGeschlechtPatientGender"; visit.PatientBirthDate as birthDate then { birthDate.data as v -> patient.birthDate = v "birthDate"; } "R25PatientGebDatumPatientBirthDate"; } group DiagnosisToCondition(source diagnosis : Diagnosis, target cond : Condition) { diagnosis -> cond.subject = create('Reference') as ref, ref.reference = '#pat' "containedpatient"; // * Identifier 0..1 http://fhir.ch/ig/ch-alis/StructureDefinition/Text "TODO" diagnosis.Identifier as identifier then { identifier.data as data -> cond.identifier as identifier, identifier.value = data "identifier"; }; diagnosis.Code as code -> cond.code = create('CodeableConcept') as cc, cc.coding = create('Coding') as coding, coding.code = (%code.data), coding.display = (%diagnosis.Display.data) then { diagnosis.Category as category then { category.data as data where (startsWith('ICD')) -> coding.system = 'http://hl7.org/fhir/sid/icd-10'; } "serviceType"; } "R316ProzedurcodeCode"; // TODO system is not yet correct diagnosis.OnsetDateTime as onsetDateTime -> cond.onset = (%onsetDateTime.data) "onsetDateTime"; diagnosis.Laterality as laterality then { laterality.data as v -> cond.bodySite = create('CodeableConcept') as cc, cc.coding = create('Coding') as coding, coding.code = translate(v, '#laterality', 'code'), coding.system = 'http://snomed.info/sct', coding.display = (%diagnosis.LateralityDisplay.data) "R318SeiteLaterality"; } "laterality"; } group DiagGroupToCondition(source diagGroup : DiagGroup, target cond : Condition) { diagGroup -> cond.subject = create('Reference') as ref, ref.reference = '#pat' "containedpatient"; diagGroup.DiagCode as data -> cond.code = create('CodeableConcept') as cc, cc.coding = create('Coding') as coding, coding.code = data then { diagGroup.DiagCatType as diagCatType then { diagCatType.data as data -> coding.system = translate(data, '#serviceMap', 'code') "R293KatalogtypDiagCatType"; } "serviceType"; } "R291DiagnosecodeDiagCode"; } group TerminationToExtension(source visit : Visit, target ext : Extension) { visit.TerminationVisit as visit then { visit.data as data -> ext.extension as ext1, ext1.url = 'TerminationVisit', ext1.value = create('date') as date, date.value = data "R27FallAbschlussTerminationVisit"; }; visit.TerminationReason as visit then { visit.data as data -> ext.extension as ext1, ext1.url = 'TerminationReason', ext1.value = create('string') as string, string.value = data "R28FallAbschlussgrundTerminationReason"; } "TerminationVisit"; } group VisitToEncounter(source visit : Visit, target encounter : Encounter) { visit where (visit.TerminationVisit or visit.TerminationReason) -> encounter.extension as ext, ext.url = 'http://fhir.ch/ig/ch-alis/StructureDefinition/ch-alis-ext-termination' then TerminationToExtension(visit, ext) "TerminationToExtension"; visit.VisitNumber as visitNumber then { // ISSUE8: what to do with falldomain? <system value="http://www.example.ch/fallnummerdomain"/> visitNumber.data as data -> encounter.identifier = create('Identifier') as identifier, identifier.value as value, value.value = data, identifier.system as idsystem, idsystem.value = 'http://www.example.ch/fallnummerdomain', identifier.type as type, type.coding as coding, coding.system as system, system.value = 'http://terminology.hl7.org/CodeSystem/v2-0203', coding.code as code, code.value = 'VN' "R21FallVisitNumber"; } "encounterID"; visit -> encounter.status = 'finished' "Finished"; visit -> encounter.class as coding, coding.system as system, system.value = 'http://terminology.hl7.org/CodeSystem/v3-ActCode', coding.code as code, code.value = 'IMP', coding.display as display, display.value = 'inpatient encounter' "R21FallVisitNumber"; visit -> encounter.subject = create('Reference') as ref, ref.reference = '#pat' "subject"; visit.DiagGroup as diaggroup -> encounter.diagnosis as diag, diag.condition = create('Reference') as ref, ref.reference = '#cond' then { diaggroup.DiagType as diagType -> diag.use as use, use.text = (%diagType.data) "R292DiagnosetypDiagType"; } "R29DiagnoseGruppeDiagGroup"; }