Files
vigilcare-clinical/VigilCareClinicalAPI/Services/QsofaService.cs
T

77 lines
2.5 KiB
C#

using Microsoft.EntityFrameworkCore;
using StackExchange.Redis;
public class QsofaService : IQsofaService
{
private readonly AppDbContext _db;
private readonly IConnectionMultiplexer _redis;
public QsofaService(AppDbContext db, IConnectionMultiplexer redis)
{
_db = db;
_redis = redis;
}
public async Task<QsofaCurrentResponse> GetCurrentAsync(Guid encounterId)
{
await EnsureEncounterExistsAsync(encounterId);
var values = await ReadCriterionValuesAsync(encounterId);
return BuildResponse(values);
}
public async Task<int> GetActiveCriteriaCountAsync(Guid encounterId)
{
var values = await ReadCriterionValuesAsync(encounterId);
return QsofaCalculator.CountActiveCriteria(values);
}
public async Task<CursorPage<ClinicalAlert>> GetHistoryAsync(
Guid encounterId, int limit, string? cursor)
{
limit = Math.Clamp(limit, 1, 100);
var query = _db.ClinicalAlerts
.AsNoTracking()
.Where(a => a.EncounterId == encounterId
&& (a.AlertType == AlertType.QsofaScreen || a.AlertType == AlertType.QsofaWarning));
var items = await query
.OrderByDescending(a => a.TriggeredAt)
.ThenByDescending(a => a.Id)
.Take(limit + 1)
.ToListAsync();
var hasMore = items.Count > limit;
if (hasMore) items.RemoveAt(limit);
return new CursorPage<ClinicalAlert>(items, null, hasMore);
}
private async Task EnsureEncounterExistsAsync(Guid encounterId)
{
var exists = await _db.Encounters.AnyAsync(e => e.Id == encounterId);
if (!exists)
throw new NotFoundException("Encounter not found.", "ENCOUNTER_NOT_FOUND");
}
private async Task<RedisValue[]> ReadCriterionValuesAsync(Guid encounterId)
{
var cache = _redis.GetDatabase();
return await cache.StringGetAsync(QsofaCalculator.AllCriterionKeys(encounterId));
}
private static QsofaCurrentResponse BuildResponse(RedisValue[] values)
{
return new QsofaCurrentResponse(
QsofaCalculator.CountActiveCriteria(values),
new QsofaCriteriaState(
ParseOptionalDecimal(values[0]),
ParseOptionalDecimal(values[1]),
ParseOptionalDecimal(values[2])));
}
private static decimal? ParseOptionalDecimal(RedisValue value) =>
value.HasValue ? decimal.Parse(value.ToString()) : null;
}