feat: 添加订单事件管道与状态流转命令
Some checks failed
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Failing after 12s
Some checks failed
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Failing after 12s
- 新增 OrderStatusChangedEvent、OrderUrgeEvent 事件类型 - 扩展 EventRoutingKeys(orders.status-changed、orders.urged) - 丰富 OrderCreatedEvent(StoreId、Channel、DeliveryType 等字段) - CreateOrderCommandHandler 注入 IEventPublisher 并发布事件 - 新增接单/拒单/出餐完成/确认送达 Command + Handler(4对) - 新增 MassTransit Consumer(OrderCreated/StatusChanged/Urge → SignalR) - Program.cs 注册 3 个 Consumer
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 接单命令。
|
||||
/// </summary>
|
||||
public sealed record AcceptOrderCommand : IRequest<OrderBoardCardDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单标识。
|
||||
/// </summary>
|
||||
public required long OrderId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户标识。
|
||||
/// </summary>
|
||||
public required long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人标识。
|
||||
/// </summary>
|
||||
public long? OperatorId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 出餐完成命令。
|
||||
/// </summary>
|
||||
public sealed record CompletePreparationCommand : IRequest<OrderBoardCardDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单标识。
|
||||
/// </summary>
|
||||
public required long OrderId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户标识。
|
||||
/// </summary>
|
||||
public required long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人标识。
|
||||
/// </summary>
|
||||
public long? OperatorId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 确认送达/取餐命令。
|
||||
/// </summary>
|
||||
public sealed record ConfirmDeliveryCommand : IRequest<OrderBoardCardDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单标识。
|
||||
/// </summary>
|
||||
public required long OrderId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户标识。
|
||||
/// </summary>
|
||||
public required long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人标识。
|
||||
/// </summary>
|
||||
public long? OperatorId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// 拒单命令。
|
||||
/// </summary>
|
||||
public sealed record RejectOrderCommand : IRequest<OrderBoardCardDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单标识。
|
||||
/// </summary>
|
||||
public required long OrderId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户标识。
|
||||
/// </summary>
|
||||
public required long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拒单原因。
|
||||
/// </summary>
|
||||
public required string Reason { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人标识。
|
||||
/// </summary>
|
||||
public long? OperatorId { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
using TakeoutSaaS.Application.Messaging;
|
||||
using TakeoutSaaS.Application.Messaging.Abstractions;
|
||||
using TakeoutSaaS.Application.Messaging.Events;
|
||||
using TakeoutSaaS.Domain.Orders.Entities;
|
||||
using TakeoutSaaS.Domain.Orders.Enums;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 接单命令处理器。
|
||||
/// </summary>
|
||||
public sealed class AcceptOrderCommandHandler(
|
||||
IOrderRepository orderRepository,
|
||||
IEventPublisher eventPublisher,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<AcceptOrderCommandHandler> logger)
|
||||
: IRequestHandler<AcceptOrderCommand, OrderBoardCardDto>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<OrderBoardCardDto> Handle(AcceptOrderCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查找订单
|
||||
var order = await orderRepository.FindByIdAsync(request.OrderId, request.TenantId, cancellationToken)
|
||||
?? throw new BusinessException(ErrorCodes.NotFound, "订单不存在");
|
||||
|
||||
// 2. 校验状态
|
||||
if (order.Status != OrderStatus.AwaitingPreparation)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, $"当前状态 {order.Status} 不允许接单");
|
||||
}
|
||||
|
||||
// 3. 更新状态
|
||||
var oldStatus = order.Status;
|
||||
order.Status = OrderStatus.InProgress;
|
||||
|
||||
// 4. 写入状态流转记录
|
||||
var history = new OrderStatusHistory
|
||||
{
|
||||
Id = idGenerator.NextId(),
|
||||
OrderId = order.Id,
|
||||
TenantId = order.TenantId,
|
||||
Status = OrderStatus.InProgress,
|
||||
OperatorId = request.OperatorId,
|
||||
Notes = "商户接单",
|
||||
OccurredAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await orderRepository.UpdateOrderAsync(order, cancellationToken);
|
||||
await orderRepository.AddStatusHistoryAsync(history, cancellationToken);
|
||||
await orderRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 5. 发布状态变更事件
|
||||
await eventPublisher.PublishAsync(EventRoutingKeys.OrderStatusChanged, new OrderStatusChangedEvent
|
||||
{
|
||||
OrderId = order.Id,
|
||||
OrderNo = order.OrderNo,
|
||||
TenantId = order.TenantId,
|
||||
StoreId = order.StoreId,
|
||||
OldStatus = (int)oldStatus,
|
||||
NewStatus = (int)order.Status,
|
||||
Channel = (int)order.Channel,
|
||||
DeliveryType = (int)order.DeliveryType,
|
||||
CustomerName = order.CustomerName,
|
||||
PaidAmount = order.PaidAmount,
|
||||
OccurredAt = history.OccurredAt
|
||||
}, cancellationToken);
|
||||
|
||||
// 6. 记录日志
|
||||
logger.LogInformation("接单 {OrderNo} ({OrderId})", order.OrderNo, order.Id);
|
||||
|
||||
// 7. 返回看板卡片 DTO
|
||||
return MapToCardDto(order);
|
||||
}
|
||||
|
||||
private static OrderBoardCardDto MapToCardDto(Order order) => new()
|
||||
{
|
||||
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,
|
||||
PaidAmount = order.PaidAmount,
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
using TakeoutSaaS.Application.Messaging;
|
||||
using TakeoutSaaS.Application.Messaging.Abstractions;
|
||||
using TakeoutSaaS.Application.Messaging.Events;
|
||||
using TakeoutSaaS.Domain.Orders.Entities;
|
||||
using TakeoutSaaS.Domain.Orders.Enums;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 出餐完成命令处理器。
|
||||
/// </summary>
|
||||
public sealed class CompletePreparationCommandHandler(
|
||||
IOrderRepository orderRepository,
|
||||
IEventPublisher eventPublisher,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<CompletePreparationCommandHandler> logger)
|
||||
: IRequestHandler<CompletePreparationCommand, OrderBoardCardDto>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<OrderBoardCardDto> Handle(CompletePreparationCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查找订单
|
||||
var order = await orderRepository.FindByIdAsync(request.OrderId, request.TenantId, cancellationToken)
|
||||
?? throw new BusinessException(ErrorCodes.NotFound, "订单不存在");
|
||||
|
||||
// 2. 校验状态
|
||||
if (order.Status != OrderStatus.InProgress)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, $"当前状态 {order.Status} 不允许标记出餐完成");
|
||||
}
|
||||
|
||||
// 3. 更新状态
|
||||
var oldStatus = order.Status;
|
||||
order.Status = OrderStatus.Ready;
|
||||
|
||||
// 4. 写入状态流转记录
|
||||
var history = new OrderStatusHistory
|
||||
{
|
||||
Id = idGenerator.NextId(),
|
||||
OrderId = order.Id,
|
||||
TenantId = order.TenantId,
|
||||
Status = OrderStatus.Ready,
|
||||
OperatorId = request.OperatorId,
|
||||
Notes = "出餐完成",
|
||||
OccurredAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await orderRepository.UpdateOrderAsync(order, cancellationToken);
|
||||
await orderRepository.AddStatusHistoryAsync(history, cancellationToken);
|
||||
await orderRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 5. 发布状态变更事件
|
||||
await eventPublisher.PublishAsync(EventRoutingKeys.OrderStatusChanged, new OrderStatusChangedEvent
|
||||
{
|
||||
OrderId = order.Id,
|
||||
OrderNo = order.OrderNo,
|
||||
TenantId = order.TenantId,
|
||||
StoreId = order.StoreId,
|
||||
OldStatus = (int)oldStatus,
|
||||
NewStatus = (int)order.Status,
|
||||
Channel = (int)order.Channel,
|
||||
DeliveryType = (int)order.DeliveryType,
|
||||
CustomerName = order.CustomerName,
|
||||
PaidAmount = order.PaidAmount,
|
||||
OccurredAt = history.OccurredAt
|
||||
}, cancellationToken);
|
||||
|
||||
// 6. 记录日志
|
||||
logger.LogInformation("出餐完成 {OrderNo} ({OrderId})", order.OrderNo, order.Id);
|
||||
|
||||
// 7. 返回看板卡片 DTO
|
||||
return MapToCardDto(order);
|
||||
}
|
||||
|
||||
private static OrderBoardCardDto MapToCardDto(Order order) => new()
|
||||
{
|
||||
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,
|
||||
PaidAmount = order.PaidAmount,
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
using TakeoutSaaS.Application.Messaging;
|
||||
using TakeoutSaaS.Application.Messaging.Abstractions;
|
||||
using TakeoutSaaS.Application.Messaging.Events;
|
||||
using TakeoutSaaS.Domain.Orders.Entities;
|
||||
using TakeoutSaaS.Domain.Orders.Enums;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 确认送达/取餐命令处理器。
|
||||
/// </summary>
|
||||
public sealed class ConfirmDeliveryCommandHandler(
|
||||
IOrderRepository orderRepository,
|
||||
IEventPublisher eventPublisher,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<ConfirmDeliveryCommandHandler> logger)
|
||||
: IRequestHandler<ConfirmDeliveryCommand, OrderBoardCardDto>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<OrderBoardCardDto> Handle(ConfirmDeliveryCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查找订单
|
||||
var order = await orderRepository.FindByIdAsync(request.OrderId, request.TenantId, cancellationToken)
|
||||
?? throw new BusinessException(ErrorCodes.NotFound, "订单不存在");
|
||||
|
||||
// 2. 校验状态
|
||||
if (order.Status != OrderStatus.Ready)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, $"当前状态 {order.Status} 不允许确认送达");
|
||||
}
|
||||
|
||||
// 3. 更新状态
|
||||
var oldStatus = order.Status;
|
||||
order.Status = OrderStatus.Completed;
|
||||
order.FinishedAt = DateTime.UtcNow;
|
||||
|
||||
// 4. 写入状态流转记录
|
||||
var history = new OrderStatusHistory
|
||||
{
|
||||
Id = idGenerator.NextId(),
|
||||
OrderId = order.Id,
|
||||
TenantId = order.TenantId,
|
||||
Status = OrderStatus.Completed,
|
||||
OperatorId = request.OperatorId,
|
||||
Notes = "确认送达/取餐",
|
||||
OccurredAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await orderRepository.UpdateOrderAsync(order, cancellationToken);
|
||||
await orderRepository.AddStatusHistoryAsync(history, cancellationToken);
|
||||
await orderRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 5. 发布状态变更事件
|
||||
await eventPublisher.PublishAsync(EventRoutingKeys.OrderStatusChanged, new OrderStatusChangedEvent
|
||||
{
|
||||
OrderId = order.Id,
|
||||
OrderNo = order.OrderNo,
|
||||
TenantId = order.TenantId,
|
||||
StoreId = order.StoreId,
|
||||
OldStatus = (int)oldStatus,
|
||||
NewStatus = (int)order.Status,
|
||||
Channel = (int)order.Channel,
|
||||
DeliveryType = (int)order.DeliveryType,
|
||||
CustomerName = order.CustomerName,
|
||||
PaidAmount = order.PaidAmount,
|
||||
OccurredAt = history.OccurredAt
|
||||
}, cancellationToken);
|
||||
|
||||
// 6. 记录日志
|
||||
logger.LogInformation("确认送达 {OrderNo} ({OrderId})", order.OrderNo, order.Id);
|
||||
|
||||
// 7. 返回看板卡片 DTO
|
||||
return MapToCardDto(order);
|
||||
}
|
||||
|
||||
private static OrderBoardCardDto MapToCardDto(Order order) => new()
|
||||
{
|
||||
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,
|
||||
PaidAmount = order.PaidAmount,
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
@@ -2,6 +2,9 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
using TakeoutSaaS.Application.Messaging;
|
||||
using TakeoutSaaS.Application.Messaging.Abstractions;
|
||||
using TakeoutSaaS.Application.Messaging.Events;
|
||||
using TakeoutSaaS.Domain.Orders.Entities;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
@@ -14,6 +17,7 @@ namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||
public sealed class CreateOrderCommandHandler(
|
||||
IOrderRepository orderRepository,
|
||||
IIdGenerator idGenerator,
|
||||
IEventPublisher eventPublisher,
|
||||
ILogger<CreateOrderCommandHandler> logger)
|
||||
: IRequestHandler<CreateOrderCommand, OrderDto>
|
||||
{
|
||||
@@ -81,10 +85,31 @@ public sealed class CreateOrderCommandHandler(
|
||||
|
||||
await orderRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 5. 记录日志
|
||||
// 5. 发布订单创建事件
|
||||
var itemsSummary = items.Count > 0
|
||||
? string.Join("、", items.Take(3).Select(x => x.ProductName))
|
||||
+ (items.Count > 3 ? $" 等{items.Count}件" : string.Empty)
|
||||
: string.Empty;
|
||||
|
||||
await eventPublisher.PublishAsync(EventRoutingKeys.OrderCreated, new OrderCreatedEvent
|
||||
{
|
||||
OrderId = order.Id,
|
||||
OrderNo = order.OrderNo,
|
||||
Amount = order.PaidAmount,
|
||||
TenantId = order.TenantId,
|
||||
StoreId = order.StoreId,
|
||||
Channel = (int)order.Channel,
|
||||
DeliveryType = (int)order.DeliveryType,
|
||||
CustomerName = order.CustomerName,
|
||||
ItemsSummary = itemsSummary,
|
||||
TableNo = order.TableNo,
|
||||
CreatedAt = order.CreatedAt
|
||||
}, cancellationToken);
|
||||
|
||||
// 6. 记录日志
|
||||
logger.LogInformation("创建订单 {OrderNo} ({OrderId})", order.OrderNo, order.Id);
|
||||
|
||||
// 6. 返回 DTO
|
||||
// 7. 返回 DTO
|
||||
return MapToDto(order, items, [], []);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Orders.Commands;
|
||||
using TakeoutSaaS.Application.App.Orders.Dto;
|
||||
using TakeoutSaaS.Application.Messaging;
|
||||
using TakeoutSaaS.Application.Messaging.Abstractions;
|
||||
using TakeoutSaaS.Application.Messaging.Events;
|
||||
using TakeoutSaaS.Domain.Orders.Entities;
|
||||
using TakeoutSaaS.Domain.Orders.Enums;
|
||||
using TakeoutSaaS.Domain.Orders.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Orders.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 拒单命令处理器。
|
||||
/// </summary>
|
||||
public sealed class RejectOrderCommandHandler(
|
||||
IOrderRepository orderRepository,
|
||||
IEventPublisher eventPublisher,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<RejectOrderCommandHandler> logger)
|
||||
: IRequestHandler<RejectOrderCommand, OrderBoardCardDto>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<OrderBoardCardDto> Handle(RejectOrderCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查找订单
|
||||
var order = await orderRepository.FindByIdAsync(request.OrderId, request.TenantId, cancellationToken)
|
||||
?? throw new BusinessException(ErrorCodes.NotFound, "订单不存在");
|
||||
|
||||
// 2. 校验状态
|
||||
if (order.Status != OrderStatus.AwaitingPreparation)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, $"当前状态 {order.Status} 不允许拒单");
|
||||
}
|
||||
|
||||
// 3. 更新状态
|
||||
var oldStatus = order.Status;
|
||||
order.Status = OrderStatus.Cancelled;
|
||||
order.CancelledAt = DateTime.UtcNow;
|
||||
order.CancelReason = request.Reason;
|
||||
|
||||
// 4. 写入状态流转记录
|
||||
var history = new OrderStatusHistory
|
||||
{
|
||||
Id = idGenerator.NextId(),
|
||||
OrderId = order.Id,
|
||||
TenantId = order.TenantId,
|
||||
Status = OrderStatus.Cancelled,
|
||||
OperatorId = request.OperatorId,
|
||||
Notes = $"商户拒单:{request.Reason}",
|
||||
OccurredAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await orderRepository.UpdateOrderAsync(order, cancellationToken);
|
||||
await orderRepository.AddStatusHistoryAsync(history, cancellationToken);
|
||||
await orderRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 5. 发布状态变更事件
|
||||
await eventPublisher.PublishAsync(EventRoutingKeys.OrderStatusChanged, new OrderStatusChangedEvent
|
||||
{
|
||||
OrderId = order.Id,
|
||||
OrderNo = order.OrderNo,
|
||||
TenantId = order.TenantId,
|
||||
StoreId = order.StoreId,
|
||||
OldStatus = (int)oldStatus,
|
||||
NewStatus = (int)order.Status,
|
||||
Channel = (int)order.Channel,
|
||||
DeliveryType = (int)order.DeliveryType,
|
||||
CustomerName = order.CustomerName,
|
||||
PaidAmount = order.PaidAmount,
|
||||
OccurredAt = history.OccurredAt
|
||||
}, cancellationToken);
|
||||
|
||||
// 6. 记录日志
|
||||
logger.LogInformation("拒单 {OrderNo} ({OrderId}),原因:{Reason}", order.OrderNo, order.Id, request.Reason);
|
||||
|
||||
// 7. 返回看板卡片 DTO
|
||||
return MapToCardDto(order);
|
||||
}
|
||||
|
||||
private static OrderBoardCardDto MapToCardDto(Order order) => new()
|
||||
{
|
||||
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,
|
||||
PaidAmount = order.PaidAmount,
|
||||
CreatedAt = order.CreatedAt
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user