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;
namespace TakeoutSaaS.Application.App.Orders.Handlers;
///
/// 获取订单看板数据查询处理器。
///
public sealed class GetOrderBoardQueryHandler(IOrderRepository orderRepository)
: IRequestHandler
{
///
public async Task Handle(GetOrderBoardQuery request, CancellationToken cancellationToken)
{
// 1. 查询活跃订单
var activeOrders = await orderRepository.GetActiveOrdersAsync(
request.TenantId, request.StoreId, cancellationToken);
// 2. 查询今日已完成订单(限 20 条)
var todayStart = DateTime.UtcNow.Date;
var completedOrders = await orderRepository.GetOrdersChangedSinceAsync(
request.TenantId, request.StoreId, todayStart, cancellationToken);
var todayCompleted = completedOrders
.Where(o => o.Status == OrderStatus.Completed)
.OrderByDescending(o => o.FinishedAt)
.Take(20)
.ToList();
// 3. 合并并按渠道筛选
var allOrders = activeOrders.Concat(todayCompleted).ToList();
if (request.Channel.HasValue)
{
allOrders = allOrders.Where(o => o.Channel == request.Channel.Value).ToList();
}
// 4. 获取商品摘要
var orderIds = allOrders.Select(o => o.Id).ToList();
var itemsMap = orderIds.Count > 0
? await orderRepository.GetItemsByOrderIdsAsync(orderIds, request.TenantId, cancellationToken)
: new Dictionary>();
// 5. 按状态分组
var cards = allOrders.Select(o => MapToCard(o, itemsMap)).ToList();
return new OrderBoardResultDto
{
Pending = cards.Where(c => c.Status == OrderStatus.AwaitingPreparation)
.OrderBy(c => c.CreatedAt).ToList(),
Making = cards.Where(c => c.Status == OrderStatus.InProgress)
.OrderBy(c => c.AcceptedAt).ToList(),
Delivering = cards.Where(c => c.Status == OrderStatus.Ready)
.OrderBy(c => c.ReadyAt).ToList(),
Completed = cards.Where(c => c.Status == OrderStatus.Completed)
.OrderByDescending(c => c.CreatedAt).ToList()
};
}
private static OrderBoardCardDto MapToCard(
Order order,
IReadOnlyDictionary> itemsMap)
{
var items = itemsMap.TryGetValue(order.Id, out var list) ? list : [];
var summary = items.Count > 0
? string.Join("、", items.Take(3).Select(x => x.ProductName))
+ (items.Count > 3 ? $" 等{items.Count}件" : string.Empty)
: string.Empty;
return new OrderBoardCardDto
{
Id = order.Id,
OrderNo = order.OrderNo,
StoreId = order.StoreId,
Channel = order.Channel,
DeliveryType = order.DeliveryType,
Status = order.Status,
CustomerName = order.CustomerName,
CustomerPhone = order.CustomerPhone,
TableNo = order.TableNo,
QueueNumber = order.QueueNumber,
ItemsSummary = summary,
PaidAmount = order.PaidAmount,
CreatedAt = order.CreatedAt
};
}
}