122 lines
5.1 KiB
C#
122 lines
5.1 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
|
|
public class DigitizationHistoryService : IDigitizationHistoryService
|
|
{
|
|
private readonly AppDbContext _db;
|
|
|
|
public DigitizationHistoryService(AppDbContext db)
|
|
{
|
|
_db = db;
|
|
}
|
|
|
|
public async Task<PatientDigitizationHistoryResponse> GetPatientHistoryAsync(Guid patientId)
|
|
{
|
|
// Verify the patient exists (has at least one batch)
|
|
var hasBatches = await _db.DigitizationBatches
|
|
.AnyAsync(b => b.PatientId == patientId);
|
|
|
|
if (!hasBatches)
|
|
throw new NotFoundException(
|
|
$"No digitization history found for patient {patientId}.",
|
|
"PATIENT_HISTORY_NOT_FOUND");
|
|
|
|
// Load all batches for this patient with their relationships
|
|
var batches = await _db.DigitizationBatches
|
|
.Include(b => b.DraftObservations)
|
|
.Include(b => b.Events)
|
|
.ThenInclude(e => e.Actor)
|
|
.Include(b => b.EnteredByUser)
|
|
.Include(b => b.VerifiedByUser)
|
|
.Include(b => b.ApprovedByUser)
|
|
.Where(b => b.PatientId == patientId)
|
|
.OrderByDescending(b => b.CreatedAt)
|
|
.ToListAsync();
|
|
|
|
// For each promoted batch, count live vs superseded observations
|
|
var promotedBatchIds = batches
|
|
.Where(b => b.Status == BatchStatus.Promoted)
|
|
.Select(b => b.Id)
|
|
.ToList();
|
|
|
|
var liveObservationCounts = await _db.LiveObservations
|
|
.Where(o => promotedBatchIds.Contains(o.SourceBatchId))
|
|
.GroupBy(o => new { o.SourceBatchId, o.IsSuperseded })
|
|
.Select(g => new
|
|
{
|
|
g.Key.SourceBatchId,
|
|
g.Key.IsSuperseded,
|
|
Count = g.Count()
|
|
})
|
|
.ToListAsync();
|
|
|
|
// Build a lookup: batchId -> (activeCount, supersededCount)
|
|
var obsCountLookup = promotedBatchIds.ToDictionary(
|
|
id => id,
|
|
id =>
|
|
{
|
|
var active = liveObservationCounts
|
|
.FirstOrDefault(x => x.SourceBatchId == id && !x.IsSuperseded)?.Count ?? 0;
|
|
var superseded = liveObservationCounts
|
|
.FirstOrDefault(x => x.SourceBatchId == id && x.IsSuperseded)?.Count ?? 0;
|
|
return (Active: active, Superseded: superseded);
|
|
});
|
|
|
|
// Build a lookup for "has been superseded" — batches that appear as
|
|
// SupersedesBatchId on another batch that reached Promoted
|
|
var supersededByLookup = await _db.DigitizationBatches
|
|
.Where(b => b.SupersedesBatchId.HasValue
|
|
&& b.Status == BatchStatus.Promoted
|
|
&& promotedBatchIds.Contains(b.SupersedesBatchId.Value))
|
|
.ToDictionaryAsync(
|
|
b => b.SupersedesBatchId!.Value,
|
|
b => b.Id);
|
|
|
|
var entries = batches.Select(b =>
|
|
{
|
|
var counts = obsCountLookup.GetValueOrDefault(b.Id, (Active: 0, Superseded: 0));
|
|
var hasBeenSuperseded = supersededByLookup.ContainsKey(b.Id);
|
|
supersededByLookup.TryGetValue(b.Id, out var supersededByBatchId);
|
|
|
|
return new DigitizationHistoryEntry(
|
|
BatchId: b.Id,
|
|
Status: b.Status.ToDbString(),
|
|
BatchType: b.BatchType.ToDbString(),
|
|
Track: b.Track.ToDbString(),
|
|
SupersedesBatchId: b.SupersedesBatchId,
|
|
IsCorrection: b.SupersedesBatchId.HasValue,
|
|
HasBeenSuperseded: hasBeenSuperseded,
|
|
SupersededByBatchId: hasBeenSuperseded ? supersededByBatchId : null,
|
|
DraftObservationCount: b.DraftObservations.Count,
|
|
LiveObservationCount: counts.Active,
|
|
SupersededObservationCount: counts.Superseded,
|
|
CreatedAt: b.CreatedAt,
|
|
PromotedAt: b.PromotedAt,
|
|
PromotionEncounterId: b.PromotionEncounterId,
|
|
EnteredByUserId: b.EnteredByUserId,
|
|
EnteredByUserName: b.EnteredByUser?.FullName,
|
|
VerifiedByUserId: b.VerifiedByUserId,
|
|
VerifiedByUserName: b.VerifiedByUser?.FullName,
|
|
ApprovedByUserId: b.ApprovedByUserId,
|
|
ApprovedByUserName: b.ApprovedByUser?.FullName,
|
|
AuditTrail: b.Events
|
|
.OrderBy(e => e.OccurredAt)
|
|
.Select(e => new DigitizationEventSummary(
|
|
e.EventType.ToDbString(),
|
|
e.OccurredAt,
|
|
e.ActorUserId,
|
|
e.Actor?.FullName ?? "Unknown",
|
|
e.MetadataJson))
|
|
.ToList()
|
|
);
|
|
}).ToList();
|
|
|
|
return new PatientDigitizationHistoryResponse(
|
|
PatientId: patientId,
|
|
TotalBatches: entries.Count,
|
|
PromotedBatches: entries.Count(e => e.Status == "PROMOTED"),
|
|
SupersededBatches: entries.Count(e => e.HasBeenSuperseded),
|
|
PendingBatches: entries.Count(e => e.Status != "PROMOTED" && e.Status != "REJECTED"),
|
|
Entries: entries
|
|
);
|
|
}
|
|
} |