Kerndatensatz Senologie
0.9.0 - ci-build

Kerndatensatz Senologie - Local Development build (v0.9.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions

StructureMap: SenologieToObdsOP

Official URL: https://www.senologie.org/fhir/StructureMap/SenologieToObdsOP Version: 0.9.0
Draft as of 2026-05-04 Computable Name: SenologieToObdsOP

title: Senologie Operation Bundle to oBDS OP-Meldung status: draft

map "https://www.senologie.org/fhir/StructureMap/SenologieToObdsOP" = "SenologieToObdsOP"

// title: Senologie Operation Bundle to oBDS OP-Meldung
// status: draft

uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as source
uses "http://hl7.org/fhir/StructureDefinition/Procedure" alias Procedure as source
uses "http://hl7.org/fhir/StructureDefinition/Condition" alias Condition as source
uses "http://hl7.org/fhir/StructureDefinition/Observation" alias Observation as source
uses "http://hl7.org/fhir/StructureDefinition/Specimen" alias Specimen as source
uses "https://www.senologie.org/fhir/StructureDefinition/obds-meldung" alias OBDSMeldung as target

imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsTumorzuordnung"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsTNM"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsHistologie"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsModulMamma"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsResidualstatus"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsNebenwirkung"

// Known limitation: Sub-groups (MapOP, MapKomplikationen, MapOperateur) use
// `target tgt : BackboneElement`. See SenologieToObdsTNM.map for details.
// ============================================================================
// Hauptgruppe: Bundle -> oBDS OP-Meldung
// Das Bundle enthaelt eine Procedure (OP), die zugehoerige Condition (Diagnose),
// sowie Observations (pTNM, Histologie) und ggf. Specimen.
// ============================================================================
group SenologieToObdsOP(source src : Bundle, target tgt : OBDSMeldung) {
  // Tumorzuordnung: aus der Condition-Ressource im Bundle
  src.entry as entry where resource.is(Condition) then {
    entry.resource as condition then {
      condition -> tgt.tumorzuordnung as tz then MapTumorzuordnung(condition, tz) "CallMapTumorzuordnung";
    } "ConditionContext";
  } "EntryConditionTZ";
  // OP: aus der Procedure-Ressource im Bundle
  src.entry as entry where resource.is(Procedure) then {
    entry.resource as procedure -> tgt.op as op then MapOP(procedure, op) "CallMapOP";
    // Bundle lookups moved from MapOP
    src.entry as histEntry where resource.is(Observation) and resource.code.coding.exists(code = '59847-4') then {
      histEntry.resource as histObs -> op.histologie as histo then MapHistologie(histObs, histo) "CallMapHistologie";
      src.entry as specEntry where resource.is(Specimen) then {
        specEntry.resource as specimen then {
          specimen.accessionIdentifier as accId then {
            accId.value as v -> histo.histologieEinsendeNr = v "SetEinsendeNrFromSpecimen";
          } "MapAccessionId";
          specimen.collection as coll then {
            coll.collected as collDt where $this.is(dateTime) -> histo.tumorHistologiedatum = collDt "SetHistologiedatumFromSpecimen";
          } "MapSpecimenCollection";
        } "SpecimenContext";
      } "EntrySpecimen";
      src.entry as gradEntry where resource.is(Observation) and resource.code.coding.exists(code = '59542-1') then {
        gradEntry.resource as gradObs then {
          gradObs.value as val then {
            val.coding as c -> histo.grading = translate(c, 'https://www.senologie.org/fhir/ConceptMap/cm-sct-to-obds-grading', 'code') "TranslateGradingSeparate";
          } "MapGradingSepValue";
        } "MapGradingSepObs";
      } "EntryGrading";
      src.entry as lkEntry where resource.is(Observation) and resource.code.coding.exists(code = '21894-1') then {
        lkEntry.resource as lkObs then {
          lkObs.value as val -> histo.lkUntersucht = val "SetLKUntersuchtSeparate";
        } "MapLKUntersuchtSep";
      } "EntryLKUntersucht";
      src.entry as lkbEntry where resource.is(Observation) and resource.code.coding.exists(code = '21893-3') then {
        lkbEntry.resource as lkbObs then {
          lkbObs.value as val -> histo.lkBefallen = val "SetLKBefallenSeparate";
        } "MapLKBefallenSep";
      } "EntryLKBefallen";
      src.entry as slkEntry where resource.is(Observation) and resource.code.coding.exists(code = '92832-5') then {
        slkEntry.resource as slkObs then {
          slkObs.value as val -> histo.sentinelLKUntersucht = val "SetSentinelLKUntersuchtSeparate";
        } "MapSentinelLKUntersuchtSep";
      } "EntrySentinelLKUntersucht";
      src.entry as slkbEntry where resource.is(Observation) and resource.code.coding.exists(code = '92831-7') then {
        slkbEntry.resource as slkbObs then {
          slkbObs.value as val -> histo.sentinelLKBefallen = val "SetSentinelLKBefallenSeparate";
        } "MapSentinelLKBefallenSep";
      } "EntrySentinelLKBefallen";
    } "EntryHistologie";
    src.entry as tnmEntry where resource.is(Observation) and resource.code.coding.exists(code = '21902-2') then {
      tnmEntry.resource as tnmObs -> op.tnm as ptnm then MapTNM(tnmObs, ptnm) "CallMapPTNM";
    } "EntryPTNM";
    entry.resource as proc2 ->  tgt.op as op2,  op2.modulMamma as mamma then MapModulMamma(src, mamma) "CallMapModulMamma";
  } "EntryProcedure";
}

// ============================================================================
// OP: Procedure -> OBDSMeldung.op
// Intention, Datum, OPS-Codes
// ============================================================================
group MapOP(source src : Procedure, target tgt : BackboneElement) {
  // OP_ID: aus Procedure.identifier
  src.identifier as id then {
    id.value as v -> tgt.opID = v "SetOPID";
  } "MapOPID";
  // Intention: aus Procedure.extension[Intention] mit Uebersetzung SNOMED -> oBDS
  src.extension as ext where url = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/StructureDefinition/mii-ex-onko-operation-intention' then {
    ext.value as val then {
      val.coding as c where system = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/CodeSystem/mii-cs-onko-intention' then {
        c.code as cd -> tgt.intention = cd "SetIntentionDirect";
      } "ExtractIntentionCode";
      val.coding as c where system = 'http://snomed.info/sct' -> tgt.intention = translate(c, 'https://www.senologie.org/fhir/ConceptMap/cm-sct-to-obds-intention', 'code') "TranslateIntention";
    } "MapIntentionValue";
  } "MapIntention";
  // Datum: aus Procedure.performedDateTime
  src.performed as perf where $this.is(dateTime) -> tgt.datum = perf "SetOPDatum";
  // OPS-Codes: aus Procedure.code.coding (OPS-System, 1..*)
  src.code as code then {
    code.coding as c where system = 'http://fhir.de/CodeSystem/bfarm/ops' -> tgt.opsKodes as ops then {
      c.code as cd -> ops.code = cd "SetOPSCode";
      c.version as v -> ops.version = v "SetOPSVersion";
    } "MapOPSCoding";
  } "MapOPSKodes";
  // Histologie, pTNM, ModulMamma bundle lookups moved to calling group.
  // Residualstatus: aus Procedure.outcome
  src.outcome as outcome -> tgt.residualstatus as rs then MapResidualstatusFromOutcome(outcome, rs) "CallMapResidualstatus";
  // Komplikationen: aus Procedure.complication
  src -> tgt.komplikationen as komp then MapKomplikationen(src, komp) "CallMapKomplikationen";
  // Operateure: aus Procedure.performer
  src.performer as perf -> tgt.operateure as op then MapOperateur(perf, op) "CallMapOperateur";
}

