Merge branch 'S02-轨迹中台第二部分' into dev

This commit is contained in:
李鹏军 2024-03-26 15:20:40 +08:00
commit 82c380b7a9
15 changed files with 110 additions and 16 deletions

View File

@ -22,6 +22,11 @@ public class TrackPushEvent
/// </summary> /// </summary>
public string OrderNo { get; set; } = null!; public string OrderNo { get; set; } = null!;
/// <summary>
/// 订单类型
/// </summary>
public int OrderType { get; set; }
/// <summary> /// <summary>
/// 轨迹内容id /// 轨迹内容id
/// </summary> /// </summary>

View File

@ -48,4 +48,9 @@ public class TrackUpsertEvent : UpsertTrackInput
/// 原轨迹报文 /// 原轨迹报文
/// </summary> /// </summary>
public string? OriginTrackData { get; set; } public string? OriginTrackData { get; set; }
/// <summary>
/// 操作人
/// </summary>
public string? OperationMan { get; set; }
} }

View File

@ -32,7 +32,7 @@ public class CAPFilter : SubscribeFilter
throw new BusinessException(_ERROR_CODE, $"检测到重复消费,消费参数:{argumentJsonStr}"); throw new BusinessException(_ERROR_CODE, $"检测到重复消费,消费参数:{argumentJsonStr}");
RedisHelper.Client.Set($"CapExcuteFilter:{hash}", 60 * 10, RedisHelper.Client.Set($"CapExcuteFilter:{hash}", 60 * 10,
TimeSpan.FromDays(1).Seconds); // 1天内不允许一模一样的参数重复消费 TimeSpan.FromHours(1).Seconds); // 1h内不允许一模一样的参数重复消费
} }
} }

View File

