From 2bedb127b6087b8e0077a608c34916a180e8a613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=86=9B?= <2357729423@qq.com> Date: Fri, 12 Apr 2024 21:34:15 +0800 Subject: [PATCH] =?UTF-8?q?opt=EF=BC=9A=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Events/OrderIdentifier.cs | 8 + .../Events/OrderLinkAfterFillTrackEvent.cs | 28 -- .../TrackChangeAfterUpdateOrderEvent.cs | 2 +- .../Events/TrackDeleteEvent.cs | 19 +- .../Events/TrackRefreshStruct.cs | 25 ++ .../Events/TrackUpsertEvent.cs | 46 +--- .../Events/TrackUpsertForRefreshEvent.cs | 94 +++++++ .../OrderLinkAfterFillTrackHandler.cs | 48 ---- ...TrackChangeAfterUpdateOrderEventHandler.cs | 85 +++--- .../EventHandlers/TrackDeleteEventHandler.cs | 71 ++--- .../TrackInsertForNotMappedEventHandler.cs | 2 +- .../EventHandlers/TrackPushEventHandler.cs | 9 +- .../EventHandlers/TrackRefreshEventHandler.cs | 44 ++- .../EventHandlers/TrackUpsertEventHandler.cs | 257 ++++++++++-------- .../ProvideServices/OrderService.Link.cs | 52 ++-- .../Services/ProvideServices/OrderService.cs | 4 +- .../Services/ProvideServices/TrackService.cs | 30 +- .../OrderAggregate/IOrderRepository.cs | 2 +- .../ITrackDetailsRepository.cs | 22 +- .../Consts/GlobalConst.MQ.cs | 5 + src/SJZY.Track.Repository/EsExtensions.cs | 22 ++ .../Repositories/OrderRepository.cs | 6 +- .../Repositories/TrackDetailsRepository.cs | 121 +++++---- 23 files changed, 568 insertions(+), 434 deletions(-) create mode 100644 src/SJZY.Track.Application.Contract/Events/OrderIdentifier.cs delete mode 100644 src/SJZY.Track.Application.Contract/Events/OrderLinkAfterFillTrackEvent.cs create mode 100644 src/SJZY.Track.Application.Contract/Events/TrackRefreshStruct.cs create mode 100644 src/SJZY.Track.Application.Contract/Events/TrackUpsertForRefreshEvent.cs delete mode 100644 src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs create mode 100644 src/SJZY.Track.Repository/EsExtensions.cs diff --git a/src/SJZY.Track.Application.Contract/Events/OrderIdentifier.cs b/src/SJZY.Track.Application.Contract/Events/OrderIdentifier.cs new file mode 100644 index 00000000..49e79b04 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Events/OrderIdentifier.cs @@ -0,0 +1,8 @@ +namespace SJZY.Track.Application.Contract.Events; + +public struct OrderIdentifier +{ + public int OrderId { get; set; } + public string OrderNo { get; set; } + public int OrderType { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/OrderLinkAfterFillTrackEvent.cs b/src/SJZY.Track.Application.Contract/Events/OrderLinkAfterFillTrackEvent.cs deleted file mode 100644 index f4caa481..00000000 --- a/src/SJZY.Track.Application.Contract/Events/OrderLinkAfterFillTrackEvent.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace SJZY.Track.Application.Contract.Events; - -public class OrderLinkAfterFillTrackEvent -{ - /// - /// 关联订单id - /// - public int OrderId { get; set; } - - /// - /// 子系统id - /// - public int SubSystemId { get; set; } - - /// - /// 关联订单 - /// - public List LinkedOrders { get; set; } = null!; -} - -public struct LinkedOrder -{ - public int SubSystemId { get; set; } - - public int OrderId { get; set; } - public string OrderNo { get; set; } - public int OrderType { get; set; } -} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/TrackChangeAfterUpdateOrderEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackChangeAfterUpdateOrderEvent.cs index c779a647..544c98b1 100644 --- a/src/SJZY.Track.Application.Contract/Events/TrackChangeAfterUpdateOrderEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackChangeAfterUpdateOrderEvent.cs @@ -5,7 +5,7 @@ public class TrackChangeAfterUpdateOrderEvent /// /// 订单Id /// - public int OrderId { get; set; } + public int[] OrderIds { get; set; } /// /// 是否删除引起的更新 diff --git a/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs index d5286726..73b4d0ac 100644 --- a/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs @@ -2,25 +2,20 @@ public class TrackDeleteEvent { - /// - /// 订单id - /// - public int OrderId { get; set; } - - /// - /// 轨迹代码 - /// - public List TrackCodes { get; set; } = null!; - /// /// 子系统id /// public int SubSystemId { get; set; } /// - /// 上游子系统id + /// 订单ids /// - public int UpSubSystemId { get; set; } + public int[] OrderIds { get; set; } = null!; + + /// + /// 轨迹代码 + /// + public List TrackCodes { get; set; } = null!; /// /// 操作人 diff --git a/src/SJZY.Track.Application.Contract/Events/TrackRefreshStruct.cs b/src/SJZY.Track.Application.Contract/Events/TrackRefreshStruct.cs new file mode 100644 index 00000000..62bcf4a2 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Events/TrackRefreshStruct.cs @@ -0,0 +1,25 @@ +namespace SJZY.Track.Application.Contract.Events; + +public struct TrackRefreshStruct +{ + /// + /// 服务商 + /// + public string? ServiceProviderName { get; set; } + + /// + /// 原轨迹内容 + /// + public string? OriginTrackContent { get; set; } + + /// + /// 原轨迹报文 + /// + public string? OriginTrackData { get; set; } + + /// + /// 表示订单是否完成(只由轨迹刷新配置决定) + /// tips:能够使得IsCompleted为true的点,全局只有一个:轨迹刷新 + /// + public bool IsCompleted { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs index 53e0d856..3b449bbf 100644 --- a/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs @@ -3,50 +3,14 @@ public class TrackUpsertEvent { /// - /// 订单id - /// - public int OrderId { get; set; } - - /// - /// 订单类型 - /// - public int OrderType { get; set; } - - /// - /// 订单号 - /// - public string OrderNo { get; set; } = null!; - - /// - /// 服务商 - /// - public string? ServiceProviderName { get; set; } - - /// - /// 原轨迹内容 - /// - public string? OriginTrackContent { get; set; } - - /// - /// 原轨迹报文 - /// - public string? OriginTrackData { get; set; } - - /// - /// 表示订单是否完成(只由轨迹刷新配置决定) - /// tips:能够使得IsCompleted为true的点,全局只有一个:轨迹刷新 - /// - public bool IsCompleted { get; set; } - - /// - /// 子系统id + /// 子系统id(操作的订单都是相同子系统下的) /// public int SubSystemId { get; set; } /// - /// 上游子系统id(0表示事件起点) + /// 订单id /// - public int UpSubSystemId { get; set; } + public OrderIdentifier[] OrderIdentifiers { get; set; } = null!; /// /// 操作人(null则默认系统) @@ -54,7 +18,7 @@ public class TrackUpsertEvent public string? OperationMan { get; set; } /// - /// true新增,false更新,null表示新增/更新 + /// true新增,false更新,null表示刷新 /// public bool? IsAdd { get; set; } @@ -82,4 +46,6 @@ public class TrackUpsertEvent /// 已经处理过的订单 /// public List Visited { get; set; } = new(); + + public TrackRefreshStruct TrackRefreshData { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/TrackUpsertForRefreshEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackUpsertForRefreshEvent.cs new file mode 100644 index 00000000..7069903a --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Events/TrackUpsertForRefreshEvent.cs @@ -0,0 +1,94 @@ +namespace SJZY.Track.Application.Contract.Events; + +public class TrackUpsertForRefreshEvent +{ + /// + /// 子系统id(操作的订单都是相同子系统下的) + /// + public int SubSystemId { get; set; } + + /// + /// 订单 + /// + public OrderIdentifier OrderIdentifiers { get; set; } + + /// + /// 服务商 + /// + public string? ServiceProviderName { get; set; } + + /// + /// 原轨迹内容 + /// + public string? OriginTrackContent { get; set; } + + /// + /// 原轨迹报文 + /// + public string? OriginTrackData { get; set; } + + /// + /// 表示订单是否完成(只由轨迹刷新配置决定) + /// tips:能够使得IsCompleted为true的点,全局只有一个:轨迹刷新 + /// + public bool IsCompleted { get; set; } + + /// + /// 轨迹内容代码 + /// + public string TrackCode { get; set; } = null!; + + /// + /// 轨迹发生地 + /// + public string TrackPlace { get; set; } = null!; + + /// + /// 轨迹发生时间 + /// + public DateTime TrackTime { get; set; } + + /// + /// 轨迹发生时区 + /// + public float TrackTimeZone { get; set; } +} + +public class TrackHandledDto +{ + /// + /// 原轨迹内容 + /// + public string? OriginTrackContent { get; set; } + + /// + /// 原轨迹报文 + /// + public string? OriginTrackData { get; set; } + + /// + /// 表示订单是否完成(只由轨迹刷新配置决定) + /// tips:能够使得IsCompleted为true的点,全局只有一个:轨迹刷新 + /// + public bool? IsCompleted { get; set; } + + /// + /// 轨迹内容代码 + /// + public string? TrackCode { get; set; } + + /// + /// 轨迹发生地 + /// + public string? TrackPlace { get; set; } + + /// + /// 轨迹发生时间 + /// + public DateTime? TrackTime { get; set; } + + /// + /// 轨迹发生时区 + /// + public float? TrackTimeZone { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs b/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs deleted file mode 100644 index 37daa472..00000000 --- a/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using DotNetCore.CAP; -using SJZY.Track.Application.Contract.Events; -using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; -using SJZY.Track.Domain.Consts; -using Volo.Abp.DependencyInjection; - -namespace SJZY.Track.Application.EventHandlers; - -public class OrderLinkAfterFillTrackHandler : ITransientDependency, ICapSubscribe -{ - private readonly ITrackDetailsRepository _trackDetailsRepository; - private readonly ICapPublisher _capPublisher; - - public OrderLinkAfterFillTrackHandler(ITrackDetailsRepository trackDetailsRepository, ICapPublisher capPublisher) - { - _trackDetailsRepository = trackDetailsRepository; - _capPublisher = capPublisher; - } - - [CapSubscribe(GlobalConst.OrderLinkAfterFillTrack)] - public async Task ConsumerAsync(OrderLinkAfterFillTrackEvent @event) - { - var tracks = await _trackDetailsRepository.GetListAsync(@event.OrderId); - - - foreach (var order in @event.LinkedOrders) - { - // 补轨迹 - foreach (var track in tracks) - { - var fillTrackEvent = new TrackUpsertEvent - { - OrderId = order.OrderId, - OrderType = order.OrderType, - OrderNo = order.OrderNo, - TrackCode = track.TrackCode, - TrackPlace = track.TrackPlace, - TrackTime = track.TrackTime, - TrackTimeZone = track.TrackTimeZone, - SubSystemId = order.SubSystemId, - UpSubSystemId = @event.SubSystemId, - }; - - await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, fillTrackEvent); - } - } - } -} \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs index a738576e..25e74d44 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs @@ -22,53 +22,70 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa [CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)] public async Task ConsumerAsync(TrackChangeAfterUpdateOrderEvent @event) { - var order = await _orderRepository.GetFirstAsync(x => x.Id == @event.OrderId); - if (order == default) return; + var orders = await _orderRepository.GetListAsync(x => @event.OrderIds.Contains(x.Id), + x => new OrderEntity + { + Id = x.Id, + IsCompleted = x.IsCompleted, + LatestTrackContent = x.LatestTrackContent, + LatestTrackEnContent = x.LatestTrackEnContent, + LatestTrackPlace = x.LatestTrackPlace, + LatestTrackTime = x.LatestTrackTime, + LatestTrackTimeZone = x.LatestTrackTimeZone, + }); + if (orders.Count == 0) return; + + // todo:delete可能发生回退,直接去es查最新轨迹,但是可能es还没有刷盘,导致回退失效,可以考虑加个定时任务弥补 if (@event.IsDelete) { - var track = await _trackDetailsRepository.GetLatestAsync(@event.OrderId); - - // 删除全部轨迹导致的重置行为 - if (track == default) + foreach (var order in orders) { - if (order.LatestTrackTime == null) return; + var tracks = await _trackDetailsRepository.GetListAsync(@event.OrderIds); - // tips:订单是支持从已完成态到未完成态的 - order.ResetTrackInfo(); + var track = tracks.Where(x => x.OrderId == order.Id).MaxBy(x => x.TrackTime); + // 删除全部轨迹导致的重置行为 + if (track == default) + { + if (order.LatestTrackTime == null) return; - await _orderRepository.UpdateAsync(order); - - return; + // tips:订单是支持从已完成态到未完成态的 + order.ResetTrackInfo(); + } + else + { + // 删除引发的回退更新 + order.IsCompleted = @event.IsCompleted; + order.LatestTrackContent = track.TrackContent; + order.LatestTrackEnContent = track.TrackEnContent; + order.LatestTrackPlace = track.TrackPlace; + order.LatestTrackTime = track.TrackTime; + order.LatestTrackTimeZone = track.TrackTimeZone; + } } - - // 删除引发的回退更新 - order.IsCompleted = @event.IsCompleted; - order.LatestTrackContent = track.TrackContent; - order.LatestTrackEnContent = track.TrackEnContent; - order.LatestTrackPlace = track.TrackPlace; - order.LatestTrackTime = track.TrackTime; - order.LatestTrackTimeZone = track.TrackTimeZone; } - else + else // upsert可以直接计算 { - if (order.LatestTrackTime != null && - @event.TrackTime.Subtract(TimeSpan.FromHours(@event.TrackTimeZone)) < - order.LatestTrackTime.Value.Subtract(TimeSpan.FromHours(order.LatestTrackTimeZone ?? 0))) + foreach (var order in orders) { - return; - } + if (order.LatestTrackTime != null && + @event.TrackTime.Subtract(TimeSpan.FromHours(@event.TrackTimeZone)) < + order.LatestTrackTime.Value.Subtract(TimeSpan.FromHours(order.LatestTrackTimeZone ?? 0))) + { + continue; + } - // upsert引发的更新 - order.IsCompleted = @event.IsCompleted; - order.LatestTrackContent = @event.TrackContent; - order.LatestTrackEnContent = @event.TrackEnContent; - order.LatestTrackPlace = @event.TrackPlace; - order.LatestTrackTime = @event.TrackTime; - order.LatestTrackTimeZone = @event.TrackTimeZone; + // upsert引发的更新 + order.IsCompleted = @event.IsCompleted; + order.LatestTrackContent = @event.TrackContent; + order.LatestTrackEnContent = @event.TrackEnContent; + order.LatestTrackPlace = @event.TrackPlace; + order.LatestTrackTime = @event.TrackTime; + order.LatestTrackTimeZone = @event.TrackTimeZone; + } } - await _orderRepository.UpdateColumnAsync(order, x => new + await _orderRepository.UpdateRangeAsync(orders, x => new { x.IsCompleted, x.LatestTrackContent, x.LatestTrackEnContent, x.LatestTrackPlace, x.LatestTrackTime, x.LatestTrackTimeZone diff --git a/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs index 28b38520..ea6698fb 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs @@ -29,34 +29,52 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe [CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)] public async Task ConsumerAsync(TrackDeleteEvent @event) { - if (@event.Visited.Contains(@event.OrderId)) + var dup = @event.Visited.Intersect(@event.OrderIds).ToArray(); + if (dup.Any()) { - LogHelper.Error($"删除轨迹订单时,发现循环依赖:{@event.Visited.JoinAsString(",")}"); + LogHelper.Error($"删除轨迹订单时,发现循环依赖:{dup.JoinAsString(",")}"); return; } - // 不同子系统需要做内容映射 - if (@event.UpSubSystemId != 0 && @event.UpSubSystemId != @event.SubSystemId) - { - var mapCodes = await _provideQueries - .MapTrackCodesAsync(@event.UpSubSystemId, @event.SubSystemId, @event.TrackCodes.ToArray()); - - if (mapCodes.Count == 0) - { - //throw new BusinessException(message: "订单跨子系统,未配置内容映射,请联系管理员"); - return; - } - - @event.TrackCodes = mapCodes; - } - await DeleteTrackAsync(@event); + + // 根据订单关联关系异步向下刷(异步) + var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderIds); + foreach (var orderId in @event.OrderIds) + { + foreach (var group in linkedOrders.Where(x => x.OrderId == orderId) + .GroupBy(x => x.SubSystemId)) + { + var nextEvent = @event.DeepCopy(); + nextEvent.Visited.AddRange(@event.OrderIds); + nextEvent.TrackCodes = @event.TrackCodes; + nextEvent.SubSystemId = group.Key; + + + // 不同子系统需要做内容映射 + if (@event.SubSystemId != nextEvent.SubSystemId) + { + var mapCodes = await _provideQueries + .MapTrackCodesAsync(@event.SubSystemId, nextEvent.SubSystemId, @event.TrackCodes.ToArray()); + + if (mapCodes.Count == 0) + { + //throw new BusinessException(message: "订单跨子系统,未配置内容映射,请联系管理员"); + return; + } + + nextEvent.TrackCodes = mapCodes; + } + + await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, nextEvent); + } + } } private async Task DeleteTrackAsync(TrackDeleteEvent @event) { - // 删除轨迹 - var isOk = await _trackDetailsRepository.DeleteTrackAsync(@event.OrderId, @event.TrackCodes); + // 删除轨迹(删的是同子系统下的单,所以code是统一的) + var isOk = await _trackDetailsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes); if (isOk) { @@ -65,22 +83,9 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe GlobalConst.TrackChangeAfterUpdateOrderSubscribe, new TrackChangeAfterUpdateOrderEvent { - OrderId = @event.OrderId, + OrderIds = @event.OrderIds, IsDelete = true }); } - - // 根据订单关联关系异步向下刷 - var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId); - foreach (var linkedOrder in linkedOrders) - { - var nextEvent = @event.DeepCopy(); - nextEvent.Visited.Add(@event.OrderId); - nextEvent.TrackCodes = @event.TrackCodes; - nextEvent.SubSystemId = linkedOrder.SubSystemId; - nextEvent.UpSubSystemId = @event.SubSystemId; - - await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, nextEvent); - } } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackInsertForNotMappedEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackInsertForNotMappedEventHandler.cs index f135b558..a0df5114 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackInsertForNotMappedEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackInsertForNotMappedEventHandler.cs @@ -45,6 +45,6 @@ public class TrackInsertForNotMappedEventHandler : ITransientDependency, ICapSub track.TrackEnContent = GlobalConst.EmptyString; track.ZeroTrackTime = track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); - await _trackDetailsRepository.UpsertAsync(track); + await _trackDetailsRepository.UpdateAsync(track); } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs index a9a207e9..65e60991 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs @@ -37,7 +37,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe var order = await _orderRepository.GetFirstAsync(x => x.Id == @event.OrderId, x => new { - x.SubSystemId, x.LatestPushTrackCode, x.QuestionType, x.CustomId + x.SubSystemId, x.LatestPushTrackCode, x.QuestionType, x.CustomId, x.OrderType }); if (order == null) return; @@ -70,10 +70,9 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe // 推送新增,需要根据上一次的推送 推断 本次推送 是否可行 config = await _trackPushCacheService.IsValidPushAsync(order.SubSystemId, order.CustomId, order.LatestPushTrackCode, @event.TrackCode); - if (config is not { IsAutoPush: true }) - { - config = null; - } + if (config == null) return; + if (!config.IsAutoPush) return; + if (config.OrderType != order.OrderType) return; } } else diff --git a/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs index 61431b30..4c132e26 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs @@ -9,6 +9,7 @@ using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Application.Helpers; using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Enums; using Volo.Abp.DependencyInjection; @@ -20,13 +21,16 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe private readonly IOrderRepository _orderRepository; private readonly ICapPublisher _capPublisher; private readonly ITrackPullCacheService _trackPullCacheService; + private readonly ITrackDetailsRepository _trackDetailsRepository; public TrackRefreshEventHandler(IOrderRepository orderRepository, - ICapPublisher capPublisher, ITrackPullCacheService trackPullCacheService) + ICapPublisher capPublisher, ITrackPullCacheService trackPullCacheService, + ITrackDetailsRepository trackDetailsRepository) { _orderRepository = orderRepository; _capPublisher = capPublisher; _trackPullCacheService = trackPullCacheService; + _trackDetailsRepository = trackDetailsRepository; } [CapSubscribe(GlobalConst.TrackRefreshSubscribe, Group = GlobalConst.TrackRefreshSubscribe)] @@ -89,15 +93,19 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe await HandleTrackAsync(item, paramWithContentConfig, context); } } - else if (orderToken is JObject) + else if (trackToken is JObject) { - await HandleTrackAsync(orderToken, paramWithContentConfig, context); + await HandleTrackAsync(trackToken, paramWithContentConfig, context); } } private async Task HandleTrackAsync(JToken trackToken, TrackPullParamWithContentConfigDto paramWithContentConfig, TrackRefreshContext context) { + var originTrackData = JsonConvert.SerializeObject(trackToken); + // 如果已经存在一模一样的报文了说明处理过了,直接return + if (await _trackDetailsRepository.AnyAsync(context.OrderId, originTrackData)) return; + var paramConfig = paramWithContentConfig.ParamConfig; var contentConfigs = paramWithContentConfig.ContentConfigs; TrackPullContentConfigDto? matchedContentConfig = null; @@ -214,23 +222,31 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe // 新增/更新轨迹 var trackUpsertEvent = new TrackUpsertEvent { - OrderId = context.OrderId, - OrderType = context.OrderType, - OrderNo = context.OrderNo, - ServiceProviderName = context.ServiceProviderName, - OriginTrackData = JsonConvert.SerializeObject(trackToken), - IsCompleted = matchedContentConfig.IsCompleted, + OrderIdentifiers = new[] + { + new OrderIdentifier + { + OrderId = context.OrderId, + OrderNo = context.OrderNo, + OrderType = context.OrderType + } + }, + TrackRefreshData = new TrackRefreshStruct + { + ServiceProviderName = context.ServiceProviderName, + OriginTrackData = originTrackData, + IsCompleted = matchedContentConfig.IsCompleted, + OriginTrackContent = paramConfig.TrackContentName != null + ? trackToken[paramConfig.TrackContentName]?.Value() + : GlobalConst.EmptyString + }, SubSystemId = context.SubSystemId, TrackCode = matchedContentConfig.TrackContentCode, TrackPlace = trackPlace ?? GlobalConst.EmptyString, TrackTime = trackTime ?? DateTime.Now, TrackTimeZone = trackTimeZone ?? matchedContentConfig.TrackTimeZoneValue ?? 8 }; - if (paramConfig.TrackContentName != null) - { - trackUpsertEvent.OriginTrackContent = trackToken[paramConfig.TrackContentName]?.Value(); - } - await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, trackUpsertEvent); + await _capPublisher.PublishAsync(GlobalConst.TrackUpsertForRefreshSubscribe, trackUpsertEvent); } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs index 105ef588..81e954fe 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs @@ -26,145 +26,166 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe _trackDetailsRepository = trackDetailsRepository; } + [CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)] [CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)] public async Task ConsumerAsync(TrackUpsertEvent @event) { - if (@event.Visited.Contains(@event.OrderId)) + var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray(); + + var dup = @event.Visited.Intersect(orderIds).ToArray(); + if (dup.Any()) { - LogHelper.Error($"轨迹订单循环依赖预警:{@event.Visited.JoinAsString(",")}"); + LogHelper.Error($"删除轨迹订单时,发现循环依赖:{dup.JoinAsString(",")}"); return; } - // 不同子系统需要做内容映射 - if (@event.UpSubSystemId != 0 && @event.UpSubSystemId != @event.SubSystemId) - { - var mapCode = (await _provideQueries - .MapTrackCodesAsync(@event.UpSubSystemId, @event.SubSystemId, @event.TrackCode)) - .FirstOrDefault(); + await HandleTrackAsync(@event); - if (mapCode == default) + // 根据订单关联关系异步向下刷(异步) + var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(orderIds); + foreach (var order in @event.OrderIdentifiers) + { + // 理论上小包在这不会分组 + foreach (var group in linkedOrders.Where(x => x.OrderId == order.OrderId) + .GroupBy(x => x.SubSystemId)) { - // 跨子系统没做映射的轨迹不处理 - return; + var nextEvent = @event.DeepCopy(); + nextEvent.Visited.AddRange(orderIds); + nextEvent.SubSystemId = group.Key; + nextEvent.OrderIdentifiers = group.Select(x => new OrderIdentifier + { + OrderId = x.OrderId, + OrderNo = x.OrderNo, + OrderType = x.OrderType + }).ToArray(); + nextEvent.TrackRefreshData = new TrackRefreshStruct + { + ServiceProviderName = @event.TrackRefreshData.ServiceProviderName, + OriginTrackContent = @event.TrackRefreshData.OriginTrackContent, + OriginTrackData = @event.TrackRefreshData.OriginTrackData, + // tips:一定要重置为false,父级订单的完成不会使得关联订单完成,关联单也必须由刷新来完成或手动设置完成!! + IsCompleted = false + }; + + // 不同子系统需要做内容映射 + if (@event.SubSystemId != nextEvent.SubSystemId) + { + var mapCode = (await _provideQueries + .MapTrackCodesAsync(@event.SubSystemId, nextEvent.SubSystemId, @event.TrackCode)) + .FirstOrDefault(); + + if (mapCode == default) + { + // 跨子系统没做映射的轨迹不处理 + return; + } + + @event.TrackCode = mapCode; + } + + await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, nextEvent); + } + } + } + + private async Task HandleTrackAsync(TrackUpsertEvent @event) + { + var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray(); + var tracks = await _trackDetailsRepository.GetListAsync(orderIds, @event.TrackCode); + + var insertTracks = new List(); + + foreach (var order in @event.OrderIdentifiers) + { + var track = tracks.FirstOrDefault(x => x.OrderId == order.OrderId); + + if (@event.IsAdd != null) + { + if (track == null && !@event.IsAdd!.Value) return; // 不存在不让改 + if (track != null && @event.IsAdd!.Value) return; // 存在不让创建 } - @event.TrackCode = mapCode; - } - - var track = await _trackDetailsRepository.GetFirstOrDefaultAsync(@event.OrderId, @event.TrackCode); - - if (@event.IsAdd != null) - { - if (track == null && !@event.IsAdd!.Value) return; // 不存在不让改 - if (track != null && @event.IsAdd!.Value) return; // 存在不让创建 - } - - // step1、upsert es轨迹 - track = await UpsertTrackAsync(track, @event); - - if (track == null) return; // 模板没配该轨迹代码,不再继续 - - // step2、触发轨迹推送事件(异步) - var trackPushEvent = new TrackPushEvent - { - OptionType = track.Id.IsNullOrWhiteSpace() ? OptionType.新增 : OptionType.修改, - OrderId = track.OrderId, - OrderNo = track.OrderNo, - TrackStatus = track.TrackStatus, - TrackCode = track.TrackCode, - TrackContent = track.TrackContent, - TrackPlace = track.TrackPlace, - TrackTime = track.TrackTime, - TrackTimeZone = track.TrackTimeZone, - }; - - await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent); - - // step3、触发订单主表更新事件(异步) - await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe, - new TrackChangeAfterUpdateOrderEvent + // step1、upsert es轨迹 + if (track == default) { + track = new TrackDetailsIndex + { + IndexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}", + OrderId = order.OrderId, + OrderNo = order.OrderNo, + OrderType = order.OrderType, + TrackCode = @event.TrackCode, + TrackPlace = @event.TrackPlace, + TrackTime = @event.TrackTime, + TrackTimeZone = @event.TrackTimeZone, + ServiceProviderName = @event.TrackRefreshData.ServiceProviderName, + OriginTrackContent = @event.TrackRefreshData.OriginTrackContent, + OriginTrackData = @event.TrackRefreshData.OriginTrackData, + IsCanDelete = false, + CreateUser = @event.OperationMan ?? GlobalConst.SystemUser, + CreateTime = DateTime.Now + }; + + //todo:可以优化? + // 根据轨迹code在订单模板内容中寻找匹配的 + var trackContent = await _provideQueries.MatchTrackContentAsync(order.OrderId, @event.TrackCode); + if (trackContent == default) + { + // 订单所绑定的模板,没有一条内容可以匹配发生的轨迹 + continue; + } + + track.TrackStatus = trackContent.Status; + track.TrackCode = trackContent.TrackCode; + track.TrackContent = trackContent.Content; + track.TrackEnContent = trackContent.EnContent; + track.IsCanDelete = trackContent.IsCanDelete; + track.ZeroTrackTime = track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); + + insertTracks.Add(track); + } + else + { + track.TrackPlace = @event.TrackPlace; + track.TrackTime = @event.TrackTime; + track.TrackTimeZone = @event.TrackTimeZone; + track.UpdateUser = @event.OperationMan ?? GlobalConst.SystemUser; + track.UpdateTime = DateTime.Now; + + await _trackDetailsRepository.UpdateAsync(track); + } + + // step2、触发轨迹推送事件(异步) + var trackPushEvent = new TrackPushEvent + { + OptionType = track.Id.IsNullOrWhiteSpace() ? OptionType.新增 : OptionType.修改, OrderId = track.OrderId, - IsCompleted = @event.IsCompleted, + OrderNo = track.OrderNo, + TrackStatus = track.TrackStatus, TrackCode = track.TrackCode, TrackContent = track.TrackContent, - TrackEnContent = track.TrackEnContent, TrackPlace = track.TrackPlace, TrackTime = track.TrackTime, - TrackTimeZone = track.TrackTimeZone - }); - - // step4、根据订单关联关系异步向下刷(异步) - var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId); - foreach (var linkedOrder in linkedOrders) - { - var nextEvent = @event.DeepCopy(); - nextEvent.Visited.Add(@event.OrderId); - // tips:一定要重置为false,父级订单的完成不会使得关联订单完成,关联单也必须由刷新来完成或手动设置完成!! - nextEvent.IsCompleted = false; // 能够使得轨迹IsCompleted为true的点,全局只有一个:轨迹刷新 - nextEvent.OrderId = linkedOrder.OrderId; - nextEvent.OrderType = linkedOrder.OrderType; - nextEvent.OrderNo = linkedOrder.OrderNo; - nextEvent.SubSystemId = linkedOrder.SubSystemId; - nextEvent.UpSubSystemId = @event.SubSystemId; - await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, nextEvent); - } - } - - /// - /// 不存在则新增轨迹,存在则更新 - /// - /// - /// - private async Task UpsertTrackAsync(TrackDetailsIndex? track, TrackUpsertEvent @event) - { - if (track == default) - { - track = new TrackDetailsIndex - { - IndexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}", - OrderId = @event.OrderId, - OrderNo = @event.OrderNo, - OrderType = @event.OrderType, - TrackCode = @event.TrackCode, - TrackPlace = @event.TrackPlace, - TrackTime = @event.TrackTime, - TrackTimeZone = @event.TrackTimeZone, - ServiceProviderName = @event.ServiceProviderName, - OriginTrackContent = @event.OriginTrackContent, - OriginTrackData = @event.OriginTrackData, - IsCanDelete = false, - CreateUser = @event.OperationMan ?? GlobalConst.SystemUser, - CreateTime = DateTime.Now + TrackTimeZone = track.TrackTimeZone, }; - //todo:可以优化 - // 根据轨迹code在订单模板内容中寻找匹配的 - var trackContent = await _provideQueries.MatchTrackContentAsync(@event.OrderId, @event.TrackCode); - if (trackContent == default) - { - // 订单所绑定的模板,没有一条内容可以匹配发生的轨迹 - return null; - } + await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent); - track.TrackStatus = trackContent.Status; - track.TrackCode = trackContent.TrackCode; - track.TrackContent = trackContent.Content; - track.TrackEnContent = trackContent.EnContent; - track.IsCanDelete = trackContent.IsCanDelete; - track.ZeroTrackTime = track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); - } - else - { - track.TrackPlace = @event.TrackPlace; - track.TrackTime = @event.TrackTime; - track.TrackTimeZone = @event.TrackTimeZone; - track.UpdateUser = @event.OperationMan ?? GlobalConst.SystemUser; - track.UpdateTime = DateTime.Now; + // step3、触发订单主表更新事件(异步) + await _capPublisher.PublishAsync(GlobalConst.TrackChangeAfterUpdateOrderSubscribe, + new TrackChangeAfterUpdateOrderEvent + { + OrderIds = new[] { track.OrderId }, + IsCompleted = @event.TrackRefreshData.IsCompleted, + TrackCode = track.TrackCode, + TrackContent = track.TrackContent, + TrackEnContent = track.TrackEnContent, + TrackPlace = track.TrackPlace, + TrackTime = track.TrackTime, + TrackTimeZone = track.TrackTimeZone + }); } - await _trackDetailsRepository.UpsertAsync(track); - - return track; + await _trackDetailsRepository.AddManyAsync(insertTracks); } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs index 5eca209c..f37ff3b5 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs @@ -2,6 +2,7 @@ using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Queries; @@ -14,6 +15,7 @@ public partial class OrderService { private readonly IBasicQuery _orderLinkQuery; private readonly ICapPublisher _capPublisher; + private readonly ITrackDetailsRepository _trackDetailsRepository; /// /// 关联、解除关联订单 @@ -52,23 +54,12 @@ public partial class OrderService if (!input.IsLink) return await UnLinkOrderAsync(input); // 关联订单 - var linkedOrders = await DoLinkOrderAsync(input, order.Id); - - // 补轨迹 - if (linkedOrders.Count > 0) - { - await _capPublisher.PublishAsync(GlobalConst.OrderLinkAfterFillTrack, new OrderLinkAfterFillTrackEvent - { - OrderId = order.Id, - SubSystemId = order.SubSystemId, - LinkedOrders = linkedOrders, - }); - } + await DoLinkOrderAsync(input, order.Id); return new UnifyResultDto(true, true); } - private async Task> DoLinkOrderAsync(LinkOrderInput input, int orderId) + private async Task DoLinkOrderAsync(LinkOrderInput input, int orderId) { // 获取已关联的订单 var linkOrderNos = await _orderLinkQuery.GetListAsync(x => @@ -81,9 +72,9 @@ public partial class OrderService // 过滤掉不存在的订单 var canLinkOrders = await _orderRepository.GetListAsync(x => x.OrderType == input.LinkOrderType && noLinkOrderNos.Contains(x.OrderNo), - x => new { x.Id, x.OrderNo, x.SubSystemId }); + x => new { x.Id, x.OrderNo, x.OrderType, x.SubSystemId }); - if (canLinkOrders.Count == 0) return new List(); + if (canLinkOrders.Count == 0) return; await _orderRepository.LinkOrderAsync(canLinkOrders.Select(x => new OrderLinkEntity { @@ -95,13 +86,32 @@ public partial class OrderService LinkOrderType = input.LinkOrderType }).ToList()); - return canLinkOrders.Select(x => new LinkedOrder + var tracks = await _trackDetailsRepository.GetListAsync(orderId); + + // 补轨迹 + foreach (var group in canLinkOrders.GroupBy(x => x.SubSystemId)) { - SubSystemId = x.SubSystemId, - OrderId = x.Id, - OrderNo = x.OrderNo, - OrderType = input.LinkOrderType - }).ToList(); + foreach (var track in tracks) + { + var fillTrackEvent = new TrackUpsertEvent + { + SubSystemId = group.Key, + OrderIdentifiers = group.Select(x => new OrderIdentifier + { + OrderId = x.Id, + OrderNo = x.OrderNo, + OrderType = x.OrderType + }).ToArray(), + TrackCode = track.TrackCode, + TrackPlace = track.TrackPlace, + TrackTime = track.TrackTime, + TrackTimeZone = track.TrackTimeZone, + IsAdd = true + }; + + await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, fillTrackEvent); + } + } } private async Task UnLinkOrderAsync(LinkOrderInput input) diff --git a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.cs b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.cs index d1086bf7..4a72f258 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.cs @@ -2,6 +2,7 @@ using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Queries; using SJZY.UserCenter.HttpApi.Services; @@ -17,9 +18,10 @@ public partial class OrderService : ApplicationService, IOrderService private readonly IOrderRepository _orderRepository; public OrderService(IOrderRepository orderRepository, IBasicQuery orderLinkQuery, - ICapPublisher capPublisher) + ICapPublisher capPublisher, ITrackDetailsRepository trackDetailsRepository) { _orderRepository = orderRepository; + _trackDetailsRepository = trackDetailsRepository; _capPublisher = capPublisher; _orderLinkQuery = orderLinkQuery; } diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs index 1d081ead..1d20b169 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs @@ -43,7 +43,7 @@ public partial class TrackService : ApplicationService, ITrackService var order = await _orderRepository.GetFirstAsync(x => x.OrderType == input.OrderType && x.OrderNo == input.OrderNo, x => new { - x.Id, x.SubSystemId + x.Id, x.SubSystemId, x.OrderNo, x.OrderType }); if (order == default) { @@ -52,8 +52,16 @@ public partial class TrackService : ApplicationService, ITrackService // 新增/更新轨迹 var @event = ObjectMapper.Map(input); - @event.OrderId = order.Id; @event.SubSystemId = order.SubSystemId; + @event.OrderIdentifiers = new[] + { + new OrderIdentifier + { + OrderId = order.Id, + OrderNo = order.OrderNo, + OrderType = order.OrderType + } + }; @event.OperationMan = CurrentUserRequest.CurrentUser.Name; await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event); return new UnifyResultDto(true, true); @@ -80,25 +88,29 @@ public partial class TrackService : ApplicationService, ITrackService x.Id, x.OrderNo, x.SubSystemId }); - foreach (var order in orders) + foreach (var group in orders.GroupBy(x => x.SubSystemId)) { // 新增/更新轨迹 var @event = new TrackUpsertEvent { + SubSystemId = group.Key, + OrderIdentifiers = group.Select(order => new OrderIdentifier + { + OrderId = order.Id, + OrderNo = order.OrderNo, + OrderType = input.OrderType + }).ToArray(), IsAdd = input.IsAdd, TrackCode = input.TrackCode, TrackPlace = input.TrackPlace, TrackTime = input.TrackTime!.Value, TrackTimeZone = input.TrackTimeZone!.Value, - OrderType = input.OrderType, - OrderNo = order.OrderNo, - OrderId = order.Id, - SubSystemId = order.SubSystemId, OperationMan = CurrentUserRequest.CurrentUser.Name }; await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event); } + return new UnifyResultDto(true, true); } @@ -132,7 +144,7 @@ public partial class TrackService : ApplicationService, ITrackService // 删除轨迹 var @event = new TrackDeleteEvent { - OrderId = order.Id, + OrderIds = new[] { order.Id }, TrackCodes = codes.Select(x => x.TrackCode).ToList(), SubSystemId = order.SubSystemId, OperationMan = CurrentUserRequest.CurrentUser.Name @@ -173,7 +185,7 @@ public partial class TrackService : ApplicationService, ITrackService { var @event = new TrackDeleteEvent { - OrderId = group.Key, + OrderIds = group.Select(x => x.OrderId).ToArray(), TrackCodes = codes.Select(x => x.TrackCode).ToList(), SubSystemId = orders.First(x => x.Id == group.Key).SubSystemId, OperationMan = CurrentUserRequest.CurrentUser.Name diff --git a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs index 7eaf030f..78cdd5df 100644 --- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs +++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs @@ -38,7 +38,7 @@ public interface IOrderRepository : IBasicRepository /// /// /// - Task> GetLinkedOrdersAsync(int orderId); + Task> GetLinkedOrdersAsync(int[] orderId); /// /// 关联订单 diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs index 628acc1f..d32ed593 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs @@ -4,11 +4,18 @@ namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; public interface ITrackDetailsRepository { - Task GetFirstOrDefaultAsync(int orderId, string trackCode); + Task> GetListAsync(int[] orderIds, string trackCode); + + Task> GetListAsync(int[] orderIds); Task AnyAsync(int orderId, DateTime trackTime); - Task UpsertAsync(TrackDetailsIndex index); + Task AnyAsync(int orderId, string originTrackData); + + Task UpdateAsync(TrackDetailsIndex index); + + Task AddManyAsync(List index); + Task> GetListAsync(int orderType, List orderNos); @@ -20,15 +27,8 @@ public interface ITrackDetailsRepository /// /// 删除轨迹 /// - /// + /// /// /// - Task DeleteTrackAsync(int orderId, List trackCodes); - - /// - /// 获取最近一条发生的轨迹 - /// - /// - /// - Task GetLatestAsync(int orderId); + Task DeleteTrackAsync(int[] orderIds, List trackCodes); } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs index 35179262..b855eb70 100644 --- a/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs @@ -7,6 +7,11 @@ public partial class GlobalConst /// public const string TrackUpsertSubscribe = "SJZY.Track.TrackUpsert"; + /// + /// 轨迹刷新引发的新增/更新 专用 + /// + public const string TrackUpsertForRefreshSubscribe = "SJZY.Track.TrackUpsertForRefresh"; + /// /// 无法映射的轨迹新增 /// diff --git a/src/SJZY.Track.Repository/EsExtensions.cs b/src/SJZY.Track.Repository/EsExtensions.cs new file mode 100644 index 00000000..b926f93b --- /dev/null +++ b/src/SJZY.Track.Repository/EsExtensions.cs @@ -0,0 +1,22 @@ +using Nest; +using SJZY.Expand.ElasticSearch; + +namespace SJZY.Track.Repository; + +public static class EsExtensions +{ + public static List ToIdList(this ISearchResponse response) where T : IdBaseIndex + { + var dtos = new List(); + + foreach (var hit in response.Hits) + { + var dto = hit.Source; + dto.Id = hit.Id; + + dtos.Add(dto); + } + + return dtos; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs index b2f48a68..5e78fc5f 100644 --- a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs @@ -67,16 +67,16 @@ AND `a`.`IsDeleted` = 0 AND `b`.`IsDeleted` = 0;"); #region 订单关联 - public async Task> GetLinkedOrdersAsync(int orderId) + public async Task> GetLinkedOrdersAsync(int[] orderIds) { return await Context.Queryable() .LeftJoin((a, b) => a.LinkOrderId == b.Id) - .Where(a => a.OrderId == orderId) + .Where(a => orderIds.Contains(a.OrderId)) .Select((a, b) => new LinkedOrderVO { OrderId = b.Id, - OrderType = b.OrderType, OrderNo = b.OrderNo, + OrderType = b.OrderType, SubSystemId = b.SubSystemId }) .ToListAsync(); diff --git a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs index 03b3c7c9..b692a3f2 100644 --- a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs @@ -2,6 +2,7 @@ using Nest; using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ElasticSearch.Services; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Dtos.TrackDetails; namespace SJZY.Track.Repository.Repositories; @@ -13,29 +14,50 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract GetFirstOrDefaultAsync(int orderId, string trackCode) + public async Task> GetListAsync(int[] orderIds, string trackCode) { var r = await Context.SearchAsync(s => s .Source() .Query(q => - q.Term(f => f.OrderId, orderId) + q.Terms(t => t + .Field(f => f.OrderId) + .Terms(orderIds)) && q.Term(f => f.TrackCode.Suffix("keyword"), trackCode) + && q.Term(f => f.ServiceProviderName.Suffix("keyword"), GlobalConst.EmptyString) ) ); - var res = r.Documents.FirstOrDefault(); - if (res != default && r.Hits.FirstOrDefault() != default) - { - res.Id = r.Hits.FirstOrDefault()!.Id; - } + return r.ToIdList(); + } - return res; + public async Task> GetListAsync(int[] orderIds) + { + var data = await Context.SearchAsync(x => x + .Source(s => s.Includes(fd => fd + .Field(f => f.TrackEnContent) + .Field(f => f.TrackContent) + .Field(f => f.TrackPlace) + .Field(f => f.TrackTime) + .Field(f => f.TrackTimeZone) + .Field(f => f.OrderId) + )) + .Query(q => + q.Terms(t => t + .Field(f => f.OrderId) + .Terms(orderIds)) + && q.Term(f => f.ServiceProviderName.Suffix("keyword"), GlobalConst.EmptyString) + ) + .Sort(s => s.Field(f => f.TrackTime, SortOrder.Descending)) + .Size(1) + ); + + return data.Documents.ToList(); } public async Task AnyAsync(int orderId, DateTime trackTime) { var r = await Context.SearchAsync(x => x - .Source(s => s.Includes(fd => fd.Field(f => f.Id))) + .Source(s => s.Includes(fd => fd.Field(f => f.TrackCode))) .Query(q => q.Term(f => f.OrderId, orderId) && q.Term(f => f.TrackTime, trackTime) @@ -45,33 +67,44 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract 0; } - public async Task UpsertAsync(TrackDetailsIndex index) + public async Task AnyAsync(int orderId, string originTrackData) { - if (index.Id.IsNullOrWhiteSpace()) - { - // 按天写入es - var r = await Context.IndexAsync(index, request => request - .Index(index.IndexName) - //.Refresh(Refresh.True) // 可选:立即刷新索引使更改立即可见 - ); + var r = await Context.SearchAsync(x => x + .Source(s => s.Includes(fd => fd.Field(f => f.TrackCode))) + .Query(q => + q.Term(f => f.OrderId, orderId) + && q.Term(f => f.OriginTrackData.Suffix("keyword"), originTrackData) + ) + ); - if (!r.IsValid) - { - LogHelper.Error($"轨迹新增失败,原因:{r.DebugInformation}。"); - } + return r.Hits.Count > 0; + } + + + public async Task UpdateAsync(TrackDetailsIndex track) + { + var r = await Context.UpdateAsync(track.Id, u => u + .Index(track.IndexName) + .Doc(track) + //.Refresh(Refresh.True) // 可选:立即刷新索引使更改立即可见 + ); + + if (!r.IsValid) + { + LogHelper.Error($"轨迹更新失败,原因:{r.DebugInformation}。"); } - else - { - var r = await Context.UpdateAsync(index.Id, u => u - .Index(index.IndexName) - .Doc(index) - //.Refresh(Refresh.True) // 可选:立即刷新索引使更改立即可见 - ); + } - if (!r.IsValid) - { - LogHelper.Error($"轨迹更新失败,原因:{r.DebugInformation}。"); - } + public async Task AddManyAsync(List tracks) + { + if (!tracks.Any()) return; + + // 按天写入es + var r = await Context.IndexManyAsync(tracks, tracks.First().IndexName); + + if (!r.IsValid) + { + LogHelper.Error($"{tracks.Count}条轨迹新增失败,原因:{r.DebugInformation}。"); } } @@ -140,32 +173,12 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract GetLatestAsync(int orderId) - { - var data = await Context.SearchAsync(x => x - .Source(s => s.Includes(fd => fd - .Field(f => f.TrackEnContent) - .Field(f => f.TrackContent) - .Field(f => f.TrackPlace) - .Field(f => f.TrackTime) - .Field(f => f.TrackTimeZone) - )) - .Query(q => - q.Term(f => f.OrderId, orderId) - ) - .Sort(s => s.Field(f => f.TrackTime, SortOrder.Descending)) - .Size(1) - ); - - return data.Documents.FirstOrDefault(); - } - - public async Task DeleteTrackAsync(int orderId, List trackCodes) + public async Task DeleteTrackAsync(int[] orderIds, List trackCodes) { var r = await Context.DeleteByQueryAsync(x => x .Query( q => - q.Term(t => t.OrderId, orderId) + q.Terms(t => t.Field(f => f.OrderId).Terms(orderIds)) && q.Term(t => t.IsCanDelete, true) && q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))) //.Refresh(Refresh.True) // 可选:立即刷新索引使更改立即可见