This commit is contained in:
xiaolipro 2024-09-07 18:14:17 +08:00
parent 8bf76305fe
commit b39d84655d
38 changed files with 621 additions and 180 deletions

View File

@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=dels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SJZY/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/UserDictionary/Words/=SJZY/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -20,7 +20,7 @@ public class EditWarningOutput
public int CustomerId { get; set; } public int CustomerId { get; set; }
/// <summary> /// <summary>
/// 通知列表 /// 轨迹状态列表
/// </summary> /// </summary>
public List<WarningNotifyWithIdDto> TrackStatusSpans { get; set; } = new(); public List<WarningNotifyWithIdDto> TrackStatusSpans { get; set; } = new();

View File

@ -29,6 +29,11 @@ public class WarningNotifyDto
/// </summary> /// </summary>
public List<int> NotifyUserIds { get; set; } public List<int> NotifyUserIds { get; set; }
/// <summary>
/// 通知人
/// </summary>
public List<string> NotifyUsers { get; set; }
/// <summary> /// <summary>
/// 通知方式 /// 通知方式
/// </summary> /// </summary>

View File

@ -10,7 +10,7 @@ public class WarningNotifyCacheEntry
public WarningNotifyCacheEntry(string notifyValue) public WarningNotifyCacheEntry(string notifyValue)
{ {
var values = notifyValue.Split(':'); var values = notifyValue.Split('_');
RuleId = int.Parse(values[0]); RuleId = int.Parse(values[0]);
OrderId = int.Parse(values[1]); OrderId = int.Parse(values[1]);
} }
@ -27,6 +27,6 @@ public class WarningNotifyCacheEntry
public override string ToString() public override string ToString()
{ {
return $"{RuleId}:{OrderId}"; return $"{RuleId}_{OrderId}";
} }
} }

View File

@ -1,9 +1,9 @@
using DotNetCore.CAP; using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Track.Application.Contract.Dtos.Forewarning; 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.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Queries;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace SJZY.Track.Application.CAP.EventHandlers; namespace SJZY.Track.Application.CAP.EventHandlers;
@ -12,17 +12,12 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
{ {
private readonly IForewarningNotifyService _forewarningNotifyService; private readonly IForewarningNotifyService _forewarningNotifyService;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly IProvideQueries _provideQueries;
private readonly ITrackPullCacheService _trackPullCacheService;
public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository, public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository,
IForewarningNotifyService forewarningNotifyService, ITrackPullCacheService trackPullCacheService, IForewarningNotifyService forewarningNotifyService)
IProvideQueries provideQueries)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_forewarningNotifyService = forewarningNotifyService; _forewarningNotifyService = forewarningNotifyService;
_trackPullCacheService = trackPullCacheService;
_provideQueries = provideQueries;
} }
[CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)] [CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)]
@ -30,7 +25,11 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
{ {
var orders = await GetOrdersAsync(@event.OrderIds); var orders = await GetOrdersAsync(@event.OrderIds);
if (orders.Count == 0) return; if (orders.Count == 0)
{
LogHelper.Warn("没有找到订单信息,无法更新轨迹信息");
return;
}
var updateOrders = new List<OrderEntity>(); var updateOrders = new List<OrderEntity>();
foreach (var order in orders) foreach (var order in orders)
@ -46,7 +45,7 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
} }
// 执行轨迹兜底时 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种 // 执行轨迹兜底时 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种
if (@event.DeficiencyTagValue > 0 && @event.DeficiencyTagValue <= 3) if (@event.DeficiencyTagValue is > 0 and <= 3)
{ {
order.DeficiencyTag = @event.DeficiencyTagValue; order.DeficiencyTag = @event.DeficiencyTagValue;
} }

View File

