track/src/SJZY.Track.Application/Services/ProvideServices/OrderService.cs

320 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
using SJZY.Track.Application.Contract.Services.ProvideServices;
using SJZY.Track.Application.Services.Warning.Handlers;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Extensions;
using SJZY.UserCenter.HttpApi.Services;
using SqlSugar;
namespace SJZY.Track.Application.Services.ProvideServices;
/// <summary>
/// 订单服务
/// </summary>
[ApiExplorerSettings(GroupName = "提供接口")]
[Route("/ProviderService")]
public partial class OrderService : ApplicationService, IOrderService
{
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<UnifyResultDto<IdBaseDto>> UpsertAsync(UpsertOrderInput input)
{
// 校验预计到达时间是否不是同时存在或同时不存在
if ((input.EstimatedDeliveryDate.HasValue && input.DestinationTimeZone.HasValue == false) ||
(input.EstimatedDeliveryDate.HasValue == false && input.DestinationTimeZone.HasValue))
{
throw new BusinessException(message: "【预计签收时间】和【签收地时区】必须同时输入");
}
var currentUser = CurrentUserRequest.CurrentUser;
// 校验订单是否已存在,存在则更新
var order = await _orderRepository.GetFirstAsync(x =>
x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo);
if (order != default)
{
// 订单已存在则视为更新
await UpdateOrderAsync(input, order);
var index = new OrderOperationRecordIndex
{
OrderId = order.Id,
OrderNo = input.OrderNo,
OptionType = OrderOperationType.修改订单.ToString(),
Content = input.ToJson(),
CreateUserId = currentUser.UserId,
CreateUserName = currentUser.Name,
};
_ = _orderOperationRecordEsRepository.AddAsync(index);
return new UnifyResultDto<IdBaseDto>(true, 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.OrderPlatformNumbers = BuiltOrderPlatformNumbers(input.PullConfigInfos);
order.TemplateCodes = input.TemplateCodes == null ? null : string.Join(',', input.TemplateCodes);
order.SetThirdPartyOrderNumber(order.OrderPlatformNumbers);
var orderId = await _orderRepository.CreateOrderAsync(order);
// 写入操作日志
var indexForAdd = new OrderOperationRecordIndex
{
OrderId = orderId,
OrderNo = input.OrderNo,
OptionType = OrderOperationType.创建订单.ToString(),
Content = input.ToJson(),
CreateUserId = currentUser.UserId,
CreateUserName = currentUser.Name,
CreateTime = DateTime.Now
};
_ = _orderOperationRecordEsRepository.AddAsync(indexForAdd);
return new UnifyResultDto<IdBaseDto>(true, new IdBaseDto
{
Id = orderId
});
}
/// <summary>
/// 批量创建/新增 轨迹订单
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="BusinessException"></exception>
[HttpPost("Order/BatchUpsert")]
public async Task<UnifyResultDto> 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 currentUser = CurrentUserRequest.CurrentUser;
var exp = Expressionable.Create<OrderEntity>();
foreach (var order in input.OrderInputs)
exp.Or(x => x.OrderType == order.OrderType && x.SubSystemId == order.SubSystemId && 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.SubSystemId == order.SubSystemId && 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.OrderPlatformNumbers = BuiltOrderPlatformNumbers(input2.PullConfigInfos);
order2.TemplateCodes = input2.TemplateCodes == null ? null : string.Join(',', input2.TemplateCodes);
order2.SetThirdPartyOrderNumber(order.OrderPlatformNumbers);
updateOrders.Add(order2);
updateRecords.Add(new OrderOperationRecordIndex
{
OrderId = order.Id,
OrderNo = order.OrderNo,
OptionType = OrderOperationType.修改订单.ToString(),
Content = input2.ToJson(),
CreateUserId = currentUser.UserId,
CreateUserName = currentUser.Name,
CreateTime = DateTime.Now
});
}
await _orderRepository.UpdateBatchOrderAsync(updateOrders);
_ = _orderOperationRecordEsRepository.AddManyAsync(updateRecords);
}
// 如果全部操作为修改
if (existsOrders.Count == input.OrderInputs.Count)
return new UnifyResultDto(true);
// 新增订单
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.OrderPlatformNumbers = BuiltOrderPlatformNumbers(insertInput.PullConfigInfos);
order.TemplateCodes = insertInput.TemplateCodes == null ? null : string.Join(',', insertInput.TemplateCodes);
order.SetThirdPartyOrderNumber(order.OrderPlatformNumbers);
insertOrders.Add(order);
createRecords.Add(new OrderOperationRecordIndex
{
//OrderId = default, //稍后补充
OrderNo = order.OrderNo,
OptionType = OrderOperationType.创建订单.ToString(),
Content = insertInput.ToJson(),
CreateUserId = currentUser.UserId,
CreateUserName = currentUser.Name,
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);
return new UnifyResultDto(true);
}
/// <summary>
/// 删除订单
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="BusinessException"></exception>
[HttpPost("Order/Delete")]
public async Task<UnifyResultDto<IdBaseDto>> DeleteOrderAsync(DeleteOrderInput input)
{
var order = await _orderRepository.GetFirstAsync(x =>
x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo);
if (order == null)
{
throw new BusinessException(message: $"订单:{input.OrderNo}不存在");
}
await _orderRepository.DeleteOrderAsync(order.Id);
// todo:预警计算
WarningCalc_OrderDeletedOrCompleted(order);
return new UnifyResultDto<IdBaseDto>(true, 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.OrderPlatformNumbers = BuiltOrderPlatformNumbers(input.PullConfigInfos);
order.TemplateCodes = input.TemplateCodes == null ? null : string.Join(',', input.TemplateCodes);
order.SetThirdPartyOrderNumber(order.OrderPlatformNumbers);
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 static List<OrderPlatformNumberEntity> BuiltOrderPlatformNumbers(List<PullConfigInfo>? pullConfigInfos)
{
if (pullConfigInfos == null) return new List<OrderPlatformNumberEntity>();
return pullConfigInfos.Select(x =>
{
var status = new OrderPlatformNumberEntity
{
//三方单号
OrderNumber = x.OrderNo,
//三方平台名称,目前认为是服务商code
Platform = x.ServiceCode,
};
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();
}
});
}
}