@ -44,7 +44,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
var isSuccess = res.Code == InterfaceRelayConst.SuccessCode; var isSuccess = res.Code == InterfaceRelayConst.SuccessCode;
// 写推送日志 // 往es 写推送日志
await _trackPushRecordsRepository.AddAsync(new TrackPushRecordIndex await _trackPushRecordsRepository.AddAsync(new TrackPushRecordIndex
{ {
IndexName = $"{GlobalConst.TrackPushRecordsIndex}-{DateTime.Now:yyyy.MM.dd}", IndexName = $"{GlobalConst.TrackPushRecordsIndex}-{DateTime.Now:yyyy.MM.dd}",
@ -52,6 +52,8 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
Message = res.Msg, Message = res.Msg,
OptionType = @event.OptionType.ToString(), OptionType = @event.OptionType.ToString(),
OrderId = @event.OrderId, OrderId = @event.OrderId,
OrderType = @event.OrderType,
OrderNo = @event.OrderNo,
TrackStatus = @event.TrackStatus, TrackStatus = @event.TrackStatus,
TrackCode = @event.TrackCode, TrackCode = @event.TrackCode,
TrackContent = @event.TrackContent, TrackContent = @event.TrackContent,

View File

@ -8,7 +8,6 @@ using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Consts;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
using SJZY.UserCenter.HttpApi.Services;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace SJZY.Track.Application.EventHandlers; namespace SJZY.Track.Application.EventHandlers;
@ -135,7 +134,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
IsCanDelete = trackContent.IsCanDelete, IsCanDelete = trackContent.IsCanDelete,
OriginTrackContent = @event.OriginTrackContent, OriginTrackContent = @event.OriginTrackContent,
OriginTrackData = @event.OriginTrackData, OriginTrackData = @event.OriginTrackData,
CreateUser = CurrentUserRequest.CurrentUser.Name, CreateUser = @event.OperationMan,
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };
@ -146,7 +145,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
track.TrackPlace = @event.TrackPlace; track.TrackPlace = @event.TrackPlace;
track.TrackTime = @event.TrackTime!.Value; track.TrackTime = @event.TrackTime!.Value;
track.TrackTimeZone = @event.TrackTimeZone!.Value; track.TrackTimeZone = @event.TrackTimeZone!.Value;
track.UpdateUser = CurrentUserRequest.CurrentUser.Name; track.UpdateUser = @event.OperationMan ?? "系统";
track.UpdateTime = DateTime.Now; track.UpdateTime = DateTime.Now;
} }
@ -192,6 +191,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
OptionType = optionType, OptionType = optionType,
ServiceProviderCode = config.ServiceProviderCode, ServiceProviderCode = config.ServiceProviderCode,
OrderNo = track.OrderNo, OrderNo = track.OrderNo,
OrderType = track.OrderType,
OrderId = track.OrderId, OrderId = track.OrderId,
TrackContentId = config.TrackContentId, TrackContentId = config.TrackContentId,
TrackStatus = track.TrackStatus, TrackStatus = track.TrackStatus,

View File

@ -86,10 +86,10 @@ public class TrackPullService : ApplicationService
} }
var orders = await _provideQueries.FindOrderWithServiceProviderAsync(config.ServiceProviderId); var orders = await _provideQueries.FindOrderWithServiceProviderAsync(config.ServiceProviderId);
var serviceProviderCode = orders.FirstOrDefault()?.ServiceProviderCode;
foreach (var group in orders.GroupBy(x => foreach (var group in orders.GroupBy(x =>
new TrackRefreshAttach(x.ServiceProviderId, x.ServiceProviderCode, x.SubSystemId, new { x.SubSystemId, x.OrderType }))
x.OrderType)))
{ {
var data = group.Select(x => new var data = group.Select(x => new
{ {
@ -98,10 +98,13 @@ public class TrackPullService : ApplicationService
// 批量获取轨迹 // 批量获取轨迹
await _httpClientProxy.Service.BatchForwardThenPushToQueueAsync( await _httpClientProxy.Service.BatchForwardThenPushToQueueAsync(
InterfaceRelayConst.GetTrackInterfaceCode, group.Key.ServiceProviderCode, data, InterfaceRelayConst.GetTrackInterfaceCode, serviceProviderCode, data,
GlobalConst.TrackRefreshSubscribe, JsonConvert.SerializeObject(group.Key)); GlobalConst.TrackRefreshSubscribe,
JsonConvert.SerializeObject(new TrackRefreshAttach(config.ServiceProviderId, serviceProviderCode!,
group.Key.SubSystemId, group.Key.OrderType)));
} }
if (config.PullInterval < 60) config.PullInterval = 60;
await RedisHelper.Client.SetExAsync(redisKey, config.PullInterval * 60, orders.Count); await RedisHelper.Client.SetExAsync(redisKey, config.PullInterval * 60, orders.Count);
} }

View File

@ -5,6 +5,7 @@ using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Application.Contract.Services; using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackPushAggregate;
using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Consts;
using SJZY.Track.Domain.Enums; using SJZY.Track.Domain.Enums;
using SJZY.UserCenter.HttpApi.Services; using SJZY.UserCenter.HttpApi.Services;
@ -22,16 +23,19 @@ public class TrackPushService : ApplicationService
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITrackPushCacheService _pushCacheService; private readonly ITrackPushCacheService _pushCacheService;
private readonly ICapPublisher _capPublisher; private readonly ICapPublisher _capPublisher;
private readonly ITrackPushRecordsRepository _trackPushRecordsRepository;
public TrackPushService(ITrackPushCacheService pushCacheService, public TrackPushService(ITrackPushCacheService pushCacheService,
ITrackDetailsRepository trackDetailsRepository ITrackDetailsRepository trackDetailsRepository
, IOrderRepository orderRepository , IOrderRepository orderRepository
, ICapPublisher capPublisher) , ICapPublisher capPublisher
, ITrackPushRecordsRepository trackPushRecordsRepository)
{ {
_pushCacheService = pushCacheService; _pushCacheService = pushCacheService;
_trackDetailsRepository = trackDetailsRepository; _trackDetailsRepository = trackDetailsRepository;
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
_trackPushRecordsRepository = trackPushRecordsRepository;
} }
/// <summary> /// <summary>
@ -47,7 +51,7 @@ public class TrackPushService : ApplicationService
var orders = await _orderRepository.GetListAsync(x => var orders = await _orderRepository.GetListAsync(x =>
x.OrderType == input.OrderType && input.OrderNos.Contains(x.OrderNo), x => new x.OrderType == input.OrderType && input.OrderNos.Contains(x.OrderNo), x => new
{ {
x.Id, x.OrderNo, x.SubSystemId, x.CustomId x.Id, x.OrderNo, x.OrderType, x.SubSystemId, x.CustomId
}); });
if (orders.Count == 0) if (orders.Count == 0)
@ -75,10 +79,13 @@ public class TrackPushService : ApplicationService
await _pushCacheService.GetPushContentConfigAsync(order.SubSystemId, order.CustomId, await _pushCacheService.GetPushContentConfigAsync(order.SubSystemId, order.CustomId,
track.TrackContentId); track.TrackContentId);
if (config == null) continue;
var trackPushEvent = new TrackPushEvent var trackPushEvent = new TrackPushEvent
{ {
ServiceProviderCode = config.ServiceProviderCode, ServiceProviderCode = config.ServiceProviderCode,
OrderNo = order.OrderNo, OrderNo = order.OrderNo,
OrderType = order.OrderType,
OrderId = order.Id, OrderId = order.Id,
TrackContentId = config.TrackContentId, TrackContentId = config.TrackContentId,
TrackStatus = track.TrackStatus, TrackStatus = track.TrackStatus,
@ -113,14 +120,30 @@ public class TrackPushService : ApplicationService
[HttpPost("Track/PushWarnForTask")] [HttpPost("Track/PushWarnForTask")]
public async Task<string> PushWarnForTaskAsync() public async Task<string> PushWarnForTaskAsync()
{ {
var time = DateTime.Now.Subtract(TimeSpan.FromHours(12)); var orders = await _orderRepository.GetPushWarnOrdersAsync();
var orders = await _orderRepository.GetListAsync(x =>
!x.IsCompleted && x.QuestionType == 0 && x.LatestPushTime < time);
orders.ForEach(x => { x.QuestionType = (int)TrackProblemType.Warn; }); var time = DateTime.Now.Subtract(TimeSpan.FromHours(12));
orders.ForEach(x =>
{
x.QuestionType = x.LatestPushTime == null || x.LatestPushTime < time
? (int)TrackProblemType.Warn
: (int)TrackProblemType.None;
});
await _orderRepository.UpdateRangeAsync(orders, x => new { x.QuestionType }); await _orderRepository.UpdateRangeAsync(orders, x => new { x.QuestionType });
return $"成功将{orders.Select(x => x.OrderNo).JoinAsString(",")}置为预警单"; return $"成功将:{orders.Count(x => x.QuestionType == (int)TrackProblemType.Warn)}个订单置为预警";
}
/// <summary>
/// 获取轨迹推送记录
/// </summary>
/// <returns></returns>
/// <param name="input"></param>
[HttpGet("Track/GetTrackPushRecords")]
public async Task<List<TrackPushRecordIndex>> GetTrackPushRecordsAsync(OrderNoInfo input)
{
return await _trackPushRecordsRepository.GetTrackPushRecordsAsync(input.OrderNo, input.OrderType);
} }
} }

View File

@ -6,6 +6,7 @@ using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Consts;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
using SJZY.UserCenter.HttpApi.Services;
namespace SJZY.Track.Application.Services.ProvideServices; namespace SJZY.Track.Application.Services.ProvideServices;
@ -56,6 +57,7 @@ public partial class TrackService : ApplicationService, ITrackService
@event.LatestPushTrackContentId = order.LatestPushTrackContentId; @event.LatestPushTrackContentId = order.LatestPushTrackContentId;
@event.CustomId = order.CustomId; @event.CustomId = order.CustomId;
@event.IsCompleted = order.IsCompleted; @event.IsCompleted = order.IsCompleted;
@event.OperationMan = CurrentUserRequest.CurrentUser.Name;
await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event); await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event);
return true; return true;
} }

