diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs index abc24922..6f878362 100644 --- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs +++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackRefreshEventHandler.cs @@ -263,7 +263,9 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe trackToken[paramConfig.TrackContentName!]?.Value() ?? GlobalConst.EmptyString; } - track.ZeroTrackTime = track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); + track.ZeroTrackTime = Math.Abs(track.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1 + ? track.TrackTime + : track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone)); await _trackDetailsRepository.AddAsync(track); } diff --git a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs index 39f5e6bf..f0c8edc9 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs @@ -67,17 +67,21 @@ public partial class OrderService x => x.LinkOrderNo); // 计算出未关联的订单 - var noLinkOrderNos = input.LinkOrderNos.Except(linkOrderNos); + var noLinkOrderNos = input.LinkOrderNos.Except(linkOrderNos).ToList(); - // 过滤掉不存在的订单 - var canLinkOrders = await _orderRepository.GetListAsync(x => + // 查询存在的订单 + var existedOrders = await _orderRepository.GetListAsync(x => x.OrderType == input.LinkOrderType && noLinkOrderNos.Contains(x.OrderNo), x => new { x.Id, x.OrderNo, x.OrderType, x.SubSystemId, x.CustomId }); - - // todo:如果有不存在的单,需要抛异常 - if (canLinkOrders.Count != noLinkOrderNos.Count() ) return; - await _orderRepository.LinkOrderAsync(canLinkOrders.Select(x => new OrderLinkEntity + // 如果有不存在的单,需要抛异常 + if (existedOrders.Count != noLinkOrderNos.Count) + { + throw new BusinessException( + message: $"关联单:{noLinkOrderNos.Except(existedOrders.Select(x => x.OrderNo)).JoinAsString(", ")}不存在"); + } + + await _orderRepository.LinkOrderAsync(existedOrders.Select(x => new OrderLinkEntity { OrderId = orderId, OrderNo = input.OrderNo, @@ -90,13 +94,14 @@ public partial class OrderService var tracks = await _trackDetailsRepository.GetListAsync(orderId); // 补轨迹 - foreach (var group in canLinkOrders.GroupBy(x => x.SubSystemId)) + foreach (var group in existedOrders.GroupBy(x => new {x.SubSystemId, x.CustomId})) { foreach (var track in tracks) { var fillTrackEvent = new TrackUpsertEvent { - SubSystemId = group.Key, + SubSystemId = group.Key.SubSystemId, + CustomId = group.Key.CustomId, OrderIdentifiers = group.Select(x => new OrderIdentifier { OrderId = x.Id, diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.Query.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.Query.cs index 295acceb..2ce8b135 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.Query.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.Query.cs @@ -27,9 +27,24 @@ public partial class TrackService var res = new List(); input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空 - - // todo:没有映射上的轨迹要过滤掉 - var details = await _trackDetailsRepository.GetListAsync(input.OrderType, input.OrderNos); + + object[]? searchAfter = null; + List details = new(); + int limit = 1000, cnt, time = 10; + + do + { + var (currentResults, nextSearchAfter) = + await _trackDetailsRepository.GetListAsync(input.OrderType, input.OrderNos, searchAfter, limit); + cnt = currentResults.Count; + details.AddRange(currentResults); + + // 更新 searchAfter 以获取下一批数据 + searchAfter = nextSearchAfter; + time--; + } while (cnt > 0 && time > 0); + + if (details.Count == limit * time) throw new BusinessException(message: "查询轨迹量过大,请缩小查询范围"); foreach (var group in details.GroupBy(x => x.OrderId)) { @@ -44,8 +59,12 @@ public partial class TrackService Content = x.TrackContent, OriginContent = x.OriginTrackContent, Location = x.TrackPlace, - Time = Math.Abs(x.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1 ? x.TrackTime: x.ZeroTrackTime.AddHours(input.TimeZone ?? 8), - TimeZone = Math.Abs(x.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1? null: input.TimeZone ?? 8 + Time = Math.Abs(x.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1 + ? x.TrackTime + : x.ZeroTrackTime.AddHours(input.TimeZone ?? 8), + TimeZone = Math.Abs(x.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1 + ? null + : input.TimeZone ?? 8 }).ToList(); res.Add(item); diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs index 3d76bd98..ed053823 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs @@ -66,6 +66,7 @@ public partial class TrackService : ApplicationService, ITrackService // 新增/更新轨迹 var @event = ObjectMapper.Map(input); @event.SubSystemId = order.SubSystemId; + @event.CustomId = order.CustomId; @event.OrderIdentifiers = new[] { new OrderIdentifier diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs index 639f92ef..cec7351b 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs @@ -8,6 +8,8 @@ public interface ITrackDetailsRepository Task> GetLatestListAsync(int[] eventOrderIds, List trackCodes); + Task<(List results, object[]? nextSearchAfter)> GetListAsync(int orderType, List orderNos, object[]? searchAfter = null, int limit = 1000); + Task AnyAsync(int orderId, DateTime trackTime); Task AnyAsync(int orderId, string originTrackDataHash); @@ -20,8 +22,6 @@ public interface ITrackDetailsRepository Task AddAsync(TrackDetailsIndex track); - Task> GetListAsync(int orderType, List orderNos); - Task<(List list, long total)> GetListAsync(TrackDetailsQueryInput input); Task> GetListAsync(int orderId); diff --git a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs index cb82921e..c3f0b0a9 100644 --- a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs @@ -210,9 +210,9 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract> GetListAsync(int orderType, List orderNos) + public async Task<(List results, object[]? nextSearchAfter)> GetListAsync(int orderType, List orderNos, object[]? searchAfter = null, int limit = 1000) { - if (orderNos.Count < 1) return new List(); + if (orderNos.Count < 1) return (new List(), null); var r = await Context.SearchAsync(x => x .Source(s => s.Includes(fd => fd @@ -226,12 +226,26 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract f.TrackTimeZone) )) .Query(q => - q.Terms(t => t - .Field(f => f.OrderNo.Suffix("keyword")) - .Terms(orderNos)) - && q.Term(f => f.OrderType, orderType) + q.Bool(b => b + .Must(mu => mu + .Terms(t => t + .Field(f => f.OrderNo.Suffix("keyword")) + .Terms(orderNos) + ), + mu => mu + .Term(f => f.OrderType, orderType) + ) + .MustNot(mn => mn + .Term(t => t.TrackCode.Suffix("keyword"), GlobalConst.EmptyString) + ) + ) ) - .Size(1000) + .Sort(s => s + .Ascending(f => f.TrackTime) // 需要根据某个字段排序 + .Ascending(f => f.OrderNo) // 可以添加更多排序字段以确保唯一性 + ) + .Size(limit) + .SearchAfter(searchAfter) ); if (!r.IsValid) @@ -239,7 +253,10 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract> GetListAsync(int orderId)