feature: Warning Alert Consumer, Orders API & Input Validation

This commit is contained in:
voltsrage
2026-06-18 15:57:55 +08:00
parent c0cd75856c
commit 7d9e53fb8d
30 changed files with 2334 additions and 29 deletions
@@ -0,0 +1,9 @@
using FluentValidation;
public class AcknowledgeAlertRequestValidator : AbstractValidator<AcknowledgeAlertRequest>
{
public AcknowledgeAlertRequestValidator()
{
RuleFor(x => x.ClinicianId).NotEmpty().MaximumLength(200);
}
}
@@ -0,0 +1,22 @@
using FluentValidation;
public class AlertThresholdRequestValidator : AbstractValidator<AlertThresholdRequest>
{
public AlertThresholdRequestValidator()
{
RuleFor(x => x.ObservationCode).NotEmpty().MaximumLength(50);
RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(200);
RuleFor(x => x.Unit).NotEmpty().MaximumLength(20);
// Threshold ordering: CriticalLow < WarningLow < WarningHigh < CriticalHigh
RuleFor(x => x)
.Must(x => !x.CriticalLow.HasValue || !x.WarningLow.HasValue || x.CriticalLow < x.WarningLow)
.WithMessage("CriticalLow must be less than WarningLow.");
RuleFor(x => x)
.Must(x => !x.WarningLow.HasValue || !x.WarningHigh.HasValue || x.WarningLow < x.WarningHigh)
.WithMessage("WarningLow must be less than WarningHigh.");
RuleFor(x => x)
.Must(x => !x.WarningHigh.HasValue || !x.CriticalHigh.HasValue || x.WarningHigh < x.CriticalHigh)
.WithMessage("WarningHigh must be less than CriticalHigh.");
}
}
@@ -0,0 +1,10 @@
using FluentValidation;
public class CreateOrderRequestValidator : AbstractValidator<CreateOrderRequest>
{
public CreateOrderRequestValidator()
{
RuleFor(x => x.Description).NotEmpty();
RuleFor(x => x.OrderedBy).NotEmpty().MaximumLength(200);
}
}
@@ -0,0 +1,13 @@
using FluentValidation;
public class IngestObservationRequestValidator : AbstractValidator<IngestObservationRequest>
{
public IngestObservationRequestValidator()
{
RuleFor(x => x.ObservationCode).NotEmpty().MaximumLength(50);
RuleFor(x => x.Unit).NotEmpty().MaximumLength(20);
RuleFor(x => x.RecordedAt)
.LessThanOrEqualTo(DateTimeOffset.UtcNow.AddMinutes(5))
.WithMessage("RecordedAt cannot be more than 5 minutes in the future.");
}
}
@@ -0,0 +1,15 @@
using FluentValidation;
public class OpenEncounterRequestValidator : AbstractValidator<OpenEncounterRequest>
{
public OpenEncounterRequestValidator()
{
RuleFor(x => x.EncounterType).IsInEnum();
RuleFor(x => x.Department).IsInEnum();
RuleFor(x => x.AttendingPhysician).NotEmpty().MaximumLength(200);
RuleFor(x => x.RoomBed).MaximumLength(20)
.When(x => x.RoomBed is not null);
RuleFor(x => x.AdmissionReason).MaximumLength(500)
.When(x => x.AdmissionReason is not null);
}
}
@@ -0,0 +1,20 @@
using FluentValidation;
public class RegisterPatientRequestValidator : AbstractValidator<RegisterPatientRequest>
{
public RegisterPatientRequestValidator()
{
RuleFor(x => x.FirstName).NotEmpty().MaximumLength(100);
RuleFor(x => x.LastName).NotEmpty().MaximumLength(100);
RuleFor(x => x.Gender).NotEmpty().MaximumLength(10);
RuleFor(x => x.DateOfBirth).NotEmpty()
.LessThanOrEqualTo(DateOnly.FromDateTime(DateTime.UtcNow))
.WithMessage("Date of birth cannot be in the future.");
RuleFor(x => x.BloodType).IsInEnum()
.When(x => x.BloodType is not null);
RuleFor(x => x.EmergencyContactName).MaximumLength(200)
.When(x => x.EmergencyContactName is not null);
RuleFor(x => x.EmergencyContactPhone).MaximumLength(20)
.When(x => x.EmergencyContactPhone is not null);
}
}
@@ -0,0 +1,9 @@
using FluentValidation;
public class TransitionOrderStatusRequestValidator : AbstractValidator<TransitionOrderStatusRequest>
{
public TransitionOrderStatusRequestValidator()
{
RuleFor(x => x.Status).IsInEnum();
}
}