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

59 lines
1.9 KiB
C#

using Microsoft.EntityFrameworkCore;
public class ObservationQueryService : IObservationQueryService
{
private readonly AppDbContext _db;
public ObservationQueryService(AppDbContext db) => _db = db;
public async Task<CursorPage<Observation>> GetHistoryAsync(
Guid encounterId,
string? code,
DateTimeOffset? from,
DateTimeOffset? to,
int limit,
string? cursorToken)
{
limit = Math.Clamp(limit, 1, 100);
var cursor = ObservationCursor.Decode(cursorToken);
var query = _db.Observations
.AsNoTracking()
.Where(o => o.EncounterId == encounterId);
if (!string.IsNullOrEmpty(code))
query = query.Where(o => o.ObservationCode == code);
if (from.HasValue)
query = query.Where(o => o.RecordedAt >= from.Value);
if (to.HasValue)
query = query.Where(o => o.RecordedAt <= to.Value);
if (cursor is not null)
{
// Keyset condition for ORDER BY recorded_at DESC, id DESC:
// next page starts just below the cursor position
var cursorTime = cursor.RecordedAt;
var cursorId = cursor.Id;
query = query.Where(o =>
o.RecordedAt < cursorTime ||
(o.RecordedAt == cursorTime && o.Id.CompareTo(cursorId) < 0));
}
var items = await query
.OrderByDescending(o => o.RecordedAt)
.ThenByDescending(o => o.Id)
.Take(limit + 1) // fetch one extra to know if there is a next page
.ToListAsync();
var hasMore = items.Count > limit;
if (hasMore) items.RemoveAt(limit);
var nextCursor = hasMore
? new ObservationCursor(items[^1].RecordedAt, items[^1].Id).Encode()
: null;
return new CursorPage<Observation>(items, nextCursor, hasMore);
}
}