View File

@ -25,6 +25,11 @@ public interface IOrderRepository : IBasicRepository<OrderEntity>
/// <returns></returns> /// <returns></returns>
Task DeleteOrderAsync(int orderId); Task DeleteOrderAsync(int orderId);
/// <summary>
/// 获取推送预警单
/// </summary>
/// <returns></returns>
Task<List<OrderEntity>> GetPushWarnOrdersAsync();
#region 订单关联 #region 订单关联

View File

@ -15,4 +15,6 @@ public interface ITrackPushRecordsRepository
/// <param name="orderId"></param> /// <param name="orderId"></param>
/// <returns></returns> /// <returns></returns>
Task<List<TrackPushRecordIndex>> GetTrackPushRecordsAsync(int orderId); Task<List<TrackPushRecordIndex>> GetTrackPushRecordsAsync(int orderId);
Task<List<TrackPushRecordIndex>> GetTrackPushRecordsAsync(string inputOrderNo, int inputOrderType);
} }

View File

@ -17,6 +17,16 @@ public class TrackPushRecordIndex : IdBaseIndex
/// </summary> /// </summary>
public int OrderId { get; set; } public int OrderId { get; set; }
/// <summary>
/// 订单号
/// </summary>
public string OrderNo { get; set; } = null!;
/// <summary>
/// 订单类型(主数据枚举TrackOrderType)
/// </summary>
public int OrderType { get; set; }
/// <summary> /// <summary>
/// 接口通请求Id /// 接口通请求Id
/// </summary> /// </summary>

