Files

93 lines
3.2 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
public sealed class PendingOrdersCheck
{
public static readonly ReconciliationCheckType CheckType = ReconciliationCheckType.PendingOrderNoResult;
private readonly AppDbContext _db;
private readonly ReconciliationPublisher _publisher;
private readonly ReconciliationJobOptions _opts;
private readonly ILogger<PendingOrdersCheck> _logger;
public PendingOrdersCheck(
AppDbContext db,
ReconciliationPublisher publisher,
IOptions<ReconciliationJobOptions> opts,
ILogger<PendingOrdersCheck> logger)
{
_db = db;
_publisher = publisher;
_opts = opts.Value;
_logger = logger;
}
public async Task<int> RunAsync(CancellationToken ct)
{
var cutoff = DateTimeOffset.UtcNow
.AddHours(-_opts.PendingOrderThresholdHours);
var staleOrders = await _db.Orders
.Where(o => (o.Status == OrderStatus.Pending || o.Status == OrderStatus.InProgress)
&& o.OrderedAt < cutoff
&& o.ResultedAt == null)
.Select(o => new
{
o.Id,
o.EncounterId,
o.OrderType,
o.Description,
o.OrderedAt,
PatientId = o.Encounter!.PatientId,
})
.ToListAsync(ct);
if (!staleOrders.Any())
{
_logger.LogDebug("[RECONCILIATION] Check2 — no stale pending orders");
return 0;
}
var byEncounter = staleOrders
.GroupBy(o => new { o.EncounterId, o.PatientId })
.ToList();
var inserted = 0;
foreach (var group in byEncounter)
{
var alreadyOpen = await _db.ReconciliationAlerts
.AnyAsync(r => r.CheckType == CheckType
&& r.EncounterId == group.Key.EncounterId
&& r.ResolvedAt == null, ct);
if (alreadyOpen) continue;
var lines = group.Select(o =>
$" [{o.OrderType.ToDbString()}] {o.Description} (ordered {o.OrderedAt:u}, "
+ $"pending {(DateTimeOffset.UtcNow - o.OrderedAt).TotalHours:F1}h) ID={o.Id}");
var details = $"{group.Count()} order(s) pending without result for encounter "
+ $"{group.Key.EncounterId}:\n{string.Join("\n", lines)}";
var rec = new ReconciliationAlert
{
Id = Guid.NewGuid(),
CheckType = CheckType, // ReconciliationCheckType enum
EncounterId = group.Key.EncounterId,
PatientId = group.Key.PatientId,
Details = details,
CreatedAt = DateTimeOffset.UtcNow,
};
_db.ReconciliationAlerts.Add(rec);
await _db.SaveChangesAsync(ct);
await _publisher.PublishAsync(rec, ct);
_logger.LogWarning(
"[RECONCILIATION] {CheckType} — encounter {EncounterId}: {Count} stale order(s)",
CheckType, group.Key.EncounterId, group.Count());
inserted++;
}
return inserted;
}
}