using Hl7.Fhir.Model; using Microsoft.Extensions.Options; public class EncounterFhirMapper { private readonly FhirReferenceResolver _refs; private readonly FhirOptions _options; public EncounterFhirMapper(FhirReferenceResolver refs, IOptions options) { _refs = refs; _options = options.Value; } public async Task ToUpsertRequestAsync(Hl7.Fhir.Model.Encounter fhir) { var identifier = _refs.ExtractPrimaryIdentifier(fhir, _options.EncounterIdentifierSystems) ?? throw new FhirMappingException("Encounter must include at least one identifier.", "required"); if (fhir.Subject is null) throw new FhirMappingException("Encounter subject is required.", "required"); var patientId = await _refs.ResolvePatientReferenceAsync(fhir.Subject); var actCode = fhir.Class?.Code ?? "IMP"; if (!_options.EncounterClassMap.TryGetValue(actCode, out var encounterTypeStr)) encounterTypeStr = _options.DefaultEncounterType; var departmentStr = _options.DefaultDepartment; var locationCode = fhir.Location?.FirstOrDefault()?.Location?.Display; if (locationCode is not null) { foreach (var (key, value) in _options.DepartmentCodeMap) { if (locationCode.Contains(key, StringComparison.OrdinalIgnoreCase)) { departmentStr = value; break; } } } var attending = fhir.Participant? .FirstOrDefault(p => p.Type?.Any(t => t.Coding?.Any(c => c.Code == "ATND") == true) == true) ?.Individual?.Display ?? "Unknown"; var targetStatus = fhir.Status switch { Hl7.Fhir.Model.Encounter.EncounterStatus.Finished => EncounterStatus.Discharged, Hl7.Fhir.Model.Encounter.EncounterStatus.Cancelled => EncounterStatus.Cancelled, _ => EncounterStatus.Active }; return new FhirEncounterUpsertRequest( IdentifierSystem: identifier.System, IdentifierValue: identifier.Value, PatientId: patientId, EncounterType: EncounterTypeExtensions.FromDbString(encounterTypeStr), Department: DepartmentExtensions.FromDbString(departmentStr), AttendingPhysician: attending, TargetStatus: targetStatus, AdmittedAt: fhir.Period?.StartElement?.ToDateTimeOffset(TimeSpan.Zero), RoomBed: fhir.Location?.FirstOrDefault()?.Location?.Display, AdmissionReason: fhir.ReasonCode?.FirstOrDefault()?.Text); } public Hl7.Fhir.Model.Encounter ToFhirResponse(Encounter encounter, (string System, string Value)? hospitalId) { var resource = new Hl7.Fhir.Model.Encounter { Id = encounter.Id.ToString(), Status = encounter.Status switch { EncounterStatus.Active => Hl7.Fhir.Model.Encounter.EncounterStatus.InProgress, EncounterStatus.Discharged => Hl7.Fhir.Model.Encounter.EncounterStatus.Finished, EncounterStatus.Cancelled => Hl7.Fhir.Model.Encounter.EncounterStatus.Cancelled, _ => Hl7.Fhir.Model.Encounter.EncounterStatus.Unknown }, Class = new Coding("http://terminology.hl7.org/CodeSystem/v3-ActCode", "IMP"), Subject = new ResourceReference($"Patient/{encounter.PatientId}"), Identifier = new List() }; if (hospitalId is not null) { resource.Identifier.Add(new Identifier { System = hospitalId.Value.System, Value = hospitalId.Value.Value }); } resource.Identifier.Add(new Identifier { System = _options.InternalEncounterIdSystem, Value = encounter.Id.ToString() }); return resource; } }