@ -14,15 +14,16 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
private readonly ICapPublisher _capPublisher; private readonly ICapPublisher _capPublisher;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly IProvideQueries _provideQueries; private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
public TrackDeleteEventHandler(IProvideQueries provideQueries, public TrackDeleteEventHandler(IProvideQueries provideQueries,
IOrderRepository orderRepository, ICapPublisher capPublisher, ITrackDetailsRepository trackDetailsRepository) IOrderRepository orderRepository, ICapPublisher capPublisher,
ITrackDetailsEsRepository trackDetailsEsRepository)
{ {
_provideQueries = provideQueries; _provideQueries = provideQueries;
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
} }
[CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)] [CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)]
@ -104,9 +105,9 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
private async Task DeleteTrackAsync(TrackDeleteEvent @event) private async Task DeleteTrackAsync(TrackDeleteEvent @event)
{ {
// 删除轨迹(删的是同子系统下的单,所以code是统一的) // 删除轨迹(删的是同子系统下的单,所以code是统一的)
var tracks = await _trackDetailsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes); var tracks = await _trackDetailsEsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes);
await _trackDetailsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes); await _trackDetailsEsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes);
var orders = await _orderRepository.GetListAsync(x => @event.OrderIds.Contains(x.Id), var orders = await _orderRepository.GetListAsync(x => @event.OrderIds.Contains(x.Id),
x => new OrderEntity x => new OrderEntity

View File

@ -13,12 +13,12 @@ namespace SJZY.Track.Application.CAP.EventHandlers;
public class TrackPushCompletedEventHandler : ITransientDependency, ICapSubscribe public class TrackPushCompletedEventHandler : ITransientDependency, ICapSubscribe
{ {
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITrackPushRecordsRepository _trackPushRecordsRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository;
public TrackPushCompletedEventHandler(ITrackPushRecordsRepository trackPushRecordsRepository, public TrackPushCompletedEventHandler(ITrackPushRecordEsRepository trackPushRecordEsRepository,
IOrderRepository orderRepository) IOrderRepository orderRepository)
{ {
_trackPushRecordsRepository = trackPushRecordsRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository;
_orderRepository = orderRepository; _orderRepository = orderRepository;
} }
@ -45,7 +45,7 @@ public class TrackPushCompletedEventHandler : ITransientDependency, ICapSubscrib
log.RequestId = @event.RequestId; log.RequestId = @event.RequestId;
// 往es 写推送日志 // 往es 写推送日志
await _trackPushRecordsRepository.AddAsync(log); await _trackPushRecordEsRepository.AddAsync(log);
// if (!log.IsSuccess) // if (!log.IsSuccess)
// { // {

View File

@ -20,21 +20,21 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
{ {
private readonly IHttpClientProxy<IInterfaceForwardServiceV2> _httpClientProxy; private readonly IHttpClientProxy<IInterfaceForwardServiceV2> _httpClientProxy;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly ITrackPushCacheService _trackPushCacheService; private readonly ITrackPushCacheService _trackPushCacheService;
private readonly ITrackPushRecordsRepository _trackPushRecordsRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository;
private List<OrderEntity> _orders = null!; private List<OrderEntity> _orders = null!;
private List<TrackPushContentConfigDto> _pushConfigs = null!; private List<TrackPushContentConfigDto> _pushConfigs = null!;
public TrackPushEventHandler(IHttpClientProxy<IInterfaceForwardServiceV2> httpClientProxy, public TrackPushEventHandler(IHttpClientProxy<IInterfaceForwardServiceV2> httpClientProxy,
IOrderRepository orderRepository, ITrackPushCacheService trackPushCacheService, IOrderRepository orderRepository, ITrackPushCacheService trackPushCacheService,
ITrackDetailsRepository trackDetailsRepository, ITrackPushRecordsRepository trackPushRecordsRepository) ITrackDetailsEsRepository trackDetailsEsRepository, ITrackPushRecordEsRepository trackPushRecordEsRepository)
{ {
_httpClientProxy = httpClientProxy; _httpClientProxy = httpClientProxy;
_orderRepository = orderRepository; _orderRepository = orderRepository;
_trackPushCacheService = trackPushCacheService; _trackPushCacheService = trackPushCacheService;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
_trackPushRecordsRepository = trackPushRecordsRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository;
} }
[CapSubscribe(GlobalConst.TrackPushSubscribe, Group = GlobalConst.TrackPushSubscribe)] [CapSubscribe(GlobalConst.TrackPushSubscribe, Group = GlobalConst.TrackPushSubscribe)]
@ -113,7 +113,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode); config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode);
if (config == null) return; if (config == null) return;
var tracks = await _trackDetailsRepository.GetListAsync(@event.OrderIds, @event.TrackCode); var tracks = await _trackDetailsEsRepository.GetListAsync(@event.OrderIds, @event.TrackCode);
tracks = tracks.DistinctBy(x => x.OrderId).ToList(); // 防止重复推送 tracks = tracks.DistinctBy(x => x.OrderId).ToList(); // 防止重复推送
if (tracks.Count == 0) return; // 一个能推的轨迹都不存在 if (tracks.Count == 0) return; // 一个能推的轨迹都不存在
@ -256,7 +256,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
if (config.IsAllPush) if (config.IsAllPush)
{ {
var history = await _trackPushRecordsRepository.GetLatestTrackPushRecordAsync(log.OrderId); var history = await _trackPushRecordEsRepository.GetLatestTrackPushRecordAsync(log.OrderId);
if (history != default) if (history != default)
{ {
body = JsonConvert.DeserializeObject<TrackPushInput>(history.PushContent); body = JsonConvert.DeserializeObject<TrackPushInput>(history.PushContent);

View File

@ -15,33 +15,33 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
private readonly ICapPublisher _capPublisher; private readonly ICapPublisher _capPublisher;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly IProvideQueries _provideQueries; private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
public TrackUpsertEventHandler(IOrderRepository orderRepository, ICapPublisher capPublisher, public TrackUpsertEventHandler(IOrderRepository orderRepository, ICapPublisher capPublisher,
IProvideQueries provideQueries, ITrackDetailsRepository trackDetailsRepository) IProvideQueries provideQueries, ITrackDetailsEsRepository trackDetailsEsRepository)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_provideQueries = provideQueries; _provideQueries = provideQueries;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
} }
[CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)] [CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)]
[CapSubscribe(GlobalConst.TrackUpsertForRefreshSubscribe, Group = GlobalConst.TrackUpsertForRefreshSubscribe)] [CapSubscribe(GlobalConst.TrackUpsertForRefreshSubscribe, Group = GlobalConst.TrackUpsertForRefreshSubscribe)]
public async Task ConsumerAsync(TrackUpsertEvent @event) public async Task ConsumerAsync(TrackUpsertEvent @event)
{ {
var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray(); if (!CanDelete(@event)) return;
var dup = @event.Visited.Intersect(orderIds).ToArray();
if (dup.Any())
{
LogHelper.Warn($"{(@event.IsAdd ? "添加" : "修改")}轨迹时,发现循环依赖:{dup.JoinAsString(",")}", true);
return;
}
var canNextOrderIds = new List<int>(); var canNextOrderIds = new List<int>();
await HandleTrackAsync(@event, canNextOrderIds); await HandleTrackAsync(@event, canNextOrderIds);
if (canNextOrderIds.Count == 0) return;
// 根据订单关联关系异步向下刷(异步)
await DownByOrderLink(@event, canNextOrderIds);
}
private async Task DownByOrderLink(TrackUpsertEvent @event, List<int> canNextOrderIds)
{
// 根据订单关联关系异步向下刷(异步) // 根据订单关联关系异步向下刷(异步)
var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(canNextOrderIds.ToArray()); var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(canNextOrderIds.ToArray());
foreach (var order in @event.OrderIdentifiers) foreach (var order in @event.OrderIdentifiers)
@ -55,7 +55,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
})) }))
{ {
var nextEvent = @event.DeepCopy(); var nextEvent = @event.DeepCopy();
nextEvent.Visited.AddRange(orderIds); nextEvent.Visited.AddRange(canNextOrderIds);
nextEvent.SubSystemId = group.Key.SubSystemId; nextEvent.SubSystemId = group.Key.SubSystemId;
nextEvent.CustomId = group.Key.CustomId; nextEvent.CustomId = group.Key.CustomId;
nextEvent.TrackRefreshData = new TrackRefreshStruct nextEvent.TrackRefreshData = new TrackRefreshStruct
@ -103,6 +103,27 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
} }
} }
private bool CanDelete(TrackUpsertEvent @event)
{
// 系统创建的轨迹不允许修改
if (@event.Visited.IsNullOrEmpty() && @event is { OperationMan: GlobalConst.SystemUser, IsAdd: false })
{
LogHelper.Warn($"系统创建的轨迹不允许被修改:{@event}", true);
return false;
}
var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray();
var dup = @event.Visited.Intersect(orderIds).ToArray();
if (dup.Any())
{
LogHelper.Warn($"{(@event.IsAdd ? "添加" : "修改")}轨迹时,发现循环依赖:{dup.JoinAsString(",")}", true);
return false;
}
return true;
}
private async Task HandleTrackAsync(TrackUpsertEvent @event, List<int> canNextOrderIds) private async Task HandleTrackAsync(TrackUpsertEvent @event, List<int> canNextOrderIds)
{ {
var trackContent = await _provideQueries.GetTrackContentAsync(@event.SubSystemId, @event.TrackCode); var trackContent = await _provideQueries.GetTrackContentAsync(@event.SubSystemId, @event.TrackCode);
@ -117,7 +138,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
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 _trackDetailsRepository.GetListAsync(orderIds, @event.TrackCode, true); var tracks = await _trackDetailsEsRepository.GetListAsync(orderIds, @event.TrackCode, true);
var insertTracks = new List<TrackDetailsIndex>(); var insertTracks = new List<TrackDetailsIndex>();
@ -167,7 +188,7 @@ 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 _trackDetailsRepository.UpdateAsync(track); await _trackDetailsEsRepository.UpdateAsync(track);
} }
canNextOrderIds.Add(order.OrderId); canNextOrderIds.Add(order.OrderId);
@ -176,7 +197,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
if (canNextOrderIds.Count == 0) return; if (canNextOrderIds.Count == 0) return;
// 批量add to es // 批量add to es
await _trackDetailsRepository.AddManyAsync(insertTracks); await _trackDetailsEsRepository.AddManyAsync(insertTracks);
// 触发订单主表更新事件(异步) // 触发订单主表更新事件(异步)
await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe, await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe,

View File

@ -28,18 +28,18 @@ public class TrackRefreshEventHandler : ITransientDependency, IRabbitHandler
private readonly ILogger<TrackRefreshEventHandler> _logger; private readonly ILogger<TrackRefreshEventHandler> _logger;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITimezoneQueries _timezoneQueries; private readonly ITimezoneQueries _timezoneQueries;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly ITrackPullCacheService _trackPullCacheService; private readonly ITrackPullCacheService _trackPullCacheService;
public TrackRefreshEventHandler(IOrderRepository orderRepository, public TrackRefreshEventHandler(IOrderRepository orderRepository,
ICapPublisher capPublisher, ITrackPullCacheService trackPullCacheService, ICapPublisher capPublisher, ITrackPullCacheService trackPullCacheService,
ITrackDetailsRepository trackDetailsRepository, ITimezoneQueries timezoneQueries, ITrackDetailsEsRepository trackDetailsEsRepository, ITimezoneQueries timezoneQueries,
ILogger<TrackRefreshEventHandler> logger) ILogger<TrackRefreshEventHandler> logger)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_trackPullCacheService = trackPullCacheService; _trackPullCacheService = trackPullCacheService;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
_timezoneQueries = timezoneQueries; _timezoneQueries = timezoneQueries;
_logger = logger; _logger = logger;
} }
@ -152,7 +152,7 @@ public class TrackRefreshEventHandler : ITransientDependency, IRabbitHandler
{ {
var originTrackDataHash = StringHelper.GetHash(JsonConvert.SerializeObject(trackToken)); var originTrackDataHash = StringHelper.GetHash(JsonConvert.SerializeObject(trackToken));
// 如果已经存在一模一样的报文了说明处理过了,直接return // 如果已经存在一模一样的报文了说明处理过了,直接return
if (await _trackDetailsRepository.AnyAsync(context.OrderId, originTrackDataHash)) if (await _trackDetailsEsRepository.AnyAsync(context.OrderId, originTrackDataHash))
{ {
return; return;
} }
@ -327,7 +327,7 @@ public class TrackRefreshEventHandler : ITransientDependency, IRabbitHandler
? track.TrackTime ? track.TrackTime
: track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); : track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone));
await _trackDetailsRepository.AddAsync(track); await _trackDetailsEsRepository.AddAsync(track);
} }
/// <summary> /// <summary>

