新增批量删除接口

This commit is contained in:
eli 2024-11-18 10:13:53 +08:00
parent 1bfac284d6
commit 7bc3e09d90
12 changed files with 225 additions and 24 deletions

View File

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class BatchDeleteTrackByEsIdInput
{
/// <summary>
/// 轨迹内容es id,必填
/// </summary>
[MaxLength(500)]
public List<string> TrackContentEsIds { get; set; } = new();
}

View File

@ -14,6 +14,11 @@ public class TrackChangeEto
/// </summary> /// </summary>
public int SubSystemId { get; set; } public int SubSystemId { get; set; }
/// <summary>
/// 单号
/// </summary>
public string OrderNo { get; set; }
/// <summary> /// <summary>
/// 客户id /// 客户id
/// </summary> /// </summary>

View File

@ -7,6 +7,11 @@ public class TrackDeleteEvent
/// </summary> /// </summary>
public int SubSystemId { get; set; } public int SubSystemId { get; set; }
/// <summary>
/// es中的id
/// </summary>
public string[] EsIds { get; set; }
/// <summary> /// <summary>
/// 订单ids /// 订单ids
/// </summary> /// </summary>

View File

@ -1,9 +1,14 @@
using System.Text;
using BSI.Stack.Rabbit;
using DotNetCore.CAP; using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
using SJZY.Track.Domain.Enums;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -13,17 +18,26 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
{ {
private readonly ICapPublisher _capPublisher; private readonly ICapPublisher _capPublisher;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITrackStatusRepository _trackStatusRepository;
private readonly ITrackContentRepository _trackContentRepository;
private readonly IProvideQueries _provideQueries; private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly RabbitClientBus _rabbitClientBus;
public TrackDeleteEventHandler(IProvideQueries provideQueries, public TrackDeleteEventHandler(IProvideQueries provideQueries,
IOrderRepository orderRepository, ICapPublisher capPublisher, IOrderRepository orderRepository, ICapPublisher capPublisher,
ITrackDetailsEsRepository trackDetailsEsRepository) ITrackDetailsEsRepository trackDetailsEsRepository,
RabbitClientBus rabbitClientBus,
ITrackStatusRepository trackStatusRepository,
ITrackContentRepository trackContentRepository)
{ {
_provideQueries = provideQueries; _provideQueries = provideQueries;
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_trackDetailsEsRepository = trackDetailsEsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
_rabbitClientBus = rabbitClientBus;
_trackStatusRepository = trackStatusRepository;
_trackContentRepository = trackContentRepository;
} }
[CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)] [CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)]
@ -31,7 +45,10 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
{ {
if (!CanDelete(@event)) return; if (!CanDelete(@event)) return;
await DeleteTrackAsync(@event); var trackList = await DeleteTrackAsync(@event);
//发布事件
await PublicTrackTopicAsync(@event, trackList);
// 根据订单关联关系异步向下刷(异步) // 根据订单关联关系异步向下刷(异步)
await DownByOrderLink(@event); await DownByOrderLink(@event);
@ -84,12 +101,8 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
private bool CanDelete(TrackDeleteEvent @event) private bool CanDelete(TrackDeleteEvent @event)
{ {
// 系统创建的轨迹不允许删除 if (@event.OrderIds == null)
if (@event.Visited.IsNullOrEmpty() && @event.OperationMan == GlobalConst.SystemUser) return true;
{
LogHelper.Warn($"系统创建的轨迹不允许被删除:{@event}", true);
return false;
}
// 订单循环关联检测 // 订单循环关联检测
var dup = @event.Visited.Intersect(@event.OrderIds).ToArray(); var dup = @event.Visited.Intersect(@event.OrderIds).ToArray();
@ -102,14 +115,79 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
return true; return true;
} }
private async Task DeleteTrackAsync(TrackDeleteEvent @event) private async Task PublicTrackTopicAsync(TrackDeleteEvent eto, List<TrackDetailsIndex> trackList)
{
if (trackList == null)
return;
var statusList = await _trackStatusRepository.GetListAsync(m => m.SubSystemId == eto.SubSystemId);
if (statusList == null)
return;
var contentList = await _trackContentRepository.GetTrackContentBySyetemIdAsync(eto.SubSystemId);
if (contentList == null)
return;
foreach (var dataItem in trackList.GroupBy(m => new
{
m.TrackCode,
m.OrderNo
}))
{
var item = dataItem.First();
var status = statusList.FirstOrDefault(m => m.Code == item.TrackStatusCode);
if (status == null || !status.IsToMq)
continue;
var content = contentList.FirstOrDefault(m => m.TrackContentCode == item.TrackCode);
var data = new TrackChangeEto()
{
OrderIdentifiers = dataItem.Select(m => new OrderIdentifier
{
OrderId = m.OrderId,
OrderNo = m.OrderNo,
OrderType = m.OrderType
}).ToArray(),
TrackStatusCode = item.TrackStatusCode,
TrackCode = item.TrackCode,
OperationMan = eto.OperationMan,
SubSystemId = eto.SubSystemId,
Option = 2
};
_rabbitClientBus.Publish(GlobalConst.TrackChangeExchange, $"TrackChange.{content.SubSystemCode}", Encoding.UTF8.GetBytes(data.ToJson()));
}
}
private async Task<List<TrackDetailsIndex>> DeleteTrackAsync(TrackDeleteEvent @event)
{
List<int> orderIds;
List<TrackDetailsIndex> tracks;
if (@event.EsIds != null && @event.EsIds.Any()) //根据明确的esid进行删除
{
tracks = await _trackDetailsEsRepository.GetDataByIds(@event.EsIds);
orderIds = tracks.Select(m => m.OrderId).Distinct().ToList();
// 外部api获取的轨迹不允许删除
if (tracks.Any(m => m.Source == TrackSourceEnum.ExternalServiceProvide.GetHashCode()))
return tracks;
// 删除轨迹
foreach (var item in tracks)
{
await _trackDetailsEsRepository.DeleteTrackByIdAsync(item.Id, item.IndexName);
}
}
else //原有逻辑,根据轨迹code和订单进行删除
{ {
// 删除轨迹(删的是同子系统下的单,所以code是统一的) // 删除轨迹(删的是同子系统下的单,所以code是统一的)
var tracks = await _trackDetailsEsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes); tracks = await _trackDetailsEsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes);
var orderIds = await _trackDetailsEsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes); orderIds = await _trackDetailsEsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes);
if (orderIds.Count == 0) return tracks;
}
if (orderIds.Count == 0) return;
var orders = await _orderRepository.GetListAsync(x => orderIds.Contains(x.Id), var orders = await _orderRepository.GetListAsync(x => orderIds.Contains(x.Id),
x => new OrderEntity x => new OrderEntity
@ -121,8 +199,7 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
LatestTrackTime = x.LatestTrackTime, LatestTrackTime = x.LatestTrackTime,
LatestTrackTimeZone = x.LatestTrackTimeZone, LatestTrackTimeZone = x.LatestTrackTimeZone,
}); });
if (orders.Count == 0) return tracks;
if (orders.Count == 0) return;
foreach (var order in orders) foreach (var order in orders)
{ {
@ -157,5 +234,7 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
x.LatestTrackTime, x.LatestTrackTime,
x.LatestTrackTimeZone x.LatestTrackTimeZone
}); });
return tracks;
} }
} }

