Encounter visit_occurrence implemented primary

One FHIR Encounter maps to one visit_occurrence row. The visit_occurrence table is the OMOP anchor for linking clinical events to a care context -- every event table (condition_occurrence, measurement, drug_exposure, etc.) carries a visit_occurrence_id FK. Encounter.class maps to visit_concept_id via a small lookup table; period maps to start/end dates; participant maps to provider_id; serviceProvider maps to care_site_id. Planned and cancelled encounters are dropped.

Conversion profile omop-encounter-visit-occurrence
A FHIR instance converts to visit_occurrence iff it validates against this profile.
Path Card Type Binding / Fixed Comment
Encounter.status 1..*MS fhir/encounter-statusrequired Allowed values restricted to finished, in-progress, onleave.
Encounter.class 1..1MS omop-visit-codesrequired
Encounter.subject 1..1MS Reference Required for visit_occurrence.person_id.
Encounter.period 1..*MS
Encounter.period.start 1..1MS Required for visit_occurrence.visit_start_date / visit_start_datetime.
Encounter.period.end MS Optional — falls back to visit_start_date when absent.
Encounter.participant MS First Practitioner-typed participant becomes visit_occurrence.provider_id.
Encounter.serviceProvider MS Maps to visit_occurrence.care_site_id.
ViewDefinition (Stage 1 flattener) omop-encounter-visit-occurrence
18 columns · resource Encounter
column name FHIRPath type
id Encounter.id id
class_actcode Encounter.class.coding.where(system='http://terminology.hl7.org/CodeSystem/v3-ActCode').first().code code
class_text Encounter.class.text string
type_snomed Encounter.type.coding.where(system='http://snomed.info/sct').first().code code
type_cpt Encounter.type.coding.where(system='http://www.ama-assn.org/go/cpt').first().code code
type_text Encounter.type.text string
subject_id Encounter.subject Reference(Patient)
visit_start_date Encounter.period.start dateTime
visit_start_datetime Encounter.period.start dateTime
visit_end_date Encounter.period.end dateTime
visit_end_datetime Encounter.period.end dateTime
performer_id Encounter.participant[0].individual Reference(Practitioner)
managing_organization_id Encounter.serviceProvider Reference(Organization)
admitted_from Encounter.hospitalization.admitSource CodeableConcept
admitted_from_text Encounter.hospitalization.admitSource CodeableConcept
discharged_to Encounter.hospitalization.dischargeDisposition CodeableConcept
discharged_to_text Encounter.hospitalization.dischargeDisposition CodeableConcept
preceding_visit_occurrence_id Encounter.partOf Reference(Encounter)
Condition: status in ('finished', 'in-progress')
Implementation: src/mapper/encounter.ts

Fields (17)

Vocabularies

visit_type

Source Display Concept ID Concept Name
IMP Inpatient 9201 Inpatient Visit
ACUTE Acute 9201 Inpatient Visit
AMB Ambulatory 9202 Outpatient Visit
EMER Emergency 9203 Emergency Room Visit
HH Home Health 581476 Home Visit
SS Short Stay 9202 Outpatient Visit
OBSENC Observation Encounter 9201 Inpatient Visit
FLD Field 9202 Outpatient Visit
VR Virtual 9202 Outpatient Visit
(unknown) Unknown/unmapped code 0 No matching concept

visit_type_concept

Source Display Concept ID Concept Name
EHR EHR 32817 EHR
EHR-derived Visit derived from EHR 44818518 Visit derived from EHR

discharge_disposition

Source Display Concept ID Concept Name
home Home 8536 Home
snf Skilled Nursing Facility 8676 Skilled Nursing Facility
rehab Rehabilitation Hospital 8615 Rehabilitation Hospital
exp Patient died 4216643 Patient died
(unmapped) Unmapped 0 No matching concept

Edge Cases

Missing period.start
Skip -- cannot create visit_occurrence without a start date.
Missing period.end
Use visit_start_date as visit_end_date.
Status = planned / cancelled / entered-in-error
Skip -- only finished and in-progress encounters produce rows.
Status = unknown with no end date
ETL-German treats as CONCEPT_STILL_PATIENT and sets end date to now().
Multiple participants
Take first Practitioner reference for provider_id. Alternatives: ATND type (fhir-x-omop), PPRF primary performer (fhir-to-omop-demo).
partOf (nested encounter)
Ideally creates visit_detail row linked to parent visit_occurrence. Our implementation does not yet support this.
No class code
visit_concept_id = 0.
Class code not in lookup
visit_concept_id = 0 (our project, omoponfhir). FhirToCdm and fhir-x-omop default to 9202.
ER-to-inpatient admission
Two separate encounters in FHIR; could merge into OMOP concept 262 (ER+Inpatient). No implementation does this automatically -- requires post-processing.
Missing subject
Skip -- cannot create visit_occurrence without person_id. All implementations skip or throw.
Encounter with location[] transfers
ETL-German creates one visit_detail row per location with separate start/end dates. Other implementations ignore location transfers.
visit_type_concept_id variation
32817 (EHR) vs 44818518 (Visit derived from EHR). Both acceptable. Choose based on CDM version guidance.
hospitalization absent
All admit/discharge fields default to 0/null. No error.
Encounter without an id
visit_occurrence_id remains undefined. Most implementations require an ID for FK resolution by downstream mappers.
Long source values
Truncate admitted_from_source_value and discharged_to_source_value to 50 chars.

Reference Implementations