View File

@ -36,18 +36,12 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
return await GetRules(subSystemId, customerId); return await GetRules(subSystemId, customerId);
} }
public Task DeleteRulesAsync(int subSystemId, int customerId)
{
_rules.Remove(WarningKey(subSystemId, customerId), out _);
return Task.CompletedTask;
}
public Task Clear(ClearRulCacheEvent @event) public Task Clear(ClearRulCacheEvent @event)
{ {
foreach (var item in @event.Items) foreach (var item in @event.Items)
{ {
DeleteRulesAsync(item.SystemId, item.CustomerId); var redisKey = WarningKey(item.SystemId, item.CustomerId);
_rules.Remove(redisKey, out _);
} }
return Task.CompletedTask; return Task.CompletedTask;
@ -91,7 +85,7 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
private List<ForewarningRuleCacheEntry> WriteRules(List<WarningRuleCacheDto> rules) private List<ForewarningRuleCacheEntry> WriteRules(List<WarningRuleCacheDto> rules)
{ {
List<ForewarningRuleCacheEntry> result = new List<ForewarningRuleCacheEntry>(); var result = new List<ForewarningRuleCacheEntry>();
foreach (var item in rules) foreach (var item in rules)
{ {
List<AreaCacheEntry>? areaList = null; List<AreaCacheEntry>? areaList = null;
@ -153,11 +147,11 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
var warnings = await _warningQueries.GetWarningRule(systemId, customerId); var warnings = await _warningQueries.GetWarningRule(systemId, customerId);
if (warnings == null || warnings.Count == 0) if (warnings == null || warnings.Count == 0)
{ {
RedisHelper.Client.Set(key, new List<WarningRuleCacheDto>(), TimeSpan.FromSeconds(20)); await RedisHelper.Client.SetAsync(key, new List<WarningRuleCacheDto>(), TimeSpan.FromSeconds(20));
return new List<ForewarningRuleCacheEntry>(); return new List<ForewarningRuleCacheEntry>();
} }
RedisHelper.Client.Set(key, warnings); await RedisHelper.Client.SetAsync(key, warnings);
ruleResult = WriteRules(warnings); ruleResult = WriteRules(warnings);
_rules.TryAdd(key, ruleResult); _rules.TryAdd(key, ruleResult);
return ruleResult; return ruleResult;
@ -169,7 +163,7 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
if (_areas.TryGetValue(areaId, out var areaInfos)) return areaInfos; if (_areas.TryGetValue(areaId, out var areaInfos)) return areaInfos;
var areas = GetAreas(areaId); var areas = GetAreas(areaId);
if (areas == null || areas.Count == 0) return null; if (areas.Count == 0) return null;
areaInfos = areas.Select(KpiAreaInfoToEntry).ToList(); areaInfos = areas.Select(KpiAreaInfoToEntry).ToList();
_areas.TryAdd(areaId, areaInfos); _areas.TryAdd(areaId, areaInfos);
@ -192,7 +186,7 @@ public class ForewarningCacheService : IForewarningCacheService, ISingletonDepen
/// 获取区域 /// 获取区域
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private List<KpiAreaInfo>? GetAreas(int areaId) private List<KpiAreaInfo> GetAreas(int areaId)
{ {
var key = AreaKey(areaId); var key = AreaKey(areaId);
var result = RedisHelper.Client.Get<List<KpiAreaInfo>>(key); var result = RedisHelper.Client.Get<List<KpiAreaInfo>>(key);

View File

@ -1,11 +1,13 @@
using System.Text; using System.Text;
using FreeRedis; using FreeRedis;
using SJZY.Expand.ABP.Core; using SJZY.Expand.ABP.Core;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Track.Application.Contract.Dtos.Forewarning; using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Application.Contract.Services; using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Dtos.Forewarning; using SJZY.Track.Domain.Dtos.Forewarning;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
using SJZY.Track.Share.Enums;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace SJZY.Track.Application.Services.ForewarningServices; namespace SJZY.Track.Application.Services.ForewarningServices;
@ -17,18 +19,20 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
{ {
private readonly IForewarningCacheService _cacheService; private readonly IForewarningCacheService _cacheService;
private readonly IWarningQueries _warningQueries; private readonly IWarningQueries _warningQueries;
private readonly IWarningRecordEsRepository _warningRecordEsRepository;
public ForewarningNotifyService(IForewarningCacheService cacheService, IWarningQueries warningQueries) public ForewarningNotifyService(IForewarningCacheService cacheService, IWarningQueries warningQueries,
IWarningRecordEsRepository warningRecordEsRepository)
{ {
_cacheService = cacheService; _cacheService = cacheService;
_warningQueries = warningQueries; _warningQueries = warningQueries;
_warningRecordEsRepository = warningRecordEsRepository;
} }
/// <summary> /// <summary>
/// 创建预警通知 /// 创建预警通知
/// </summary> /// </summary>
/// <param name="dto">创建预警通知需要的订单信息</param> /// <param name="dto">创建预警通知需要的订单信息</param>
/// <returns>创建的通知总量,0表示没有规则</returns>
public async Task WarningCalculateAsync(WarningDto dto) public async Task WarningCalculateAsync(WarningDto dto)
{ {
if (dto.Orders.Count == 0) return; if (dto.Orders.Count == 0) return;
@ -36,19 +40,30 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
var rules = await _cacheService.GetRulesAsync(dto.SubSystemId, dto.CustomerId); var rules = await _cacheService.GetRulesAsync(dto.SubSystemId, dto.CustomerId);
if (rules == null || rules.Count == 0) return; if (rules == null || rules.Count == 0) return;
var adds = new List<(int ruleId, int orderId, int cnt, long ts)>(); var adds = new List<(int ruleId, int orderId, long ts)>();
var dels = new List<(int ruleId, int orderId)>(); var dels = new List<(int ruleId, int orderId)>();
foreach (var order in dto.Orders) foreach (var order in dto.Orders)
{ {
// 加左区间
MatchRule( MatchRule(
rules.Where(rule => rule.StartTrackStatusId == dto.TrackStatusId).ToList(), rules.Where(rule => rule.StartTrackStatusId == dto.TrackStatusId).ToList(),
order order
).ForEach(rule => ).ForEach(rule =>
{ {
var timestamp = GetTimestamp(order.TrackTime.AddMinutes(rule.WarnTimeSpan)); var interval = (rule.TotalTimeSpan - rule.WarnTimeSpan) / rule.WarnCount;
adds.Add((rule.Id, order.Id, rule.WarnCount, timestamp)); var startTime = order.TrackTime.AddMinutes(rule.WarnTimeSpan);
for (var i = 0; i < rule.WarnCount; i++)
{
var timestamp = GetTimestamp(startTime);
startTime = startTime.AddMinutes(interval);
// 计算预警时间戳,作为排序依据
adds.Add((rule.Id, order.Id, timestamp));
}
}); });
// 删右区间
MatchRule( MatchRule(
rules.Where(rule => rule.EndTrackStatusId == dto.TrackStatusId).ToList(), rules.Where(rule => rule.EndTrackStatusId == dto.TrackStatusId).ToList(),
order order
@ -57,40 +72,96 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
var tran = RedisHelper.Client.Multi(); var tran = RedisHelper.Client.Multi();
// 维护预警队列 // 左区间加入预警队列
foreach (var kvp in adds.ToDictionary(x => $"{x.ruleId}_{x.orderId}", x => x.cnt))
{
await tran.HSetNxAsync(GlobalConst.ForewarningNotifyCntKey, kvp.Key, kvp.Value); // nx: not exist
}
await tran.ZAddAsync(GlobalConst.ForewarningNotifyKey, adds.Select(x => await tran.ZAddAsync(GlobalConst.ForewarningNotifyKey, adds.Select(x =>
{ {
var entry = new WarningNotifyCacheEntry(x.ruleId, x.orderId); var entry = new WarningNotifyCacheEntry(x.ruleId, x.orderId);
return new ZMember(entry.ToString(), x.ts); // update timestamp return new ZMember(entry.ToString(), x.ts);
}).ToArray()); }).ToArray());
// 移出预警队列 // 右区间移出预警队列
await tran.HDelAsync(GlobalConst.ForewarningNotifyCntKey, var right = dels.Select(x => new WarningNotifyCacheEntry(x.ruleId, x.orderId)).ToList();
dels.Select(x => $"{x.ruleId}_{x.orderId}").ToArray()); if (!right.IsNullOrEmpty())
await tran.ZRemAsync(GlobalConst.ForewarningNotifyKey, {
dels.Select(x => $"{x.ruleId}:{x.orderId}").ToArray()); await tran.ZRemAsync(GlobalConst.ForewarningNotifyKey, right.Select(x => x.ToString()).ToArray());
var res = tran.Exec(); await _warningRecordEsRepository.BulkUpdateAsync(dels); // 标记处理完成
}
if (res == null) throw new BusinessException(message: "轨迹预警计算失败"); tran.Exec();
} }
public async Task SendNotificationAsync() public async Task SendNotificationAsync()
{ {
var max = GetTimestamp(DateTime.Now); var timestamp = GetTimestamp(DateTime.Now);
var set = await RedisHelper.Client.ZRangeByScoreAsync(GlobalConst.ForewarningNotifyKey, 0, max); var set = await RedisHelper.Client.ZRangeByScoreAsync(GlobalConst.ForewarningNotifyKey, 0, timestamp);
if (set.IsNullOrEmpty()) return; if (set.IsNullOrEmpty())
{
LogHelper.Info("没有运输时效需要预警");
return;
}
var entries = set.Select(x => new WarningNotifyCacheEntry(x)).ToList(); var entries = set.Select(x => new WarningNotifyCacheEntry(x)).ToList();
var ruleIds = entries.Select(x => x.RuleId).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);
}
}
var warningRecords = new List<WarningRecordIndex>();
foreach (var entry in entries)
{
var rule = notifyRules.FirstOrDefault(x => x.RuleId == entry.RuleId);
if (rule == null) continue;
warningRecords.Add(new WarningRecordIndex
{
SubSystemId = rule.SubSystemId,
WarningName = rule.WarningName,
CustomName = rule.CustomName,
RuleId = entry.RuleId,
Rule = rule.ToString(),
OrderId = entry.OrderId,
WarningStatus = WarningStatus.UnProcessed,
NotifyUser = rule.NotifyUser,
CreateTime = DateTime.Now,
});
}
await _warningRecordEsRepository.BulkInsertAsync(warningRecords);
foreach (var userRule in userRules)
{
var siteInternalContent = BuildNotifyContent(userRule.Value, entries, NotifyMode.SiteInternal);
var feiShuContent = BuildNotifyContent(userRule.Value, entries, NotifyMode.FeiShu);
if (!string.IsNullOrEmpty(siteInternalContent))
{
// todo:发送站内通知
}
if (!string.IsNullOrEmpty(feiShuContent))
{
// todo:发送飞书通知
}
}
}
private string BuildNotifyContent(List<GetWarningNotifiesVo> rules, List<WarningNotifyCacheEntry> entries,
NotifyMode mode)
{
/* 以人的维度发送通知
* *
预警名称:字节全程时效 预警名称:字节全程时效
预警规则: 预警规则:
@ -101,15 +172,10 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
{起飞-落地+普货+12345678+美国 时效9,预警时效7,次数3} 命中订单总数:124,详情点击https://middlebusiness.pet.shijizhongyun.com/trajectoryCenter/trajectoryOrder {起飞-落地+普货+12345678+美国 时效9,预警时效7,次数3} 命中订单总数:124,详情点击https://middlebusiness.pet.shijizhongyun.com/trajectoryCenter/trajectoryOrder
{清关-提货+普货+12345678+美国 时效4,预警时效3,次数1} 命中订单总数:3250,详情点击https://middlebusiness.pet.shijizhongyun.com/trajectoryCenter/trajectoryOrder {清关-提货+普货+12345678+美国 时效4,预警时效3,次数1} 命中订单总数:3250,详情点击https://middlebusiness.pet.shijizhongyun.com/trajectoryCenter/trajectoryOrder
*/ */
foreach (var group in notifyRules.GroupBy(x => new
{
x.NotifyMode,
x.NotifyUserId
}))
{
var notifyContent = new StringBuilder(); var notifyContent = new StringBuilder();
foreach (var warningGroup in group.GroupBy(x => x.WarningName)) foreach (var warningGroup in rules.Where(x => x.NotifyModes.Contains(mode))
.GroupBy(x => x.WarningName))
{ {
notifyContent.AppendLine($"预警名称:{warningGroup.Key}"); notifyContent.AppendLine($"预警名称:{warningGroup.Key}");
notifyContent.AppendLine($"预警规则:"); notifyContent.AppendLine($"预警规则:");
@ -117,14 +183,12 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
foreach (var rule in warningGroup.ToList()) foreach (var rule in warningGroup.ToList())
{ {
var cnt = entries.Count(x => x.RuleId == rule.RuleId); var cnt = entries.Count(x => x.RuleId == rule.RuleId);
if (cnt > 0)
{
notifyContent.AppendLine( notifyContent.AppendLine(
$"{rule.ToString()} 命中订单总数:{cnt},详情点击https://middlebusiness.pet.shijizhongyun.com/trajectoryCenter/trajectoryOrder"); $"{rule.ToString()} 命中订单总数:{cnt},详情点击https://middlebusiness.pet.shijizhongyun.com/trajectoryCenter/trajectoryOrder");
} }
} }
}
} return notifyContent.ToString();
} }
private static List<ForewarningRuleCacheEntry> MatchRule(List<ForewarningRuleCacheEntry> rules, private static List<ForewarningRuleCacheEntry> MatchRule(List<ForewarningRuleCacheEntry> rules,

View File

@ -22,6 +22,7 @@ public class ForewarningService : ApplicationService
_forewarningCacheService = forewarningCacheService; _forewarningCacheService = forewarningCacheService;
} }
/// <summary> /// <summary>
/// 获取预警分页列表 /// 获取预警分页列表
/// </summary> /// </summary>
@ -150,7 +151,7 @@ public class ForewarningService : ApplicationService
await _warningRepository.TurnWarningAsync(warning); await _warningRepository.TurnWarningAsync(warning);
// 清除缓存 // 清除缓存
await _forewarningCacheService.DeleteRulesAsync(warning.SubSystemId, warning.CustomerId); await _forewarningCacheService.ClearRedisBySystemIdAndCustomer(warning.SubSystemId, warning.CustomerId);
return true; return true;
} }
@ -194,7 +195,7 @@ public class ForewarningService : ApplicationService
await _warningRepository.ModifyTimeSpansAsync(warningRules); await _warningRepository.ModifyTimeSpansAsync(warningRules);
// 清除缓存 // 清除缓存
await _forewarningCacheService.DeleteRulesAsync(warning.SubSystemId, warning.CustomerId); await _forewarningCacheService.ClearRedisBySystemIdAndCustomer(warning.SubSystemId, warning.CustomerId);
return true; return true;
} }
} }

View File

@ -14,7 +14,7 @@ public partial class OrderService
{ {
private readonly ICapPublisher _capPublisher; private readonly ICapPublisher _capPublisher;
private readonly IBasicQuery<OrderLinkEntity> _orderLinkQuery; private readonly IBasicQuery<OrderLinkEntity> _orderLinkQuery;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
/// <summary> /// <summary>
/// 关联、解除关联订单 /// 关联、解除关联订单
@ -99,7 +99,7 @@ public partial class OrderService
LinkOrderType = input.LinkOrderType LinkOrderType = input.LinkOrderType
}).ToList()); }).ToList());
var tracks = await _trackDetailsRepository.GetListAsync(orderId); var tracks = await _trackDetailsEsRepository.GetListAsync(orderId);
// 补轨迹(按子系统、按客户分,同样是为了方便轨迹upsert和push) // 补轨迹(按子系统、按客户分,同样是为了方便轨迹upsert和push)
foreach (var group in existedOrders.GroupBy(x => new foreach (var group in existedOrders.GroupBy(x => new

View File

@ -16,16 +16,16 @@ namespace SJZY.Track.Application.Services.ProvideServices;
[Route("/ProviderService")] [Route("/ProviderService")]
public partial class OrderService : ApplicationService, IOrderService public partial class OrderService : ApplicationService, IOrderService
{ {
private readonly IOrderOperationRecordRepository _orderOperationRecordRepository; private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
public OrderService(IOrderRepository orderRepository, IBasicQuery<OrderLinkEntity> orderLinkQuery, public OrderService(IOrderRepository orderRepository, IBasicQuery<OrderLinkEntity> orderLinkQuery,
ICapPublisher capPublisher, ITrackDetailsRepository trackDetailsRepository, ICapPublisher capPublisher, ITrackDetailsEsRepository trackDetailsEsRepository,
IOrderOperationRecordRepository orderOperationRecordRepository) IOrderOperationRecordEsRepository orderOperationRecordEsRepository)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_orderOperationRecordRepository = orderOperationRecordRepository; _orderOperationRecordEsRepository = orderOperationRecordEsRepository;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_orderLinkQuery = orderLinkQuery; _orderLinkQuery = orderLinkQuery;
} }
@ -54,7 +54,7 @@ public partial class OrderService : ApplicationService, IOrderService
Content = input.ToJson(), Content = input.ToJson(),
}; };
_ = _orderOperationRecordRepository.AddAsync(index); _ = _orderOperationRecordEsRepository.AddAsync(index);
return new UnifyResultDto<IdBaseDto>(true, new IdBaseDto return new UnifyResultDto<IdBaseDto>(true, new IdBaseDto
{ {
@ -79,7 +79,7 @@ public partial class OrderService : ApplicationService, IOrderService
CreateUserId = CurrentUserRequest.CurrentUser.UserId, CreateUserId = CurrentUserRequest.CurrentUser.UserId,
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };
_ = _orderOperationRecordRepository.AddAsync(indexForAdd); _ = _orderOperationRecordEsRepository.AddAsync(indexForAdd);
return new UnifyResultDto<IdBaseDto>(true, new IdBaseDto return new UnifyResultDto<IdBaseDto>(true, new IdBaseDto

View File

@ -19,16 +19,16 @@ public class TrackPushService : ApplicationService
private readonly ICapPublisher _capPublisher; private readonly ICapPublisher _capPublisher;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly IHttpClientProxy<IRequestCurrentUserService> _requestCurrentUserService; private readonly IHttpClientProxy<IRequestCurrentUserService> _requestCurrentUserService;
private readonly ITrackPushRecordsRepository _trackPushRecordsRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository;
public TrackPushService(IOrderRepository orderRepository public TrackPushService(IOrderRepository orderRepository
, ICapPublisher capPublisher , ICapPublisher capPublisher
, ITrackPushRecordsRepository trackPushRecordsRepository, , ITrackPushRecordEsRepository trackPushRecordEsRepository,
IHttpClientProxy<IRequestCurrentUserService> requestCurrentUserService) IHttpClientProxy<IRequestCurrentUserService> requestCurrentUserService)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_trackPushRecordsRepository = trackPushRecordsRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository;
_requestCurrentUserService = requestCurrentUserService; _requestCurrentUserService = requestCurrentUserService;
} }
@ -115,6 +115,6 @@ public class TrackPushService : ApplicationService
throw new BusinessException(message: "订单不存在"); throw new BusinessException(message: "订单不存在");
} }
return await _trackPushRecordsRepository.GetTrackPushRecordsAsync(orderId); return await _trackPushRecordEsRepository.GetTrackPushRecordsAsync(orderId);
} }
} }

View File

@ -8,7 +8,7 @@ namespace SJZY.Track.Application.Services.ProvideServices;
/// </summary> /// </summary>
public partial class TrackService public partial class TrackService
{ {
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
/// <summary> /// <summary>
/// 查询轨迹 /// 查询轨迹
@ -22,7 +22,7 @@ public partial class TrackService
var res = new List<GetTrackOutput>(); var res = new List<GetTrackOutput>();
input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空 input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空
var details = await _trackDetailsRepository.GetListAsync(input.SubSystemId, input.OrderType, input.OrderNos); var details = await _trackDetailsEsRepository.GetListAsync(input.SubSystemId, input.OrderType, input.OrderNos);
// 是否对外 // 是否对外
var trackCodes = details.Select(x => x.TrackCode) var trackCodes = details.Select(x => x.TrackCode)

View File

@ -23,14 +23,14 @@ public partial class TrackService : ApplicationService, ITrackService
private readonly ITrackContentRepository _trackContentRepository; private readonly ITrackContentRepository _trackContentRepository;
public TrackService(IOrderRepository orderRepository, ICapPublisher capPublisher, public TrackService(IOrderRepository orderRepository, ICapPublisher capPublisher,
ITrackDetailsRepository trackDetailsRepository, ITrackContentRepository trackContentRepository, ITrackDetailsEsRepository trackDetailsEsRepository, ITrackContentRepository trackContentRepository,
IHttpClientProxy<IRequestCurrentUserService> requestCurrentUserService) IHttpClientProxy<IRequestCurrentUserService> requestCurrentUserService)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_trackContentRepository = trackContentRepository; _trackContentRepository = trackContentRepository;
_requestCurrentUserService = requestCurrentUserService; _requestCurrentUserService = requestCurrentUserService;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,64 @@
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Dtos.Forewarning;
namespace SJZY.Track.Application.Services.TrackOrders;
public class OrderWarningService
{
private readonly IOrderRepository _orderRepository;
private readonly IWarningRecordEsRepository _warningRecordEsRepository;
public OrderWarningService(IWarningRecordEsRepository warningRecordEsRepository, IOrderRepository orderRepository)
{
_warningRecordEsRepository = warningRecordEsRepository;
_orderRepository = orderRepository;
}
/// <summary>
/// 获取订单运输时效预警分页列表
/// </summary>
/// <param name="inputVo"></param>
/// <param name="warningRecordEsRepository"></param>
/// <returns></returns>
[HttpPost("GetOrderWarningPageList")]
public async Task<UnifyPageResultDto<GetOrderWarningPageOutput>> GetOrderWarningPageListAsync(
GetOrderWarningPageListVo inputVo)
{
var result = await _warningRecordEsRepository.GetOrderWarningPageListAsync(inputVo);
var orderIds = result.list.Select(x => x.OrderId).ToList();
var orders = await _orderRepository.GetListAsync(x => orderIds.Contains(x.Id), x => new
{
x.Id,
x.LatestTrackContent,
x.LatestTrackTime,
x.LatestTrackPlace,
x.OrderNo
});
var list = new List<GetOrderWarningPageOutput>();
result.list.ForEach(x =>
{
var item = new GetOrderWarningPageOutput
{
Rule = x.Rule,
WarningName = x.WarningName,
WarningStatus = x.WarningStatus,
CreateTime = x.CreateTime,
NotifyUser = x.NotifyUser,
CustomName = x.CustomName,
};
var order = orders.FirstOrDefault(o => o.Id == x.OrderId);
if (order == default) return;
item.OrderNo = order.OrderNo;
item.LatestTrackTime = order.LatestTrackTime;
item.LatestTrackPlace = order.LatestTrackPlace;
item.LatestTrackContent = order.LatestTrackContent;
});
return new UnifyPageResultDto<GetOrderWarningPageOutput>(list, inputVo.PageIndex, inputVo.PageSize,
(int) result.total);
}
}

View File

@ -12,24 +12,24 @@ namespace SJZY.Track.Application.Services.TrackOrders;
[Route("/Track/Order")] [Route("/Track/Order")]
public class TrackOrderService : ApplicationService public class TrackOrderService : ApplicationService
{ {
private readonly IOrderOperationRecordRepository _orderOperationRecordRepository; private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITrackContentRepository _trackContentRepository; private readonly ITrackContentRepository _trackContentRepository;
private readonly ITrackDetailsRepository _trackDetailsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly ITrackPushRecordsRepository _trackPushRecordsRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository;
public TrackOrderService( public TrackOrderService(
IOrderRepository orderRepository, IOrderRepository orderRepository,
ITrackDetailsRepository trackDetailsRepository, ITrackDetailsEsRepository trackDetailsEsRepository,
ITrackContentRepository trackContentRepository, ITrackContentRepository trackContentRepository,
ITrackPushRecordsRepository trackPushRecordsRepository, ITrackPushRecordEsRepository trackPushRecordEsRepository,
IOrderOperationRecordRepository orderOperationRecordRepository) IOrderOperationRecordEsRepository orderOperationRecordEsRepository)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
_trackContentRepository = trackContentRepository; _trackContentRepository = trackContentRepository;
_trackPushRecordsRepository = trackPushRecordsRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository;
_orderOperationRecordRepository = orderOperationRecordRepository; _orderOperationRecordEsRepository = orderOperationRecordEsRepository;
} }
#region 轨迹订单列表 #region 轨迹订单列表
@ -74,7 +74,7 @@ public class TrackOrderService : ApplicationService
[HttpGet("GetTrackPushRecords")] [HttpGet("GetTrackPushRecords")]
public async Task<List<TrackPushRecordOutput>> GetTrackPushRecordsAsync(int orderId) public async Task<List<TrackPushRecordOutput>> GetTrackPushRecordsAsync(int orderId)
{ {
var records = await _trackPushRecordsRepository.GetTrackPushRecordsAsync(orderId); var records = await _trackPushRecordEsRepository.GetTrackPushRecordsAsync(orderId);
var res = ObjectMapper.Map<List<TrackPushRecordIndex>, List<TrackPushRecordOutput>>(records); var res = ObjectMapper.Map<List<TrackPushRecordIndex>, List<TrackPushRecordOutput>>(records);
@ -103,7 +103,7 @@ public class TrackOrderService : ApplicationService
throw new BusinessException(message: "订单不存在"); throw new BusinessException(message: "订单不存在");
} }
var trackDetails = await _trackDetailsRepository.GetListAsync(orderId); var trackDetails = await _trackDetailsEsRepository.GetListAsync(orderId);
if (trackDetails.IsNullOrEmpty()) if (trackDetails.IsNullOrEmpty())
{ {
return new List<TrackOrderDetailDto>(); return new List<TrackOrderDetailDto>();
@ -162,7 +162,7 @@ public class TrackOrderService : ApplicationService
[HttpPost("DeleteTrackById")] [HttpPost("DeleteTrackById")]
public async Task<bool> DeleteTrackByIdAsync(string trackId) public async Task<bool> DeleteTrackByIdAsync(string trackId)
{ {
var track = await _trackDetailsRepository.GetByIdAsync(trackId); var track = await _trackDetailsEsRepository.GetByIdAsync(trackId);
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (track == null) if (track == null)
@ -170,7 +170,7 @@ public class TrackOrderService : ApplicationService
throw new BusinessException(message: "轨迹不存在!"); throw new BusinessException(message: "轨迹不存在!");
} }
await _trackDetailsRepository.DeleteTrackByIdAsync(trackId, track.IndexName); await _trackDetailsEsRepository.DeleteTrackByIdAsync(trackId, track.IndexName);
return true; return true;
} }
@ -182,6 +182,6 @@ public class TrackOrderService : ApplicationService
[HttpGet("GetOrderOperationsById")] [HttpGet("GetOrderOperationsById")]
public async Task<List<OrderOperationRecordIndex>> GetOrderOperationsByIdAsync(int orderId) public async Task<List<OrderOperationRecordIndex>> GetOrderOperationsByIdAsync(int orderId)
{ {
return await _orderOperationRecordRepository.GetOrderOperationsByIdAsync(orderId); return await _orderOperationRecordEsRepository.GetOrderOperationsByIdAsync(orderId);
} }
} }

