Files
vigilcare-clinical/VigilCare.WardGateway/Services/LocalWarningEvaluator.cs
T

76 lines
2.9 KiB
C#

using Microsoft.EntityFrameworkCore;
public class LocalWarningEvaluator
{
private readonly GatewayDbContext _db;
private readonly ILogger<LocalWarningEvaluator> _logger;
public LocalWarningEvaluator(GatewayDbContext db, ILogger<LocalWarningEvaluator> logger)
{
_db = db;
_logger = logger;
}
public async Task<bool> TryEvaluateAsync(
Guid observationId, Guid encounterId, Guid patientId,
string observationCode, decimal value, ThresholdCacheEntry threshold)
{
if (!IsWarningBreach(value, threshold)) return false;
if (IsCriticalBreach(value, threshold)) return false;
var alertType = AlertTypeExtensions.WarningFor(observationCode);
var clientAlertId = Guid.NewGuid();
var triggeredAt = DateTimeOffset.UtcNow;
var details = BuildWarningDetails(observationCode, value, threshold);
var exists = await _db.ClinicalAlerts.AnyAsync(a =>
a.EncounterId == encounterId
&& a.AlertType == alertType
&& (a.Status == AlertStatus.Open || a.Status == AlertStatus.Acknowledged));
if (exists) return false;
var alert = new LocalClinicalAlert
{
Id = Guid.NewGuid(),
ClientAlertId = clientAlertId,
EncounterId = encounterId,
PatientId = patientId,
ObservationId = observationId,
AlertType = alertType,
Severity = AlertSeverity.Warning,
Details = details,
Status = AlertStatus.Open,
TriggeredAt = triggeredAt
};
_db.ClinicalAlerts.Add(alert);
BufferedSyncWriter.Enqueue(_db, BufferedSyncItemType.Alert, new
{
clientAlertId,
encounterId,
alertType = alertType.ToDbString(),
severity = AlertSeverity.Warning.ToDbString(),
details,
generatedAt = triggeredAt
}, $"alert:{clientAlertId}", encounterId, triggeredAt);
_logger.LogInformation(
"WARNING alert {AlertId} created locally for encounter {EncounterId}",
alert.Id, encounterId);
return true;
}
private static bool IsWarningBreach(decimal value, ThresholdCacheEntry t) =>
(t.WarningHigh.HasValue && value > t.WarningHigh.Value) ||
(t.WarningLow.HasValue && value < t.WarningLow.Value);
private static bool IsCriticalBreach(decimal value, ThresholdCacheEntry t) =>
(t.CriticalLow.HasValue && value < t.CriticalLow.Value) ||
(t.CriticalHigh.HasValue && value > t.CriticalHigh.Value);
private static string BuildWarningDetails(string code, decimal value, ThresholdCacheEntry t) =>
t.WarningHigh.HasValue && value > t.WarningHigh.Value
? $"{code} value {value} is above warning high of {t.WarningHigh}."
: $"{code} value {value} is below warning low of {t.WarningLow}.";
}