优化
This commit is contained in:
parent
4a2b87ba36
commit
e0e376404e
@ -7,9 +7,22 @@ public class WarningDto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int TrackStatusId { get; set; }
|
public int TrackStatusId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 子系统id
|
||||||
|
/// </summary>
|
||||||
public int SubSystemId { get; set; }
|
public int SubSystemId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户id
|
||||||
|
/// </summary>
|
||||||
public int CustomerId { get; set; }
|
public int CustomerId { get; set; }
|
||||||
|
|
||||||
public List<WarningOrderDto> Orders { get; set; } = new();
|
public List<WarningOrderDto> Orders { get; set; } = new();
|
||||||
|
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"子系统:{SubSystemId},客户:{CustomerId},订单:{Orders.Select(x => x.Id)
|
||||||
|
.JoinAsString(",")},发生轨迹状态{TrackStatusId}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,16 +2,6 @@ namespace SJZY.Track.Application.Contract.Events;
|
|||||||
|
|
||||||
public class TrackChangeAfterUpdateOrderEvent
|
public class TrackChangeAfterUpdateOrderEvent
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 子系统id
|
|
||||||
/// </summary>
|
|
||||||
public int SubSystemId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 客户id
|
|
||||||
/// </summary>
|
|
||||||
public int CustomId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 订单Id
|
/// 订单Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -32,11 +22,6 @@ public class TrackChangeAfterUpdateOrderEvent
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string TrackEnContent { get; set; } = null!;
|
public string TrackEnContent { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 轨迹状态Id
|
|
||||||
/// </summary>
|
|
||||||
public int TrackStatusId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 轨迹发生地
|
/// 轨迹发生地
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -52,11 +37,6 @@ public class TrackChangeAfterUpdateOrderEvent
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float TrackTimeZone { get; set; }
|
public float TrackTimeZone { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 轨迹内容代码
|
|
||||||
/// </summary>
|
|
||||||
public string? TrackCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种
|
/// 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
namespace SJZY.Track.Application.Contract.Events;
|
||||||
|
|
||||||
|
public class TrackWarningCalcEvent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 子系统id
|
||||||
|
/// </summary>
|
||||||
|
public int SubSystemId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户id
|
||||||
|
/// </summary>
|
||||||
|
public int CustomId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 轨迹状态Id
|
||||||
|
/// </summary>
|
||||||
|
public int TrackStatusId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单id
|
||||||
|
/// </summary>
|
||||||
|
public int[] OrderIds { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 轨迹发生时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime TrackTime { get; set; }
|
||||||
|
}
|
||||||
@ -1,8 +1,6 @@
|
|||||||
using DotNetCore.CAP;
|
using DotNetCore.CAP;
|
||||||
using SJZY.Expand.ABP.Core.Logger;
|
using SJZY.Expand.ABP.Core.Logger;
|
||||||
using SJZY.Track.Application.Contract.Dtos.Forewarning;
|
|
||||||
using SJZY.Track.Application.Contract.Events;
|
using SJZY.Track.Application.Contract.Events;
|
||||||
using SJZY.Track.Application.Contract.Services;
|
|
||||||
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
@ -10,14 +8,11 @@ namespace SJZY.Track.Application.CAP.EventHandlers;
|
|||||||
|
|
||||||
public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICapSubscribe
|
public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICapSubscribe
|
||||||
{
|
{
|
||||||
private readonly IForewarningNotifyService _forewarningNotifyService;
|
|
||||||
private readonly IOrderRepository _orderRepository;
|
private readonly IOrderRepository _orderRepository;
|
||||||
|
|
||||||
public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository,
|
public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository)
|
||||||
IForewarningNotifyService forewarningNotifyService)
|
|
||||||
{
|
{
|
||||||
_orderRepository = orderRepository;
|
_orderRepository = orderRepository;
|
||||||
_forewarningNotifyService = forewarningNotifyService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)]
|
[CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)]
|
||||||
@ -27,7 +22,7 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
|
|||||||
|
|
||||||
if (orders.Count == 0)
|
if (orders.Count == 0)
|
||||||
{
|
{
|
||||||
LogHelper.Warn("没有找到订单信息,无法更新轨迹信息");
|
LogHelper.Warn($"没有找到订单信息:{@event.OrderIds.JoinAsString(",")},无法更新轨迹信息");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +69,6 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
|
|||||||
x.LatestTrackTimeZone,
|
x.LatestTrackTimeZone,
|
||||||
x.DeficiencyTag
|
x.DeficiencyTag
|
||||||
});
|
});
|
||||||
|
|
||||||
// 预警计算
|
|
||||||
await _forewarningNotifyService.WarningCalculateAsync(BuiltWarningDto(orders, @event));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<OrderEntity>> GetOrdersAsync(int[] orderIds)
|
private async Task<List<OrderEntity>> GetOrdersAsync(int[] orderIds)
|
||||||
@ -92,41 +84,6 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
|
|||||||
LatestTrackPlace = order.LatestTrackPlace,
|
LatestTrackPlace = order.LatestTrackPlace,
|
||||||
LatestTrackTime = order.LatestTrackTime,
|
LatestTrackTime = order.LatestTrackTime,
|
||||||
LatestTrackTimeZone = order.LatestTrackTimeZone,
|
LatestTrackTimeZone = order.LatestTrackTimeZone,
|
||||||
|
|
||||||
// 因素
|
|
||||||
CargoType = order.CargoType,
|
|
||||||
CreateTime = order.CreateTime,
|
|
||||||
ArrivalCountry = order.ArrivalCountry,
|
|
||||||
ArrivalProvince = order.ArrivalProvince,
|
|
||||||
ArrivalCity = order.ArrivalCity,
|
|
||||||
ArrivalPostCode = order.ArrivalPostCode,
|
|
||||||
IsTransit = order.IsTransit,
|
|
||||||
LeavePort = order.LeavePort,
|
|
||||||
ProductCode = order.ProductCode,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private WarningDto BuiltWarningDto(List<OrderEntity> orders, TrackChangeAfterUpdateOrderEvent @event)
|
|
||||||
{
|
|
||||||
return new WarningDto
|
|
||||||
{
|
|
||||||
TrackStatusId = @event.TrackStatusId,
|
|
||||||
SubSystemId = @event.SubSystemId,
|
|
||||||
CustomerId = @event.CustomId,
|
|
||||||
Orders = orders.Select(order => new WarningOrderDto
|
|
||||||
{
|
|
||||||
Id = order.Id,
|
|
||||||
TrackTime = @event.TrackTime,
|
|
||||||
CargoType = order.CargoType,
|
|
||||||
Month = order.CreateTime.Month,
|
|
||||||
IsTransit = order.IsTransit,
|
|
||||||
LeavePort = order.LeavePort,
|
|
||||||
ProductCode = order.ProductCode,
|
|
||||||
ArrivalCountry = order.ArrivalCountry,
|
|
||||||
ArrivalProvince = order.ArrivalProvince,
|
|
||||||
ArrivalCity = order.ArrivalCity,
|
|
||||||
ArrivalPostCode = order.ArrivalPostCode,
|
|
||||||
}).ToList()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ using SJZY.Expand.ABP.Core.PublicMethords;
|
|||||||
using SJZY.Track.Application.Contract.Events;
|
using SJZY.Track.Application.Contract.Events;
|
||||||
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
||||||
|
using SJZY.Track.Domain.Dtos.TrackContents;
|
||||||
using SJZY.Track.Domain.Queries;
|
using SJZY.Track.Domain.Queries;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
using OrderIdentifier = SJZY.Track.Application.Contract.Events.OrderIdentifier;
|
using OrderIdentifier = SJZY.Track.Application.Contract.Events.OrderIdentifier;
|
||||||
@ -135,12 +136,74 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var insertTracks = await UpsertTrackAsync(@event, canNextOrderIds, trackContent);
|
||||||
|
|
||||||
|
if (canNextOrderIds.Count == 0) return;
|
||||||
|
|
||||||
|
if (insertTracks.Any())
|
||||||
|
{
|
||||||
|
// 批量add to es
|
||||||
|
await _trackDetailsEsRepository.AddManyAsync(insertTracks);
|
||||||
|
|
||||||
|
// 添加轨迹触发订单拉取状态更新
|
||||||
|
await _orderRepository.UpdatePullStatusToSilenceAsync(insertTracks.Select(x => x.OrderId).ToList(),
|
||||||
|
@event.TrackCode);
|
||||||
|
|
||||||
|
// 添加轨迹触发预警计算(异步)
|
||||||
|
await _capPublisher.PublishAsync(GlobalConst.TrackWarningCalcSubscribe, new TrackWarningCalcEvent
|
||||||
|
{
|
||||||
|
SubSystemId = @event.SubSystemId,
|
||||||
|
CustomId = @event.CustomId,
|
||||||
|
OrderIds = canNextOrderIds.ToArray(),
|
||||||
|
TrackStatusId = trackContent.TrackStatusId,
|
||||||
|
TrackTime = @event.TrackTime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 触发订单主表更新事件(异步)
|
||||||
|
await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe,
|
||||||
|
new TrackChangeAfterUpdateOrderEvent
|
||||||
|
{
|
||||||
|
OrderIds = canNextOrderIds.ToArray(),
|
||||||
|
IsCompleted = trackContent.IsCompleted,
|
||||||
|
TrackContent = trackContent.TrackContent,
|
||||||
|
TrackEnContent = trackContent.TrackEnContent,
|
||||||
|
TrackPlace = @event.TrackPlace,
|
||||||
|
TrackTime = @event.TrackTime,
|
||||||
|
TrackTimeZone = @event.TrackTimeZone,
|
||||||
|
DeficiencyTagValue = @event.DeficiencyTagValue
|
||||||
|
});
|
||||||
|
|
||||||
|
// 触发轨迹推送事件(异步)
|
||||||
|
var trackPushEvent = new TrackPushEvent
|
||||||
|
{
|
||||||
|
OptionType = @event.IsAdd ? OptionType.新增 : OptionType.修改,
|
||||||
|
SubSystemId = @event.SubSystemId,
|
||||||
|
CustomId = @event.CustomId,
|
||||||
|
OrderIds = canNextOrderIds.ToArray(),
|
||||||
|
TrackCode = @event.TrackCode,
|
||||||
|
SystemPushInfo = new SystemPushStruct
|
||||||
|
{
|
||||||
|
TrackStatus = trackContent.TrackStatus,
|
||||||
|
TrackContent = trackContent.TrackContent,
|
||||||
|
TrackPlace = @event.TrackPlace,
|
||||||
|
TrackTime = @event.TrackTime,
|
||||||
|
TrackTimeZone = @event.TrackTimeZone
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<TrackDetailsIndex>> UpsertTrackAsync(TrackUpsertEvent @event, List<int> canNextOrderIds,
|
||||||
|
TrackContentVO trackContent)
|
||||||
|
{
|
||||||
var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray();
|
var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray();
|
||||||
|
|
||||||
// important:轨迹code相同,时间、发生地不同的,可能存在多条!!
|
// important:轨迹code相同,时间、发生地不同的,可能存在多条!!
|
||||||
var tracks = await _trackDetailsEsRepository.GetListAsync(orderIds, @event.TrackCode, true);
|
var tracks = await _trackDetailsEsRepository.GetListAsync(orderIds, @event.TrackCode, true);
|
||||||
|
|
||||||
var insertTracks = new List<TrackDetailsIndex>();
|
var insertTracks = new List<TrackDetailsIndex>();
|
||||||
|
var updateTracks = new List<TrackDetailsIndex>();
|
||||||
|
|
||||||
foreach (var order in @event.OrderIdentifiers)
|
foreach (var order in @event.OrderIdentifiers)
|
||||||
{
|
{
|
||||||
@ -204,59 +267,17 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
track.UpdateUser = @event.OperationMan ?? GlobalConst.SystemUser;
|
track.UpdateUser = @event.OperationMan ?? GlobalConst.SystemUser;
|
||||||
track.UpdateTime = DateTime.Now;
|
track.UpdateTime = DateTime.Now;
|
||||||
|
|
||||||
await _trackDetailsEsRepository.UpdateAsync(track);
|
updateTracks.Add(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
canNextOrderIds.Add(order.OrderId);
|
canNextOrderIds.Add(order.OrderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canNextOrderIds.Count == 0) return;
|
if (updateTracks.Any())
|
||||||
|
|
||||||
if (insertTracks.Any())
|
|
||||||
{
|
{
|
||||||
// 批量add to es
|
await _trackDetailsEsRepository.UpdateManyAsync(updateTracks);
|
||||||
await _trackDetailsEsRepository.AddManyAsync(insertTracks);
|
|
||||||
|
|
||||||
// add track触发订单拉取状态更新
|
|
||||||
await _orderRepository.UpdatePullStatusToSilenceAsync(insertTracks.Select(x => x.OrderId).ToList(),
|
|
||||||
@event.TrackCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发订单主表更新事件(异步)
|
return insertTracks;
|
||||||
await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe,
|
|
||||||
new TrackChangeAfterUpdateOrderEvent
|
|
||||||
{
|
|
||||||
SubSystemId = @event.SubSystemId,
|
|
||||||
CustomId = @event.CustomId,
|
|
||||||
OrderIds = canNextOrderIds.ToArray(),
|
|
||||||
IsCompleted = trackContent.IsCompleted,
|
|
||||||
TrackContent = trackContent.TrackContent,
|
|
||||||
TrackEnContent = trackContent.TrackEnContent,
|
|
||||||
TrackStatusId = trackContent.TrackStatusId,
|
|
||||||
TrackPlace = @event.TrackPlace,
|
|
||||||
TrackTime = @event.TrackTime,
|
|
||||||
TrackTimeZone = @event.TrackTimeZone,
|
|
||||||
TrackCode = @event.TrackCode,
|
|
||||||
DeficiencyTagValue = @event.DeficiencyTagValue
|
|
||||||
});
|
|
||||||
|
|
||||||
// 触发轨迹推送事件(异步)
|
|
||||||
var trackPushEvent = new TrackPushEvent
|
|
||||||
{
|
|
||||||
OptionType = @event.IsAdd ? OptionType.新增 : OptionType.修改,
|
|
||||||
SubSystemId = @event.SubSystemId,
|
|
||||||
CustomId = @event.CustomId,
|
|
||||||
OrderIds = canNextOrderIds.ToArray(),
|
|
||||||
TrackCode = @event.TrackCode,
|
|
||||||
SystemPushInfo = new SystemPushStruct
|
|
||||||
{
|
|
||||||
TrackStatus = trackContent.TrackStatus,
|
|
||||||
TrackContent = trackContent.TrackContent,
|
|
||||||
TrackPlace = @event.TrackPlace,
|
|
||||||
TrackTime = @event.TrackTime,
|
|
||||||
TrackTimeZone = @event.TrackTimeZone
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,75 @@
|
|||||||
|
using DotNetCore.CAP;
|
||||||
|
using SJZY.Expand.ABP.Core.Logger;
|
||||||
|
using SJZY.Track.Application.Contract.Dtos.Forewarning;
|
||||||
|
using SJZY.Track.Application.Contract.Events;
|
||||||
|
using SJZY.Track.Application.Contract.Services;
|
||||||
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
|
namespace SJZY.Track.Application.CAP.EventHandlers;
|
||||||
|
|
||||||
|
public class TrackWarningCalcEventHandler : ITransientDependency, ICapSubscribe
|
||||||
|
{
|
||||||
|
private readonly IForewarningNotifyService _forewarningNotifyService;
|
||||||
|
private readonly IOrderRepository _orderRepository;
|
||||||
|
|
||||||
|
public TrackWarningCalcEventHandler(IOrderRepository orderRepository,
|
||||||
|
IForewarningNotifyService forewarningNotifyService)
|
||||||
|
{
|
||||||
|
_orderRepository = orderRepository;
|
||||||
|
_forewarningNotifyService = forewarningNotifyService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CapSubscribe(GlobalConst.TrackWarningCalcSubscribe)]
|
||||||
|
public async Task ConsumerAsync(TrackWarningCalcEvent @event)
|
||||||
|
{
|
||||||
|
var orders = await _orderRepository.GetListAsync(order => @event.OrderIds.Contains(order.Id), order =>
|
||||||
|
new OrderEntity
|
||||||
|
{
|
||||||
|
Id = order.Id,
|
||||||
|
// 因素
|
||||||
|
CargoType = order.CargoType,
|
||||||
|
CreateTime = order.CreateTime,
|
||||||
|
ArrivalCountry = order.ArrivalCountry,
|
||||||
|
ArrivalProvince = order.ArrivalProvince,
|
||||||
|
ArrivalCity = order.ArrivalCity,
|
||||||
|
ArrivalPostCode = order.ArrivalPostCode,
|
||||||
|
IsTransit = order.IsTransit,
|
||||||
|
LeavePort = order.LeavePort,
|
||||||
|
ProductCode = order.ProductCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (orders.Count == 0)
|
||||||
|
{
|
||||||
|
LogHelper.Warn($"没有找到订单信息:{@event.OrderIds.JoinAsString(",")},无法做轨迹预警计算");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预警计算
|
||||||
|
await _forewarningNotifyService.WarningCalculateAsync(BuiltWarningDto(orders, @event));
|
||||||
|
}
|
||||||
|
|
||||||
|
private WarningDto BuiltWarningDto(List<OrderEntity> orders, TrackWarningCalcEvent @event)
|
||||||
|
{
|
||||||
|
return new WarningDto
|
||||||
|
{
|
||||||
|
TrackStatusId = @event.TrackStatusId,
|
||||||
|
SubSystemId = @event.SubSystemId,
|
||||||
|
CustomerId = @event.CustomId,
|
||||||
|
Orders = orders.Select(order => new WarningOrderDto
|
||||||
|
{
|
||||||
|
Id = order.Id,
|
||||||
|
TrackTime = @event.TrackTime,
|
||||||
|
CargoType = order.CargoType,
|
||||||
|
Month = order.CreateTime.Month,
|
||||||
|
IsTransit = order.IsTransit,
|
||||||
|
LeavePort = order.LeavePort,
|
||||||
|
ProductCode = order.ProductCode,
|
||||||
|
ArrivalCountry = order.ArrivalCountry,
|
||||||
|
ArrivalProvince = order.ArrivalProvince,
|
||||||
|
ArrivalCity = order.ArrivalCity,
|
||||||
|
ArrivalPostCode = order.ArrivalPostCode,
|
||||||
|
}).ToList()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -89,25 +89,28 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
}
|
}
|
||||||
|
|
||||||
var redisKey = GetForewarningNotifySetKeyRedisKey(dto.SubSystemId);
|
var redisKey = GetForewarningNotifySetKeyRedisKey(dto.SubSystemId);
|
||||||
|
long addCounter, delCounter = 0;
|
||||||
|
|
||||||
var tran = RedisHelper.Client.Multi();
|
var tran = RedisHelper.Client.Multi();
|
||||||
|
|
||||||
// 左区间加入预警队列
|
// 左区间加入预警队列,【只有第一次发生的才会被加入】
|
||||||
await tran.ZAddAsync(redisKey, adds.Select(x =>
|
addCounter = await tran.ZAddNxAsync(redisKey, adds.Select(x =>
|
||||||
{
|
{
|
||||||
var entry = new WarningNotifyCacheEntry(x.ruleId, x.orderId, x.counter);
|
var entry = new WarningNotifyCacheEntry(x.ruleId, x.orderId, x.counter);
|
||||||
return new ZMember(entry.ToString(), x.ts);
|
return new ZMember(entry.ToString(), x.ts);
|
||||||
}).ToArray());
|
}).ToArray());
|
||||||
|
|
||||||
// 右区间移出预警队列
|
// 右区间移出预警队列,【只要发生了就移除】
|
||||||
var right = dels.Select(x => new WarningNotifyCacheEntry(x.ruleId, x.orderId, x.counter)).ToList();
|
var right = dels.Select(x => new WarningNotifyCacheEntry(x.ruleId, x.orderId, x.counter)).ToList();
|
||||||
if (!right.IsNullOrEmpty())
|
if (!right.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
await tran.ZRemAsync(redisKey, right.Select(x => x.ToString()).ToArray());
|
delCounter = await tran.ZRemAsync(redisKey, right.Select(x => x.ToString()).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
tran.Exec();
|
tran.Exec();
|
||||||
|
|
||||||
|
LogHelper.Info($"本次共计产生{addCounter}条预警,移除{delCounter}条预警,触发缘由是");
|
||||||
|
|
||||||
await _warningRecordEsRepository.BulkUpdateAsync(dels); // 标记处理完成
|
await _warningRecordEsRepository.BulkUpdateAsync(dels); // 标记处理完成
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,21 +130,21 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
var ruleIds = entries.Select(x => x.RuleId).Distinct().ToList();
|
var ruleIds = entries.Select(x => x.RuleId).Distinct().ToList();
|
||||||
var notifyRules = await _warningQueries.GetWarningNotifyRulesAsync(ruleIds);
|
var notifyRules = await _warningQueries.GetWarningNotifyRulesAsync(ruleIds);
|
||||||
|
|
||||||
var userRules = new Dictionary<int, List<GetWarningNotifiesVo>>();
|
|
||||||
foreach (var rule in notifyRules)
|
|
||||||
{
|
|
||||||
foreach (var userId in rule.NotifyUserIds)
|
|
||||||
{
|
|
||||||
if (!userRules.ContainsKey(userId))
|
|
||||||
{
|
|
||||||
userRules[userId] = new List<GetWarningNotifiesVo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
userRules[userId].Add(rule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入es预警记录
|
// 写入es预警记录
|
||||||
|
var warningRecords = await WriteWarningRecordAsync(entries, notifyRules);
|
||||||
|
|
||||||
|
// 发通知
|
||||||
|
await SendCoreAsync(entries, notifyRules);
|
||||||
|
|
||||||
|
// 移除已处理的预警
|
||||||
|
await RedisHelper.Client.ZRemRangeByScoreAsync(redisKey, 0, timestamp);
|
||||||
|
|
||||||
|
return warningRecords.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<WarningRecordIndex>> WriteWarningRecordAsync(List<WarningNotifyCacheEntry> entries,
|
||||||
|
List<GetWarningNotifiesVo> notifyRules)
|
||||||
|
{
|
||||||
var warningRecords = new List<WarningRecordIndex>();
|
var warningRecords = new List<WarningRecordIndex>();
|
||||||
foreach (var entry in entries)
|
foreach (var entry in entries)
|
||||||
{
|
{
|
||||||
@ -163,9 +166,25 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _warningRecordEsRepository.BulkInsertAsync(warningRecords);
|
await _warningRecordEsRepository.BulkInsertAsync(warningRecords);
|
||||||
|
return warningRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task SendCoreAsync(List<WarningNotifyCacheEntry> entries, List<GetWarningNotifiesVo> notifyRules)
|
||||||
|
{
|
||||||
|
var userRules = new Dictionary<int, List<GetWarningNotifiesVo>>();
|
||||||
|
foreach (var rule in notifyRules)
|
||||||
|
{
|
||||||
|
foreach (var userId in rule.NotifyUserIds)
|
||||||
|
{
|
||||||
|
if (!userRules.ContainsKey(userId))
|
||||||
|
{
|
||||||
|
userRules[userId] = new List<GetWarningNotifiesVo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
userRules[userId].Add(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 发通知
|
|
||||||
foreach (var userRule in userRules)
|
foreach (var userRule in userRules)
|
||||||
{
|
{
|
||||||
var siteInternalContent = BuildNotifyContent(userRule.Value, entries, NotifyMode.SiteInternal);
|
var siteInternalContent = BuildNotifyContent(userRule.Value, entries, NotifyMode.SiteInternal);
|
||||||
@ -173,48 +192,62 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(siteInternalContent))
|
if (!string.IsNullOrEmpty(siteInternalContent))
|
||||||
{
|
{
|
||||||
// todo:发送站内通知
|
_ = Task.Run(async () =>
|
||||||
_ = _requestSendMessageService.Service.SendMessageByEmptyTemplateAsync(
|
{
|
||||||
new SendMessageByEmptyTemplateInput
|
// todo:发送站内通知
|
||||||
|
var res = await _requestSendMessageService.Service.SendMessageByEmptyTemplateAsync(
|
||||||
|
new SendMessageByEmptyTemplateInput
|
||||||
|
{
|
||||||
|
IsNeedToHandle = null,
|
||||||
|
BizId = null,
|
||||||
|
MsgSource = null,
|
||||||
|
SystemId = 0,
|
||||||
|
TemplateCode = null,
|
||||||
|
Channels = null,
|
||||||
|
MsgTitle = null,
|
||||||
|
MsgContent = null,
|
||||||
|
PcURl = null,
|
||||||
|
MobileURl = null,
|
||||||
|
FileUrl = null,
|
||||||
|
fileName = null,
|
||||||
|
receivers = null,
|
||||||
|
SiteLetterComponentStyle = (ComponentStyle) 0
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.Code != GlobalConst.SuccessCode)
|
||||||
{
|
{
|
||||||
IsNeedToHandle = null,
|
LogHelper.Error($"发送站内通知失败,用户:{userRule.Key},内容:{siteInternalContent}");
|
||||||
BizId = null,
|
}
|
||||||
MsgSource = null,
|
});
|
||||||
SystemId = 0,
|
|
||||||
TemplateCode = null,
|
|
||||||
Channels = null,
|
|
||||||
MsgTitle = null,
|
|
||||||
MsgContent = null,
|
|
||||||
PcURl = null,
|
|
||||||
MobileURl = null,
|
|
||||||
FileUrl = null,
|
|
||||||
fileName = null,
|
|
||||||
receivers = null,
|
|
||||||
SiteLetterComponentStyle = (ComponentStyle) 0
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(feiShuContent))
|
if (!string.IsNullOrEmpty(feiShuContent))
|
||||||
{
|
{
|
||||||
// 发送飞书通知
|
_ = Task.Run(async () =>
|
||||||
_ = _messageClient.SendMessageAsync(new SendMessageInput
|
|
||||||
{
|
{
|
||||||
AppId = null,
|
// 发送飞书通知
|
||||||
AppSecret = null,
|
var res = await _messageClient.SendMessageAsync(new SendMessageInput
|
||||||
ReceiveIdType = IdTypeEnums.user_id,
|
|
||||||
MsgType = MsgTypeEnums.文本,
|
|
||||||
ReceiveIds = new List<string>
|
|
||||||
{
|
{
|
||||||
userRule.Key.ToString()
|
AppId = null,
|
||||||
},
|
AppSecret = null,
|
||||||
Content = feiShuContent
|
ReceiveIdType = IdTypeEnums.user_id,
|
||||||
|
MsgType = MsgTypeEnums.文本,
|
||||||
|
ReceiveIds = new List<string>
|
||||||
|
{
|
||||||
|
userRule.Key.ToString()
|
||||||
|
},
|
||||||
|
Content = feiShuContent
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.Code != GlobalConst.SuccessCode)
|
||||||
|
{
|
||||||
|
LogHelper.Error($"发送飞书通知失败,用户:{userRule.Key},内容:{feiShuContent}");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await RedisHelper.Client.ZRemRangeByScoreAsync(redisKey, 0, timestamp);
|
return Task.CompletedTask;
|
||||||
|
|
||||||
return warningRecords.Count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetForewarningNotifySetKeyRedisKey(int subSystemId) =>
|
private string GetForewarningNotifySetKeyRedisKey(int subSystemId) =>
|
||||||
@ -259,6 +292,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
var res = new List<ForewarningRuleCacheEntry>();
|
var res = new List<ForewarningRuleCacheEntry>();
|
||||||
foreach (var rule in rules)
|
foreach (var rule in rules)
|
||||||
{
|
{
|
||||||
|
// 规则至少有一个因素,如果订单任一因素不符合则不命中
|
||||||
if (rule.IsTransit != null)
|
if (rule.IsTransit != null)
|
||||||
{
|
{
|
||||||
if (order.IsTransit != rule.IsTransit) continue;
|
if (order.IsTransit != rule.IsTransit) continue;
|
||||||
@ -287,7 +321,8 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
if (!rule.Areas.IsNullOrEmpty())
|
if (!rule.Areas.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
var inArea = false;
|
var inArea = false;
|
||||||
foreach (var area in rule.Areas!.Where(area => order.ArrivalCountry == area.Country))
|
var areas = rule.Areas!.Where(area => order.ArrivalCountry == area.Country).ToList();
|
||||||
|
foreach (var area in areas)
|
||||||
{
|
{
|
||||||
if (!area.LeftPostcode.IsNullOrEmpty() && !area.RightPostcode.IsNullOrEmpty())
|
if (!area.LeftPostcode.IsNullOrEmpty() && !area.RightPostcode.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
@ -296,12 +331,31 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
string.CompareOrdinal(order.ArrivalPostCode, area.RightPostcode) > 0) continue;
|
string.CompareOrdinal(order.ArrivalPostCode, area.RightPostcode) > 0) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!area.City.IsNullOrEmpty() && order.ArrivalCity != area.City) continue;
|
|
||||||
if (!area.Province.IsNullOrEmpty() && order.ArrivalProvince != area.Province) continue;
|
|
||||||
inArea = true;
|
inArea = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!inArea)
|
||||||
|
{
|
||||||
|
foreach (var area in areas)
|
||||||
|
{
|
||||||
|
if (!area.City.IsNullOrEmpty() && order.ArrivalCity != area.City) continue;
|
||||||
|
inArea = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inArea)
|
||||||
|
{
|
||||||
|
foreach (var area in areas)
|
||||||
|
{
|
||||||
|
if (!area.Province.IsNullOrEmpty() && order.ArrivalProvince != area.Province) continue;
|
||||||
|
inArea = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!inArea) continue;
|
if (!inArea) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,8 @@ public interface ITrackDetailsEsRepository : IElasticsearchClientService<TrackDe
|
|||||||
|
|
||||||
Task UpdateAsync(TrackDetailsIndex index);
|
Task UpdateAsync(TrackDetailsIndex index);
|
||||||
|
|
||||||
|
Task UpdateManyAsync(List<TrackDetailsIndex> indexes, int maxRetries = 3);
|
||||||
|
|
||||||
Task AddManyAsync(List<TrackDetailsIndex> index);
|
Task AddManyAsync(List<TrackDetailsIndex> index);
|
||||||
|
|
||||||
Task AddAsync(TrackDetailsIndex track);
|
Task AddAsync(TrackDetailsIndex track);
|
||||||
|
|||||||
@ -50,5 +50,5 @@ public partial class GlobalConst
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 预警计算任务
|
/// 预警计算任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string TrackWarningCalc = "SJZY.Track.TrackWarningCalc";
|
public const string TrackWarningCalcSubscribe = "SJZY.Track.TrackWarningCalc";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,6 +154,57 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task UpdateManyAsync(List<TrackDetailsIndex> indexes, int maxRetries = 3)
|
||||||
|
{
|
||||||
|
var retryCount = 0;
|
||||||
|
var updateSuccessful = false;
|
||||||
|
var track = indexes.First();
|
||||||
|
|
||||||
|
while (retryCount < maxRetries && !updateSuccessful)
|
||||||
|
{
|
||||||
|
var response = await Context.UpdateByQueryAsync<TrackDetailsIndex>(u => u
|
||||||
|
.Index(GlobalConst.TrackDetailsIndex)
|
||||||
|
.Query(q => q
|
||||||
|
.Ids(t => t.Values(indexes.Select(x => x.Id)))
|
||||||
|
)
|
||||||
|
.Script(s => s
|
||||||
|
.Source(@"
|
||||||
|
ctx._source.TrackPlace = params.trackPlace;
|
||||||
|
ctx._source.TrackTime = params.trackTime;
|
||||||
|
ctx._source.TrackTimeZone = params.trackTimeZone;
|
||||||
|
ctx._source.UpdateUser = params.updateUser;
|
||||||
|
ctx._source.UpdateTime = params.updateTime;
|
||||||
|
")
|
||||||
|
.Params(p => p
|
||||||
|
.Add("trackPlace", track.TrackPlace)
|
||||||
|
.Add("trackTime", track.TrackTime)
|
||||||
|
.Add("trackTimeZone", track.TrackTimeZone)
|
||||||
|
.Add("updateUser", track.UpdateUser)
|
||||||
|
.Add("updateTime", DateTime.Now)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.IsValid)
|
||||||
|
{
|
||||||
|
updateSuccessful = true;
|
||||||
|
}
|
||||||
|
else if (response.ServerError?.Status == 409) // 409 表示版本冲突
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount >= maxRetries)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"轨迹更新冲突达到最大次数,track:{indexes.Count}条,原因:{response.DebugInformation}。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"轨迹更新失败,track:{indexes.Count}条,原因:{response.DebugInformation}。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task AddManyAsync(List<TrackDetailsIndex> tracks)
|
public async Task AddManyAsync(List<TrackDetailsIndex> tracks)
|
||||||
{
|
{
|
||||||
// 按天写入es
|
// 按天写入es
|
||||||
|
|||||||
@ -49,7 +49,7 @@ public class WarningRecordEsRepository : ElasticSearchContextAbstract<WarningRec
|
|||||||
foreach (var rule in rules)
|
foreach (var rule in rules)
|
||||||
{
|
{
|
||||||
var r = await Context.UpdateByQueryAsync<WarningRecordIndex>(u => u
|
var r = await Context.UpdateByQueryAsync<WarningRecordIndex>(u => u
|
||||||
.Index($"{GlobalConst.TrackWarningRecordIndex}-*")
|
.Index(GlobalConst.TrackWarningRecordIndex)
|
||||||
.Query(q =>
|
.Query(q =>
|
||||||
q.Term(f => f.RuleId, rule.ruleId)
|
q.Term(f => f.RuleId, rule.ruleId)
|
||||||
&& q.Term(f => f.OrderId, rule.orderId)
|
&& q.Term(f => f.OrderId, rule.orderId)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user