View File

@ -43,6 +43,8 @@ public partial class OrderService : ApplicationService, IOrderService
throw new BusinessException(message: "【目的地时区】和【预计到达时间】必须同时输入"); throw new BusinessException(message: "【目的地时区】和【预计到达时间】必须同时输入");
} }
var currentUser = CurrentUserRequest.CurrentUser;
// 校验订单是否已存在,存在则更新 // 校验订单是否已存在,存在则更新
var order = await _orderRepository.GetFirstAsync(x => var order = await _orderRepository.GetFirstAsync(x =>
x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo); x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo);
@ -55,8 +57,10 @@ public partial class OrderService : ApplicationService, IOrderService
{ {
OrderId = order.Id, OrderId = order.Id,
OrderNo = input.OrderNo, OrderNo = input.OrderNo,
OptionType = OptionType.修改.ToString(), OptionType = OrderOperationType.修改订单.ToString(),
Content = input.ToJson(), Content = input.ToJson(),
CreateUserId = currentUser.UserId,
CreateUserString = currentUser.Name,
}; };
_ = _orderOperationRecordEsRepository.AddAsync(index); _ = _orderOperationRecordEsRepository.AddAsync(index);
@ -76,13 +80,15 @@ public partial class OrderService : ApplicationService, IOrderService
var orderId = await _orderRepository.CreateOrderAsync(order); var orderId = await _orderRepository.CreateOrderAsync(order);
// 写入操作日志 // 写入操作日志
var indexForAdd = new OrderOperationRecordIndex var indexForAdd = new OrderOperationRecordIndex
{ {
OrderId = orderId, OrderId = orderId,
OrderNo = input.OrderNo, OrderNo = input.OrderNo,
OptionType = OptionType.新增.ToString(), OptionType = OrderOperationType.创建订单.ToString(),
Content = input.ToJson(), Content = input.ToJson(),
CreateUserId = CurrentUserRequest.CurrentUser.UserId, CreateUserId = currentUser.UserId,
CreateUserString = currentUser.Name,
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };
_ = _orderOperationRecordEsRepository.AddAsync(indexForAdd); _ = _orderOperationRecordEsRepository.AddAsync(indexForAdd);
@ -156,6 +162,7 @@ public partial class OrderService : ApplicationService, IOrderService
return status; return status;
}).ToList(); }).ToList();
} }
private List<OrderPlatformNumberEntity> BuiltOrderPlatformNumbers(List<PullConfigInfo>? pullConfigInfos) private List<OrderPlatformNumberEntity> BuiltOrderPlatformNumbers(List<PullConfigInfo>? pullConfigInfos)
{ {
if (pullConfigInfos == null) return new List<OrderPlatformNumberEntity>(); if (pullConfigInfos == null) return new List<OrderPlatformNumberEntity>();

View File

@ -175,6 +175,42 @@ public partial class TrackService : ApplicationService, ITrackService
return new UnifyResultDto(true, true); return new UnifyResultDto(true, true);
} }
/// <summary>
/// 根据esid删除轨迹内容
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("Track/BatchDeleteByEsId")]
public async Task<UnifyResultDto> BatchDeleteTrackByEsIdAsync(BatchDeleteTrackByEsIdInput input)
{
var tracks = await _trackDetailsEsRepository.GetDataByIds(input.TrackContentEsIds.ToArray());
if (tracks == null || tracks.Count == 0)
return new UnifyResultDto(false, "未找到指定id下的轨迹内容");
if (tracks.Any(m => m.Source == TrackSourceEnum.ExternalServiceProvide.GetHashCode()))
return new UnifyResultDto(false, "存在来源于外部服务商的轨迹,不允许删除");
if (tracks.GroupBy(m => m.SubSystemId).Count() > 1)
return new UnifyResultDto(false, "暂不支持跨子系统批量删除");
// 获取用户name
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
{
throw new BusinessException(message: $"调用用户中心,获取用户信息失败:{userInfo.Msg}");
}
// 删除轨迹
var @event = new TrackDeleteEvent
{
EsIds = input.TrackContentEsIds.ToArray(),
SubSystemId = tracks.First().SubSystemId,
OperationMan = userInfo.Data.UserName,
};
await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, @event);
return new UnifyResultDto(true);
}
/// <summary> /// <summary>
/// 批量删除轨迹 /// 批量删除轨迹
@ -217,7 +253,7 @@ public partial class TrackService : ApplicationService, ITrackService
OrderIds = orderIds.ToArray(), OrderIds = orderIds.ToArray(),
TrackCodes = input.TrackCodes, TrackCodes = input.TrackCodes,
SubSystemId = input.SubSystemId, SubSystemId = input.SubSystemId,
OperationMan = userInfo.Data.UserName OperationMan = userInfo.Data.UserName,
}; };
await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, @event); await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, @event);

