feature: FHIR R4 Inbound Facade

This commit is contained in:
voltsrage
2026-06-21 13:53:38 +08:00
parent 9f96f54007
commit a43db52813
42 changed files with 2873 additions and 3 deletions
@@ -0,0 +1,103 @@
using Hl7.Fhir.Model;
using Microsoft.Extensions.Options;
public class EncounterFhirMapper
{
private readonly FhirReferenceResolver _refs;
private readonly FhirOptions _options;
public EncounterFhirMapper(FhirReferenceResolver refs, IOptions<FhirOptions> options)
{
_refs = refs;
_options = options.Value;
}
public async Task<FhirEncounterUpsertRequest> 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<Identifier>()
};
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;
}
}