diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/BatchDeleteTrackInput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/BatchDeleteTrackInput.cs
index 07db4f25..45ccc51c 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/BatchDeleteTrackInput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/BatchDeleteTrackInput.cs
@@ -5,9 +5,9 @@ namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class BatchDeleteTrackInput : OrderNosInfo
{
///
- /// 轨迹code,必填
+ /// 轨迹标识符集合,必填
///
[Required]
[MaxLength(500)]
- public List TrackCodes { get; set; } = new();
+ public List TrackIdentifiers { get; set; } = new();
}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/DeleteOrderInput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/DeleteOrderInput.cs
index c70c9b42..de305c57 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/DeleteOrderInput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/DeleteOrderInput.cs
@@ -9,8 +9,8 @@ public class DeleteOrderInput : OrderNoInfo
public class DeleteTrackInput : OrderNoInfo
{
///
- /// 轨迹code
+ /// 轨迹标识符集合,必填
///
[Required]
- public List TrackCodes { get; set; } = new();
+ public List TrackIdentifiers { get; set; } = new();
}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/TrackIdentifierDto.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/TrackIdentifierDto.cs
new file mode 100644
index 00000000..993de61c
--- /dev/null
+++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/TrackIdentifierDto.cs
@@ -0,0 +1,21 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
+
+///
+/// 轨迹标识符,用于唯一标识一个轨迹
+///
+public sealed class TrackIdentifierDto
+{
+ ///
+ /// 轨迹code
+ ///
+ [Required]
+ public string TrackCode { get; set; }
+
+ ///
+ /// 轨迹发生时间
+ ///
+ [Required]
+ public DateTime TrackTime { get; set; }
+}
diff --git a/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs
index e8072e27..0859de6b 100644
--- a/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs
+++ b/src/SJZY.Track.Application.Contract/Events/TrackDeleteEvent.cs
@@ -1,3 +1,5 @@
+using SJZY.Track.Application.Contract.Dtos.ProvideServices;
+
namespace SJZY.Track.Application.Contract.Events;
public class TrackDeleteEvent
@@ -18,9 +20,9 @@ public class TrackDeleteEvent
public int[] OrderIds { get; set; } = null!;
///
- /// 轨迹代码
+ /// 轨迹标识符
///
- public List TrackCodes { get; set; } = null!;
+ public List TrackIdentifiers { get; set; } = null!;
///
/// 操作人
@@ -40,6 +42,6 @@ public class TrackDeleteEvent
public override string ToString()
{
return $"[TrackDelete by {OperationMan}] SubSystemId: {SubSystemId}, OrderIds: {string.Join(",",
- OrderIds)}, TrackCodes: {string.Join(",", TrackCodes)}";
+ OrderIds)}, TrackCodes: {string.Join(",", TrackIdentifiers.Select(x=>x.TrackCode))}";
}
}
diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/TrackDeleteEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackDeleteEventHandler.cs
index 288face2..dd4704ca 100644
--- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackDeleteEventHandler.cs
+++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackDeleteEventHandler.cs
@@ -3,6 +3,7 @@ using BSI.Stack.Rabbit;
using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
+using SJZY.Track.Application.Contract.Dtos.ProvideServices;
using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
@@ -67,22 +68,29 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
{
var nextEvent = @event.DeepCopy();
nextEvent.Visited.AddRange(@event.OrderIds);
- nextEvent.TrackCodes = @event.TrackCodes;
+ nextEvent.TrackIdentifiers = @event.TrackIdentifiers;
nextEvent.SubSystemId = group.Key;
// 不同子系统需要做内容映射
if (@event.SubSystemId != nextEvent.SubSystemId)
{
- var mapCodes = await _provideQueries
- .MapTrackCodesAsync(@event.SubSystemId, nextEvent.SubSystemId, @event.TrackCodes.ToArray());
+ var codeMaps = await _provideQueries
+ .GetTrackCodeMapsAsync(@event.SubSystemId, nextEvent.SubSystemId,
+ @event.TrackIdentifiers.Select(x => x.TrackCode).ToArray());
- if (mapCodes.Count == 0)
+ if (codeMaps.Count == 0)
{
LogHelper.Warn($"订单跨子系统,未配置内容映射,请联系管理员:{@event}", true);
continue;
}
- nextEvent.TrackCodes = mapCodes;
+ //映射轨迹code
+ foreach (var trackIdentity in nextEvent.TrackIdentifiers)
+ {
+ var match = codeMaps.FirstOrDefault(x => x.MapTrackContentCode == trackIdentity.TrackCode);
+ if (match == null) continue;
+ trackIdentity.TrackCode = match.TrackContentCode;
+ }
}
var identifiers = group.Select(x => x.OrderId).ToList();
@@ -172,7 +180,11 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
tracks = await _trackDetailsEsRepository.GetDataByIds(@event.EsIds);
orderIds = tracks.Select(m => m.OrderId).Distinct().ToList();
@event.OrderIds = orderIds.ToArray();
- @event.TrackCodes = tracks.Select(x => x.TrackCode).Distinct().ToList();
+ @event.TrackIdentifiers = tracks.Select(x => new TrackIdentifierDto
+ {
+ TrackCode = x.TrackCode,
+ TrackTime = x.TrackTime
+ }).ToList();
// 外部api获取的轨迹不允许删除
if (tracks.Any(m => m.Source == TrackSourceEnum.ExternalServiceProvide.GetHashCode()))
@@ -189,11 +201,24 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
}
else //原有逻辑,根据轨迹code和订单进行删除
{
+ var trackCodes = @event.TrackIdentifiers.Select(x => x.TrackCode).ToList();
// 删除轨迹(删的是同子系统下的单,所以code是统一的)
- tracks = await _trackDetailsEsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes);
+ tracks = await _trackDetailsEsRepository.GetListAsync(@event.OrderIds, trackCodes,null);
- orderIds = await _trackDetailsEsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes);
- if (orderIds.Count == 0) return tracks;
+ //构建标识符集合
+ var ids = @event.TrackIdentifiers.Select(x => $"{x.TrackCode}{x.TrackTime}").ToList();
+ //根据标识符选出要删除的轨迹明细
+ var deleteTracks = tracks.Where(x => ids.Contains($"{x.TrackCode}{x.TrackTime}")).ToList();
+
+ if (deleteTracks.Count == 0) return deleteTracks;
+
+ foreach (var track in deleteTracks)
+ {
+ await _trackDetailsEsRepository.DeleteTrackByIdAsync(track.Id, track.IndexName);
+ }
+
+ orderIds = tracks.Select(m => m.OrderId).Distinct().ToList();
+ tracks = deleteTracks;
}
diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs
index ab931373..8023836a 100644
--- a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs
+++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs
@@ -163,8 +163,14 @@ public partial class TrackService : ApplicationService, ITrackService
//删除轨迹约束,只要其中有一条来源是外部的就立即返回错误
var tracks = await _trackDetailsEsRepository
- .GetListAsync(new[] { orderId }, input.TrackCodes, TrackSourceEnum.ExternalServiceProvide);
- if (tracks.Count > 0)
+ .GetListAsync(new[] { orderId },
+ input.TrackIdentifiers.Select(x => x.TrackCode).ToList(),
+ TrackSourceEnum.ExternalServiceProvide);
+
+ //当要删除的轨迹标识出现交叉则不允许删除
+ var intersect = tracks.Select(x => $"{x.TrackCode}{x.TrackTime}")
+ .Intersect(input.TrackIdentifiers.Select(y => $"{y.TrackCode}{y.TrackTime}")).ToList();
+ if (intersect.Count > 0)
{
throw new BusinessException(message: "存在来源于外部服务商的轨迹,不允许删除");
}
@@ -173,7 +179,7 @@ public partial class TrackService : ApplicationService, ITrackService
var @event = new TrackDeleteEvent
{
OrderIds = new[] { orderId },
- TrackCodes = input.TrackCodes,
+ TrackIdentifiers = input.TrackIdentifiers,
SubSystemId = input.SubSystemId,
OperationMan = name
};
@@ -254,8 +260,14 @@ public partial class TrackService : ApplicationService, ITrackService
//删除轨迹约束,只要其中有一条来源是外部的就立即返回错误
var tracks = await _trackDetailsEsRepository
- .GetListAsync(orderIds.ToArray(), input.TrackCodes, TrackSourceEnum.ExternalServiceProvide);
- if (tracks.Count > 0)
+ .GetListAsync(orderIds.ToArray(),
+ input.TrackIdentifiers.Select(x => x.TrackCode).ToList(),
+ TrackSourceEnum.ExternalServiceProvide);
+
+ //当要删除的轨迹标识出现交叉则不允许删除
+ var intersect = tracks.Select(x => $"{x.TrackCode}{x.TrackTime}")
+ .Intersect(input.TrackIdentifiers.Select(y => $"{y.TrackCode}{y.TrackTime}")).ToList();
+ if (intersect.Count > 0)
{
throw new BusinessException(message: "存在来源于外部服务商的轨迹,不允许删除");
}
@@ -264,7 +276,7 @@ public partial class TrackService : ApplicationService, ITrackService
var @event = new TrackDeleteEvent
{
OrderIds = orderIds.ToArray(),
- TrackCodes = input.TrackCodes,
+ TrackIdentifiers = input.TrackIdentifiers,
SubSystemId = input.SubSystemId,
OperationMan = userInfo.Data.UserName,
};
diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsEsRepository.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsEsRepository.cs
index 482d7142..c57b797b 100644
--- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsEsRepository.cs
+++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsEsRepository.cs
@@ -1,4 +1,5 @@
using SJZY.Expand.ElasticSearch.Services;
+using SJZY.Track.Domain.Dtos.TrackContents;
using SJZY.Track.Domain.Enums;
namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
@@ -23,7 +24,7 @@ public interface ITrackDetailsEsRepository : IElasticsearchClientService> GetListAsync(int orderId);
- Task> GetListAsync(int[] orderIds, List trackCodes, TrackSourceEnum source);
+ Task> GetListAsync(int[] orderIds, List trackCodes, TrackSourceEnum? source);
Task> DeleteTrackAsync(int[] orderIds, List trackCodes);
diff --git a/src/SJZY.Track.Domain/Dtos/TrackContents/TrackCodeMapVO.cs b/src/SJZY.Track.Domain/Dtos/TrackContents/TrackCodeMapVO.cs
new file mode 100644
index 00000000..c06fc740
--- /dev/null
+++ b/src/SJZY.Track.Domain/Dtos/TrackContents/TrackCodeMapVO.cs
@@ -0,0 +1,27 @@
+namespace SJZY.Track.Domain.Dtos.TrackContents;
+
+///
+/// 轨迹代码映射
+///
+public sealed class TrackCodeMapVO
+{
+ ///
+ /// 源子系统id
+ ///
+ public int SubSystemId { get; set; }
+
+ ///
+ /// 源轨迹内容code
+ ///
+ public string TrackContentCode { get; set; } = null!;
+
+ ///
+ /// 映射子系统id
+ ///
+ public int MapSubSystemId { get; set; }
+
+ ///
+ /// 映射轨迹内容code
+ ///
+ public string MapTrackContentCode { get; set; } = null!;
+}
diff --git a/src/SJZY.Track.Domain/Queries/IProvideQueries.cs b/src/SJZY.Track.Domain/Queries/IProvideQueries.cs
index 60c0b330..351224c5 100644
--- a/src/SJZY.Track.Domain/Queries/IProvideQueries.cs
+++ b/src/SJZY.Track.Domain/Queries/IProvideQueries.cs
@@ -18,6 +18,14 @@ public interface IProvideQueries
///
Task> MapTrackCodesAsync(int upSubSystemId, int subSystemId, params string[] trackCodes);
+ ///
+ /// 获取子系统内容Code映射
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetTrackCodeMapsAsync(int upSubSystemId, int subSystemId, params string[] trackCodes);
///
/// 根据订单模板找对应服务商
///
diff --git a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs
index 31855027..8dd6fc96 100644
--- a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs
+++ b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs
@@ -33,6 +33,22 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
.ToListAsync();
}
+ public async Task> GetTrackCodeMapsAsync(int upSubSystemId, int subSystemId, params string[] trackCodes)
+ {
+ // 根据上游code得到下游code
+ return await Context.Queryable()
+ .Where(x => x.SubSystemId == subSystemId && x.MapSubSystemId == upSubSystemId &&
+ trackCodes.Contains(x.MapTrackContentCode))
+ .Select(x => new TrackCodeMapVO()
+ {
+ SubSystemId = x.SubSystemId,
+ TrackContentCode = x.TrackContentCode,
+ MapSubSystemId = x.MapSubSystemId,
+ MapTrackContentCode = x.MapTrackContentCode
+ })
+ .ToListAsync();
+ }
+
///
public async Task> FindOrderWithServiceProviderAsync(int subSystemId,
List orderNos)
@@ -46,7 +62,7 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
.Select((a, b, c) => new OrderWithServiceProviderVO
{
//优先使用第三方的订单号,为空时才使用主单号
- OrderNo = b.OrderNo ?? a.OrderNo,
+ OrderNo = b.OrderNo.IsNullOrWhiteSpace() ? a.OrderNo : b.OrderNo!,
OrderType = a.OrderType,
SubSystemId = a.SubSystemId,
ServiceProviderCode = b.ServiceProviderCode,
@@ -67,7 +83,7 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
.Select((a, b) => new OrderWithServiceProviderVO
{
//优先使用第三方的订单号,为空时才使用主单号
- OrderNo = b.OrderNo ?? a.OrderNo,
+ OrderNo = b.OrderNo.IsNullOrWhiteSpace() ? a.OrderNo : b.OrderNo!,
OrderType = a.OrderType,
SubSystemId = a.SubSystemId,
ServiceProviderCode = b.ServiceProviderCode
diff --git a/src/SJZY.Track.Repository/Repositories/TrackDetailsEsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackDetailsEsRepository.cs
index cb62b1b1..346d8c57 100644
--- a/src/SJZY.Track.Repository/Repositories/TrackDetailsEsRepository.cs
+++ b/src/SJZY.Track.Repository/Repositories/TrackDetailsEsRepository.cs
@@ -3,6 +3,7 @@ using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Expand.ElasticSearch.Services;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Consts;
+using SJZY.Track.Domain.Dtos.TrackContents;
using SJZY.Track.Domain.Enums;
namespace SJZY.Track.Repository.Repositories;
@@ -75,6 +76,8 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract f.TrackTimeZone)
.Field(f => f.OrderId)
.Field(f => f.TrackCode)
+ .Field(f => f.Id)
+ .Field(f => f.IndexName)
))
.Query(q => q
.Bool(b => b
@@ -99,6 +102,17 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract so
.Field(f => f.ZeroTrackTime, SortOrder.Descending)
)
+ .Source(s2 => s2.Includes(fd2 => fd2
+ .Field(f => f.TrackEnContent)
+ .Field(f => f.TrackContent)
+ .Field(f => f.TrackPlace)
+ .Field(f => f.TrackTime)
+ .Field(f => f.TrackTimeZone)
+ .Field(f => f.OrderId)
+ .Field(f => f.TrackCode)
+ .Field(f => f.Id)
+ .Field(f => f.IndexName)
+ ))
)
)
)
@@ -343,15 +357,26 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract> GetListAsync(int[] orderIds, List trackCodes, TrackSourceEnum source)
+ public async Task> GetListAsync(int[] orderIds, List trackCodes, TrackSourceEnum? source)
{
+ var query = new QueryContainer();
+
+ if (orderIds.Length > 0)
+ {
+ query &= Query.Terms(t => t.Field(f => f.OrderId).Terms(orderIds));
+ }
+ if (trackCodes.Count > 0)
+ {
+ query &= Query.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes));
+ }
+ if (source.HasValue)
+ {
+ query &= Query.Term(t => t.Field(f => f.Source).Value(source.Value));
+ }
+
var r = await Context.SearchAsync(x => x
.Index(GlobalConst.TrackDetailsIndex)
- .Query(q =>
- q.Terms(t => t.Field(f => f.OrderId).Terms(orderIds))
- && q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))
- && q.Term(t => t.Source, (int) source)
- )
+ .Query(q => query)
.Size(SafelyLimit)
.Sort(s => s.Field(f => f.ZeroTrackTime, SortOrder.Descending)));
@@ -474,5 +499,4 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract