80 lines
2.9 KiB
C#
80 lines
2.9 KiB
C#
using Microsoft.Extensions.Options;
|
|
|
|
public class MedicationCorrelationHelper
|
|
{
|
|
private readonly IMedicationService _medicationService;
|
|
private readonly MedicationCorrelationOptions _options;
|
|
|
|
public MedicationCorrelationHelper(
|
|
IMedicationService medicationService,
|
|
IOptions<MedicationCorrelationOptions> options)
|
|
{
|
|
_medicationService = medicationService;
|
|
_options = options.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Appends medication context to alert details if a correlated administration
|
|
/// exists within the lookback window. Returns the original details if none found.
|
|
/// </summary>
|
|
public async Task<string> TryAnnotateDetailsAsync(
|
|
Guid encounterId,
|
|
string observationCode,
|
|
string details,
|
|
CancellationToken ct = default)
|
|
{
|
|
var recent = await _medicationService.GetRecentForEncounterAsync(
|
|
encounterId, observationCode, _options.CorrelationWindowMinutes);
|
|
|
|
if (recent.Count == 0)
|
|
return details;
|
|
|
|
// Use the most recent correlated administration
|
|
var med = recent[0];
|
|
var minutesAgo = (int)(DateTimeOffset.UtcNow - med.AdministeredAt).TotalMinutes;
|
|
|
|
return $"{details} — note: {med.DrugName} {med.Dose}{med.DoseUnit} " +
|
|
$"({med.Route}) administered {minutesAgo} min ago";
|
|
}
|
|
|
|
public async Task<MedicationContext?> TryGetContextAsync(
|
|
Guid encounterId,
|
|
string observationCode,
|
|
CancellationToken ct = default)
|
|
{
|
|
var recent = await _medicationService.GetRecentForEncounterAsync(
|
|
encounterId, observationCode, _options.CorrelationWindowMinutes);
|
|
|
|
if (recent.Count == 0)
|
|
return null;
|
|
|
|
var med = recent[0];
|
|
return new MedicationContext
|
|
{
|
|
DrugName = med.DrugName,
|
|
Dose = $"{med.Dose}{med.DoseUnit}",
|
|
Route = med.Route,
|
|
AdministeredAt = med.AdministeredAt,
|
|
RelevanceNote = BuildRelevanceNote(med.DrugName, observationCode)
|
|
};
|
|
}
|
|
|
|
private string? BuildRelevanceNote(string drugName, string observationCode)
|
|
{
|
|
var drug = drugName.ToLowerInvariant();
|
|
return observationCode switch
|
|
{
|
|
"TEMP_C" when drug is "acetaminophen" or "ibuprofen"
|
|
=> "Antipyretic — may affect temperature trend",
|
|
"HEART_RATE" or "SYSTOLIC_BP" or "DIASTOLIC_BP"
|
|
when _options.DrugVitalMappings.TryGetValue(drug, out var codes)
|
|
&& codes.Contains(observationCode, StringComparer.OrdinalIgnoreCase)
|
|
=> "Cardiovascular agent — may affect blood pressure or heart rate",
|
|
"RESP_RATE" or "SPO2"
|
|
=> "Sedative/opioid — may affect respiratory parameters",
|
|
"GLUCOSE_MG_DL"
|
|
=> "Glucose management — may affect blood sugar",
|
|
_ => null
|
|
};
|
|
}
|
|
} |