// ============================================================================
// Komplikationen: Procedure -> OBDSMeldung.op.komplikationen
// Komplikationskuerzel (oBDS) und ICD-10-kodierte Komplikationen
// ============================================================================
group MapKomplikationen(source src : Procedure, target tgt : BackboneElement) {
  // Keine Komplikation: wenn complication leer ist
  src where complication.exists().not() -> tgt.komplikationNeinOderUnbekannt = 'N' "SetKeineKomplikation";
  // Komplikationen vorhanden: oBDS-Kuerzel aus complication[compl_obds]
  src.complication as comp then {
    comp.coding as c where system = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/CodeSystem/mii-cs-onko-operation-komplikation' -> tgt.komplikation as k then {
      c.code as cd -> k.kuerzel = cd "SetKomplikationKuerzel";
    } "MapKomplikationObds";
  } "MapKomplikationenObds";
  // Komplikationen mit ICD-10-Kodierung aus complication[compl_icd10]
  src.complication as comp then {
    comp.coding as c where system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm' -> tgt.komplikation as k then {
      c -> k.icd as icd then {
        c.code as cd -> icd.code = cd "SetKompIcdCode";
        c.version as v -> icd.version = v "SetKompIcdVersion";
      } "MapKompIcd";
    } "MapKomplikationIcd";
  } "MapKomplikationenIcd";
}

// ============================================================================
// Operateur: Procedure.performer -> OBDSMeldung.op.operateure
// Nachname, Vornamen, Hauptoperateur-Kennzeichen
// ============================================================================
group MapOperateur(source src : BackboneElement, target tgt : BackboneElement) {
  // Operateur-Daten aus Procedure.performer.actor (Reference -> Practitioner)
  // Nachname + Vornamen aus actor.display (Format: "Nachname, Vornamen")
  src.actor as actor then {
    actor.display as d -> tgt.nachname = d "SetOperateurName";
  } "MapOperateurName";
  // Hauptoperateur: aus Procedure.performer.function
  src.function as func then {
    func.coding as c where code = 'primary' -> tgt.hauptoperateur = 'J' "SetHauptoperateurJa";
    func.coding as c where code = 'secondary' -> tgt.hauptoperateur = 'N' "SetHauptoperateurNein";
  } "MapHauptoperateur";
  // Fallback: wenn keine function angegeben, erster Performer = Hauptoperateur
  src where function.exists().not() -> tgt.hauptoperateur = 'J' "SetHauptoperateurDefault";
}