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: SenologieToObdsVerlauf

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

title: Senologie Verlauf Bundle to oBDS Verlaufsmeldung status: draft

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

// title: Senologie Verlauf Bundle to oBDS Verlaufsmeldung
// status: draft

uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle 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 "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/SenologieToObdsFernmetastasen"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToObdsLeistungszustand"

// Known limitation: Sub-groups (MapVerlauf) use `target tgt : BackboneElement`.
// See SenologieToObdsTNM.map for details.
// ============================================================================
// Hauptgruppe: Bundle -> oBDS Verlaufsmeldung
// Das Bundle enthaelt eine Condition (Rezidiv, clinicalStatus = recurrence)
// sowie zugehoerige Observations (TNM, Histologie, Fernmetastasen,
// Hormonrezeptoren, Leistungszustand).
// ============================================================================
group SenologieToObdsVerlauf(source src : Bundle, target tgt : OBDSMeldung) {
  // Tumorzuordnung: aus der Condition-Ressource (Rezidiv verweist auf gleichen Tumor)
  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";
  // Verlauf: aus der Condition (Rezidiv) + Observations aus dem Bundle
  src.entry as entry where resource.is(Condition) then {
    entry.resource as condition -> tgt.verlauf as verl then MapVerlauf(condition, verl) "CallMapVerlauf";
    // Bundle lookups moved from MapVerlauf
    entry.resource as cond2 -> tgt.verlauf as verl2 then MapFernmetastasenFromBundle(src, verl2) "CallMapFernmetastasen";
    src.entry as histEntry where resource.is(Observation) and resource.code.coding.exists(code = '59847-4') then {
      histEntry.resource as histObs ->  tgt.verlauf as verl3,  verl3.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 = '21908-9') then {
      tnmEntry.resource as tnmObs ->  tgt.verlauf as verl4,  verl4.tnm as tnm then MapTNM(tnmObs, tnm) "CallMapTNMClinical";
    } "EntryTNMClinical";
    src.entry as tnmEntry where resource.is(Observation) and resource.code.coding.exists(code = '21902-2') then {
      tnmEntry.resource as tnmObs ->  tgt.verlauf as verl5,  verl5.tnm as tnm then MapTNM(tnmObs, tnm) "CallMapTNMPathological";
    } "EntryTNMPathological";
    entry.resource as cond3 -> tgt.verlauf as verl6 then MapLeistungszustandFromBundle(src, verl6) "CallMapLeistungszustand";
    entry.resource as cond4 ->  tgt.verlauf as verl7,  verl7.modulMamma as mamma then MapModulMamma(src, mamma) "CallMapModulMamma";
  } "EntryConditionVerlauf";
}

// ============================================================================
// Verlauf: Condition (Rezidiv) -> OBDSMeldung.verlauf
// Verlauf_ID, Meldeanlass, Untersuchungsdatum, Gesamtbeurteilung Tumorstatus,
// lokaler Tumorstatus, LK-Status, FM-Status
// ============================================================================
group MapVerlauf(source src : Condition, target tgt : BackboneElement) {
  // Verlauf_ID: aus Condition.identifier
  src.identifier as id then {
    id.value as v -> tgt.verlaufID = v "SetVerlaufID";
  } "MapVerlaufID";
  // Meldeanlass: Verlaufsmeldung ist immer "statusaenderung"
  src -> tgt.meldeanlass = 'statusaenderung' "SetMeldeanlass";
  // Untersuchungsdatum: aus Condition.extension[Feststellungsdatum] oder recordedDate
  src.extension as ext where url = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/StructureDefinition/mii-ex-onko-feststellungsdatum' then {
    ext.value as val where $this.is(dateTime) -> tgt.untersuchungsdatum = val "SetUntersuchungsdatumExt";
  } "MapUntersuchungsdatumExt";
  // Fallback: recordedDate als Untersuchungsdatum
  src.recordedDate as rd -> tgt.untersuchungsdatum = rd "SetUntersuchungsdatumFallback";
  // Gesamtbeurteilung Tumorstatus: aus Condition.stage (Verlaufsbeurteilung)
  // Uebersetzung SNOMED -> oBDS via ConceptMap
  src.stage as stg then {
    stg.summary as sum then {
      sum.coding as c where system = 'http://snomed.info/sct' -> tgt.gesamtbeurteilungTumorstatus = translate(c, 'https://www.senologie.org/fhir/ConceptMap/cm-sct-to-obds-verlauf-gesamtbeurteilung', 'code') "TranslateGesamtbeurteilung";
    } "ExtractGesamtbeurteilungCoding";
  } "MapGesamtbeurteilung";
  // Fallback: Bei Rezidiv (clinicalStatus = recurrence) -> Y (Rezidiv)
  src.clinicalStatus as cs where coding.exists(code = 'recurrence') -> tgt.gesamtbeurteilungTumorstatus = 'Y' "SetGesamtbeurteilungRezidiv";
  // Verlauf_Lokaler_Tumorstatus: aus Extension oder Observation im Bundle
  // MII Onko Verlauf lokaler Tumorstatus
  src.extension as ext where url = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/StructureDefinition/mii-ex-onko-verlauf-lokaler-tumorstatus' then {
    ext.value as val then {
      val.coding as c then {
        c.code as cd -> tgt.verlaufLokalerTumorstatus = cd "SetLokalerTumorstatus";
      } "ExtractLokalerStatus";
    } "MapLokalerStatusValue";
  } "MapLokalerTumorstatus";
  // Verlauf_Tumorstatus_Lymphknoten: aus Extension
  src.extension as ext where url = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/StructureDefinition/mii-ex-onko-verlauf-tumorstatus-lymphknoten' then {
    ext.value as val then {
      val.coding as c then {
        c.code as cd -> tgt.verlaufTumorstatusLymphknoten = cd "SetLKStatus";
      } "ExtractLKStatus";
    } "MapLKStatusValue";
  } "MapTumorstatusLymphknoten";
  // Verlauf_Tumorstatus_Fernmetastasen: aus Extension
  src.extension as ext where url = 'https://www.medizininformatik-initiative.de/fhir/ext/modul-onko/StructureDefinition/mii-ex-onko-verlauf-tumorstatus-fernmetastasen' then {
    ext.value as val then {
      val.coding as c then {
        c.code as cd -> tgt.verlaufTumorstatusFernmetastasen = cd "SetFMStatus";
      } "ExtractFMStatus";
    } "MapFMStatusValue";
  } "MapTumorstatusFernmetastasen";
// Fernmetastasen, Histologie, TNM, Leistungszustand, ModulMamma
// bundle lookups moved to calling group.
}