feature: Improve dashboard functionality
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
public record SepsisBundleElementSummary(
|
||||
Guid Id,
|
||||
SepsisBundleElementType ElementType,
|
||||
SepsisBundleElementStatus Status,
|
||||
DateTimeOffset? CompletedAt);
|
||||
|
||||
public record SepsisBundleSummary(
|
||||
Guid Id,
|
||||
Guid EncounterId,
|
||||
string Mrn,
|
||||
string FirstName,
|
||||
string LastName,
|
||||
string? RoomBed,
|
||||
Department Department,
|
||||
string TriggeringAlertType,
|
||||
DateTimeOffset RecognizedAt,
|
||||
DateTimeOffset DeadlineAt,
|
||||
SepsisBundleComplianceStatus ComplianceStatus,
|
||||
DateTimeOffset? CompletedAt,
|
||||
IReadOnlyList<SepsisBundleElementSummary> Elements);
|
||||
@@ -98,10 +98,14 @@ public class AlertService : IAlertService
|
||||
$"Alert cannot be acknowledged from status '{alert.Status}'.",
|
||||
"ALERT_NOT_ACKNOWLEDGEABLE");
|
||||
|
||||
var roleLabel = _currentUser.Role?.ToDbString() ?? "UNKNOWN";
|
||||
var userId = _currentUser.UserId;
|
||||
var acknowledgmentNote = FormatAcknowledgmentNote(roleLabel, displayName, req.Note);
|
||||
|
||||
var previousStatus = alert.Status;
|
||||
alert.Status = AlertStatus.Acknowledged;
|
||||
alert.AcknowledgedAt = DateTimeOffset.UtcNow;
|
||||
alert.AcknowledgedBy = displayName;
|
||||
alert.AcknowledgedBy = $"{displayName} ({roleLabel})";
|
||||
|
||||
// Write an outbox event so the Kafka consumer (Phase 6) can cancel the
|
||||
// pending RabbitMQ escalation timer when it sees this acknowledgment.
|
||||
@@ -113,9 +117,11 @@ public class AlertService : IAlertService
|
||||
{
|
||||
alertId = alert.Id,
|
||||
encounterId = alert.EncounterId,
|
||||
acknowledgedBy = displayName,
|
||||
acknowledgedBy = alert.AcknowledgedBy,
|
||||
userId,
|
||||
role = roleLabel,
|
||||
acknowledgedAt = alert.AcknowledgedAt,
|
||||
note = req.Note
|
||||
note = acknowledgmentNote
|
||||
}),
|
||||
PartitionKey = alert.EncounterId.ToString(),
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
@@ -141,8 +147,8 @@ public class AlertService : IAlertService
|
||||
"ClinicalAlert",
|
||||
alert.Id,
|
||||
previousValue: new { status = previousStatus.ToDbString() },
|
||||
newValue: new { status = alert.Status.ToDbString(), alert.AcknowledgedBy },
|
||||
reason: req.Note);
|
||||
newValue: new { status = alert.Status.ToDbString(), alert.AcknowledgedBy, role = roleLabel, userId },
|
||||
reason: acknowledgmentNote);
|
||||
|
||||
if (alert.AlertType.IsSuppressible())
|
||||
{
|
||||
@@ -151,7 +157,7 @@ public class AlertService : IAlertService
|
||||
"ClinicalAlert",
|
||||
alert.Id,
|
||||
newValue: new { alert.AlertType, alert.EncounterId },
|
||||
reason: req.Note);
|
||||
reason: acknowledgmentNote);
|
||||
}
|
||||
|
||||
return alert;
|
||||
@@ -244,4 +250,10 @@ public class AlertService : IAlertService
|
||||
alert.ResolvedAt = resolve.ResolvedAt;
|
||||
await _db.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
private static string FormatAcknowledgmentNote(string roleLabel, string displayName, string? note)
|
||||
{
|
||||
var prefix = $"[{roleLabel}] Acknowledged by {displayName}.";
|
||||
return string.IsNullOrWhiteSpace(note) ? prefix : $"{prefix} {note.Trim()}";
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ public interface ISepsisBundleService
|
||||
Guid encounterId, Guid triggeringAlertId, AlertType alertType, CancellationToken ct = default);
|
||||
Task<SepsisBundle?> GetCurrentByEncounterAsync(Guid encounterId);
|
||||
Task<SepsisBundle> GetByIdAsync(Guid id);
|
||||
Task<PagedResult<SepsisBundle>> ListAsync(SepsisBundleComplianceStatus? status, int page, int pageSize);
|
||||
Task<PagedResult<SepsisBundleSummary>> ListAsync(SepsisBundleComplianceStatus? status, int page, int pageSize);
|
||||
Task OnOrderResultedAsync(Guid orderId, CancellationToken ct = default);
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public class SepsisBundleService : ISepsisBundleService
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public async Task<PagedResult<SepsisBundle>> ListAsync(
|
||||
public async Task<PagedResult<SepsisBundleSummary>> ListAsync(
|
||||
SepsisBundleComplianceStatus? status, int page, int pageSize)
|
||||
{
|
||||
pageSize = Math.Clamp(pageSize, 1, 100);
|
||||
@@ -132,19 +132,39 @@ public class SepsisBundleService : ISepsisBundleService
|
||||
var query = _db.SepsisBundles
|
||||
.AsNoTracking()
|
||||
.Include(b => b.Elements)
|
||||
.Include(b => b.Encounter)
|
||||
.ThenInclude(e => e.Patient)
|
||||
.AsQueryable();
|
||||
|
||||
if (status.HasValue)
|
||||
query = query.Where(b => b.ComplianceStatus == status.Value);
|
||||
|
||||
var total = await query.CountAsync();
|
||||
var items = await query
|
||||
var bundles = await query
|
||||
.OrderByDescending(b => b.RecognizedAt)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
return new PagedResult<SepsisBundle>(items, page, pageSize, total);
|
||||
var items = bundles.Select(b => new SepsisBundleSummary(
|
||||
b.Id,
|
||||
b.EncounterId,
|
||||
b.Encounter.Patient.Mrn,
|
||||
b.Encounter.Patient.FirstName,
|
||||
b.Encounter.Patient.LastName,
|
||||
b.Encounter.RoomBed,
|
||||
b.Encounter.Department,
|
||||
b.TriggeringAlertType,
|
||||
b.RecognizedAt,
|
||||
b.DeadlineAt,
|
||||
b.ComplianceStatus,
|
||||
b.CompletedAt,
|
||||
b.Elements
|
||||
.Select(e => new SepsisBundleElementSummary(e.Id, e.ElementType, e.Status, e.CompletedAt))
|
||||
.ToList()))
|
||||
.ToList();
|
||||
|
||||
return new PagedResult<SepsisBundleSummary>(items, page, pageSize, total);
|
||||
}
|
||||
|
||||
public async Task OnOrderResultedAsync(Guid orderId, CancellationToken ct = default)
|
||||
|
||||
Reference in New Issue
Block a user