All checks were successful
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Successful in 1m50s
114 lines
3.9 KiB
C#
114 lines
3.9 KiB
C#
using MediatR;
|
|
using TakeoutSaaS.Application.App.Orders.Dto;
|
|
using TakeoutSaaS.Application.App.Orders.Queries;
|
|
using TakeoutSaaS.Domain.Orders.Entities;
|
|
using TakeoutSaaS.Domain.Orders.Enums;
|
|
using TakeoutSaaS.Domain.Orders.Repositories;
|
|
using TakeoutSaaS.Shared.Abstractions.Results;
|
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
|
|
|
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
|
|
|
/// <summary>
|
|
/// 全部订单列表查询处理器。
|
|
/// </summary>
|
|
public sealed class SearchOrderAllListQueryHandler(
|
|
IOrderRepository orderRepository,
|
|
ITenantProvider tenantProvider)
|
|
: IRequestHandler<SearchOrderAllListQuery, PagedResult<OrderAllListItemDto>>
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task<PagedResult<OrderAllListItemDto>> Handle(SearchOrderAllListQuery request, CancellationToken cancellationToken)
|
|
{
|
|
var tenantId = tenantProvider.GetCurrentTenantId();
|
|
var page = Math.Max(1, request.Page);
|
|
var pageSize = Math.Clamp(request.PageSize, 1, 200);
|
|
|
|
var (pagedOrders, totalCount) = await orderRepository.SearchAllOrdersPageAsync(
|
|
tenantId,
|
|
request.StoreId,
|
|
request.StartAt,
|
|
request.EndAt,
|
|
request.Status,
|
|
request.RefundedOnly,
|
|
request.DeliveryType,
|
|
request.PaymentMethod,
|
|
request.Keyword,
|
|
request.SortBy,
|
|
request.SortDescending,
|
|
page,
|
|
pageSize,
|
|
cancellationToken);
|
|
|
|
var refundedSet = await LoadRefundedOrderIdsAsync(
|
|
pagedOrders.Select(order => order.Id).ToList(),
|
|
tenantId,
|
|
cancellationToken);
|
|
|
|
var itemsLookup = await orderRepository.GetItemsByOrderIdsAsync(
|
|
pagedOrders.Select(order => order.Id).ToList(),
|
|
tenantId,
|
|
cancellationToken);
|
|
|
|
var rows = pagedOrders
|
|
.Select(order =>
|
|
{
|
|
var isRefunded = refundedSet.Contains(order.Id);
|
|
return new OrderAllListItemDto
|
|
{
|
|
OrderId = order.Id,
|
|
OrderNo = order.OrderNo,
|
|
OrderedAt = order.CreatedAt,
|
|
DeliveryType = order.DeliveryType,
|
|
Status = order.Status,
|
|
CustomerName = string.IsNullOrWhiteSpace(order.CustomerName) ? "--" : order.CustomerName,
|
|
ItemsSummary = BuildItemSummary(order.Id, itemsLookup),
|
|
Amount = ResolveDisplayAmount(order),
|
|
IsRefunded = isRefunded,
|
|
IsDimmed = order.Status == OrderStatus.Cancelled || isRefunded
|
|
};
|
|
})
|
|
.ToList();
|
|
|
|
return new PagedResult<OrderAllListItemDto>(rows, page, pageSize, totalCount);
|
|
}
|
|
|
|
private async Task<HashSet<long>> LoadRefundedOrderIdsAsync(
|
|
IReadOnlyCollection<long> orderIds,
|
|
long tenantId,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
if (orderIds.Count == 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
var refunded = await orderRepository.GetRefundedOrderIdsAsync(orderIds, tenantId, cancellationToken);
|
|
return refunded.ToHashSet();
|
|
}
|
|
|
|
private static decimal ResolveDisplayAmount(Order order)
|
|
{
|
|
return order.PaidAmount > 0 ? order.PaidAmount : order.PayableAmount;
|
|
}
|
|
|
|
private static string BuildItemSummary(
|
|
long orderId,
|
|
IReadOnlyDictionary<long, IReadOnlyList<OrderItem>> itemsLookup)
|
|
{
|
|
if (!itemsLookup.TryGetValue(orderId, out var items) || items.Count == 0)
|
|
{
|
|
return "--";
|
|
}
|
|
|
|
var first = string.IsNullOrWhiteSpace(items[0].ProductName) ? "商品" : items[0].ProductName.Trim();
|
|
var totalQuantity = items.Sum(item => Math.Max(0, item.Quantity));
|
|
if (totalQuantity <= 0)
|
|
{
|
|
totalQuantity = items.Count;
|
|
}
|
|
|
|
return $"{first}等{totalQuantity}件";
|
|
}
|
|
}
|