View File

@ -40,8 +40,22 @@ public class OrderOperationRecordIndex : IdBaseIndex
/// </summary> /// </summary>
public int CreateUserId { get; set; } public int CreateUserId { get; set; }
/// <summary>
/// 创建人姓名
/// </summary>
public string CreateUserString { get; set; }
/// <summary> /// <summary>
/// 创建时间 /// 创建时间
/// </summary> /// </summary>
public DateTime CreateTime { get; set; } public DateTime CreateTime { get; set; }
} }
public enum OrderOperationType
{
创建订单 = 1,
修改订单 = 2,
创建轨迹 = 3,
修改轨迹 = 4,
删除轨迹 = 5
}

View File

@ -28,4 +28,5 @@ public interface ITrackContentRepository : IBasicRepository<TrackContentEntity>
Task<bool> GetTemplateIsExist(int trackContentId); Task<bool> GetTemplateIsExist(int trackContentId);
Task<TrackContentEntity> GetByCodeAsync(int systemId, string code); Task<TrackContentEntity> GetByCodeAsync(int systemId, string code);
Task<List<TrackContentEntity>> GetListBySystemIdAsync(int systemId); Task<List<TrackContentEntity>> GetListBySystemIdAsync(int systemId);
Task<List<TrackContentVO>> GetTrackContentBySyetemIdAsync(int subSystemId);
} }

