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

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

title: Senologie FHIR Bundle to IQTIG QS 18.1 Mammachirurgie (Orchestrator) status: draft

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

// title: Senologie FHIR Bundle to IQTIG QS 18.1 Mammachirurgie (Orchestrator)
// status: draft

uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as source
uses "http://hl7.org/fhir/StructureDefinition/Encounter" alias Encounter as source
uses "http://hl7.org/fhir/StructureDefinition/Condition" alias Condition as source
uses "http://hl7.org/fhir/StructureDefinition/Procedure" alias Procedure 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 "http://hl7.org/fhir/StructureDefinition/Organization" alias Organization as source
uses "https://www.senologie.org/fhir/StructureDefinition/iqtig-mammachirurgie-181" alias IQTIG181 as target

imports "https://www.senologie.org/fhir/StructureMap/SenologieToIqtigBasis"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToIqtigBrust"
imports "https://www.senologie.org/fhir/StructureMap/SenologieToIqtigOperation"

// ============================================================================
// Master Orchestrator: Bundle -> IQTIG QS 18.1 Mammachirurgie
// Empfaengt ein FHIR Bundle mit Senologie-Ressourcen (Patient, Encounter,
// Condition, Procedure, Specimen, Observations) und erzeugt eine vollstaendige
// IQTIG-QS-Meldung mit den drei Teildatensaetzen:
// - Teildatensatz Basis (B): Patient + Encounter
// - Teildatensatz Brust (BRUST): Condition + Pathologie (ein Eintrag je Seite)
// - Teildatensatz Operation (O): Procedure + Specimen (ein Eintrag je OP)
// Analog zur IRegG-Meldung wird eine einzelne QS-Meldung pro Behandlungsfall
// erzeugt. Die Zuordnung der Teildatensaetze Brust und Operation erfolgt ueber
// die laufenden Nummern (LNRBRUST, LNROP).
// ============================================================================
group SenologieToIqtigMammachirurgie181(source src : Bundle, target tgt : IQTIG181) {
  // --- Teildatensatz Basis (B) ---
  src -> tgt.teildatensatzBasis as basis then MapBasis(src, basis) "CallMapBasis";
  // --- Teildatensatz Brust (BRUST): pro Condition mit Brust-Diagnose ---
  src.entry as entry where resource.is(Condition) and (resource.meta.profile.exists($this.contains('senologie-diagnose')) or resource.code.coding.exists((system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm') and code.startsWith('C50'))) then {
    entry.resource as condition -> tgt.teildatensatzBrust as brust then MapBrust(condition, brust) "CallMapBrust";
    // Bundle lookups for Brust (moved from MapBrust)
    src.entry as tEntry where resource.is(Observation) and resource.code.coding.exists(code = '21905-5') then {
      tEntry.resource as tObs then {
        tObs.value as val then {
          val.coding as c then {
            c.code as cd -> brust.cT = cd "SetCT";
          } "MapCTCoding";
        } "MapCTValue";
      } "MapCTObs";
    } "EntryCT";
    src.entry as nEntry where resource.is(Observation) and resource.code.coding.exists(code = '21906-3') then {
      nEntry.resource as nObs then {
        nObs.value as val then {
          val.coding as c then {
            c.code as cd -> brust.cN = cd "SetCN";
          } "MapCNCoding";
        } "MapCNValue";
      } "MapCNObs";
    } "EntryCN";
    src.entry as mEntry where resource.is(Observation) and resource.code.coding.exists(code = '21907-1') then {
      mEntry.resource as mObs then {
        mObs.value as val then {
          val.coding as c then {
            c.code as cd -> brust.cM = cd "SetCM";
          } "MapCMCoding";
        } "MapCMValue";
      } "MapCMObs";
    } "EntryCM";
    src.entry as uiccEntry where resource.is(Observation) and resource.code.coding.exists(code = '21902-2') then {
      uiccEntry.resource as uiccObs then {
        uiccObs.value as val then {
          val.coding as c then {
            c.code as cd -> brust.uiccStadiumKlinisch = cd "SetUICCKlin";
          } "MapUICCKlinCoding";
        } "MapUICCKlinValue";
      } "MapUICCKlinObs";
    } "EntryUICCKlin";
    src.entry as tgEntry where resource.is(Observation) and resource.code.coding.exists(code = '44648-0') then {
      tgEntry.resource as tgObs then {
        tgObs.value as val then {
          val.value as v -> brust.tumorgroesseKlinisch = truncate(v) "SetTGroesseKlin";
        } "MapTGroesseKlinValue";
      } "MapTGroesseKlinObs";
    } "EntryTGroesseKlin";
    src.entry as bildEntry where resource.is(Observation) and resource.meta.profile.exists($this.contains('senologie-bildgebung')) then {
      bildEntry.resource as bildObs then {
        bildObs.method as m then {
          m.coding as c where system = 'http://snomed.info/sct' then {
            c.code as cd where $this = '71651007' -> brust.bildgebendeMethode = '1' "SetMethMammo";
            c.code as cd where $this = '16310003' -> brust.bildgebendeMethode = '2' "SetMethSono";
            c.code as cd where $this = '113091000' -> brust.bildgebendeMethode = '3' "SetMethMRT";
            c.code as cd where $this = '710324008' -> brust.bildgebendeMethode = '4' "SetMethTomo";
          } "MapBildMethodCoding";
        } "MapBildMethod";
      } "MapBildObs";
    } "EntryBildgebung";
    src.entry as biradsEntry where resource.is(Observation) and resource.code.coding.exists(code = '72133-2') then {
      biradsEntry.resource as biradsObs then {
        biradsObs.value as val then {
          val.coding as c then {
            c.code as cd -> brust.birads = cd "SetBIRADS";
          } "MapBIRADSCoding";
        } "MapBIRADSValue";
      } "MapBIRADSObs";
    } "EntryBIRADS";
    src.entry as befEntry where resource.is(Observation) and resource.meta.profile.exists($this.contains('senologie-pathologie-befund')) then {
      befEntry.resource as befObs then {
        befObs.value as val then {
          val.coding as c where system = 'https://www.senologie.org/fhir/CodeSystem/cs-senologie-befundcode-b' then {
            c.code as cd -> brust.befundcode = cd "SetBefundB";
          } "MapBefundBCoding";
        } "MapBefundValue";
      } "MapBefundObs";
    } "EntryBefund";
    src.entry as srEntry where resource.is(ServiceRequest) and resource.meta.profile.exists($this.contains('senologie-op-planung')) then {
      srEntry.resource as sr then {
        sr.extension as ext where url = 'https://www.senologie.org/fhir/StructureDefinition/preOpMarkierung' then {
          ext.value as val then {
            val.coding as c then {
              c.code as cd where $this = 'M' -> brust.drahtmarkierung = '1' "SetDrahtMammo";
              c.code as cd where $this = 'S' -> brust.drahtmarkierung = '2' "SetDrahtSono";
              c.code as cd where $this = 'T' -> brust.drahtmarkierung = '3' "SetDrahtMRT";
              c.code as cd where $this = 'N' -> brust.drahtmarkierung = '0' "SetDrahtKeine";
            } "MapDrahtCoding";
          } "MapDrahtValue";
        } "MapDrahtExt";
      } "SRContext";
    } "EntryDraht";
  } "EntryBrust";
  // --- Teildatensatz Operation (O): pro Procedure (Senologie_BrustOP / Senologie_Operation) ---
  src.entry as entry where resource.is(Procedure) and resource.meta.profile.exists($this.contains('senologie-brustop') or $this.contains('senologie-operation')) then {
    entry.resource as procedure -> tgt.teildatensatzOperation as op then MapOperation(procedure, op) "CallMapOperation";
    // Bundle lookups for Operation (moved from MapOperation)
    src.entry as digEntry where resource.is(Observation) and resource.code.coding.exists(code = '22748-9') then {
      digEntry.resource as digObs then {
        digObs.value as val then {
          val.coding as c then {
            c.code as cd where $this = '1222584008' -> op.dignitaetIntraop = '1' "SetDigMaligne";
            c.code as cd where $this = '36103009' -> op.dignitaetIntraop = '2' "SetDigBenigne";
          } "MapDigCoding";
        } "MapDigValue";
      } "MapDigObs";
    } "EntryDignitaet";
    src.entry as specEntry where resource.is(Specimen) and resource.meta.profile.exists($this.contains('senologie-pathologie-praeparat')) then {
      specEntry.resource as specimen then {
        specimen.processing as proc where procedure.coding.exists(code = '123038009') -> op.intraopSchnellschnitt = '1' "SetSchnellschnittJa";
      } "SpecContextSS";
    } "EntrySchnellschnitt";
    src.entry as specEntry2 where resource.is(Specimen) then {
      specEntry2.resource as specimen then {
        specimen.processing as proc then {
          proc.procedure as p then {
            p.coding as c where system = 'http://snomed.info/sct' then {
              c.code as cd where $this = '71651007' -> op.intraopPraeparatkontrolle = '1' "SetPraepkMammo";
              c.code as cd where $this = '16310003' -> op.intraopPraeparatkontrolle = '2' "SetPraepkSono";
            } "MapPraepkCoding";
          } "MapPraepkProcedure";
        } "MapPraepkProcessing";
      } "SpecContextPK";
    } "EntryPraeparatkontrolle";
    src.entry as histEntry where resource.is(Observation) and resource.code.coding.exists(code = '59847-4') then {
      histEntry.resource as histObs then {
        histObs.value as val then {
          val.coding as c where system = 'urn:oid:2.16.840.1.113883.6.43.1' -> op.histologieICDO as histo then {
            c.code as cd -> histo.code = cd "SetHistCode";
            c.version as v -> histo.version = v "SetHistVersion";
          } "MapHistICDO";
        } "MapHistValue";
      } "MapHistObs";
    } "EntryHistologie";
    src.entry as gradEntry where resource.is(Observation) and resource.code.coding.exists(code = '33732-9') then {
      gradEntry.resource as gradObs then {
        gradObs.value as val then {
          val.coding as c then {
            c.code as cd -> op.grading = cd "SetGrading";
          } "MapGradingCoding";
        } "MapGradingValue";
      } "MapGradingObs";
    } "EntryGrading";
    src.entry as tgInvEntry where resource.is(Observation) and resource.code.coding.exists(code = '33728-7') then {
      tgInvEntry.resource as tgInvObs then {
        tgInvObs.value as val then {
          val.value as v -> op.tumorgroesseInvasiv = truncate(v) "SetTGroesseInv";
        } "MapTGroesseInvValue";
      } "MapTGroesseInvObs";
    } "EntryTGroesseInv";
    src.entry as tgDcisEntry where resource.is(Observation) and resource.code.coding.exists(code = '44648-0') and resource.meta.profile.exists($this.contains('pathologie')) then {
      tgDcisEntry.resource as tgDcisObs then {
        tgDcisObs.value as val then {
          val.value as v -> op.tumorgroesseDCIS = truncate(v) "SetTGroesseDCIS";
        } "MapTGroesseDCISValue";
      } "MapTGroesseDCISObs";
    } "EntryTGroesseDCIS";
    src.entry as mfEntry where resource.is(Observation) and resource.code.coding.exists(code = '44638-1') then {
      mfEntry.resource as mfObs then {
        mfObs.value as val then {
          val.coding as c then {
            c.code as cd where $this = '56061002' -> op.multifokalitaet = '0' "SetMFNein";
            c.code as cd where $this = '399566009' -> op.multifokalitaet = '1' "SetMFJa";
            c.code as cd where $this = '367651003' -> op.multifokalitaet = '2' "SetMFMZ";
          } "MapMFCoding";
        } "MapMFValue";
      } "MapMFObs";
    } "EntryMultifokal";
    src.entry as ptEntry where resource.is(Observation) and resource.code.coding.exists(code = '21899-0') then {
      ptEntry.resource as ptObs then {
        ptObs.value as val then {
          val.coding as c then {
            c.code as cd -> op.pT = cd "SetPT";
          } "MapPTCoding";
        } "MapPTValue";
      } "MapPTObs";
    } "EntryPT";
    src.entry as pnEntry where resource.is(Observation) and resource.code.coding.exists(code = '21900-6') then {
      pnEntry.resource as pnObs then {
        pnObs.value as val then {
          val.coding as c then {
            c.code as cd -> op.pN = cd "SetPN";
          } "MapPNCoding";
        } "MapPNValue";
      } "MapPNObs";
    } "EntryPN";
    src.entry as pmEntry where resource.is(Observation) and resource.code.coding.exists(code = '21901-4') then {
      pmEntry.resource as pmObs then {
        pmObs.value as val then {
          val.coding as c then {
            c.code as cd -> op.pM = cd "SetPM";
          } "MapPMCoding";
        } "MapPMValue";
      } "MapPMObs";
    } "EntryPM";
    src.entry as uiccEntry where resource.is(Observation) and resource.code.coding.exists(code = '21902-2') then {
      uiccEntry.resource as uiccObs then {
        uiccObs.value as val then {
          val.coding as c then {
            c.code as cd -> op.uiccStadiumPatho = cd "SetUICCPatho";
          } "MapUICCPathoCoding";
        } "MapUICCPathoValue";
      } "MapUICCPathoObs";
    } "EntryUICCPatho";
    src.entry as lkuEntry where resource.is(Observation) and resource.code.coding.exists(code = '21894-1') then {
      lkuEntry.resource as lkuObs then {
        lkuObs.value as val then {
          val.value as v -> op.lkUntersucht = truncate(v) "SetLKUntersucht";
        } "MapLKUntersuchtValue";
      } "MapLKUntersuchtObs";
    } "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 then {
          val.value as v -> op.lkBefallen = truncate(v) "SetLKBefallen";
        } "MapLKBefallenValue";
      } "MapLKBefallenObs";
    } "EntryLKBefallen";
    src.entry as slkuEntry where resource.is(Observation) and resource.code.coding.exists(code = '92832-5') then {
      slkuEntry.resource as slkuObs then {
        slkuObs.value as val then {
          val.value as v -> op.sentinelLkUntersucht = truncate(v) "SetSLKUntersucht";
        } "MapSLKUntersuchtValue";
      } "MapSLKUntersuchtObs";
    } "EntrySLKUntersucht";
    src.entry as slkbEntry where resource.is(Observation) and resource.code.coding.exists(code = '92833-3') then {
      slkbEntry.resource as slkbObs then {
        slkbObs.value as val then {
          val.value as v -> op.sentinelLkBefallen = truncate(v) "SetSLKBefallen";
        } "MapSLKBefallenValue";
      } "MapSLKBefallenObs";
    } "EntrySLKBefallen";
    src.entry as erEntry where resource.is(Observation) and resource.code.coding.exists(code = '85337-4') then {
      erEntry.resource as erObs then {
        erObs.value as val then {
          val.coding as c where code = '10828004' -> op.hormonrezeptorStatusER = 'P' "SetERPositiv";
          val.coding as c where code = '260385009' -> op.hormonrezeptorStatusER = 'N' "SetERNegativ";
          val.coding as c where code = '261665006' -> op.hormonrezeptorStatusER = 'U' "SetERUnbekannt";
        } "MapERValue";
      } "MapERObs";
    } "EntryER";
    src.entry as prEntry where resource.is(Observation) and resource.code.coding.exists(code = '85339-0') then {
      prEntry.resource as prObs then {
        prObs.value as val then {
          val.coding as c where code = '10828004' -> op.hormonrezeptorStatusPR = 'P' "SetPRPositiv";
          val.coding as c where code = '260385009' -> op.hormonrezeptorStatusPR = 'N' "SetPRNegativ";
          val.coding as c where code = '261665006' -> op.hormonrezeptorStatusPR = 'U' "SetPRUnbekannt";
        } "MapPRValue";
      } "MapPRObs";
    } "EntryPR";
    src.entry as herEntry where resource.is(Observation) and resource.code.coding.exists(code = '85319-2') then {
      herEntry.resource as herObs then {
        herObs.value as val then {
          val.coding as c where code = '10828004' -> op.her2Status = 'P' "SetHER2Positiv";
          val.coding as c where code = '260385009' -> op.her2Status = 'N' "SetHER2Negativ";
          val.coding as c where code = '261665006' -> op.her2Status = 'U' "SetHER2Unbekannt";
        } "MapHER2Value";
      } "MapHER2Obs";
    } "EntryHER2";
    src.entry as kompEntry where resource.is(Observation) and resource.meta.profile.exists($this.contains('senologie-operative-komplikation')) then {
      kompEntry.resource as kompObs -> op.komplikationen as kompItem then {
        kompObs.value as val then {
          val.coding as c then {
            c.code as cd -> kompItem.kuerzel = cd "SetKomplKuerzel";
          } "MapKomplKuerzelCoding";
        } "MapKomplValue";
      } "MapKomplObs";
    } "EntryKomplikationen";
    src.entry as kcEntry where resource.is(Condition) and resource.category.coding.exists(code = 'problem-list-item') then {
      kcEntry.resource as kcCond -> op.komplikationen as kompItem then {
        kcCond.code as code then {
          code.coding as c where system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm' then {
            c.code as cd -> kompItem.icdCode = cd "SetKomplICD";
          } "MapKomplICDCoding";
        } "MapKomplCondCode";
      } "MapKomplCondItem";
    } "EntryKomplikationenCond";
  } "EntryOperation";
}