View File

@ -1,6 +1,7 @@
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate; using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate;
using SJZY.Track.Domain.Dtos.Order; using SJZY.Track.Domain.Dtos.Order;
using SJZY.Track.Domain.Enums;
using SJZY.Track.Domain.Queries; using SJZY.Track.Domain.Queries;
using SJZY.Track.Domain.VEntities; using SJZY.Track.Domain.VEntities;
using SJZY.Track.Repository.VData.Entitys; using SJZY.Track.Repository.VData.Entitys;
@ -38,6 +39,7 @@ public class TrackOrderQueries : ISugarRepository, ITrackOrderQueries,
.WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId) .WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId)
.WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType) .WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType)
.WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType) .WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType)
.WhereIF(input.TabType == (int)TrackProblemType.Warn, (a, b, c) => !a.IsCompleted)
.OrderByDescending((a, b, c) => a.CreateTime) .OrderByDescending((a, b, c) => a.CreateTime)
.Select((a, b, c) => new TrackOrderVO .Select((a, b, c) => new TrackOrderVO
{ {

View File

@ -1,6 +1,8 @@
using SJZY.Track.Domain; using SJZY.Track.Domain;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackPushAggregate;
using SJZY.Track.Domain.Dtos.Order; using SJZY.Track.Domain.Dtos.Order;
using SJZY.Track.Domain.Enums;
namespace SJZY.Track.Repository.Repositories; namespace SJZY.Track.Repository.Repositories;
@ -53,6 +55,23 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
tran.Complete(); tran.Complete();
} }
public async Task<List<OrderEntity>> GetPushWarnOrdersAsync()
{
var errorType = (int)TrackProblemType.Error;
return await Context.Queryable<TrackPushConfigEntity>()
.LeftJoin<OrderEntity>((a, b) => a.SubSystemId == b.SubSystemId && a.CustomId == b.CustomId)
.Where((a, b) => !b.IsCompleted && b.QuestionType != errorType)
.Where("a.CreateTime < DATE_SUB(now(),INTERVAL 12 hour)") // 过滤掉创建时间不足12小时的
.Select((a, b) => new OrderEntity
{
Id = b.Id,
QuestionType = b.QuestionType,
LatestPushTime = b.LatestPushTime
})
.ToListAsync();
}
#region 订单关联 #region 订单关联
public async Task<List<LinkedOrderVO>> GetLinkedOrdersAsync(int orderId) public async Task<List<LinkedOrderVO>> GetLinkedOrdersAsync(int orderId)

View File

@ -93,10 +93,12 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract<TrackDetail
var data = await Context.SearchAsync<TrackDetailsIndex>(x => x var data = await Context.SearchAsync<TrackDetailsIndex>(x => x
.Source(s => s.Includes(fd => fd .Source(s => s.Includes(fd => fd
.Field(f => f.OrderId)
.Field(f => f.OrderNo) .Field(f => f.OrderNo)
.Field(f => f.TrackStatus) .Field(f => f.TrackStatus)
.Field(f => f.TrackCode) .Field(f => f.TrackCode)
.Field(f => f.TrackContent) .Field(f => f.TrackContent)
.Field(f => f.TrackContentId)
.Field(f => f.TrackPlace) .Field(f => f.TrackPlace)
.Field(f => f.TrackTime) .Field(f => f.TrackTime)
.Field(f => f.TrackTimeZone) .Field(f => f.TrackTimeZone)

View File

@ -40,4 +40,18 @@ public class TrackPushRecordsRepository : ElasticSearchContextAbstract<TrackDeta
return data.Documents.ToList(); return data.Documents.ToList();
} }
public async Task<List<TrackPushRecordIndex>> GetTrackPushRecordsAsync(string orderNo, int orderType)
{
var data = await Context.SearchAsync<TrackPushRecordIndex>(x => x
.Index(GlobalConst.TrackPushRecordsIndex)
.Query(q =>
q.Term(t => t.OrderNo.Suffix("keyword"), orderNo)
&& q.Term(f => f.OrderType, orderType)
)
.Size(1000)
.Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending)));
return data.Documents.ToList();
}
} }