77 lines
2.9 KiB
C#
77 lines
2.9 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
|
|
public class LocalAlertService : ILocalAlertService
|
|
{
|
|
private readonly GatewayDbContext _db;
|
|
|
|
public LocalAlertService(GatewayDbContext db) => _db = db;
|
|
|
|
public async Task<LocalClinicalAlert> AcknowledgeAsync(
|
|
Guid id, AcknowledgeAlertRequest req, string clinicianId)
|
|
{
|
|
var alert = await _db.ClinicalAlerts.FindAsync(id)
|
|
?? throw new NotFoundException("Alert not found.", "ALERT_NOT_FOUND");
|
|
|
|
if (alert.Status is not (AlertStatus.Open or AlertStatus.Escalated))
|
|
throw new ConflictException("Alert cannot be acknowledged.", "ALERT_NOT_ACKNOWLEDGEABLE");
|
|
|
|
alert.Status = AlertStatus.Acknowledged;
|
|
alert.AcknowledgedAt = DateTimeOffset.UtcNow;
|
|
alert.AcknowledgedBy = clinicianId;
|
|
|
|
BufferedSyncWriter.Enqueue(_db, BufferedSyncItemType.Ack, new
|
|
{
|
|
clientRef = Guid.NewGuid(),
|
|
alert.ClientAlertId,
|
|
clinicianId,
|
|
acknowledgedAt = alert.AcknowledgedAt,
|
|
req.Note
|
|
}, $"ack:{alert.ClientAlertId}:{alert.AcknowledgedAt:o}", alert.EncounterId, alert.AcknowledgedAt!.Value);
|
|
|
|
await _db.SaveChangesAsync();
|
|
return alert;
|
|
}
|
|
|
|
public async Task<LocalClinicalAlert> ResolveAsync(Guid id)
|
|
{
|
|
var alert = await _db.ClinicalAlerts.FindAsync(id)
|
|
?? throw new NotFoundException("Alert not found.", "ALERT_NOT_FOUND");
|
|
|
|
if (alert.Status != AlertStatus.Acknowledged)
|
|
throw new ConflictException("Alert must be acknowledged first.", "ALERT_NOT_ACKNOWLEDGED");
|
|
|
|
alert.Status = AlertStatus.Resolved;
|
|
alert.ResolvedAt = DateTimeOffset.UtcNow;
|
|
|
|
BufferedSyncWriter.Enqueue(_db, BufferedSyncItemType.Resolve, new
|
|
{
|
|
clientRef = Guid.NewGuid(),
|
|
alert.ClientAlertId,
|
|
clinicianId = alert.AcknowledgedBy,
|
|
resolvedAt = alert.ResolvedAt,
|
|
note = (string?)null
|
|
}, $"resolve:{alert.ClientAlertId}", alert.EncounterId, alert.ResolvedAt!.Value);
|
|
|
|
await _db.SaveChangesAsync();
|
|
return alert;
|
|
}
|
|
|
|
public async Task<PagedResult<LocalClinicalAlert>> ListAsync(
|
|
Guid? encounterId, string? status, int page, int pageSize)
|
|
{
|
|
page = Math.Max(1, page);
|
|
pageSize = Math.Clamp(pageSize, 1, 100);
|
|
|
|
var q = _db.ClinicalAlerts.AsNoTracking().AsQueryable();
|
|
if (encounterId.HasValue) q = q.Where(a => a.EncounterId == encounterId);
|
|
if (!string.IsNullOrEmpty(status))
|
|
{
|
|
var parsedStatus = AlertStatusExtensions.FromDbString(status);
|
|
q = q.Where(a => a.Status == parsedStatus);
|
|
}
|
|
var total = await q.CountAsync();
|
|
var items = await q.OrderByDescending(a => a.TriggeredAt)
|
|
.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
|
|
return new PagedResult<LocalClinicalAlert>(items, page, pageSize, total);
|
|
}
|
|
} |