View File

@ -12,14 +12,6 @@ public interface IForewarningCacheService
/// <returns></returns> /// <returns></returns>
Task<List<ForewarningRuleCacheEntry>?> GetRulesAsync(int subSystemId, int customerId); Task<List<ForewarningRuleCacheEntry>?> GetRulesAsync(int subSystemId, int customerId);
/// <summary>
/// 删除规则
/// </summary>
/// <param name="subSystemId"></param>
/// <param name="customerId"></param>
/// <returns></returns>
Task DeleteRulesAsync(int subSystemId, int customerId);
/// <summary> /// <summary>
/// 重置本地缓存 /// 重置本地缓存
/// </summary> /// </summary>

View File

@ -0,0 +1,34 @@
using SJZY.Track.Domain.Dtos.Forewarning;
namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate;
public interface IWarningRecordEsRepository
{
/// <summary>
/// 添加预警记录
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
Task AddAsync(WarningRecordIndex index);
/// <summary>
/// 批量添加预警记录
/// </summary>
/// <param name="warningRecords"></param>
/// <returns></returns>
Task BulkInsertAsync(List<WarningRecordIndex> warningRecords);
/// <summary>
/// 批量更新预警记录
/// </summary>
/// <param name="warningRecords"></param>
/// <returns></returns>
Task BulkUpdateAsync(List<(int ruleId, int orderId)> warningRecords);
/// <summary>
/// 获取订单运输时效预警分页列表
/// </summary>
/// <param name="inputVo"></param>
/// <returns></returns>
Task<(List<WarningRecordIndex> list, long total)> GetOrderWarningPageListAsync(GetOrderWarningPageListVo inputVo);
}

