fix: 修复删除轨迹失败

This commit is contained in:
云龙 王 2024-11-25 18:16:42 +08:00
parent c98e1e7d8a
commit ea77583ce4
11 changed files with 168 additions and 32 deletions

View File

@ -5,9 +5,9 @@ namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class BatchDeleteTrackInput : OrderNosInfo
{
/// <summary>
/// 轨迹code,必填
/// 轨迹标识符集合,必填
/// </summary>
[Required]
[MaxLength(500)]
public List<string> TrackCodes { get; set; } = new();
public List<TrackIdentifierDto> TrackIdentifiers { get; set; } = new();
}

View File

@ -9,8 +9,8 @@ public class DeleteOrderInput : OrderNoInfo
public class DeleteTrackInput : OrderNoInfo
{
/// <summary>
/// 轨迹code
/// 轨迹标识符集合,必填
/// </summary>
[Required]
public List<string> TrackCodes { get; set; } = new();
public List<TrackIdentifierDto> TrackIdentifiers { get; set; } = new();
}

View File

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
/// <summary>
/// 轨迹标识符,用于唯一标识一个轨迹
/// </summary>
public sealed class TrackIdentifierDto
{
/// <summary>
/// 轨迹code
/// </summary>
[Required]
public string TrackCode { get; set; }
/// <summary>
/// 轨迹发生时间
/// </summary>
[Required]
public DateTime TrackTime { get; set; }
}

View File

@ -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!;
/// <summary>
/// 轨迹代码
/// 轨迹标识符
/// </summary>
public List<string> TrackCodes { get; set; } = null!;
public List<TrackIdentifierDto> TrackIdentifiers { get; set; } = null!;
/// <summary>
/// 操作人
@ -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))}";
}
}

View File

@ -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;
}

View File

@ -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,
};

View File

@ -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<TrackDe
Task<List<TrackDetailsIndex>> GetListAsync(int orderId);
Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, List<string> trackCodes, TrackSourceEnum source);
Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, List<string> trackCodes, TrackSourceEnum? source);
Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes);

View File

@ -0,0 +1,27 @@
namespace SJZY.Track.Domain.Dtos.TrackContents;
/// <summary>
/// 轨迹代码映射
/// </summary>
public sealed class TrackCodeMapVO
{
/// <summary>
/// 源子系统id
/// </summary>
public int SubSystemId { get; set; }
/// <summary>
/// 源轨迹内容code
/// </summary>
public string TrackContentCode { get; set; } = null!;
/// <summary>
/// 映射子系统id
/// </summary>
public int MapSubSystemId { get; set; }
/// <summary>
/// 映射轨迹内容code
/// </summary>
public string MapTrackContentCode { get; set; } = null!;
}

View File

@ -18,6 +18,14 @@ public interface IProvideQueries
/// <returns></returns>
Task<List<string>> MapTrackCodesAsync(int upSubSystemId, int subSystemId, params string[] trackCodes);
/// <summary>
/// 获取子系统内容Code映射
/// </summary>
/// <param name="upSubSystemId"></param>
/// <param name="subSystemId"></param>
/// <param name="trackCodes"></param>
/// <returns></returns>
Task<List<TrackCodeMapVO>> GetTrackCodeMapsAsync(int upSubSystemId, int subSystemId, params string[] trackCodes);
/// <summary>
/// 根据订单模板找对应服务商
/// </summary>

View File

@ -33,6 +33,22 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
.ToListAsync();
}
public async Task<List<TrackCodeMapVO>> GetTrackCodeMapsAsync(int upSubSystemId, int subSystemId, params string[] trackCodes)
{
// 根据上游code得到下游code
return await Context.Queryable<TrackContentMapEntity>()
.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();
}
/// <inheritdoc />
public async Task<List<OrderWithServiceProviderVO>> FindOrderWithServiceProviderAsync(int subSystemId,
List<string> 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

View File

@ -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<TrackDetail
.Field(f => 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<TrackDetail
.Sort(so => 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<TrackDetail
return r.ToIdList();
}
public async Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, List<string> trackCodes, TrackSourceEnum source)
public async Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, List<string> trackCodes, TrackSourceEnum? source)
{
var query = new QueryContainer();
if (orderIds.Length > 0)
{
query &= Query<TrackDetailsIndex>.Terms(t => t.Field(f => f.OrderId).Terms(orderIds));
}
if (trackCodes.Count > 0)
{
query &= Query<TrackDetailsIndex>.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes));
}
if (source.HasValue)
{
query &= Query<TrackDetailsIndex>.Term(t => t.Field(f => f.Source).Value(source.Value));
}
var r = await Context.SearchAsync<TrackDetailsIndex>(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<TrackDetail
return res.Documents.FirstOrDefault();
}
}