Files
TakeoutSaaS.TenantApi/src/Application/TakeoutSaaS.Application/App/Orders/Handlers/GetOrderAllStatsQueryHandler.cs
MSuMshk 11a1521b6a
All checks were successful
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Successful in 1m51s
feat(order): add all-orders APIs and query workflow
2026-02-27 10:09:19 +08:00

82 lines
2.6 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.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.App.Orders.Handlers;
/// <summary>
/// 全部订单统计查询处理器。
/// </summary>
public sealed class GetOrderAllStatsQueryHandler(
IOrderRepository orderRepository,
ITenantProvider tenantProvider)
: IRequestHandler<GetOrderAllStatsQuery, OrderAllStatsDto>
{
/// <inheritdoc />
public async Task<OrderAllStatsDto> 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<HashSet<long>> LoadRefundedOrderIdsAsync(
IReadOnlyCollection<Order> 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;
}
}