All checks were successful
Build and Deploy / deploy (push) Successful in 57s
Co-authored-by: Cursor <cursoragent@cursor.com>
631 lines
27 KiB
C#
631 lines
27 KiB
C#
using Fake.FeiShu;
|
||
using InterfaceForward.Domain.Shared.Helpers;
|
||
using Microsoft.Extensions.Logging;
|
||
using TrackCenter.Domain;
|
||
using TrackCenter.Domain.Aggregates.OrderAggregate;
|
||
using TrackCenter.Domain.Consts;
|
||
using TrackCenter.Domain.Dtos.Order;
|
||
using TrackCenter.Domain.Enums;
|
||
|
||
namespace TrackCenter.Repository.Repositories;
|
||
|
||
public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, ITransientDependency
|
||
{
|
||
private readonly IFeiShuNotificationService _feiShuNotification;
|
||
|
||
public OrderRepository(IFeiShuNotificationService feiShuNotification)
|
||
{
|
||
_feiShuNotification = feiShuNotification;
|
||
}
|
||
public async Task<PagedResult<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input)
|
||
{
|
||
PagedResult<TrackOrderVO> pageList;
|
||
if (input.OrderNos.IsNullOrEmpty())
|
||
{
|
||
pageList = await ApplyTrackOrderListFilters(Context.Queryable<OrderEntity>(), input)
|
||
.OrderByDescending(a => a.CreateTime)
|
||
.Select(TrackOrderListSelector)
|
||
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||
}
|
||
else
|
||
{
|
||
var orderNos = input.OrderNos!.Distinct().ToList();
|
||
|
||
//匹配主单
|
||
var orderIds = await Context.Queryable<OrderEntity>()
|
||
.Where(x => orderNos.Contains(x.OrderNo))
|
||
.Select(x => x.Id)
|
||
.ToListAsync();
|
||
|
||
//匹配外部单
|
||
var orderIdsForThirdParty = await Context.Queryable<OrderPullStatusEntity>()
|
||
.Where(x => !string.IsNullOrWhiteSpace(x.OrderNo) && orderNos.Contains(x.OrderNo))
|
||
.Select(x => x.OrderId)
|
||
.ToListAsync();
|
||
|
||
var orderHashset = orderIds.ToHashSet();
|
||
orderHashset.UnionWith(orderIdsForThirdParty);
|
||
orderIds = orderHashset.ToList();
|
||
|
||
if (orderIds.Count == 0)
|
||
{
|
||
return new PagedResult<TrackOrderVO>();
|
||
}
|
||
|
||
pageList = await ApplyTrackOrderListFilters(
|
||
Context.Queryable<OrderEntity>().Where(a => orderIds.Contains(a.Id)), input)
|
||
.OrderByDescending(a => a.CreateTime)
|
||
.Select(TrackOrderListSelector)
|
||
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||
}
|
||
|
||
pageList.Items.ForEach(x =>
|
||
{
|
||
x.OrderTypeName = x.OrderType.GetDescription();
|
||
x.QuestionTypeName = x.QuestionType.GetDescription();
|
||
});
|
||
|
||
return pageList;
|
||
}
|
||
|
||
private static System.Linq.Expressions.Expression<Func<OrderEntity, TrackOrderVO>> TrackOrderListSelector =>
|
||
a => new TrackOrderVO
|
||
{
|
||
Id = a.Id,
|
||
OrderNumber = a.OrderNo,
|
||
OrderType = a.OrderType,
|
||
QuestionType = a.QuestionType,
|
||
Customer = a.Customer,
|
||
NewestTrackStatus = a.LatestTrackStatus,
|
||
NewestTrackContent = a.LatestTrackContent,
|
||
NewestTrackEnContent = a.LatestTrackEnContent,
|
||
NewestTrackPlace = a.LatestTrackPlace,
|
||
NewestTrackTime = a.LatestTrackTime,
|
||
NewestTrackTimeZone = a.LatestTrackTimeZone,
|
||
IsFinish = a.IsCompleted,
|
||
CreateTime = a.CreateTime,
|
||
AppKey = a.AppKey,
|
||
DestinationTimeZone = a.DestinationTimeZone,
|
||
EstimatedDeliveryDate = a.EstimatedDeliveryDate,
|
||
TrackNo = a.TrackNo,
|
||
OtherNo = a.ThirdPartyOrderNumber,
|
||
Channel = a.Channel,
|
||
Product = a.ProductCode,
|
||
ApiCode = a.ServiceProviderCode,
|
||
CountryCode = a.ArrivalCountry,
|
||
Province = a.ArrivalProvince,
|
||
Postcode = a.ArrivalPostCode,
|
||
City = a.ArrivalCity,
|
||
Email = a.ArrivalEmail
|
||
};
|
||
|
||
/// <summary>
|
||
/// 表头筛选:客户/单号/产品/渠道/轨迹内容等
|
||
/// </summary>
|
||
private static ISugarQueryable<OrderEntity> ApplyTrackOrderListFilters(
|
||
ISugarQueryable<OrderEntity> query,
|
||
GetPageTrackOrderInputVO input)
|
||
{
|
||
var trackNos = SplitMultiValues(input.TrackNo);
|
||
var otherNos = SplitMultiValues(input.OtherNo);
|
||
|
||
query = query
|
||
.WhereIF(!input.AppKey.IsNullOrWhiteSpace(), a => a.AppKey == input.AppKey)
|
||
.WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue,
|
||
a => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd)
|
||
.WhereIF(input.CreateTimeStart.HasValue && !input.CreateTimeEnd.HasValue,
|
||
a => a.CreateTime >= input.CreateTimeStart)
|
||
.WhereIF(!input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue,
|
||
a => a.CreateTime <= input.CreateTimeEnd)
|
||
.WhereIF(!input.Customer.IsNullOrWhiteSpace(), a => a.Customer.Contains(input.Customer!))
|
||
.WhereIF(input.TrackOrderType > 0, a => a.OrderType == input.TrackOrderType)
|
||
.WhereIF(input.TabType > 0, a => a.QuestionType == input.TabType)
|
||
.WhereIF(input.TabType == TrackProblemType.Warn, a => !a.IsCompleted)
|
||
.WhereIF(trackNos.Count == 1, a => a.TrackNo.Contains(trackNos[0]))
|
||
.WhereIF(trackNos.Count > 1, a => trackNos.Contains(a.TrackNo))
|
||
.WhereIF(otherNos.Count == 1, a => a.ThirdPartyOrderNumber != null && a.ThirdPartyOrderNumber.Contains(otherNos[0]))
|
||
.WhereIF(otherNos.Count > 1, a => a.ThirdPartyOrderNumber != null && otherNos.Contains(a.ThirdPartyOrderNumber))
|
||
.WhereIF(!input.Product.IsNullOrWhiteSpace(), a => a.ProductCode != null && a.ProductCode.Contains(input.Product!))
|
||
.WhereIF(!input.Channel.IsNullOrWhiteSpace(), a => a.Channel != null && a.Channel.Contains(input.Channel!))
|
||
.WhereIF(!input.ApiCode.IsNullOrWhiteSpace(),
|
||
a => a.ServiceProviderCode != null && a.ServiceProviderCode.Contains(input.ApiCode!))
|
||
.WhereIF(!input.CountryCode.IsNullOrWhiteSpace(), a => a.ArrivalCountry.Contains(input.CountryCode!))
|
||
.WhereIF(!input.Province.IsNullOrWhiteSpace(), a => a.ArrivalProvince != null && a.ArrivalProvince.Contains(input.Province!))
|
||
.WhereIF(!input.City.IsNullOrWhiteSpace(), a => a.ArrivalCity.Contains(input.City!))
|
||
.WhereIF(!input.Postcode.IsNullOrWhiteSpace(),
|
||
a => a.ArrivalPostCode != null && a.ArrivalPostCode.Contains(input.Postcode!))
|
||
.WhereIF(!input.Email.IsNullOrWhiteSpace(), a => a.ArrivalEmail != null && a.ArrivalEmail.Contains(input.Email!))
|
||
.WhereIF(!input.NewestTrackStatus.IsNullOrWhiteSpace(),
|
||
a => a.LatestTrackStatus != null && a.LatestTrackStatus.Contains(input.NewestTrackStatus!))
|
||
.WhereIF(!input.NewestTrackContent.IsNullOrWhiteSpace(),
|
||
a => a.LatestTrackContent != null && a.LatestTrackContent.Contains(input.NewestTrackContent!))
|
||
.WhereIF(!input.NewestTrackEnContent.IsNullOrWhiteSpace(),
|
||
a => a.LatestTrackEnContent != null && a.LatestTrackEnContent.Contains(input.NewestTrackEnContent!))
|
||
.WhereIF(!input.NewestTrackPlace.IsNullOrWhiteSpace(),
|
||
a => a.LatestTrackPlace != null && a.LatestTrackPlace.Contains(input.NewestTrackPlace!))
|
||
.WhereIF(input.NewestTrackTimeStart.HasValue && input.NewestTrackTimeEnd.HasValue,
|
||
a => a.LatestTrackTime >= input.NewestTrackTimeStart && a.LatestTrackTime <= input.NewestTrackTimeEnd)
|
||
.WhereIF(input.NewestTrackTimeStart.HasValue && !input.NewestTrackTimeEnd.HasValue,
|
||
a => a.LatestTrackTime >= input.NewestTrackTimeStart)
|
||
.WhereIF(!input.NewestTrackTimeStart.HasValue && input.NewestTrackTimeEnd.HasValue,
|
||
a => a.LatestTrackTime <= input.NewestTrackTimeEnd)
|
||
.WhereIF(input.NewestTrackTimeZone.HasValue, a => a.LatestTrackTimeZone == input.NewestTrackTimeZone)
|
||
.WhereIF(input.IsFinish.HasValue, a => a.IsCompleted == input.IsFinish.Value)
|
||
.WhereIF(input.EstimatedDeliveryDateStart.HasValue && input.EstimatedDeliveryDateEnd.HasValue,
|
||
a => a.EstimatedDeliveryDate >= input.EstimatedDeliveryDateStart &&
|
||
a.EstimatedDeliveryDate <= input.EstimatedDeliveryDateEnd)
|
||
.WhereIF(input.EstimatedDeliveryDateStart.HasValue && !input.EstimatedDeliveryDateEnd.HasValue,
|
||
a => a.EstimatedDeliveryDate >= input.EstimatedDeliveryDateStart)
|
||
.WhereIF(!input.EstimatedDeliveryDateStart.HasValue && input.EstimatedDeliveryDateEnd.HasValue,
|
||
a => a.EstimatedDeliveryDate <= input.EstimatedDeliveryDateEnd)
|
||
.WhereIF(input.DestinationTimeZone.HasValue, a => a.DestinationTimeZone == input.DestinationTimeZone);
|
||
|
||
return query;
|
||
}
|
||
|
||
private static List<string> SplitMultiValues(string? raw)
|
||
{
|
||
if (raw.IsNullOrWhiteSpace()) return new List<string>();
|
||
return raw!
|
||
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||
.ToList();
|
||
}
|
||
|
||
public async Task<(int MainOrderId, string OrderNo, string Customer)> GetTrackOrderByProviderAndOrderNo(
|
||
string serviceProviderCode, string orderNo, string? appKey = null, TrackOrderType? orderType = null)
|
||
{
|
||
// 拉取优先级可能配置为客户单号 / 跟踪号 / 其他单号,回传的 orderNo 不一定是主单号
|
||
var orderList = await Context.Queryable<OrderEntity>()
|
||
.InnerJoin<OrderPullStatusEntity>((a, b) => a.Id == b.OrderId)
|
||
.Where((a, b) => b.ServiceProviderCode == serviceProviderCode)
|
||
.WhereIF(!appKey.IsNullOrWhiteSpace(), a => a.AppKey == appKey)
|
||
.WhereIF(orderType.HasValue, a => a.OrderType == orderType!.Value)
|
||
.Where((a, b) => a.OrderNo == orderNo
|
||
|| a.TrackNo == orderNo
|
||
|| a.ThirdPartyOrderNumber == orderNo
|
||
|| b.OrderNo == orderNo)
|
||
.Select((a, b) => new
|
||
{
|
||
a.Id,
|
||
a.Customer,
|
||
a.OrderNo,
|
||
a.TrackNo,
|
||
a.ThirdPartyOrderNumber,
|
||
PullOrderNo = b.OrderNo
|
||
})
|
||
.ToListAsync();
|
||
|
||
if (orderList.Count == 0)
|
||
{
|
||
return default;
|
||
}
|
||
|
||
// 多条时按匹配精度优先:拉取状态外部单号 > 跟踪号 > 其他单号 > 客户单号
|
||
var matchOrder =
|
||
orderList.FirstOrDefault(x => x.PullOrderNo == orderNo)
|
||
?? orderList.FirstOrDefault(x => x.TrackNo == orderNo)
|
||
?? orderList.FirstOrDefault(x => x.ThirdPartyOrderNumber == orderNo)
|
||
?? orderList.First();
|
||
|
||
return (matchOrder.Id, matchOrder.OrderNo, matchOrder.Customer);
|
||
}
|
||
|
||
public async Task<int> CreateOrderAsync(OrderEntity order)
|
||
{
|
||
using var tran = TransactionHelper.GetReadCommitted();
|
||
|
||
var orderId = await InsertReturnIdentityAsync(order);
|
||
order.OrderFlights.ForEach(x => x.OrderId = orderId);
|
||
await Context.Insertable(order.OrderFlights).ExecuteCommandAsync();
|
||
order.OrderPullStatus.ForEach(x => x.OrderId = orderId);
|
||
await Context.Insertable(order.OrderPullStatus).ExecuteCommandAsync();
|
||
|
||
tran.Complete();
|
||
|
||
return orderId;
|
||
}
|
||
|
||
public async Task<Dictionary<string, int>> CreateBatchOrderAsync(List<OrderEntity> orders)
|
||
{
|
||
Dictionary<string, int> orderNoIdDict;
|
||
using var tran = TransactionHelper.GetReadCommitted();
|
||
|
||
var orderFlights = orders.SelectMany(x => x.OrderFlights).ToList();
|
||
var orderPullStatus = orders.SelectMany(x => x.OrderPullStatus).ToList();
|
||
|
||
try
|
||
{
|
||
// 先批量插入
|
||
await Context.Insertable(orders).ExecuteCommandAsync();
|
||
|
||
var exp = Expressionable.Create<OrderEntity>();
|
||
foreach (var order in orders)
|
||
exp.Or(x => x.OrderType == order.OrderType && x.AppKey == order.AppKey && x.OrderNo == order.OrderNo);
|
||
|
||
// 查出id
|
||
var queryOrders = await GetListAsync(exp.ToExpression(), x => new
|
||
{
|
||
x.Id,
|
||
x.OrderNo
|
||
});
|
||
|
||
// 填充订单关联数据中的OrderId
|
||
orderNoIdDict = queryOrders.ToDictionary(x => x.OrderNo, x => x.Id);
|
||
foreach (var order in orders)
|
||
{
|
||
var orderId = orderNoIdDict[order.OrderNo];
|
||
order.OrderFlights.ForEach(x => x.OrderId = orderId);
|
||
order.OrderPullStatus.ForEach(x => x.OrderId = orderId);
|
||
}
|
||
|
||
await Context.Insertable(orderFlights).ExecuteCommandAsync();
|
||
await Context.Insertable(orderPullStatus).ExecuteCommandAsync();
|
||
}
|
||
finally
|
||
{
|
||
tran.Complete();
|
||
}
|
||
|
||
return orderNoIdDict;
|
||
}
|
||
|
||
public Task<int> UpdateBatchIdsAsync(List<int> ids, int newValue)
|
||
{
|
||
var idsString = string.Join(",", ids);
|
||
return Context.Ado.ExecuteCommandAsync(
|
||
$"UPDATE `t_order` SET `DeficiencyTag` = @newValue ,UpdateTime= current_timestamp WHERE `Id` IN ({idsString})",
|
||
new
|
||
{
|
||
newValue
|
||
});
|
||
}
|
||
|
||
public async Task UpdateOrderAsync(OrderEntity order)
|
||
{
|
||
using var tran = TransactionHelper.GetReadCommitted();
|
||
|
||
// 注意:UpdateAsync(entity, cols) 的 cols 是 IgnoreColumns;
|
||
// 指定要更新的列必须用 UpdateColumnAsync。
|
||
await UpdateColumnAsync(order, x => new
|
||
{
|
||
x.Customer,
|
||
x.AppKey,
|
||
x.TrackNo,
|
||
x.ThirdPartyOrderNumber,
|
||
x.Channel,
|
||
x.ProductCode,
|
||
x.ServiceProviderCode,
|
||
x.ArrivalCountry,
|
||
x.ArrivalProvince,
|
||
x.ArrivalPostCode,
|
||
x.ArrivalCity,
|
||
x.ArrivalEmail,
|
||
x.LeaveCountry,
|
||
x.LeaveCity,
|
||
x.IsTransit,
|
||
x.IsCompleted,
|
||
x.LatestTrackStatus,
|
||
x.LatestTrackContent,
|
||
x.LatestTrackEnContent,
|
||
x.LatestTrackTime,
|
||
x.LatestTrackTimeZone,
|
||
x.LatestTrackPlace,
|
||
x.EstimatedDeliveryDate,
|
||
x.DestinationTimeZone,
|
||
});
|
||
|
||
// 更新订单拉取状态
|
||
await Context.Deleteable<OrderPullStatusEntity>().Where(x => x.OrderId == order.Id).ExecuteCommandAsync();
|
||
order.OrderPullStatus.ForEach(x => x.OrderId = order.Id);
|
||
await Context.Insertable(order.OrderPullStatus).ExecuteCommandAsync();
|
||
|
||
// 更新订单航班
|
||
await Context.Deleteable<OrderFlightEntity>().Where(x => x.OrderId == order.Id).ExecuteCommandAsync();
|
||
order.OrderFlights.ForEach(x => x.OrderId = order.Id);
|
||
await Context.Insertable(order.OrderFlights).ExecuteCommandAsync();
|
||
|
||
tran.Complete();
|
||
}
|
||
|
||
public async Task UpdateBatchOrderAsync(List<OrderEntity> orders)
|
||
{
|
||
using var tran = TransactionHelper.GetReadCommitted();
|
||
|
||
try
|
||
{
|
||
// 更新订单主表(与 UpdateOrderAsync 字段对齐)
|
||
await UpdateRangeAsync(orders, x => new
|
||
{
|
||
x.Customer,
|
||
x.AppKey,
|
||
x.TrackNo,
|
||
x.ThirdPartyOrderNumber,
|
||
x.Channel,
|
||
x.ProductCode,
|
||
x.ServiceProviderCode,
|
||
x.ArrivalCountry,
|
||
x.ArrivalProvince,
|
||
x.ArrivalPostCode,
|
||
x.ArrivalCity,
|
||
x.ArrivalEmail,
|
||
x.LeaveCountry,
|
||
x.LeaveCity,
|
||
x.IsTransit,
|
||
x.IsCompleted,
|
||
x.LatestTrackStatus,
|
||
x.LatestTrackContent,
|
||
x.LatestTrackEnContent,
|
||
x.LatestTrackTime,
|
||
x.LatestTrackTimeZone,
|
||
x.LatestTrackPlace,
|
||
x.EstimatedDeliveryDate,
|
||
x.DestinationTimeZone,
|
||
});
|
||
|
||
var orderIds = orders.Select(x => x.Id).ToHashSet();
|
||
var orderFlights = orders.SelectMany(x => x.OrderFlights).ToList();
|
||
var orderPullStatus = orders.SelectMany(x => x.OrderPullStatus).ToList();
|
||
foreach (var order in orders)
|
||
{
|
||
order.OrderPullStatus.ForEach(x => x.OrderId = order.Id);
|
||
order.OrderFlights.ForEach(x => x.OrderId = order.Id);
|
||
}
|
||
|
||
// 更新订单模板
|
||
await Context.Deleteable<OrderPullStatusEntity>().Where(x => orderIds.Contains(x.OrderId)).ExecuteCommandAsync();
|
||
await Context.Insertable(orderPullStatus).ExecuteCommandAsync();
|
||
|
||
// 更新订单航班
|
||
await Context.Deleteable<OrderFlightEntity>().Where(x => orderIds.Contains(x.OrderId)).ExecuteCommandAsync();
|
||
await Context.Insertable(orderFlights).ExecuteCommandAsync();
|
||
}
|
||
finally
|
||
{
|
||
tran.Complete();
|
||
}
|
||
}
|
||
|
||
public async Task DeleteOrderAsync(int orderId)
|
||
{
|
||
using var tran = TransactionHelper.GetReadCommitted();
|
||
|
||
// 软删订单主表
|
||
await SoftDeleteAsync(x => x.Id == orderId);
|
||
|
||
// 软删订单航班
|
||
// 软删订单关联关系
|
||
// 软删订单拉取状态
|
||
|
||
tran.Complete();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新推送预警单
|
||
/// </summary>
|
||
/// <param name="appKey"></param>
|
||
/// <param name="pageSize"></param>
|
||
/// <param name="pageindex"></param>
|
||
/// <returns></returns>
|
||
public async Task<int> PushWarnOrdersAsync(string appKey, int pageSize, int pageindex)
|
||
{
|
||
var ordersToUpdate = await Context.Queryable<OrderEntity>()
|
||
.Where(b => b.AppKey == appKey && !b.IsCompleted && b.QuestionType != TrackProblemType.Error)
|
||
.Select(b => new
|
||
{
|
||
b.LatestPushTime,
|
||
b.Id,
|
||
b.QuestionType
|
||
})
|
||
.ToPageListAsync(pageindex, pageSize);
|
||
|
||
var latestPushTimeIds = new List<int>();
|
||
var questionZeroIds = new List<int>();
|
||
foreach (var item in ordersToUpdate)
|
||
{
|
||
var questionType = !item.LatestPushTime.HasValue || item.LatestPushTime < DateTime.Now.AddHours(-12)
|
||
? TrackProblemType.Warn
|
||
: TrackProblemType.None;
|
||
if (item.QuestionType == questionType) continue;
|
||
if (questionType == TrackProblemType.Warn) latestPushTimeIds.Add(item.Id);
|
||
else questionZeroIds.Add(item.Id);
|
||
}
|
||
|
||
if (latestPushTimeIds.Count > 0) UpdateOrderQuestionType(2, latestPushTimeIds);
|
||
if (questionZeroIds.Count > 0) UpdateOrderQuestionType(0, questionZeroIds);
|
||
return ordersToUpdate.Count;
|
||
}
|
||
|
||
private int UpdateOrderQuestionType(int questionType, IEnumerable<int> ids)
|
||
{
|
||
var idsString = string.Join(",", ids);
|
||
return Context.Ado.ExecuteCommand(
|
||
$"UPDATE `t_order` SET `QuestionType` = @questionType ,UpdateTime= current_timestamp WHERE `Id` IN ({idsString})",
|
||
new
|
||
{
|
||
questionType
|
||
});
|
||
}
|
||
|
||
#region 订单关联
|
||
|
||
public async Task<List<LinkedOrderVO>> GetLinkedOrdersAsync(int[] orderIds)
|
||
{
|
||
return await Context.Queryable<OrderLinkEntity>()
|
||
.LeftJoin<OrderEntity>((a, b) => a.LinkOrderId == b.Id)
|
||
.Where(a => orderIds.Contains(a.OrderId))
|
||
.Select((a, b) => new LinkedOrderVO
|
||
{
|
||
OwnerOrderId = a.OrderId,
|
||
OrderId = b.Id,
|
||
OrderNo = b.OrderNo,
|
||
OrderType = b.OrderType,
|
||
AppKey = b.AppKey,
|
||
Customer = b.Customer
|
||
})
|
||
.ToListAsync();
|
||
}
|
||
|
||
public async Task<List<string>> GetLinkedOrdersAsync(int orderId, string linkAppKey, TrackOrderType linkOrderType)
|
||
{
|
||
return await Context.Queryable<OrderLinkEntity>()
|
||
.LeftJoin<OrderEntity>((a, b) => a.LinkOrderId == b.Id)
|
||
.Where((a, b) => orderId == a.OrderId && b.AppKey == linkAppKey && b.OrderType == linkOrderType)
|
||
.Select((a, b) => b.OrderNo)
|
||
.ToListAsync();
|
||
}
|
||
|
||
public async Task<List<int>> GetLinkedOrdersAsync(int orderId, string linkAppKey, TrackOrderType linkOrderType,
|
||
List<string> linkOrderNos)
|
||
{
|
||
return await Context.Queryable<OrderLinkEntity>()
|
||
.LeftJoin<OrderEntity>((a, b) => a.LinkOrderId == b.Id)
|
||
.Where((a, b) => orderId == a.OrderId && b.AppKey == linkAppKey && b.OrderType == linkOrderType
|
||
&& linkOrderNos.Contains(b.OrderNo))
|
||
.Select((a, b) => a.Id)
|
||
.ToListAsync();
|
||
}
|
||
|
||
public async Task LinkOrderAsync(List<OrderLinkEntity> orderLinkEntities)
|
||
{
|
||
await Context.Insertable(orderLinkEntities).ExecuteCommandAsync();
|
||
}
|
||
|
||
public async Task UnLinkByIdsAsync(List<int> linkIds)
|
||
{
|
||
await Context.Deleteable<OrderLinkEntity>(linkIds).ExecuteCommandAsync();
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
#region 订单拉取
|
||
|
||
public async Task UpdatePullStatusToSilenceAsync(List<int> orderIds, string trackCode)
|
||
{
|
||
// var status = await Context.Queryable<OrderPullStatusEntity>()
|
||
// .Where(x => orderIds.Contains(x.OrderId) && x.StartTrackCode == trackCode)
|
||
// .Where(x => x.PullStatus == TrackPullStatus.Init || x.PullStatus == TrackPullStatus.Pulling)
|
||
// .Select(x => new
|
||
// {
|
||
// x.Id,
|
||
// x.PullStatus,
|
||
// x.SilenceBeforeStart,
|
||
// x.SilenceAfterEnd,
|
||
// x.StartTime,
|
||
// x.EndTime
|
||
// })
|
||
// .ToListAsync();
|
||
//
|
||
// // 初始态-》静默前、拉取中-》静默后
|
||
// var changes = status.Select(x => new
|
||
// {
|
||
// x.Id,
|
||
// PullStatus = x.PullStatus == TrackPullStatus.Init
|
||
// ? x.SilenceBeforeStart > 0
|
||
// ? TrackPullStatus.SilenceBeforeStart
|
||
// : TrackPullStatus.Pulling
|
||
// : x.SilenceAfterEnd > 0
|
||
// ? TrackPullStatus.SilenceAfterEnd
|
||
// : TrackPullStatus.Completed,
|
||
// StartTime =
|
||
// x.PullStatus == TrackPullStatus.Init ? DateTime.Now.AddHours(x.SilenceBeforeStart) : x.StartTime,
|
||
// EndTime = x.PullStatus == TrackPullStatus.Pulling ? DateTime.Now.AddHours(x.SilenceAfterEnd) : x.EndTime
|
||
// });
|
||
// await Context.Updateable<OrderPullStatusEntity>(changes).ExecuteCommandAsync();
|
||
|
||
// 初始态-》静默前
|
||
await Context.Updateable<OrderPullStatusEntity>()
|
||
.SetColumns(x => x.PullStatus == TrackPullStatus.SilenceBeforeStart)
|
||
.SetColumns(x => x.StartTime == DateTime.Now.AddHours(x.SilenceBeforeStart))
|
||
.Where(x => orderIds.Contains(x.OrderId) && x.StartTrackCode == trackCode)
|
||
.Where(x => x.PullStatus == TrackPullStatus.Init)
|
||
.ExecuteCommandAsync();
|
||
|
||
// 拉取中-》静默后
|
||
await Context.Updateable<OrderPullStatusEntity>()
|
||
.SetColumns(x => x.PullStatus == TrackPullStatus.SilenceAfterEnd)
|
||
.SetColumns(x => x.EndTime == DateTime.Now.AddHours(x.SilenceAfterEnd)) // >0才有意义
|
||
.Where(x => orderIds.Contains(x.OrderId) && x.EndTrackCode == trackCode)
|
||
.Where(x => x.PullStatus == TrackPullStatus.Pulling)
|
||
.ExecuteCommandAsync();
|
||
}
|
||
|
||
public async Task<int> UpdatePullStatusBySilenceAsync()
|
||
{
|
||
var cnt1 = await Context.Updateable<OrderPullStatusEntity>()
|
||
.SetColumns(x => x.PullStatus == TrackPullStatus.Pulling)
|
||
.Where(x => x.PullStatus == TrackPullStatus.SilenceBeforeStart && x.StartTime < DateTime.Now)
|
||
.ExecuteCommandAsync();
|
||
_feiShuNotification.Enqueue($"{cnt1}条订单的拉取状态由{nameof(TrackPullStatus.SilenceBeforeStart)}更新为{nameof(TrackPullStatus.Pulling)}", LogLevel.Error);
|
||
|
||
var cnt2 = await Context.Updateable<OrderPullStatusEntity>()
|
||
.SetColumns(x => x.PullStatus == TrackPullStatus.Completed)
|
||
.Where(x => x.PullStatus == TrackPullStatus.SilenceAfterEnd && x.EndTime < DateTime.Now)
|
||
.ExecuteCommandAsync();
|
||
_feiShuNotification.Enqueue($"{cnt2}条订单的拉取状态由{nameof(TrackPullStatus.SilenceAfterEnd)}更新为{nameof(TrackPullStatus.Completed)}", LogLevel.Error);
|
||
|
||
return cnt1 + cnt2;
|
||
}
|
||
|
||
public async Task<int> ClearPullStatusAsync()
|
||
{
|
||
var time = DateTime.Now.Subtract(TimeSpan.FromDays(30));
|
||
return await Context.Deleteable<OrderPullStatusEntity>().Where(x =>
|
||
x.PullStatus == TrackPullStatus.Completed || x.StartTime < time)
|
||
.ExecuteCommandAsync();
|
||
}
|
||
|
||
public async Task<List<FindOrderPullConfigsOutputVO>> FindOrderPullConfigsAsync(
|
||
string appKey,
|
||
TrackOrderType orderType,
|
||
List<string> orderNos)
|
||
{
|
||
if (orderNos.Count == 0)
|
||
{
|
||
return [];
|
||
}
|
||
|
||
return await Context.Queryable<OrderEntity>()
|
||
.InnerJoin<OrderPullStatusEntity>((order, pullStatus) => order.Id == pullStatus.OrderId)
|
||
.Where((order, pullStatus) => order.AppKey == appKey
|
||
&& order.OrderType == orderType
|
||
&& orderNos.Contains(order.OrderNo))
|
||
.Select((order, pullStatus) => new FindOrderPullConfigsOutputVO
|
||
{
|
||
OrderNo = order.OrderNo,
|
||
ServiceCode = pullStatus.ServiceProviderCode,
|
||
PullOrderNo = pullStatus.OrderNo,
|
||
StartCode = pullStatus.StartTrackCode,
|
||
EndCode = pullStatus.EndTrackCode,
|
||
SilenceTime = pullStatus.SilenceBeforeStart,
|
||
StopTime = pullStatus.SilenceAfterEnd,
|
||
PullStatus = pullStatus.PullStatus,
|
||
StartTime = pullStatus.StartTime,
|
||
EndTime = pullStatus.EndTime
|
||
})
|
||
.ToListAsync();
|
||
}
|
||
|
||
public async Task<int> UpdateOrderPullConfigForServiceProviderAsync(
|
||
UpdateOrderPullConfigsInputVo inputVo)
|
||
{
|
||
// tips:如此更新,影响范围是否可控?状态是否正确?
|
||
return await Context.Updateable<OrderPullStatusEntity>()
|
||
.SetColumns(x => x.ServiceProviderCode == inputVo.ServiceCode)
|
||
.SetColumns(x => x.StartTrackCode == inputVo.StartCode)
|
||
.SetColumns(x => x.EndTrackCode == inputVo.EndCode)
|
||
.SetColumns(x => x.SilenceBeforeStart == inputVo.SilenceTime)
|
||
.SetColumns(x => x.SilenceAfterEnd == inputVo.StopTime)
|
||
// 直接将订单拉取状态更新为拉取中,不再考虑性能
|
||
.SetColumns(x => x.StartTime == DateTime.Now)
|
||
.SetColumns(x => x.EndTime == GlobalConst.MaxDateTime)
|
||
.SetColumns(x => x.PullStatus == TrackPullStatus.Pulling)
|
||
.Where(x => inputVo.OrderIds.Contains(x.OrderId))
|
||
.ExecuteCommandAsync();
|
||
}
|
||
|
||
#endregion
|
||
}
|