320 lines
13 KiB
C#
320 lines
13 KiB
C#
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();
|
||
}
|
||
});
|
||
}
|
||
}
|