feat: 增加分页排序与FluentValidation
This commit is contained in:
@@ -138,4 +138,9 @@ public sealed class OrderDto
|
||||
/// 退款申请。
|
||||
/// </summary>
|
||||
public IReadOnlyList<RefundRequestDto> Refunds { get; init; } = Array.Empty<RefundRequestDto>();
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间。
|
||||
/// </summary>
|
||||
public DateTime CreatedAt { get; init; }
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ public sealed class CreateOrderCommandHandler(
|
||||
RequestedAt = x.RequestedAt,
|
||||
ProcessedAt = x.ProcessedAt,
|
||||
ReviewNotes = x.ReviewNotes
|
||||
}).ToList()
|
||||
}).ToList(),
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ public sealed class GetOrderByIdQueryHandler(
|
||||
RequestedAt = x.RequestedAt,
|
||||
ProcessedAt = x.ProcessedAt,
|
||||
ReviewNotes = x.ReviewNotes
|
||||
}).ToList()
|
||||
}).ToList(),
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,7 +36,13 @@ public sealed class SearchOrdersQueryHandler(
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return orders.Select(order => new OrderDto
|
||||
var sorted = ApplySorting(orders, request.SortBy, request.SortDescending);
|
||||
var paged = sorted
|
||||
.Skip((request.Page - 1) * request.PageSize)
|
||||
.Take(request.PageSize)
|
||||
.ToList();
|
||||
|
||||
return paged.Select(order => new OrderDto
|
||||
{
|
||||
Id = order.Id,
|
||||
TenantId = order.TenantId,
|
||||
@@ -59,7 +65,22 @@ public sealed class SearchOrdersQueryHandler(
|
||||
FinishedAt = order.FinishedAt,
|
||||
CancelledAt = order.CancelledAt,
|
||||
CancelReason = order.CancelReason,
|
||||
Remark = order.Remark
|
||||
Remark = order.Remark,
|
||||
CreatedAt = order.CreatedAt
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private static IOrderedEnumerable<Domain.Orders.Entities.Order> ApplySorting(
|
||||
IReadOnlyCollection<Domain.Orders.Entities.Order> orders,
|
||||
string? sortBy,
|
||||
bool sortDescending)
|
||||
{
|
||||
return sortBy?.ToLowerInvariant() switch
|
||||
{
|
||||
"paidat" => sortDescending ? orders.OrderByDescending(x => x.PaidAt) : orders.OrderBy(x => x.PaidAt),
|
||||
"status" => sortDescending ? orders.OrderByDescending(x => x.Status) : orders.OrderBy(x => x.Status),
|
||||
"payableamount" => sortDescending ? orders.OrderByDescending(x => x.PayableAmount) : orders.OrderBy(x => x.PayableAmount),
|
||||
_ => sortDescending ? orders.OrderByDescending(x => x.CreatedAt) : orders.OrderBy(x => x.CreatedAt)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ public sealed class UpdateOrderCommandHandler(
|
||||
RequestedAt = x.RequestedAt,
|
||||
ProcessedAt = x.ProcessedAt,
|
||||
ReviewNotes = x.ReviewNotes
|
||||
}).ToList()
|
||||
}).ToList(),
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,4 +29,24 @@ public sealed class SearchOrdersQuery : IRequest<IReadOnlyList<OrderDto>>
|
||||
/// 订单号(模糊或精确,由调用方控制)。
|
||||
/// </summary>
|
||||
public string? OrderNo { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 页码。
|
||||
/// </summary>
|
||||
public int Page { get; init; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 每页条数。
|
||||
/// </summary>
|
||||
public int PageSize { get; init; } = 20;
|
||||
|
||||
/// <summary>
|
||||
/// 排序字段(createdAt/paidAt/status/payableAmount)。
|
||||
/// </summary>
|
||||
public string? SortBy { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否倒序。
|
||||
/// </summary>
|
||||
public bool SortDescending { get; init; } = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 创建订单命令验证器。
|
||||
/// </summary>
|
||||
public sealed class CreateOrderCommandValidator : AbstractValidator<CreateOrderCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public CreateOrderCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.OrderNo).NotEmpty().MaximumLength(32);
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.CustomerPhone).MaximumLength(32);
|
||||
RuleFor(x => x.CustomerName).MaximumLength(64);
|
||||
RuleFor(x => x.TableNo).MaximumLength(32);
|
||||
RuleFor(x => x.QueueNumber).MaximumLength(32);
|
||||
RuleFor(x => x.CancelReason).MaximumLength(256);
|
||||
RuleFor(x => x.Remark).MaximumLength(512);
|
||||
RuleFor(x => x.ItemsAmount).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.DiscountAmount).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.PayableAmount).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0);
|
||||
|
||||
RuleFor(x => x.Items)
|
||||
.NotEmpty()
|
||||
.WithMessage("订单明细不能为空");
|
||||
|
||||
RuleForEach(x => x.Items).ChildRules(item =>
|
||||
{
|
||||
item.RuleFor(i => i.ProductId).GreaterThan(0);
|
||||
item.RuleFor(i => i.ProductName).NotEmpty().MaximumLength(128);
|
||||
item.RuleFor(i => i.SkuName).MaximumLength(128);
|
||||
item.RuleFor(i => i.Unit).MaximumLength(16);
|
||||
item.RuleFor(i => i.Quantity).GreaterThan(0);
|
||||
item.RuleFor(i => i.UnitPrice).GreaterThanOrEqualTo(0);
|
||||
item.RuleFor(i => i.DiscountAmount).GreaterThanOrEqualTo(0);
|
||||
item.RuleFor(i => i.SubTotal).GreaterThanOrEqualTo(0);
|
||||
item.RuleFor(i => i.AttributesJson).MaximumLength(4000);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Orders.Queries;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 订单列表查询验证器。
|
||||
/// </summary>
|
||||
public sealed class SearchOrdersQueryValidator : AbstractValidator<SearchOrdersQuery>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public SearchOrdersQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.Page).GreaterThan(0);
|
||||
RuleFor(x => x.PageSize).InclusiveBetween(1, 200);
|
||||
RuleFor(x => x.SortBy).MaximumLength(64);
|
||||
RuleFor(x => x.OrderNo).MaximumLength(32);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 更新订单命令验证器。
|
||||
/// </summary>
|
||||
public sealed class UpdateOrderCommandValidator : AbstractValidator<UpdateOrderCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public UpdateOrderCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.OrderId).GreaterThan(0);
|
||||
RuleFor(x => x.OrderNo).NotEmpty().MaximumLength(32);
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.CustomerPhone).MaximumLength(32);
|
||||
RuleFor(x => x.CustomerName).MaximumLength(64);
|
||||
RuleFor(x => x.TableNo).MaximumLength(32);
|
||||
RuleFor(x => x.QueueNumber).MaximumLength(32);
|
||||
RuleFor(x => x.CancelReason).MaximumLength(256);
|
||||
RuleFor(x => x.Remark).MaximumLength(512);
|
||||
RuleFor(x => x.ItemsAmount).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.DiscountAmount).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.PayableAmount).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.PaidAmount).GreaterThanOrEqualTo(0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user