using System.Diagnostics; using System.Linq.Expressions; using DotNetCore.CAP; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SJZY.InterfaceRelay.Application.Contracts; using SJZY.Track.Application.Contract.Dtos.TrackPull; 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; namespace SJZY.Track.Application.EventHandlers; 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, ITrackDetailsRepository trackDetailsRepository) { _orderRepository = orderRepository; _capPublisher = capPublisher; _trackPullCacheService = trackPullCacheService; _trackDetailsRepository = trackDetailsRepository; } [CapSubscribe(GlobalConst.TrackRefreshSubscribe, Group = GlobalConst.TrackRefreshSubscribe)] public async Task ConsumerAsync(InterfaceRelayForwardReplayEvent @event) { if (!@event.IsSuccess) return; var attach = Base64Helper.DeSerialize(@event.Attach); if (attach is null) return; var config = await _trackPullCacheService.GetPullParamWithContentConfigAsync(attach.SubSystemId, attach.ServiceProviderId); if (@event.Data == null || config == null) return; var data = JObject.Parse(@event.Data); var orderToken = data[config.ParamConfig.OrderPath]; if (orderToken is JArray orderTokens) { foreach (var token in orderTokens) { await HandleOrderAsync(token, config, attach); } } else if (orderToken is JObject) { await HandleOrderAsync(orderToken, config, attach); } } private async Task HandleOrderAsync(JToken orderToken, TrackPullParamWithContentConfigDto paramWithContentConfig, TrackRefreshAttach attach) { var paramConfig = paramWithContentConfig.ParamConfig; var orderNo = orderToken[paramConfig.OrderNoName]?.Value(); if (orderNo.IsNullOrWhiteSpace()) return; var trackToken = orderToken[paramConfig.TrackDetailsPath]; if (trackToken is null) return; var order = await _orderRepository.GetFirstAsync(x => x.OrderType == attach.OrderType && x.OrderNo == orderNo, x => new { x.Id, x.LatestPushTrackCode, x.CustomId }); if (order == default) return; var context = new TrackRefreshContext { OrderId = order.Id, OrderType = attach.OrderType, OrderNo = orderNo!, ServiceProviderName = attach.ServiceProviderName, CustomId = order.CustomId, SubSystemId = attach.SubSystemId }; if (trackToken is JArray trackTokens) { foreach (var item in trackTokens) { await HandleTrackAsync(item, paramWithContentConfig, context); } } else if (trackToken is JObject) { 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; // 1、匹配轨迹代码 if (paramConfig.TrackContentCodeName != null) { var trackCode = trackToken[paramConfig.TrackContentCodeName]?.Value(); if (!trackCode.IsNullOrWhiteSpace()) { matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentCodeValue == trackCode); } } // 2、匹配轨迹状态 else if (paramConfig.TrackStatusName != null) { var trackStatus = trackToken[paramConfig.TrackStatusName]?.Value(); if (!trackStatus.IsNullOrWhiteSpace()) { matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackStatusValue == trackStatus); } } // 3、匹配轨迹内容 else if (paramConfig.TrackContentName != null) { var trackContent = trackToken[paramConfig.TrackContentName]?.Value(); if (!trackContent.IsNullOrWhiteSpace()) { Debug.Assert(trackContent != null, nameof(trackContent) + " != null"); matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentValue == trackContent); // 按关键字分析轨迹内容 if (matchedContentConfig is null) { foreach (var contentConfig in contentConfigs) { foreach (var keyword in contentConfig.TrackKeyword?.Split(',') ?? Enumerable.Empty()) { if (trackContent.Contains(keyword, StringComparison.OrdinalIgnoreCase)) { matchedContentConfig = contentConfig; break; } } if (matchedContentConfig is null) continue; foreach (var keyword in contentConfig.TrackKeywordReverse?.Split(',') ?? Enumerable.Empty()) { if (trackContent.Contains(keyword, StringComparison.OrdinalIgnoreCase)) { matchedContentConfig = null; break; } } } } } } // 轨迹发生地 var trackPlace = paramConfig.TrackPlaceName == null ? null : trackToken[paramConfig.TrackPlaceName]?.Value(); if (trackPlace.IsNullOrWhiteSpace()) { Expression> resultExpression = (TrackLocationValue?)matchedContentConfig?.TrackPlaceValue switch { TrackLocationValue.ArrivalPort => x => x.ArrivalPort, TrackLocationValue.ArriveCity => x => x.ArrivalCity, TrackLocationValue.ArrivalCountry => x => x.ArrivalCountry, TrackLocationValue.LeavePort => x => x.LeavePort, TrackLocationValue.LeaveCity => x => x.LeaveCity, TrackLocationValue.LeaveCountry => x => x.LeaveCountry, _ => x => x.LeaveCountry }; trackPlace = await _orderRepository.GetFirstAsync(x => x.Id == context.OrderId, resultExpression); } // 轨迹发生时间 var trackTime = paramConfig.TrackTimeName == null ? null : trackToken[paramConfig.TrackTimeName]?.Value(); // 轨迹发生时区 var trackTimeZone = paramConfig.TrackTimeZoneName == null ? null : trackToken[paramConfig.TrackTimeZoneName]?.Value(); if (matchedContentConfig is null) { var notMappedEvent = new TrackInsertForNotMappedEvent { OrderId = context.OrderId, OrderType = context.OrderType, OrderNo = context.OrderNo, ServiceProviderName = context.ServiceProviderName, OriginTrackData = JsonConvert.SerializeObject(trackToken), TrackPlace = trackPlace ?? GlobalConst.EmptyString, TrackTime = trackTime ?? DateTime.Now, TrackTimeZone = trackTimeZone ?? matchedContentConfig?.TrackTimeZoneValue ?? 8 }; if (paramConfig.TrackContentName != null) { notMappedEvent.OriginTrackContent = trackToken[paramConfig.TrackContentName]?.Value(); } await _capPublisher.PublishAsync(GlobalConst.TrackInsertForNotMappedEventSubscribe, notMappedEvent); return; } // 新增/更新轨迹 var trackUpsertEvent = new TrackUpsertEvent { OrderIdentifiers = [ new OrderIdentifier { OrderId = context.OrderId, OrderNo = context.OrderNo, OrderType = context.OrderType, CustomId = context.CustomId } ], 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 }; trackUpsertEvent.IsAdd = !await _trackDetailsRepository.AnyByCodeAsync(context.OrderId, matchedContentConfig.TrackContentCode); await _capPublisher.PublishAsync(GlobalConst.TrackUpsertForRefreshSubscribe, trackUpsertEvent); } }