using MediatR; using TakeoutSaaS.Application.App.Orders.Dto; using TakeoutSaaS.Application.App.Orders.Queries; using TakeoutSaaS.Domain.Orders.Entities; using TakeoutSaaS.Domain.Orders.Repositories; using TakeoutSaaS.Shared.Abstractions.Tenancy; namespace TakeoutSaaS.Application.App.Orders.Handlers; /// /// 全部订单统计查询处理器。 /// public sealed class GetOrderAllStatsQueryHandler( IOrderRepository orderRepository, ITenantProvider tenantProvider) : IRequestHandler { /// public async Task Handle(GetOrderAllStatsQuery request, CancellationToken cancellationToken) { var tenantId = tenantProvider.GetCurrentTenantId(); var orders = (await orderRepository.SearchAllOrdersAsync( tenantId, request.StoreId, request.StartAt, request.EndAt, request.Status, request.DeliveryType, request.PaymentMethod, request.Keyword, cancellationToken)) .ToList(); var refundedIds = await LoadRefundedOrderIdsAsync(orders, tenantId, cancellationToken); if (request.RefundedOnly) { orders = orders.Where(order => refundedIds.Contains(order.Id)).ToList(); } var totalOrders = orders.Count; if (totalOrders == 0) { return new OrderAllStatsDto(); } var totalAmount = orders.Sum(ResolveDisplayAmount); var averageAmount = decimal.Round(totalAmount / totalOrders, 2, MidpointRounding.AwayFromZero); var refundCount = request.RefundedOnly ? totalOrders : orders.Count(order => refundedIds.Contains(order.Id)); return new OrderAllStatsDto { TotalOrders = totalOrders, TotalAmount = totalAmount, AverageAmount = averageAmount, RefundCount = refundCount }; } private async Task> LoadRefundedOrderIdsAsync( IReadOnlyCollection orders, long tenantId, CancellationToken cancellationToken) { var orderIds = orders.Select(order => order.Id).ToList(); 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; } }