MedicationDispense
→
drug_exposure
documented
primary
Pharmacy dispensing events. One FHIR MedicationDispense produces one OMOP drug_exposure row with drug_type_concept_id = 38000175 (Prescription dispensed in pharmacy). Date is taken from whenHandedOver (fallback whenPrepared). End date is computed from start + daysSupply, or defaults to start date. No reviewed reference implementation covers this mapping; the spec is reconstructed from OMOP drug_exposure schema and FHIR R4 MedicationDispense definition.
Conversion profile
omop-medication-dispense-drug-exposure
A FHIR instance converts to drug_exposure iff it validates against this profile.
| Path | Card | Type | Binding / Fixed | Comment |
|---|---|---|---|---|
| MedicationDispense.status | 1..*MS | fhir/medicationdispense-statusrequired | ||
| MedicationDispense.medication[x] | 1..*MS | CodeableConcept | omop-drug-codesrequired | |
| MedicationDispense.subject | 1..1 | Reference | Required for drug_exposure.person_id. | |
| MedicationDispense.whenHandedOver | 1..1MS | Required for drug_exposure.drug_exposure_start_date. Falls back to whenPrepared only when whenHandedOver is absent — this profile requires whenHandedOver for OMOP-grade conversion. |
ViewDefinition (Stage 1 flattener)
omop-medicationdispense-drug-exposure
18 columns · resource MedicationDispense
| column name | FHIRPath | type |
|---|---|---|
| id | MedicationDispense.id | id |
| drug_rxnorm | MedicationDispense.medicationCodeableConcept.coding.where(system='http://www.nlm.nih.gov/research/umls/rxnorm').first().code | code |
| drug_ndc | MedicationDispense.medicationCodeableConcept.coding.where(system='http://hl7.org/fhir/sid/ndc').first().code | code |
| drug_atc | MedicationDispense.medicationCodeableConcept.coding.where(system='http://www.whocc.no/atc').first().code | code |
| drug_snomed | MedicationDispense.medicationCodeableConcept.coding.where(system='http://snomed.info/sct').first().code | code |
| drug_text | MedicationDispense.medicationCodeableConcept.text | string |
| subject_id | MedicationDispense.subject | Reference(Patient) |
| drug_exposure_start_date | MedicationDispense.whenHandedOver | dateTime |
| drug_exposure_start_datetime | MedicationDispense.whenHandedOver | dateTime |
| drug_exposure_end_date | MedicationDispense.daysSupply | Duration |
| quantity | MedicationDispense.quantity.value | decimal |
| days_supply | MedicationDispense.daysSupply.value | integer |
| sig | MedicationDispense.dosageInstruction[].text | string |
| route | MedicationDispense.dosageInstruction[].route | CodeableConcept |
| route_text | MedicationDispense.dosageInstruction[].route.text | string |
| performer_id | MedicationDispense.performer[0].actor | Reference(Practitioner | PractitionerRole | Organization) |
| encounter_id | MedicationDispense.context | Reference(Encounter) |
| dose_unit_text | MedicationDispense.dosageInstruction[].doseAndRate[].doseQuantity.unit | string |
Condition: status != 'entered-in-error' AND status != 'cancelled' AND status != 'declined' AND status != 'stopped'
Fields (23)
-
drug_exposure_id← — integer · idPKrequiredSurrogate key, generated deterministically from MedicationDispense.id -
person_id←MedicationDispense.subjectinteger · Reference(Patient)FK→PERSONrequiredResolve Patient reference to person_id -
drug_concept_id←MedicationDispense.medication[x]integer · CodeableConcept | Reference(Medication)FK→CONCEPTrequiredmap:drugRxNorm / ATC / NDC -> OMOP standard concept. Resolve medicationCodeableConcept or medicationReference -
drug_exposure_start_date←MedicationDispense.whenHandedOverdate · dateTimerequiredtransform:date(whenHandedOver ?? whenPrepared)The date medication was supplied. Fallback to whenPrepared if whenHandedOver absent -
drug_exposure_start_datetime←MedicationDispense.whenHandedOverdatetime · dateTimetransform:whenHandedOver ?? whenPreparedFull ISO datetime -
drug_exposure_end_date←MedicationDispense.daysSupplydate · Durationrequiredtransform:date(start + daysSupply) ?? start_dateIf daysSupply present: end = start + daysSupply. Otherwise fallback to start date -
drug_exposure_end_datetime← — datetime · dateTimeNull if no daysSupply -
verbatim_end_date← — date · dateLeave null. MedicationDispense does not carry a verbatim end date -
drug_type_concept_id← constant integer · integerFK→CONCEPTrequired=38000175Prescription dispensed in pharmacy. Alternative: 32817 (EHR) used by FhirToCdm/ETL-German for other medication resources2 sources ▾
-
This project and OMOP CDM guidance use 38000175 (Prescription dispensed in pharmacy) — the semantically precise type for a dispense event
-
FhirToCdm and ETL-German use 32817 (EHR) universally across all medication resource types; neither implements MedicationDispense but their pattern would apply
- FhirToCdm(csharp) refs/refs/FhirToCdm/FhirToCdmMappings.cs — Type concept 32817 used for all medication resources (line 338)
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/MedicationStatementMapper.java — CONCEPT_CLAIM (32817) used universally
-
-
stop_reason← — varchar(20) · stringLeave null. MedicationDispense does not carry a discontinuation reason -
refills← — integer · integerLeave null. Refills are tracked on the originating MedicationRequest, not the dispense -
quantity←MedicationDispense.quantity.valuefloat · decimalDispensed quantity (the total handed over) -
days_supply←MedicationDispense.daysSupply.valueinteger · integerDays of medication supplied. Direct FHIR field on MedicationDispense (unlike MedicationRequest where it must be computed) -
sig←MedicationDispense.dosageInstruction[].textvarchar(MAX) · stringFree-text dosage instructions. Fallback to patientInstruction -
route_concept_id←MedicationDispense.dosageInstruction[].routeinteger · CodeableConceptFK→CONCEPTmap:routeSNOMED route codes -> OMOP Route domain -
route_source_value←MedicationDispense.dosageInstruction[].route.textvarchar(50) · stringRaw route text or coding[0].display -
lot_number← — varchar(50) · stringNot used for MedicationDispense -
provider_id←MedicationDispense.performer[0].actorinteger · Reference(Practitioner | PractitionerRole | Organization)FK→PROVIDERThe dispensing pharmacist or actor -
visit_occurrence_id←MedicationDispense.contextinteger · Reference(Encounter)FK→VISIT_OCCURRENCEEncounter reference. Resolve to visit_occurrence_id -
visit_detail_id← — integer · integerFK→VISIT_DETAILLeave null -
drug_source_value←MedicationDispense.medication[x].coding[best].codevarchar(50) · codeBest code by vocabulary priority (RxNorm > ATC > NDC > SNOMED) -
drug_source_concept_id←MedicationDispense.medication[x]integer · integerFK→CONCEPT=0Source vocabulary concept. Placeholder: 0 -
dose_unit_source_value←MedicationDispense.dosageInstruction[].doseAndRate[].doseQuantity.unitvarchar(50) · stringRaw dose unit string from doseQuantity.unit or .code
Vocabularies
drug_type
| Source | Display | Concept ID | Concept Name |
|---|---|---|---|
| MedicationDispense | Pharmacy dispense event | 38000175 | Prescription dispensed in pharmacy |
| MedicationDispense (EHR variant) | EHR-based type used by FhirToCdm/ETL-German | 32817 | EHR |
Edge Cases
status = 'entered-in-error'
Skip -- do not create drug_exposure row. Consensus across implementations for all medication resources.
status = 'cancelled' / 'declined' / 'stopped'
Skip. No reference implementation precedent for MedicationDispense specifically. Recommended: skip non-completed dispenses.
whenHandedOver absent, whenPrepared present
Use whenPrepared as drug_exposure_start_date.
Both whenHandedOver and whenPrepared absent
Fallback to context (encounter) start date, or null. Consider dropping the record if no date can be resolved.
daysSupply absent
End date = start date. days_supply column left null.
quantity absent
Leave quantity column null.
Multiple dosageInstruction entries
Take first entry. Consistent with handling in other medication resources (MedicationRequest, MedicationStatement).
Cross-reference to originating MedicationRequest via authorizingPrescription
Currently no implementation links these for OMOP. Could be used to inherit dosage/refill metadata in future.
Medication resolution: medicationReference to contained or external Medication
Resolve contained Medication inline. For external references, look up by reference. Most implementations handle inline medicationCodeableConcept only.
Multiple codings on medication[x]
Pick best by vocabulary priority: RxNorm > ATC > NDC > SNOMED.
drug_source_value truncation
OMOP varchar(50) limit. Truncate to 50 characters.
Reference Implementations
- omoponfhir(java) refs/refs/omoponfhir-omopv5-r4-mapping/ — Implements MedicationRequest + MedicationStatement only, NOT MedicationDispense
- FhirToCdm(csharp) refs/refs/FhirToCdm/ — Implements MedicationRequest + Immunization only, NOT MedicationDispense
- ETL-German-FHIR-Core(java) refs/refs/ETL-German-FHIR-Core/ — Implements MedicationStatement + MedicationAdministration only, NOT MedicationDispense
- fhir-to-omop-demo(jq) refs/refs/fhir-to-omop-demo/ — Implements MedicationRequest + MedicationAdministration only, NOT MedicationDispense
- NACHC-fhir-to-omop(java) refs/refs/NACHC-fhir-to-omop/ — MedicationRequest only, NOT MedicationDispense
- fhir-omop-ig(fml) refs/refs/fhir-omop-ig/input/maps/medication.fml — MedicationStatement only, NOT MedicationDispense