SMART PH4H
0.9.9 - release

This page is part of the PH4H (v0.9.9: Releases Draft) based on FHIR (HL7® FHIR® Standard) R4. This is the current published version. For a full list of available versions, see the Directory of published versions

StructureMap: MedicationOverviewMinToMedicationOverviewLM

Official URL: http://smart.who.int/ph4h/StructureMap/MedicationOverviewMinToMedicationOverviewLM Version: 0.9.9
Draft as of 2026-07-09 Computable Name: MedicationOverviewMinToMedicationOverviewLM

map "http://smart.who.int/ph4h/StructureMap/MedicationOverviewMinToMedicationOverviewLM" = "MedicationOverviewMinToMedicationOverviewLM"

uses "http://smart.who.int/ph4h/StructureDefinition/MedicationOverviewMin" alias MedicationOverviewMin as source
uses "http://smart.who.int/ph4h/StructureDefinition/MedicationTreatmentLineMin" alias MedicationTreatmentLineMin as source
uses "https://profiles.ihe.net/PHARM/MEOW/StructureDefinition/MedicationOverviewLM" alias MedicationOverviewLM as target
uses "https://profiles.ihe.net/PHARM/MEOW/StructureDefinition/PatientLM" alias PatientLM as target
uses "https://profiles.ihe.net/PHARM/MEOW/StructureDefinition/MedicationTreatmentLineLM" alias MedicationTreatmentLineLM as target

// ---------------------------------------------------------------------------
// Top-level group: 1 patient + 0..* medication treatment lines
// ---------------------------------------------------------------------------
group MedicationOverviewMinToMedicationOverviewLM(source src : MedicationOverviewMin, target tgt : MedicationOverviewLM) {
  src -> tgt.patient as patient then MedicationOverviewMinToPatientLM(src, patient) "patient";
  src.m as line -> tgt.medicationTreatmentLine as tline then MedicationTreatmentLineMinToMedicationTreatmentLineLM(line, tline) "treatmentLine";
}

// ---------------------------------------------------------------------------
// MedicationOverviewMin demographic fields -> PatientLM
// ---------------------------------------------------------------------------
group MedicationOverviewMinToPatientLM(source src : MedicationOverviewMin, target tgt : PatientLM) {
  // Name: create HumanName, populate, assign
  src.n as n ->  create('HumanName') as hn,  hn.text = n,  tgt.name = hn "name";
  src.dob as dob -> tgt.dateOfBirth = dob "dateOfBirth";
  // Gender: create Coding, then CodeableConcept wrapping it, assign
  src.s as s ->  create('Coding') as gc,  gc.system = 'http://hl7.org/fhir/administrative-gender',  gc.code = s,  create('CodeableConcept') as g,  g.coding = gc,  tgt.gender = g "gender";
  // Identifier: create Identifier, populate, assign. Identifier.type is intentionally
  // NOT emitted: the Min 'dt' code carries no code system, which produced
  // unvalidatable type.coding warnings (no system / not in IdentifierType VS).
  // Identifier.type is optional (0..1); the value alone is sufficient here.
  src.id as id -> create('Identifier') as ident then {
    id -> ident.value = id "identifierValue";
    id -> tgt.identifier = ident "identifierAssign";
  } "identifier";
}

// ---------------------------------------------------------------------------
// One MedicationTreatmentLineMin -> one MedicationTreatmentLineLM
// ---------------------------------------------------------------------------
group MedicationTreatmentLineMinToMedicationTreatmentLineLM(source src : MedicationTreatmentLineMin, target tgt : MedicationTreatmentLineLM) {
  // Status: the Min source carries no record status; default to 'active'.
  // LM.status is 1..1 and the downstream R4 MedicationStatement.status is
  // 1..1 required — without this rule, stage 2 emits status-less statements
  // that fail MEOW Bundle profile validation.
  src -> tgt.status = 'active' "status";
  // Medication: create Coding, then CodeableConcept wrapping it, assign.
  // The Min 'm' field is a bare code with no system; RACSEL production data uses
  // SNOMED CT, so tag it as SNOMED to satisfy validation.
  // NOTE: the ATC-coded example (e.g. L02BG03) is mislabelled by this fixed system.
  // If mixed code systems must be supported, the Min model should carry the system
  // alongside the code (e.g. an 'ms' field) rather than assuming SNOMED here.
  // Display intentionally NOT set: the Min 'm' field carries only a code, and
  // emitting the code as the display fails SNOMED display validation
  // ("Wrong Display Name"). Leaving it absent lets the term server supply it.
  src.m as med ->  create('Coding') as c,  c.system = 'http://snomed.info/sct',  c.code = med,  create('CodeableConcept') as cc,  cc.coding = c,  tgt.medication = cc "medication";
  // Effective period: create Period, populate, assign
  // (Period uses .start/.end — NOT .low/.high; those are Range properties.)
  src -> create('Period') as ep then {
    src.es as es -> ep.start = es "effStart";
    src.ee as ee -> ep.end = ee "effEnd";
    src -> tgt.effectivePeriod = ep "effAssign";
  } "effectivePeriod";
  // recordingMetadata is a BackboneElement defined inline in the LM — navigate.
  src.da as da -> tgt.recordingMetadata as rm then {
    da -> rm.recordedTime = da "recordedTime";
  } "dateAsserted";
  // Dosage as free text. Route to preparationInstructions (a plain string array)
  // rather than comment.commentText: comment is a BackboneElement with several
  // 1..1 sub-fields (author, date, commentText) that the Min source can't
  // populate, so creating a half-empty comment confuses matchbox's serializer.
  // preparationInstructions is a string field, no nested required structure.
  src.d as d -> tgt.preparationInstructions = d "dosage";
  src.r as r -> tgt.indicationText = r "reason";
  // Adherence (treatmentStatus): MEOW requires adherence 1..1 downstream, so always
  // emit it. Default the code to 'active' and override with the source 'a' when it is
  // present. System is medication-statement-status (see $adherenceStatusVS alias — the
  // R4 stand-in for the R5 adherence value set), which includes 'active'.
  src ->  create('Coding') as tsc,  tsc.system = 'http://hl7.org/fhir/CodeSystem/medication-statement-status',  tsc.code = 'active',  create('CodeableConcept') as ts,  ts.coding = tsc,  tgt.treatmentStatus = ts then {
    src.a as a -> tsc.code = a "adherenceValue";
  } "adherence";
}