View File

@ -34,8 +34,14 @@ public class WarningNotifyEntity : IFullAuditedBasicEntitys, IEntity
public string NotifyMode { get; set; } public string NotifyMode { get; set; }
/// <summary> /// <summary>
/// 通知人,多个逗号分隔 /// 通知人id,多个逗号分隔
/// </summary> /// </summary>
[SugarColumn(ColumnName = "NotifyUserId")] [SugarColumn(ColumnName = "NotifyUserId")]
public string NotifyUserId { get; set; } public string NotifyUserId { get; set; }
/// <summary>
/// 通知人,多个逗号分隔
/// </summary>
[SugarColumn(ColumnName = "NotifyUser")]
public string NotifyUser { get; set; }
} }

View File

@ -7,6 +7,11 @@ namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate;
[ElasticsearchType(RelationName = GlobalConst.TrackWarningRecordIndex)] [ElasticsearchType(RelationName = GlobalConst.TrackWarningRecordIndex)]
public class WarningRecordIndex : IdBaseIndex public class WarningRecordIndex : IdBaseIndex
{ {
/// <summary>
/// 子系统
/// </summary>
public int SubSystemId { get; set; }
/// <summary> /// <summary>
/// 索引名称 /// 索引名称
/// </summary> /// </summary>
@ -18,14 +23,14 @@ public class WarningRecordIndex : IdBaseIndex
public string WarningName { get; set; } = null!; public string WarningName { get; set; } = null!;
/// <summary> /// <summary>
/// 规则Id /// 客户简称
/// </summary> /// </summary>
public int RuleId { get; set; } public string CustomName { get; set; }
/// <summary> /// <summary>
/// 规则 /// 预警规则id
/// </summary> /// </summary>
public string Rule { get; set; } = null!; public int RuleId { get; set; }
/// <summary> /// <summary>
/// 订单Id /// 订单Id
@ -33,12 +38,22 @@ public class WarningRecordIndex : IdBaseIndex
public int OrderId { get; set; } public int OrderId { get; set; }
/// <summary> /// <summary>
/// 订单号 /// 预警规则
/// </summary> /// </summary>
public string OrderNo { get; set; } = null!; public string Rule { get; set; } = null!;
/// <summary> /// <summary>
/// /// 预警状态
/// </summary> /// </summary>
public int CustomId { get; set; } public WarningStatus WarningStatus { get; set; }
/// <summary>
/// 通知用户
/// </summary>
public string NotifyUser { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
} }

View File

@ -0,0 +1,14 @@
namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate;
public enum WarningStatus
{
/// <summary>
/// 待处理
/// </summary>
UnProcessed = 1,
/// <summary>
/// 已处理
/// </summary>
Processed = 2,
}

View File

@ -1,6 +1,6 @@
namespace SJZY.Track.Domain.Aggregates.OrderAggregate; namespace SJZY.Track.Domain.Aggregates.OrderAggregate;
public interface IOrderOperationRecordRepository public interface IOrderOperationRecordEsRepository
{ {
/// <summary> /// <summary>
/// 添加订单操作记录 /// 添加订单操作记录

View File

@ -2,7 +2,7 @@ using SJZY.Expand.ElasticSearch.Services;
namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
public interface ITrackDetailsRepository : IElasticsearchClientService<TrackDetailsIndex> public interface ITrackDetailsEsRepository : IElasticsearchClientService<TrackDetailsIndex>
{ {
Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, string trackCode, bool forUpsert = false); Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, string trackCode, bool forUpsert = false);

View File

@ -1,6 +1,6 @@
namespace SJZY.Track.Domain.Aggregates.TrackPushAggregate; namespace SJZY.Track.Domain.Aggregates.TrackPushAggregate;
public interface ITrackPushRecordsRepository public interface ITrackPushRecordEsRepository
{ {
/// <summary> /// <summary>
/// 添加推送记录 /// 添加推送记录

View File

@ -3,22 +3,22 @@ namespace SJZY.Track.Domain.Consts;
public partial class GlobalConst public partial class GlobalConst
{ {
/// <summary> /// <summary>
/// 轨迹明细 es索引名称(模板) /// 轨迹明细 es索引名称(模板按天)
/// </summary> /// </summary>
public const string TrackIndex = "sjzy_track_details"; public const string TrackIndex = "sjzy_track_details";
/// <summary> /// <summary>
/// 轨迹推送记录 es索引名称(模板) /// 轨迹推送记录 es索引名称(模板按天)
/// </summary> /// </summary>
public const string TrackPushRecordsIndex = "sjzy_track_push_records"; public const string TrackPushRecordsIndex = "sjzy_track_push_records";
/// <summary> /// <summary>
/// 预警记录 es索引名称(模板) /// 运输时效预警记录 es索引名称(模板按天)
/// </summary> /// </summary>
public const string TrackWarningRecordIndex = "sjzy_track_warning_records"; public const string TrackWarningRecordIndex = "sjzy_track_warning_records";
/// <summary> /// <summary>
/// 订单操作记录 es索引名称(模板) /// 订单操作记录 es索引名称(模板按天)
/// </summary> /// </summary>
public const string OrderOperationRecordIndex = "sjzy_track_order_operation_records"; public const string OrderOperationRecordIndex = "sjzy_track_order_operation_records";
} }

View File

@ -0,0 +1,48 @@
using System.ComponentModel.DataAnnotations;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
namespace SJZY.Track.Domain.Dtos.Forewarning;
public class GetOrderWarningPageListVo : PageInfoInput
{
/// <summary>
/// 子系统id
/// </summary>
public int? SubSystemId { get; set; }
/// <summary>
/// 订单号
/// </summary>
[MaxLength(500)]
public List<string>? OrderNos { get; set; }
/// <summary>
/// 预警状态
/// </summary>
public WarningStatus? WarningStatus { get; set; }
/// <summary>
/// 客户简称
/// </summary>
public string? CustomName { get; set; }
/// <summary>
/// 预警名称
/// </summary>
public string? WarningName { get; set; }
/// <summary>
/// 通知用户
/// </summary>
public string? NotifyUser { get; set; }
/// <summary>
/// 创建时间开始
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 创建时间结束
/// </summary>
public DateTime? EndTime { get; set; }
}

View File

@ -0,0 +1,53 @@
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
namespace SJZY.Track.Domain.Dtos.Forewarning;
public class GetOrderWarningPageOutput
{
/// <summary>
/// 预警名称
/// </summary>
public string WarningName { get; set; } = null!;
/// <summary>
/// 客户简称
/// </summary>
public string CustomName { get; set; }
/// <summary>
/// 预警规则
/// </summary>
public string Rule { get; set; } = null!;
/// <summary>
/// 预警状态
/// </summary>
public WarningStatus WarningStatus { get; set; }
/// <summary>
/// 通知用户
/// </summary>
public string NotifyUser { get; set; }
/// <summary>
/// 最新轨迹内容(异步维护)
/// </summary>
public string? LatestTrackContent { get; set; }
/// <summary>
/// 最新轨迹时间(异步维护)
/// </summary>
public DateTime? LatestTrackTime { get; set; }
/// <summary>
/// 最新轨迹发生地(异步维护)
/// </summary>
public string? LatestTrackPlace { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
public string OrderNo { get; set; }
}

View File

@ -6,6 +6,11 @@ namespace SJZY.Track.Domain.Dtos.Forewarning;
public class GetWarningNotifiesVo public class GetWarningNotifiesVo
{ {
/// <summary>
/// 子系统
/// </summary>
public int SubSystemId { get; set; }
/// <summary> /// <summary>
/// 规则 id /// 规则 id
/// </summary> /// </summary>
@ -16,6 +21,11 @@ public class GetWarningNotifiesVo
/// </summary> /// </summary>
public string WarningName { get; set; } = null!; public string WarningName { get; set; } = null!;
/// <summary>
/// 客户简称
/// </summary>
public string CustomName { get; set; }
/// <summary> /// <summary>
/// 时效(小时) /// 时效(小时)
/// </summary> /// </summary>
@ -85,6 +95,8 @@ public class GetWarningNotifiesVo
public List<int> NotifyUserIds { get; set; } public List<int> NotifyUserIds { get; set; }
public string NotifyUser { get; set; }
/// <summary> /// <summary>
/// 因素类型排序 /// 因素类型排序
/// </summary> /// </summary>

View File

@ -5,6 +5,12 @@ public class WarningRuleCacheDto
public int Id { get; set; } public int Id { get; set; }
public int SystemId { get; set; } public int SystemId { get; set; }
public int CustomerId { get; set; } public int CustomerId { get; set; }
/// <summary>
/// 客户简称
/// </summary>
public string CustomName { get; set; }
public int WarningId { get; set; } public int WarningId { get; set; }
public float TotalTimeSpan { get; set; } public float TotalTimeSpan { get; set; }
public float WarnTimeSpan { get; set; } public float WarnTimeSpan { get; set; }

View File

@ -2,6 +2,7 @@ using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; using SJZY.Track.Domain.Aggregates.KPIAreaAggregate;
using SJZY.Track.Domain.Dtos.Forewarning; using SJZY.Track.Domain.Dtos.Forewarning;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
using SJZY.Track.Domain.VEntities;
using SJZY.Track.Share.Enums; using SJZY.Track.Share.Enums;
namespace SJZY.Track.Repository.Queries; namespace SJZY.Track.Repository.Queries;
@ -19,12 +20,15 @@ public class WarningQueries : ISugarRepository, IWarningQueries,
.LeftJoin<WarningNotifyEntity>((w, wr, a, wn) => .LeftJoin<WarningNotifyEntity>((w, wr, a, wn) =>
wr.WarningId == wn.WarningId && wr.StartTrackStatusId == wn.StartTrackStatusId && wr.WarningId == wn.WarningId && wr.StartTrackStatusId == wn.StartTrackStatusId &&
wr.EndTrackStatusId == wn.EndTrackStatusId) wr.EndTrackStatusId == wn.EndTrackStatusId)
.LeftJoin<VExternalSubjectEntity>((w, wr, a, wn, cus) => w.CustomerId == cus.Id)
.Filter(null, true) // 支持历史规则 .Filter(null, true) // 支持历史规则
.Where((w, wr) => ruleIds.Contains(wr.Id)) .Where((w, wr) => ruleIds.Contains(wr.Id))
.Select<GetWarningNotifiesVo>((w, wr, a, wn) => new GetWarningNotifiesVo .Select<GetWarningNotifiesVo>((w, wr, a, wn, cus) => new GetWarningNotifiesVo
{ {
SubSystemId = w.SubSystemId,
RuleId = wr.Id, RuleId = wr.Id,
WarningName = w.Name, WarningName = w.Name,
CustomName = cus.Name,
TotalTimeSpan = wr.TotalTimeSpan, TotalTimeSpan = wr.TotalTimeSpan,
WarnTimeSpan = wr.WarnTimeSpan, WarnTimeSpan = wr.WarnTimeSpan,
WarnCount = wr.WarnCount, WarnCount = wr.WarnCount,
@ -37,6 +41,7 @@ public class WarningQueries : ISugarRepository, IWarningQueries,
LeavePort = wr.LeavePort, LeavePort = wr.LeavePort,
ProductCode = wr.ProductCode, ProductCode = wr.ProductCode,
NotifyMode = wn.NotifyMode, NotifyMode = wn.NotifyMode,
NotifyUser = wn.NotifyUser,
NotifyUserId = wn.NotifyUserId, NotifyUserId = wn.NotifyUserId,
FactorTypeSort = w.FactorTypeSort FactorTypeSort = w.FactorTypeSort
}) })

View File

@ -7,11 +7,11 @@ using SJZY.Track.Domain.Consts;
namespace SJZY.Track.Repository.Repositories; namespace SJZY.Track.Repository.Repositories;
public class OrderOperationRecordRepository : ElasticSearchContextAbstract<TrackDetailsIndex>, public class OrderOperationRecordEsRepository : ElasticSearchContextAbstract<TrackDetailsIndex>,
IOrderOperationRecordRepository, IOrderOperationRecordEsRepository,
ITransientDependency ITransientDependency
{ {
public OrderOperationRecordRepository(ConnectionFactory connectionFactory) : base(connectionFactory) public OrderOperationRecordEsRepository(ConnectionFactory connectionFactory) : base(connectionFactory)
{ {
} }
@ -26,7 +26,7 @@ public class OrderOperationRecordRepository : ElasticSearchContextAbstract<Track
if (!r.IsValid) if (!r.IsValid)
{ {
LogHelper.Error($"轨迹推送记录写入es失败,原因:{r.DebugInformation}。"); LogHelper.Error($"订单操作记录写入es失败,原因:{r.DebugInformation}。");
} }
} }

View File

@ -6,12 +6,12 @@ using SJZY.Track.Domain.Consts;
namespace SJZY.Track.Repository.Repositories; namespace SJZY.Track.Repository.Repositories;
internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetailsIndex>, ITrackDetailsRepository, internal class DetailsEsRepository : ElasticSearchContextAbstract<TrackDetailsIndex>, ITrackDetailsEsRepository,
ITransientDependency ITransientDependency
{ {
const int SafelyLimit = GlobalConst.SafelyLimit; const int SafelyLimit = GlobalConst.SafelyLimit;
public TrackDetailsRepository(ConnectionFactory connectionFactory) : base(connectionFactory) public DetailsEsRepository(ConnectionFactory connectionFactory) : base(connectionFactory)
{ {
} }

View File

@ -7,10 +7,10 @@ using SJZY.Track.Domain.Consts;
namespace SJZY.Track.Repository.Repositories; namespace SJZY.Track.Repository.Repositories;
public class TrackPushRecordsRepository : ElasticSearchContextAbstract<TrackDetailsIndex>, ITrackPushRecordsRepository, public class PushRecordEsRepository : ElasticSearchContextAbstract<TrackDetailsIndex>, ITrackPushRecordEsRepository,
ITransientDependency ITransientDependency
{ {
public TrackPushRecordsRepository(ConnectionFactory connectionFactory) : base(connectionFactory) public PushRecordEsRepository(ConnectionFactory connectionFactory) : base(connectionFactory)
{ {
} }

View File

@ -0,0 +1,106 @@
using Nest;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ElasticSearch.Services;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Consts;
using SJZY.Track.Domain.Dtos.Forewarning;
namespace SJZY.Track.Repository.Repositories;
public class WarningRecordEsRepository : ElasticSearchContextAbstract<WarningRecordIndex>, IWarningRecordEsRepository,
ITransientDependency
{
public WarningRecordEsRepository(ConnectionFactory connectionFactory) : base(connectionFactory)
{
}
public async Task AddAsync(WarningRecordIndex index)
{
index.IndexName = $"{GlobalConst.TrackWarningRecordIndex}-{DateTime.Now:yyyy.MM.dd}";
index.CreateTime = DateTime.Now;
// 按天写入es
var r = await Context.IndexAsync(index, request => request
.Index(index.IndexName)
);
if (!r.IsValid)
{
LogHelper.Error($"运输时效预警记录写入es失败,原因:{r.DebugInformation}。");
}
}
public async Task BulkInsertAsync(List<WarningRecordIndex> warningRecords)
{
if (!warningRecords.Any()) return;
// 按天写入es
var indexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}";
warningRecords.ForEach(x => x.IndexName = indexName);
var r = await Context.IndexManyAsync(warningRecords, indexName);
if (!r.IsValid)
{
throw new InvalidOperationException($"{warningRecords.Count}条运输时效预警记录新增失败,原因:{r.DebugInformation}。");
}
}
public async Task BulkUpdateAsync(List<(int ruleId, int orderId)> rules)
{
foreach (var rule in rules)
{
var r = await Context.UpdateByQueryAsync<WarningRecordIndex>(u =>
u.Query(q =>
q.Term(f => f.RuleId, rule.ruleId)
&& q.Term(f => f.OrderId, rule.orderId)
)
.Script(s => s.Source("ctx._source.warningStatus = params.warningStatus")
.Params(p => p.Add("warningStatus", WarningStatus.Processed))
)
);
if (!r.IsValid)
{
throw new InvalidOperationException(
$"运输时效预警记录更新失败,ruleId:{rule.ruleId},orderId:{rule.orderId},原因:{r.DebugInformation}。");
}
}
}
public async Task<(List<WarningRecordIndex> list, long total)> GetOrderWarningPageListAsync(
GetOrderWarningPageListVo input)
{
Func<QueryContainerDescriptor<WarningRecordIndex>, QueryContainer> query = q =>
(input.SubSystemId.HasValue ? q.Term(f => f.SubSystemId, input.SubSystemId) : null)
&& (!input.OrderNos.IsNullOrEmpty()
? q.Terms(t => t
.Field(f => f.OrderId.Suffix("keyword"))
.Terms(input.OrderNos))
: null)
&& (input.WarningStatus.HasValue ? q.Term(f => f.WarningStatus, input.WarningStatus) : null)
&& (!input.CustomName.IsNullOrWhiteSpace()
? q.Wildcard(w => w.CustomName, $"*{input.CustomName}*")
: null)
&& (!input.WarningName.IsNullOrWhiteSpace()
? q.Wildcard(w => w.WarningName, $"*{input.WarningName}*")
: null)
&& (!input.NotifyUser.IsNullOrWhiteSpace()
? q.Wildcard(w => w.NotifyUser, $"*{input.NotifyUser}*")
: null)
&& (input.StartTime.HasValue
? q.DateRange(r => r.Field(f => f.CreateTime).GreaterThanOrEquals(input.StartTime))
: null)
&& (input.EndTime.HasValue
? q.DateRange(r => r.Field(f => f.CreateTime).LessThanOrEquals(input.EndTime))
: null);
var data = await Context.SearchAsync<WarningRecordIndex>(x => x
.Source()
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending))
.From((input.PageIndex - 1) * input.PageSize)
.Size(input.PageSize)
.TrackTotalHits()
);
return (data.Documents.ToList(), data.Total);
}
}