View File

@ -28,4 +28,5 @@ public interface ITrackDetailsEsRepository : IElasticsearchClientService<TrackDe
Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes); Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes);
Task DeleteTrackByIdAsync(string id, string indexName); Task DeleteTrackByIdAsync(string id, string indexName);
Task<List<TrackDetailsIndex>> GetDataByIds(string[] ids);
} }

View File

@ -56,4 +56,9 @@ public class TrackContentVO
/// 是否广播 /// 是否广播
/// </summary> /// </summary>
public bool IsToMq { get; set; } public bool IsToMq { get; set; }
/// <summary>
/// 轨迹内容code
/// </summary>
public string TrackContentCode { get; set; }
} }

View File

@ -248,4 +248,27 @@ public class TrackContentRepository : BasicRepository<TrackContentEntity>, ITrac
}) })
.ToListAsync(); .ToListAsync();
} }
public Task<List<TrackContentVO>> GetTrackContentBySyetemIdAsync(int subSystemId)
{
return Context.Queryable<TrackContentEntity>()
.LeftJoin<TrackStatusEntity>((x, y) => x.TrackStatusId == y.Id)
.LeftJoin<VSystemEntity>((x, y, z) => x.SubSystemId == z.Id)
.Where(x => x.SubSystemId == subSystemId)
.Select((x, y, z) => new TrackContentVO
{
SubSystemCode = z.Key,
TrackStatusId = x.TrackStatusId,
TrackStatus = y.Status,
TrackStatusCode = y.Code,
TrackContent = x.Content,
TrackContentCode = x.Code,
TrackEnContent = x.EnContent,
IsCompleted = y.IsCompleted,
IsRepeatable = x.IsRepeatable,
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
IsToMq = y.IsToMq,
}).ToListAsync();
}
} }

View File

@ -408,6 +408,7 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
return tracks.Select(x => x.OrderId).ToList(); return tracks.Select(x => x.OrderId).ToList();
} }
public async Task DeleteTrackByIdAsync(string id, string indexName) public async Task DeleteTrackByIdAsync(string id, string indexName)
{ {
var r = await Context.DeleteAsync<TrackDetailsIndex>(id, u => u var r = await Context.DeleteAsync<TrackDetailsIndex>(id, u => u
@ -419,4 +420,15 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
throw new InvalidOperationException($"轨迹删除失败,id:{indexName},原因:{r.DebugInformation}。"); throw new InvalidOperationException($"轨迹删除失败,id:{indexName},原因:{r.DebugInformation}。");
} }
} }
public async Task<List<TrackDetailsIndex>> GetDataByIds(string[] ids)
{
var res = await Context.SearchAsync<TrackDetailsIndex>(m => m
.Index(GlobalConst.TrackDetailsIndex)
.Query(
q => q.Ids(i => i.Values(ids))
));
return res.ToIdList();
}
} }