diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs index 729d166..60f3d0c 100644 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs +++ b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/CreateOrderCommandValidator.cs @@ -1,5 +1,7 @@ using FluentValidation; using TakeoutSaaS.Application.App.Orders.Commands; +using TakeoutSaaS.Domain.Orders.Enums; +using TakeoutSaaS.Domain.Payments.Enums; namespace TakeoutSaaS.Application.App.Orders.Validators; @@ -25,6 +27,37 @@ public sealed class CreateOrderCommandValidator : AbstractValidator x.DiscountAmount).GreaterThanOrEqualTo(0); RuleFor(x => x.PayableAmount).GreaterThanOrEqualTo(0); RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0); + RuleFor(x => x.PayableAmount) + .Must((cmd, payable) => payable == cmd.ItemsAmount - cmd.DiscountAmount) + .WithMessage("应付金额必须等于商品金额减去优惠金额"); + RuleFor(x => x.PaidAmount) + .LessThanOrEqualTo(x => x.PayableAmount) + .WithMessage("实付金额不得超过应付金额"); + + RuleFor(x => x.PaymentStatus) + .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) + .WithMessage("支付状态不合法"); + When(x => x.PaymentStatus == PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); + RuleFor(x => x.PaidAmount).GreaterThan(0).WithMessage("支付成功时实付金额必须大于 0"); + }); + When(x => x.PaymentStatus != PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); + }); + When(x => x.PaymentStatus == PaymentStatus.Refunded, () => + { + RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0).WithMessage("退款状态下实付金额需合法"); + }); + When(x => x.Status == OrderStatus.Cancelled, () => + { + RuleFor(x => x.CancelReason).NotEmpty().WithMessage("取消订单必须提供取消原因"); + }); + When(x => x.Status != OrderStatus.Cancelled, () => + { + RuleFor(x => x.CancelReason).Must(reason => string.IsNullOrWhiteSpace(reason)).WithMessage("非取消状态不应包含取消原因"); + }); RuleFor(x => x.Items) .NotEmpty() diff --git a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs index 2dba2f7..745f033 100644 --- a/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs +++ b/src/Application/TakeoutSaaS.Application/App/Orders/Validators/UpdateOrderCommandValidator.cs @@ -1,5 +1,7 @@ using FluentValidation; using TakeoutSaaS.Application.App.Orders.Commands; +using TakeoutSaaS.Domain.Orders.Enums; +using TakeoutSaaS.Domain.Payments.Enums; namespace TakeoutSaaS.Application.App.Orders.Validators; @@ -26,5 +28,36 @@ public sealed class UpdateOrderCommandValidator : AbstractValidator x.DiscountAmount).GreaterThanOrEqualTo(0); RuleFor(x => x.PayableAmount).GreaterThanOrEqualTo(0); RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0); + RuleFor(x => x.PayableAmount) + .Must((cmd, payable) => payable == cmd.ItemsAmount - cmd.DiscountAmount) + .WithMessage("应付金额必须等于商品金额减去优惠金额"); + RuleFor(x => x.PaidAmount) + .LessThanOrEqualTo(x => x.PayableAmount) + .WithMessage("实付金额不得超过应付金额"); + + RuleFor(x => x.PaymentStatus) + .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) + .WithMessage("支付状态不合法"); + When(x => x.PaymentStatus == PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); + RuleFor(x => x.PaidAmount).GreaterThan(0).WithMessage("支付成功时实付金额必须大于 0"); + }); + When(x => x.PaymentStatus != PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); + }); + When(x => x.PaymentStatus == PaymentStatus.Refunded, () => + { + RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0).WithMessage("退款状态下实付金额需合法"); + }); + When(x => x.Status == OrderStatus.Cancelled, () => + { + RuleFor(x => x.CancelReason).NotEmpty().WithMessage("取消订单必须提供取消原因"); + }); + When(x => x.Status != OrderStatus.Cancelled, () => + { + RuleFor(x => x.CancelReason).Must(reason => string.IsNullOrWhiteSpace(reason)).WithMessage("非取消状态不应包含取消原因"); + }); } } diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs index f7e7abb..5041e1d 100644 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs +++ b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/CreatePaymentCommandValidator.cs @@ -1,5 +1,6 @@ using FluentValidation; using TakeoutSaaS.Application.App.Payments.Commands; +using TakeoutSaaS.Domain.Payments.Enums; namespace TakeoutSaaS.Application.App.Payments.Validators; @@ -15,8 +16,30 @@ public sealed class CreatePaymentCommandValidator : AbstractValidator x.OrderId).GreaterThan(0); RuleFor(x => x.Amount).GreaterThan(0); + RuleFor(x => x.Method) + .Must(method => method != PaymentMethod.Unknown) + .WithMessage("支付方式不可为空"); RuleFor(x => x.TradeNo).MaximumLength(64); RuleFor(x => x.ChannelTransactionId).MaximumLength(64); RuleFor(x => x.Remark).MaximumLength(256); + + RuleFor(x => x.Status) + .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) + .WithMessage("支付状态不合法"); + When(x => x.Status == PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); + }); + When(x => x.Status != PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); + }); + + When(x => x.Method is PaymentMethod.Cash or PaymentMethod.Card or PaymentMethod.Balance, () => + { + RuleFor(x => x.Status) + .Must(status => status is not PaymentStatus.Paying) + .WithMessage("线下/余额支付不允许处于 Paying 状态"); + }); } } diff --git a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs index 997e07b..65dfd1c 100644 --- a/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs +++ b/src/Application/TakeoutSaaS.Application/App/Payments/Validators/UpdatePaymentCommandValidator.cs @@ -1,5 +1,6 @@ using FluentValidation; using TakeoutSaaS.Application.App.Payments.Commands; +using TakeoutSaaS.Domain.Payments.Enums; namespace TakeoutSaaS.Application.App.Payments.Validators; @@ -16,8 +17,30 @@ public sealed class UpdatePaymentCommandValidator : AbstractValidator x.PaymentId).GreaterThan(0); RuleFor(x => x.OrderId).GreaterThan(0); RuleFor(x => x.Amount).GreaterThan(0); + RuleFor(x => x.Method) + .Must(method => method != PaymentMethod.Unknown) + .WithMessage("支付方式不可为空"); RuleFor(x => x.TradeNo).MaximumLength(64); RuleFor(x => x.ChannelTransactionId).MaximumLength(64); RuleFor(x => x.Remark).MaximumLength(256); + + RuleFor(x => x.Status) + .Must(status => status is PaymentStatus.Unpaid or PaymentStatus.Paying or PaymentStatus.Paid or PaymentStatus.Failed or PaymentStatus.Refunded) + .WithMessage("支付状态不合法"); + When(x => x.Status == PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).NotNull().WithMessage("支付成功必须包含支付时间"); + }); + When(x => x.Status != PaymentStatus.Paid, () => + { + RuleFor(x => x.PaidAt).Must(paidAt => paidAt == null).WithMessage("非支付成功状态不应包含支付时间"); + }); + + When(x => x.Method is PaymentMethod.Cash or PaymentMethod.Card or PaymentMethod.Balance, () => + { + RuleFor(x => x.Status) + .Must(status => status is not PaymentStatus.Paying) + .WithMessage("线下/余额支付不允许处于 Paying 状态"); + }); } }