feature: Ward Gateway Service (Local-First Clinical Path)

This commit is contained in:
voltsrage
2026-06-23 16:45:38 +08:00
parent d8e142fffe
commit 1bf8359097
100 changed files with 5474 additions and 4 deletions
@@ -0,0 +1,15 @@
using System.Text.Json;
using System.Text.Json.Serialization;
public static class CentralApiJson
{
public static JsonSerializerOptions Options { get; } = new()
{
PropertyNameCaseInsensitive = true,
Converters =
{
new JsonStringEnumConverter(),
new DepartmentJsonConverter()
}
};
}
@@ -0,0 +1,50 @@
public sealed class CentralEncounterListPage
{
public List<CentralWardEncounterSummary> Items { get; set; } = [];
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPages { get; set; }
}
public sealed class CentralWardEncounterSummary
{
public Guid EncounterId { get; set; }
public Guid PatientId { get; set; }
}
public sealed class CentralEncounterDetail
{
public Guid Id { get; set; }
public Guid PatientId { get; set; }
public EncounterType EncounterType { get; set; }
public EncounterStatus Status { get; set; }
public Department Department { get; set; }
public string AttendingPhysician { get; set; } = null!;
public string? RoomBed { get; set; }
public DateTimeOffset AdmittedAt { get; set; }
public CentralPatientDetail Patient { get; set; } = null!;
}
public sealed class CentralPatientDetail
{
public Guid Id { get; set; }
public string Mrn { get; set; } = null!;
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
public DateOnly DateOfBirth { get; set; }
public string Gender { get; set; } = null!;
}
public sealed class CentralAlertThreshold
{
public Guid Id { get; set; }
public string ObservationCode { get; set; } = null!;
public string DisplayName { get; set; } = null!;
public string Unit { get; set; } = null!;
public decimal? CriticalLow { get; set; }
public decimal? WarningLow { get; set; }
public decimal? WarningHigh { get; set; }
public decimal? CriticalHigh { get; set; }
public int? SuppressionWindowMinutes { get; set; }
}
@@ -0,0 +1 @@
public record AcknowledgeAlertRequest(string? Note);
@@ -0,0 +1,13 @@
public record EncounterDetail(
Guid Id,
Guid PatientId,
string Mrn,
string FirstName,
string LastName,
Department Department,
EncounterStatus Status,
string? RoomBed,
string AttendingPhysician,
DateTimeOffset AdmittedAt,
IReadOnlyList<LocalObservation> RecentObservations,
IReadOnlyList<LocalClinicalAlert> OpenAlerts);
@@ -0,0 +1,13 @@
public record WardEncounterSummary(
Guid EncounterId,
string Mrn,
string FirstName,
string LastName,
Department Department,
string? RoomBed,
string AttendingPhysician,
DateTimeOffset AdmittedAt,
int OpenAlertCount,
int? News2Score,
int? QsofaScore,
string? SepsisBundleStatus);
@@ -0,0 +1,7 @@
public record LocalIngestResult(bool IsDuplicate, LocalObservation Observation, LocalClinicalAlert? Alert)
{
public static LocalIngestResult Created(LocalObservation o, LocalClinicalAlert? a) =>
new(false, o, a);
public static LocalIngestResult Duplicate(LocalObservation o) =>
new(true, o, null);
}
@@ -0,0 +1,7 @@
public record IngestObservationRequest(
string ObservationCode,
decimal Value,
string Unit,
ObservationSource Source,
DateTimeOffset RecordedAt,
string? IdempotencyKey);
@@ -0,0 +1,25 @@
using System.Text;
using System.Text.Json;
public record ObservationCursor(DateTimeOffset RecordedAt, Guid Id)
{
public string Encode()
{
var json = JsonSerializer.Serialize(this);
return Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
}
public static ObservationCursor? Decode(string? encoded)
{
if (string.IsNullOrEmpty(encoded)) return null;
try
{
var json = Encoding.UTF8.GetString(Convert.FromBase64String(encoded));
return JsonSerializer.Deserialize<ObservationCursor>(json);
}
catch
{
return null;
}
}
}
@@ -0,0 +1,6 @@
public record ThresholdCacheEntry(
string ObservationCode,
decimal? CriticalLow,
decimal? WarningLow,
decimal? WarningHigh,
decimal? CriticalHigh);