track/src/TrackCenter.Application/Services/ProvideServices/OrderService.cs
2025-08-04 17:46:29 +08:00

285 lines
11 KiB
C#

using DotNetCore.CAP;
using InterfaceForward.Domain.Shared.Helpers;
using TrackCenter.Application.Dtos.ProvideServices;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.TrackDetailsAggregate;
using SqlSugar;
using TrackCenter.Application.Services.Warning.Handlers;
using TrackCenter.Repository.Aggregates.OrderAggregate;
namespace TrackCenter.Application.Services.ProvideServices;
/// <summary>
/// 订单服务
/// </summary>
[ApiExplorerSettings(GroupName = "提供接口")]
[Route("/ProviderService")]
public partial class OrderService : ApplicationServiceBase
{
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
private readonly IOrderRepository _orderRepository;
private readonly IServiceProvider _serviceProvider;
public OrderService(
IOrderRepository orderRepository,
ICapPublisher capPublisher,
ITrackDetailsEsRepository trackDetailsEsRepository,
IOrderOperationRecordEsRepository orderOperationRecordEsRepository,
IServiceProvider serviceProvider
)
{
_orderRepository = orderRepository;
_orderOperationRecordEsRepository = orderOperationRecordEsRepository;
_serviceProvider = serviceProvider;
_trackDetailsEsRepository = trackDetailsEsRepository;
_capPublisher = capPublisher;
}
/// <summary>
/// 新增、更新订单(存在就更新)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("Order/Upsert")]
public async Task<IdBaseDto> UpsertAsync(UpsertOrderInput input)
{
// 校验预计到达时间是否不是同时存在或同时不存在
if ((input.EstimatedDeliveryDate.HasValue && input.DestinationTimeZone.HasValue == false) ||
(input.EstimatedDeliveryDate.HasValue == false && input.DestinationTimeZone.HasValue))
{
throw new BusinessException(message: "【预计签收时间】和【签收地时区】必须同时输入");
}
// 校验订单是否已存在,存在则更新
var order = await _orderRepository.GetFirstAsync(x =>
x.AppKey == input.AppKey && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo);
if (order != null)
{
// 订单已存在则视为更新
await UpdateOrderAsync(input, order);
var index = new OrderOperationRecordIndex
{
OrderId = order.Id,
OrderNo = input.OrderNo,
OptionType = OrderOperationType.修改订单.ToString(),
Content = input.ToJson(),
CreateUserId = CurrentUser.Id ?? Guid.Empty,
CreateUserName = CurrentUser.UserName ?? string.Empty,
};
_ = _orderOperationRecordEsRepository.AddAsync(index);
return new IdBaseDto
{
Id = order.Id
};
}
order = ObjectMapper.Map<UpsertOrderInput, OrderEntity>(input);
order.OrderFlights = ObjectMapper.Map<List<OrderFlightInfo>, List<OrderFlightEntity>>(input.FlightInfos);
order.OrderPullStatus = BuiltOrderPullStatus(input.PullConfigInfos);
order.SetThirdPartyOrderNumber(order.OrderPullStatus);
var orderId = await _orderRepository.CreateOrderAsync(order);
// 写入操作日志
var indexForAdd = new OrderOperationRecordIndex
{
OrderId = orderId,
OrderNo = input.OrderNo,
OptionType = nameof(OrderOperationType.创建订单),
Content = input.ToJson(),
CreateUserId = CurrentUser.Id ?? Guid.Empty,
CreateUserName = CurrentUser.UserName ?? string.Empty,
CreateTime = DateTime.Now
};
_ = _orderOperationRecordEsRepository.AddAsync(indexForAdd);
return new IdBaseDto
{
Id = orderId
};
}
/// <summary>
/// 批量创建/新增 轨迹订单
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="BusinessException"></exception>
[HttpPost("Order/BatchUpsert")]
public async Task BatchUpsertAsync(BatchUpsertOrderInput input)
{
if (input.OrderInputs.Any(x => (x.EstimatedDeliveryDate.HasValue && x.DestinationTimeZone.HasValue == false) ||
(x.EstimatedDeliveryDate.HasValue == false && x.DestinationTimeZone.HasValue)))
{
throw new BusinessException(message: "【预计签收时间】和【签收地时区】必须同时输入");
}
var exp = Expressionable.Create<OrderEntity>();
foreach (var order in input.OrderInputs)
exp.Or(x => x.OrderType == order.OrderType && x.AppKey == order.AppKey && x.OrderNo == order.OrderNo);
// 获取已存在的订单
var existsOrders = await _orderRepository.GetListAsync(exp.ToExpression());
var updateOrders = existsOrders.Count > 0 ? new List<OrderEntity>(existsOrders.Count) : Empty<OrderEntity>.List;
var updateRecords = existsOrders.Count > 0 ? new List<OrderOperationRecordIndex>(existsOrders.Count) : Empty<OrderOperationRecordIndex>.List;
if (existsOrders.Count > 0)
{
foreach (var order in existsOrders)
{
var input2 = input.OrderInputs.First(x => x.OrderType == order.OrderType && x.AppKey == order.AppKey && x.OrderNo == order.OrderNo);
var order2 = ObjectMapper.Map(input2, order);
order2.OrderFlights = ObjectMapper.Map<List<OrderFlightInfo>, List<OrderFlightEntity>>(input2.FlightInfos);
order2.OrderPullStatus = BuiltOrderPullStatus(input2.PullConfigInfos);
order2.SetThirdPartyOrderNumber(order.OrderPullStatus);
updateOrders.Add(order2);
updateRecords.Add(new OrderOperationRecordIndex
{
OrderId = order.Id,
OrderNo = order.OrderNo,
OptionType = nameof(OrderOperationType.修改订单),
Content = input2.ToJson(),
CreateUserId = CurrentUser.Id ?? Guid.Empty,
CreateUserName = CurrentUser.UserName ?? string.Empty,
CreateTime = DateTime.Now
});
}
await _orderRepository.UpdateBatchOrderAsync(updateOrders);
_ = _orderOperationRecordEsRepository.AddManyAsync(updateRecords);
}
// 如果全部操作为修改
if (existsOrders.Count == input.OrderInputs.Count) return;
// 新增订单
var existsOrderNos = existsOrders.Select(x => x.OrderNo).ToHashSet();
var insertInputs = input.OrderInputs
.WhereIf(existsOrderNos.Count > 0, x => !existsOrderNos.Contains(x.OrderNo))
.ToList();
var insertOrders = new List<OrderEntity>(insertInputs.Count);
var createRecords = new List<OrderOperationRecordIndex>(insertInputs.Count);
foreach (var insertInput in insertInputs)
{
var order = ObjectMapper.Map<UpsertOrderInput, OrderEntity>(insertInput);
order.OrderFlights = ObjectMapper.Map<List<OrderFlightInfo>, List<OrderFlightEntity>>(insertInput.FlightInfos);
order.OrderPullStatus = BuiltOrderPullStatus(insertInput.PullConfigInfos);
order.SetThirdPartyOrderNumber(order.OrderPullStatus);
insertOrders.Add(order);
createRecords.Add(new OrderOperationRecordIndex
{
//OrderId = default, //稍后补充
OrderNo = order.OrderNo,
OptionType = OrderOperationType.创建订单.ToString(),
Content = insertInput.ToJson(),
CreateUserId = CurrentUser.Id ?? Guid.Empty,
CreateUserName = CurrentUser.UserName ?? string.Empty,
CreateTime = DateTime.Now
});
}
// 创建订单,创建操作记录
var orderNoIdDict = await _orderRepository.CreateBatchOrderAsync(insertOrders);
foreach (var record in createRecords)
{
var orderId = orderNoIdDict[record.OrderNo];
record.OrderId = orderId;
}
_ = _orderOperationRecordEsRepository.AddManyAsync(createRecords);
}
/// <summary>
/// 删除订单
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="BusinessException"></exception>
[HttpPost("Order/Delete")]
public async Task<IdBaseDto> DeleteOrderAsync(DeleteOrderInput input)
{
var order = await _orderRepository.GetFirstAsync(x =>
x.AppKey == input.AppKey && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo);
if (order == null)
{
throw new BusinessException(message: $"订单:{input.OrderNo}不存在");
}
await _orderRepository.DeleteOrderAsync(order.Id);
// 预警计算
WarningCalc_OrderDeletedOrCompleted(order);
return new IdBaseDto
{
Id = order.Id
};
}
private async Task UpdateOrderAsync(UpdateOrderInput input, OrderEntity order)
{
order = ObjectMapper.Map(input, order);
order.OrderFlights = ObjectMapper.Map<List<OrderFlightInfo>, List<OrderFlightEntity>>(input.FlightInfos);
order.OrderPullStatus = BuiltOrderPullStatus(input.PullConfigInfos);
order.SetThirdPartyOrderNumber(order.OrderPullStatus);
await _orderRepository.UpdateOrderAsync(order);
}
private static List<OrderPullStatusEntity> BuiltOrderPullStatus(List<PullConfigInfo>? pullConfigInfos)
{
if (pullConfigInfos == null) return new List<OrderPullStatusEntity>();
return pullConfigInfos.Select(x =>
{
var status = new OrderPullStatusEntity
{
ServiceProviderCode = x.ServiceCode,
OrderNo = x.OrderNo,
PullStatus = TrackPullStatus.Init,
StartTrackCode = x.StartCode ?? GlobalConst.EmptyString,
EndTrackCode = x.EndCode ?? GlobalConst.EmptyString,
SilenceBeforeStart = x.SilenceTime,
SilenceAfterEnd = x.StopTime,
StartTime = GlobalConst.MaxDateTime,
EndTime = GlobalConst.MaxDateTime,
};
// 没有开始轨迹则立即进入拉取前静默期
if (x.StartCode == null)
{
status.PullStatus = TrackPullStatus.SilenceBeforeStart; // 会被定时任务扫描到并启动
status.StartTime = DateTime.Now.AddHours(x.SilenceTime);
}
return status;
}).ToList();
}
private void WarningCalc_OrderDeletedOrCompleted(OrderEntity order)
{
order.IsDeleted = true;
_ = Task.Run(async () =>
{
var scope = _serviceProvider.CreateAsyncScope();
try
{
var handler = scope.ServiceProvider.GetRequiredService<IOrderWarningHandler>();
await handler.HandleOrderDeletedOrCompletedAsync(order);
}
catch (Exception ex)
{
LogHelper.Error(ex);
}
finally
{
await scope.DisposeAsync();
}
});
}
}