diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetPageTrackOrderInput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetPageTrackOrderInput.cs index c6a143df..d9c87ab0 100644 --- a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetPageTrackOrderInput.cs +++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetPageTrackOrderInput.cs @@ -7,15 +7,15 @@ public class GetPageTrackOrderInput : PageInfoInput /// public int SubSystemId { get; set; } - ///// - ///// 单号 - ///// - //public List? OrderNos { get; set; } - /// /// 单号 /// - public string? OrderNos { get; set; } + public List? OrderNos { get; set; } + + ///// + ///// 单号 + ///// + //public string? OrderNos { get; set; } /// /// tab标签类型 0 全部, 1 异常 2 预警 @@ -136,7 +136,7 @@ public class TrackOrderDto /// /// 子系统 /// - public string SubSystem { get; set; } + public string? SubSystem { get; set; } /// /// 子系统id @@ -153,13 +153,13 @@ public class TrackOrderDto /// public string? QuestionTypeName { get; set; } - /// - /// 问题描述(主数据枚举TrackProblemDescription) - /// - public int ProblemDescription { get; set; } + ///// + ///// 问题描述(主数据枚举TrackProblemDescription) + ///// + //public int ProblemDescription { get; set; } - /// - /// 问题描述名称 - /// - public string? ProblemDescriptionName { get; set; } + ///// + ///// 问题描述名称 + ///// + //public string? ProblemDescriptionName { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/PushTrackInput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/PushTrackInput.cs new file mode 100644 index 00000000..5eaff31e --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/PushTrackInput.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace SJZY.Track.Application.Contract.Dtos.ProvideServices; + +public class PushTrackInput : OrderNosInfo +{ + /// + /// 轨迹code,必填 + /// + [Required] + public string TrackCode { get; set; } = null!; +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/TrackPushContentConfigDto.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/TrackPushContentConfigDto.cs new file mode 100644 index 00000000..a019087f --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/TrackPushContentConfigDto.cs @@ -0,0 +1,72 @@ +namespace SJZY.Track.Application.Contract.Dtos.ProvideServices; + +public class TrackPushConfigDto +{ + /// + /// 是否自动推送 + /// + public bool IsAutoPush { get; set; } + + /// + /// 轨迹推送内容配置 + /// + public List ContentConfigs { get; set; } = new(); +} + +public class TrackPushContentConfigDto +{ + /// + /// 是否自动推送 + /// + public bool IsAutoPush { get; set; } + + /// + /// 是否支持更新 + /// + public bool IsCanUpdate { get; set; } + + /// + /// 服务商code + /// + public string ServiceProviderCode { get; set; } = null!; + + /// + /// 扩展字段参数值 + /// + public string? ExpandFieldsValue { get; set; } + + /// + /// 推送单号类型(主数据枚举TrackOrderType) + /// + public int OrderType { get; set; } + + /// + /// 轨迹代码参数值 + /// + public string? TrackContentCodeValue { get; set; } + + /// + /// 轨迹内容id + /// + public int TrackContentId { get; set; } + + /// + /// 轨迹内容参数值 + /// + public string? TrackContentValue { get; set; } + + /// + /// 轨迹内容英文参数值 + /// + public string? TrackEnContentValue { get; set; } + + /// + /// 轨迹状态参数值 + /// + public string? TrackStatusValue { get; set; } + + /// + /// 轨迹时区GMT + /// + public double? TrackTimeZone { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackOrder/GetTrackCounterOutput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackOrder/GetTrackCounterOutput.cs new file mode 100644 index 00000000..e330fabb --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackOrder/GetTrackCounterOutput.cs @@ -0,0 +1,19 @@ +namespace SJZY.Track.Application.Contract.Dtos.TrackOrder; + +public class GetTrackCounterOutput +{ + /// + /// 总条数 + /// + public int TotalCount { get; set; } + + /// + /// 异常数 + /// + public int ErrorCount { get; set; } + + /// + /// 预警数 + /// + public int WarnCount { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackOrder/TrackPushRecordItem.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackOrder/TrackPushRecordItem.cs new file mode 100644 index 00000000..f01d9869 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackOrder/TrackPushRecordItem.cs @@ -0,0 +1,5 @@ +namespace SJZY.Track.Application.Contract.Dtos.TrackOrder; + +public class TrackPushRecordItem +{ +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullConfigDto.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullConfigDto.cs index f6020d9f..10f78964 100644 --- a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullConfigDto.cs +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullConfigDto.cs @@ -1,8 +1,19 @@ -namespace SJZY.Track.Application.Contract.Dtos.TrackPull; +namespace SJZY.Track.Application.Contract.Dtos.TrackPull; public class TrackPullConfigDto { - public TrackPullParamConfigDto ParamConfig { get; set; } + /// + /// 服务商拉取频率(分钟) + /// + public int PullInterval { get; set; } - public List ContentConfigs { get; set; } + /// + /// 服务商id + /// + public int ServiceProviderId { get; set; } + + /// + /// 子系统id + /// + public int SubSystemId { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamConfigDto.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamConfigDto.cs index b8f22ac1..79af5185 100644 --- a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamConfigDto.cs +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamConfigDto.cs @@ -10,32 +10,32 @@ public class TrackPullParamConfigDto /// /// 轨迹时区参数名 /// - public string TrackTimeZoneName { get; set; } = null!; + public string? TrackTimeZoneName { get; set; } /// /// 轨迹代码参数名 /// - public string TrackContentCodeName { get; set; } = null!; + public string? TrackContentCodeName { get; set; } /// /// 轨迹内容参数名 /// - public string TrackContentName { get; set; } = null!; + public string? TrackContentName { get; set; } /// /// 轨迹发生地参数名 /// - public string TrackPlaceName { get; set; } = null!; + public string? TrackPlaceName { get; set; } /// /// 轨迹状态参数名 /// - public string TrackStatusName { get; set; } = null!; + public string? TrackStatusName { get; set; } /// /// 轨迹发生时间参数名 /// - public string TrackTimeName { get; set; } = null!; + public string? TrackTimeName { get; set; } /// /// 订单数组路径 diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamWithContentConfigDto.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamWithContentConfigDto.cs new file mode 100644 index 00000000..ba38457f --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/TrackPull/TrackPullParamWithContentConfigDto.cs @@ -0,0 +1,8 @@ +namespace SJZY.Track.Application.Contract.Dtos.TrackPull; + +public class TrackPullParamWithContentConfigDto +{ + public TrackPullParamConfigDto ParamConfig { get; set; } + + public List ContentConfigs { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/TrackPushAfterUpdateOrderEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackPushAfterUpdateOrderEvent.cs new file mode 100644 index 00000000..f57fad41 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Events/TrackPushAfterUpdateOrderEvent.cs @@ -0,0 +1,29 @@ +namespace SJZY.Track.Application.Contract.Events; + +public class TrackPushAfterUpdateOrderEvent +{ + /// + /// 操作类型 + /// + public OptionType OptionType { get; set; } = OptionType.新增; + + /// + /// 订单Id + /// + public int OrderId { get; set; } + + /// + /// 轨迹内容id + /// + public int TrackContentId { get; set; } + + /// + /// 问题类型 + /// + public bool IsSuccess { get; set; } + + /// + /// 问题描述 + /// + public string? Message { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/TrackPushEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackPushEvent.cs new file mode 100644 index 00000000..8434072e --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Events/TrackPushEvent.cs @@ -0,0 +1,89 @@ +namespace SJZY.Track.Application.Contract.Events; + +public class TrackPushEvent +{ + /// + /// 操作类型 + /// + public OptionType OptionType { get; set; } = OptionType.新增; + + /// + /// 服务商code + /// + public string ServiceProviderCode { get; set; } = null!; + + /// + /// 订单id + /// + public int OrderId { get; set; } + + /// + /// 订单号 + /// + public string OrderNo { get; set; } = null!; + + /// + /// 轨迹内容id + /// + public int TrackContentId { get; set; } + + /// + /// 轨迹状态 + /// + public string TrackStatus { get; set; } = null!; + + /// + /// 轨迹内容代码 + /// + public string TrackCode { get; set; } = null!; + + /// + /// 轨迹内容 + /// + public string TrackContent { get; set; } = null!; + + /// + /// 轨迹发生地 + /// + public string TrackPlace { get; set; } = null!; + + /// + /// 轨迹发生时间 + /// + public DateTime TrackTime { get; set; } + + /// + /// 轨迹发生时区 + /// + public float TrackTimeZone { get; set; } + + /// + /// 轨迹代码参数值 + /// + public string? TrackContentCodeValue { get; set; } + + /// + /// 轨迹内容参数值 + /// + public string? TrackContentValue { get; set; } + + /// + /// 轨迹内容英文参数值 + /// + public string? TrackEnContentValue { get; set; } + + /// + /// 轨迹状态参数值 + /// + public string? TrackStatusValue { get; set; } + + /// + /// 扩展字段参数值 + /// + public string? ExpandFieldsValue { get; set; } + + /// + /// 操作人 + /// + public string? OperationMan { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/UpdateOrderTrackEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackUpsertAfterUpdateOrderEvent.cs similarity index 85% rename from src/SJZY.Track.Application.Contract/Events/UpdateOrderTrackEvent.cs rename to src/SJZY.Track.Application.Contract/Events/TrackUpsertAfterUpdateOrderEvent.cs index 779415e2..bf3907b4 100644 --- a/src/SJZY.Track.Application.Contract/Events/UpdateOrderTrackEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackUpsertAfterUpdateOrderEvent.cs @@ -1,6 +1,6 @@ namespace SJZY.Track.Application.Contract.Events; -public class UpdateOrderTrackEvent +public class TrackUpsertAfterUpdateOrderEvent { /// /// 订单Id @@ -41,4 +41,9 @@ public class UpdateOrderTrackEvent /// 轨迹时区 /// public float TrackTimeZone { get; set; } + + /// + /// 轨迹代码 + /// + public string TrackCode { get; set; } = null!; } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs b/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs index 04f91415..eb836245 100644 --- a/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs +++ b/src/SJZY.Track.Application.Contract/Events/TrackUpsertEvent.cs @@ -9,6 +9,11 @@ public class TrackUpsertEvent : UpsertTrackInput /// public int OrderId { get; set; } + /// + /// 订单是否完成 + /// + public bool IsCompleted { get; set; } + /// /// 客户id /// @@ -20,9 +25,9 @@ public class TrackUpsertEvent : UpsertTrackInput public int SubSystemId { get; set; } /// - /// 订单是否推送完成(异步维护) + /// 最新推送轨迹内容id(异步维护) /// - public bool IsPushCompleted { get; set; } + public int? LatestPushTrackContentId { get; set; } /// /// 上游子系统id diff --git a/src/SJZY.Track.Application.Contract/Services/ITrackPullCacheService.cs b/src/SJZY.Track.Application.Contract/Services/ITrackPullCacheService.cs index 7eb93992..486d4157 100644 --- a/src/SJZY.Track.Application.Contract/Services/ITrackPullCacheService.cs +++ b/src/SJZY.Track.Application.Contract/Services/ITrackPullCacheService.cs @@ -4,13 +4,22 @@ namespace SJZY.Track.Application.Contract.Services; public interface ITrackPullCacheService { + string TrackPullKey(int subSystemId, int serviceProviderId); + string TrackPullContentKey(int subSystemId, int serviceProviderId); + + /// + /// 获取所有拉取配置 + /// + /// + Task> GetAllPullConfigsAsync(); + /// /// 获取服务商拉取配置 /// /// 子系统id /// 服务商id /// - Task GetPullConfigAsync(int subSystemId, int serviceProviderId); + Task GetPullParamWithContentConfigAsync(int subSystemId, int serviceProviderId); /// /// 设置拉取配置缓存 @@ -19,5 +28,6 @@ public interface ITrackPullCacheService /// 子系统id /// 服务商id /// - Task SetPullConfigAsync(int? id = null, int? subSystemId = null, int? serviceProviderId = null); + Task SetPullConfigAsync(int? id = null, int? subSystemId = null, + int? serviceProviderId = null); } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Services/ITrackPushCacheService.cs b/src/SJZY.Track.Application.Contract/Services/ITrackPushCacheService.cs index 04369975..a4a57bc0 100644 --- a/src/SJZY.Track.Application.Contract/Services/ITrackPushCacheService.cs +++ b/src/SJZY.Track.Application.Contract/Services/ITrackPushCacheService.cs @@ -1,18 +1,42 @@ -namespace SJZY.Track.Application.Contract.Services; +using SJZY.Track.Application.Contract.Dtos.ProvideServices; + +namespace SJZY.Track.Application.Contract.Services; public interface ITrackPushCacheService { /// - /// 判断客户是否需要推送 + /// 获取服务商拉取配置 /// - /// + /// 子系统id + /// 服务商id /// - Task IsPushAsync(int customId); + Task> GetPushContentConfigsAsync(int subSystemId, int customId); /// - /// 更新缓存 + /// 获取服务商拉取配置 /// + /// 子系统id + /// 服务商id + /// + /// + Task GetPushContentConfigAsync(int subSystemId, int customId, int trackContentId); + + /// + /// 根据轨迹代码推断下一个(升序)要推送的内容,如果找不到或者已经是最后一个了,返回null + /// + /// /// - /// - Task UpdateAsync(int customId, bool isPush); + /// + /// + Task InferNextPushContentOrNullAsync(int subSystemId, int customId, + int? trackContentId); + + /// + /// 设置推送配置缓存 + /// + /// + /// 子系统id + /// 客户id + /// + Task SetPushContentConfigsAsync(int? id = null, int? subSystemId = null, int? customId = null); } \ No newline at end of file diff --git a/src/SJZY.Track.Application/AutoMapper/OrderAutoMapperProfile.cs b/src/SJZY.Track.Application/AutoMapper/OrderAutoMapperProfile.cs index 25cb3b57..da077adf 100644 --- a/src/SJZY.Track.Application/AutoMapper/OrderAutoMapperProfile.cs +++ b/src/SJZY.Track.Application/AutoMapper/OrderAutoMapperProfile.cs @@ -1,8 +1,13 @@ using AutoMapper; +using Google.Protobuf.WellKnownTypes; +using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; using SJZY.Track.Domain.Dtos.Order; +using SJZY.Track.Domain.Enums; +using System.ComponentModel; +using System.Reflection; using Volo.Abp.AutoMapper; namespace SJZY.Track.Application.AutoMapper; @@ -20,7 +25,10 @@ public class OrderAutoMapperProfile : Profile CreateMap(MemberList.None); CreateMap(MemberList.None); - CreateMap(MemberList.None); + CreateMap(MemberList.None) + .ForMember(dest => dest.OrderTypeName, opt => opt.MapFrom(source => GetEnumDescription(2, source.OrderType))) + .ForMember(dest => dest.QuestionTypeName, opt => opt.MapFrom(source => GetEnumDescription(1, source.QuestionType))); + CreateMap, UnifyPageResultDto>(MemberList.None); CreateMap(MemberList.None).Ignore(dest => dest.TrackTimeZone) .ForMember(dest => dest.Id, opt => opt.Ignore()) @@ -29,4 +37,34 @@ public class OrderAutoMapperProfile : Profile .ForMember(dest => dest.EnContent, opt => opt.MapFrom(m => m.TrackEnContent)) .ForMember(dest => dest.TrackTimeZoneValue, opt => opt.MapFrom(m => m.TrackTimeZone)); } + + /// + /// 通过类型int获取枚举描述 + /// + /// 1 问题类型枚举 2 订单枚举 + /// + /// + public static string GetEnumDescription(int type, int value) + { + string enumDescription = string.Empty; + if (type == 1) + { + TrackProblemType trackProblem = (TrackProblemType)value; // 将int值转换为枚举 + if (trackProblem.GetDescription().IsNullOrWhiteSpace()) + enumDescription = ""; + else + enumDescription = trackProblem.GetDescription(); // 获取描述标记 + } + else + { + OrderType orderType = (OrderType)value; // 将int值转换为枚举 + if (orderType.GetDescription().IsNullOrWhiteSpace()) + enumDescription = ""; + else + enumDescription = orderType.GetDescription(); // 获取描述标记 + + } + + return enumDescription; + } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/AutoMapper/TrackPushAutoMapperProfile.cs b/src/SJZY.Track.Application/AutoMapper/TrackPushAutoMapperProfile.cs index eed8b90b..6be69d46 100644 --- a/src/SJZY.Track.Application/AutoMapper/TrackPushAutoMapperProfile.cs +++ b/src/SJZY.Track.Application/AutoMapper/TrackPushAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Application.Contract.Dtos.TrackPush; using SJZY.Track.Domain.Aggregates.TrackPullAggregate; using SJZY.Track.Domain.Aggregates.TrackPushAggregate; @@ -14,5 +15,7 @@ public class TrackPushAutoMapperProfile : Profile CreateMap(MemberList.None).Ignore(dest => dest.Id) .ForMember(dest => dest.IsPush, opt => opt.MapFrom(source => true)); CreateMap(MemberList.None); + CreateMap(MemberList.None) + .ForMember(dest => dest.OrderType, opt => opt.MapFrom(source => source.OrderNoType)); } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs b/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs index 4a014b49..1d628a3a 100644 --- a/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/OrderLinkAfterFillTrackHandler.cs @@ -2,6 +2,7 @@ using SJZY.Track.Application.Contract.Events; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Consts; using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.EventHandlers; @@ -31,7 +32,7 @@ public class OrderLinkAfterFillTrackHandler : ITransientDependency, ICapSubscrib var order = await _orderRepository.GetFirstAsync(x => x.Id == linkOrderId, x => new { - x.OrderType, x.OrderNo, x.CustomId, x.IsPushCompleted, x.SubSystemId + x.OrderType, x.OrderNo, x.CustomId, x.LatestPushTrackContentId, x.SubSystemId }); if (order == default) continue; @@ -50,7 +51,7 @@ public class OrderLinkAfterFillTrackHandler : ITransientDependency, ICapSubscrib OrderId = linkOrderId, CustomId = order.CustomId, SubSystemId = order.SubSystemId, - IsPushCompleted = order.IsPushCompleted, + LatestPushTrackContentId = order.LatestPushTrackContentId, UpSubSystemId = @event.SubSystemId, }; diff --git a/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs index 1994118d..1a1f0df0 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackDeleteEventHandler.cs @@ -3,6 +3,7 @@ using SJZY.Expand.ABP.Core.Logger; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Queries; using Volo.Abp.DependencyInjection; @@ -63,12 +64,12 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe { var track = await _trackDetailsRepository.GetLatestAsync(@event.OrderId); var updateOrderEvent = track == default - ? new UpdateOrderTrackEvent + ? new TrackUpsertAfterUpdateOrderEvent { OrderId = @event.OrderId, IsDelete = true } - : new UpdateOrderTrackEvent + : new TrackUpsertAfterUpdateOrderEvent { OrderId = @event.OrderId, IsCompleted = track.IsCompleted, @@ -76,9 +77,10 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe TrackEnContent = track.TrackEnContent, TrackPlace = track.TrackPlace, TrackTime = track.TrackTime, - TrackTimeZone = track.TrackTimeZone + TrackTimeZone = track.TrackTimeZone, + IsDelete = true }; - await _capPublisher.PublishAsync(GlobalConst.UpdateOrderTrackSubscribe, updateOrderEvent); + await _capPublisher.PublishAsync(GlobalConst.TrackUpsertAfterUpdateOrderSubscribe, updateOrderEvent); } // 根据订单关联关系异步向下刷 diff --git a/src/SJZY.Track.Application/EventHandlers/TrackPushAfterUpdateOrderEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackPushAfterUpdateOrderEventHandler.cs new file mode 100644 index 00000000..268db6c1 --- /dev/null +++ b/src/SJZY.Track.Application/EventHandlers/TrackPushAfterUpdateOrderEventHandler.cs @@ -0,0 +1,50 @@ +using DotNetCore.CAP; +using SJZY.Track.Application.Contract.Events; +using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Enums; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.EventHandlers; + +public class TrackPushAfterUpdateOrderEventHandler : ITransientDependency, ICapSubscribe +{ + private readonly IOrderRepository _orderRepository; + + public TrackPushAfterUpdateOrderEventHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + [CapSubscribe(GlobalConst.TrackPushAfterUpdateOrderSubscribe)] + public async Task ConsumerAsync(TrackPushAfterUpdateOrderEvent @event) + { + var order = await _orderRepository.GetFirstAsync(x => x.Id == @event.OrderId); + if (order == default) return; + + /* + * 异常:最近一条推送是失败 + */ + if (!@event.IsSuccess) + { + order.QuestionType = (int)TrackProblemType.Error; + order.ProblemDescription = @event.Message; + } + else + { + order.QuestionType = (int)TrackProblemType.None; + if (@event.OptionType == OptionType.新增) + { + // tips:只有新增会影响推送进度? + order.LatestPushTrackContentId = @event.TrackContentId; + order.LatestPushTime = DateTime.Now; + } + } + + + await _orderRepository.UpdateColumnAsync(order, x => new + { + x.LatestPushTrackContentId, x.QuestionType, x.ProblemDescription, x.LatestPushTime + }); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs new file mode 100644 index 00000000..c1ca1b19 --- /dev/null +++ b/src/SJZY.Track.Application/EventHandlers/TrackPushEventHandler.cs @@ -0,0 +1,139 @@ +using DotNetCore.CAP; +using SJZY.InterfaceRelay.Application.Contracts; +using SJZY.Track.Application.Contract.Events; +using SJZY.Track.Domain.Aggregates.TrackPushAggregate; +using SJZY.Track.Domain.Consts; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client.DynamicProxying; + +namespace SJZY.Track.Application.EventHandlers; + +public class TrackPushEventHandler : ITransientDependency, ICapSubscribe +{ + private readonly IHttpClientProxy _httpClientProxy; + private readonly ITrackPushRecordsRepository _trackPushRecordsRepository; + private readonly ICapPublisher _capPublisher; + + public TrackPushEventHandler(IHttpClientProxy httpClientProxy, + ITrackPushRecordsRepository trackPushRecordsRepository, ICapPublisher capPublisher) + { + _httpClientProxy = httpClientProxy; + _trackPushRecordsRepository = trackPushRecordsRepository; + _capPublisher = capPublisher; + } + + [CapSubscribe(GlobalConst.TrackPushSubscribe)] + public async Task ConsumerAsync(TrackPushEvent @event) + { + InterfaceRelayUnifyResultDto res = null!; + switch (@event.OptionType) + { + case OptionType.无: + return; + case OptionType.新增: + res = await PushAddAsync(@event); + break; + case OptionType.删除: + break; + case OptionType.修改: + res = await PushUpdateAsync(@event); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + var isSuccess = res.Code == InterfaceRelayConst.SuccessCode; + + // 写推送日志 + await _trackPushRecordsRepository.AddAsync(new TrackPushRecordIndex + { + IndexName = $"{GlobalConst.TrackPushRecordsIndex}-{DateTime.Now:yyyy.MM.dd}", + RequestId = res.RequestId, + Message = res.Msg, + OptionType = @event.OptionType.ToString(), + TrackStatus = @event.TrackStatus, + TrackCode = @event.TrackCode, + TrackContent = @event.TrackContent, + TrackPlace = @event.TrackPlace, + TrackTime = @event.TrackTime, + TrackTimeZone = @event.TrackTimeZone, + TrackContentCodeValue = @event.TrackContentCodeValue, + TrackContentValue = @event.TrackContentValue, + TrackEnContentValue = @event.TrackEnContentValue, + TrackStatusValue = @event.TrackStatusValue, + ExpandFieldsValue = @event.ExpandFieldsValue, + IsSuccess = isSuccess, + CreateUser = @event.OperationMan ?? "系统", + CreateTime = DateTime.Now + }); + + // 更新订单主表(异步) + await _capPublisher.PublishAsync(GlobalConst.TrackPushAfterUpdateOrderSubscribe, + new TrackPushAfterUpdateOrderEvent + { + OptionType = @event.OptionType, + OrderId = @event.OrderId, + TrackContentId = @event.TrackContentId, + IsSuccess = isSuccess, + Message = res.Msg + }); + } + + private async Task PushAddAsync(TrackPushEvent @event) + { + var data = new + { + orderNo = @event.OrderNo, + data = new[] + { + new + { + // 推真实的发生地和发生时间(时间是计算后的) + location = @event.TrackPlace, + date = @event.TrackTime, + timeZone = @event.TrackTimeZone, + description = @event.TrackEnContentValue, + description_cn = @event.TrackContentValue, + code = @event.TrackContentCodeValue, + status = @event.TrackStatusValue, + extra = @event.ExpandFieldsValue + } + } + }; + + + var res = await _httpClientProxy.Service.ForwardWithSubscribeAsync(InterfaceRelayConst.PushTrackInterfaceCode, + @event.ServiceProviderCode, data); + + return res; + } + + private async Task PushUpdateAsync(TrackPushEvent @event) + { + var data = new + { + orderNo = @event.OrderNo, + data = new[] + { + new + { + // 推真实的发生地和发生时间 + location = @event.TrackPlace, + date = @event.TrackTime, + timeZone = @event.TrackTimeZone, + description = @event.TrackEnContentValue, + description_cn = @event.TrackContentValue, + code = @event.TrackContentCodeValue, + status = @event.TrackStatusValue, + extra = @event.ExpandFieldsValue + } + } + }; + + + var res = await _httpClientProxy.Service.ForwardWithSubscribeAsync(InterfaceRelayConst.TrackUpdateInterfaceCode, + @event.ServiceProviderCode, data); + + return res; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs index e898fcf7..9d0e410d 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackRefreshEventHandler.cs @@ -9,6 +9,7 @@ using SJZY.Track.Application.Contract.Dtos.TrackPull; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Enums; using Volo.Abp.DependencyInjection; @@ -28,15 +29,15 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe _trackPullCacheService = trackPullCacheService; } - [CapSubscribe(GlobalConst.TrackRefreshSubscribe)] - public async Task ConsumerAsync(InterfaceRelayTrackRefreshEvent @event) + [CapSubscribe(GlobalConst.TrackRefreshSubscribe, Group = GlobalConst.TrackRefreshSubscribe)] + public async Task ConsumerAsync(InterfaceRelayForwardReplayEvent @event) { - // tips:attach返回的是服务商id,必有 var attach = JsonConvert.DeserializeObject(@event.Attach); if (attach is null) return; - var config = await _trackPullCacheService.GetPullConfigAsync(attach.ServiceProviderId, attach.SubSystemId); + var config = await _trackPullCacheService.GetPullParamWithContentConfigAsync(attach.SubSystemId, + attach.ServiceProviderId); - var data = JObject.FromObject(@event.Data); + var data = JObject.Parse(@event.Data.ToString()!); var orderToken = data[config.ParamConfig.OrderPath]; if (orderToken is JArray orderTokens) { @@ -51,16 +52,17 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe } } - private async Task HandleOrderAsync(JToken orderToken, TrackPullConfigDto config, int orderType) + private async Task HandleOrderAsync(JToken orderToken, TrackPullParamWithContentConfigDto paramWithContentConfig, + int orderType) { - var paramConfig = config.ParamConfig; + var paramConfig = paramWithContentConfig.ParamConfig; var orderNo = orderToken[paramConfig.OrderNoName]?.Value(); if (orderNo.IsNullOrWhiteSpace()) return; var order = await _orderRepository.GetFirstAsync(x => x.OrderType == orderType && x.OrderNo == orderNo, x => new { - x.Id, x.SubSystemId, x.IsPushCompleted, x.CustomId + x.Id, x.SubSystemId, x.LatestPushTrackContentId, x.CustomId }); if (order == default) return; @@ -70,7 +72,7 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe { OrderId = order.Id, SubSystemId = order.SubSystemId, - IsPushCompleted = order.IsPushCompleted, + LatestPushTrackContentId = order.LatestPushTrackContentId, CustomId = order.CustomId, OrderType = orderType, OrderNo = orderNo!, @@ -80,48 +82,49 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe { foreach (var item in trackTokens) { - await HandleTrackAsync(item, config, trackUpsertEvent); + await HandleTrackAsync(item, paramWithContentConfig, trackUpsertEvent); } } else if (orderToken is JObject) { - await HandleTrackAsync(orderToken, config, trackUpsertEvent); + await HandleTrackAsync(orderToken, paramWithContentConfig, trackUpsertEvent); } } - private async Task HandleTrackAsync(JToken trackToken, TrackPullConfigDto config, + private async Task HandleTrackAsync(JToken trackToken, TrackPullParamWithContentConfigDto paramWithContentConfig, TrackUpsertEvent @event) { var trackUpsertEvent = @event.DeepCopy(); - var paramConfig = config.ParamConfig; - var contentConfigs = config.ContentConfigs; + var paramConfig = paramWithContentConfig.ParamConfig; + var contentConfigs = paramWithContentConfig.ContentConfigs; TrackPullContentConfigDto? matchedContentConfig = null; // 1、匹配轨迹代码 - var trackCode = trackToken[paramConfig.TrackContentCodeName]?.Value(); - if (!trackCode.IsNullOrWhiteSpace()) + if (paramConfig.TrackContentCodeName != null) { - matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentCodeValue == trackCode); + var trackCode = trackToken[paramConfig.TrackContentCodeName]?.Value(); + if (!trackCode.IsNullOrWhiteSpace()) + { + matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentCodeValue == trackCode); + } } - // 2、匹配轨迹状态 - if (matchedContentConfig is null) + else if (paramConfig.TrackStatusName != null) { var trackStatus = trackToken[paramConfig.TrackStatusName]?.Value(); if (!trackStatus.IsNullOrWhiteSpace()) { - matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackStatusValue == trackCode); + matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackStatusValue == trackStatus); } } - // 3、匹配轨迹内容 - if (matchedContentConfig is null) + else if (paramConfig.TrackContentName != null) { var trackContent = trackToken[paramConfig.TrackContentName]?.Value(); if (!trackContent.IsNullOrWhiteSpace()) { Debug.Assert(trackContent != null, nameof(trackContent) + " != null"); - matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentValue == trackCode); + matchedContentConfig = contentConfigs.FirstOrDefault(x => x.TrackContentValue == trackContent); // 按关键字分析轨迹内容 if (matchedContentConfig is null) @@ -155,7 +158,10 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe if (matchedContentConfig is null) return; - var trackPlace = trackToken[paramConfig.TrackPlaceName]?.Value(); + // 轨迹发生地 + var trackPlace = paramConfig.TrackPlaceName == null + ? null + : trackToken[paramConfig.TrackPlaceName]?.Value(); if (trackPlace.IsNullOrWhiteSpace()) { Expression> resultExpression = @@ -173,12 +179,20 @@ public class TrackRefreshEventHandler : ITransientDependency, ICapSubscribe x.Id == trackUpsertEvent.OrderId, resultExpression); } + // 轨迹发生时间 + var trackTime = paramConfig.TrackTimeName == null + ? null + : trackToken[paramConfig.TrackTimeName]?.Value(); + // 轨迹发生时区 + var trackTimeZone = paramConfig.TrackTimeZoneName == null + ? null + : trackToken[paramConfig.TrackTimeZoneName]?.Value(); + // 新增/更新轨迹 trackUpsertEvent.TrackCode = matchedContentConfig.TrackContentCode; trackUpsertEvent.TrackPlace = trackPlace ?? "CN"; - trackUpsertEvent.TrackTime = trackToken[paramConfig.TrackTimeName]?.Value() ?? DateTime.Now; - trackUpsertEvent.TrackTimeZone = trackToken[paramConfig.TrackTimeZoneName]?.Value() ?? - matchedContentConfig.TrackTimeZoneValue ?? 8; + trackUpsertEvent.TrackTime = trackTime ?? DateTime.Now; + trackUpsertEvent.TrackTimeZone = trackTimeZone ?? matchedContentConfig.TrackTimeZoneValue ?? 8; await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, trackUpsertEvent); } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/EventHandlers/UpdateOrderTrackEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackUpsertAfterUpdateOrderEventHandler.cs similarity index 61% rename from src/SJZY.Track.Application/EventHandlers/UpdateOrderTrackEventHandler.cs rename to src/SJZY.Track.Application/EventHandlers/TrackUpsertAfterUpdateOrderEventHandler.cs index 72316cef..1ce9ae93 100644 --- a/src/SJZY.Track.Application/EventHandlers/UpdateOrderTrackEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackUpsertAfterUpdateOrderEventHandler.cs @@ -1,21 +1,22 @@ using DotNetCore.CAP; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Consts; using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.EventHandlers; -public class UpdateOrderTrackEventHandler : ITransientDependency, ICapSubscribe +public class TrackUpsertAfterUpdateOrderEventHandler : ITransientDependency, ICapSubscribe { private readonly IOrderRepository _orderRepository; - public UpdateOrderTrackEventHandler(IOrderRepository orderRepository) + public TrackUpsertAfterUpdateOrderEventHandler(IOrderRepository orderRepository) { _orderRepository = orderRepository; } - [CapSubscribe(GlobalConst.UpdateOrderTrackSubscribe)] - public async Task ConsumerAsync(UpdateOrderTrackEvent @event) + [CapSubscribe(GlobalConst.TrackUpsertAfterUpdateOrderSubscribe)] + public async Task ConsumerAsync(TrackUpsertAfterUpdateOrderEvent @event) { var order = await _orderRepository.GetFirstAsync(x => x.Id == @event.OrderId); if (order == default) return; @@ -25,18 +26,32 @@ public class UpdateOrderTrackEventHandler : ITransientDependency, ICapSubscribe if (@event.TrackTime == default) { if (order.LatestTrackTime == null) return; + // 删除全部轨迹导致的重置行为 + // tips:订单是支持从已完成态到未完成态的 order.ResetTrackInfo(); + + await _orderRepository.UpdateAsync(order); + + return; + } + + // 删除引发的回退更新 + if (order.LatestTrackTime != null && + @event.TrackTime.Subtract(TimeSpan.FromHours(@event.TrackTimeZone)) == + order.LatestTrackTime.Value.Subtract(TimeSpan.FromHours(order.LatestTrackTimeZone ?? 0))) + { + return; } - else if (order.LatestTrackTime != null && - order.LatestTrackTime.Value.Subtract(TimeSpan.FromHours(order.LatestTrackTimeZone ?? 0)) == - @event.TrackTime.Subtract(TimeSpan.FromHours(@event.TrackTimeZone))) return; } else // upsert引发的更新 { if (order.LatestTrackTime != null && - order.LatestTrackTime.Value.Subtract(TimeSpan.FromHours(order.LatestTrackTimeZone ?? 0)) > - @event.TrackTime.Subtract(TimeSpan.FromHours(@event.TrackTimeZone))) return; + @event.TrackTime.Subtract(TimeSpan.FromHours(@event.TrackTimeZone)) < + order.LatestTrackTime.Value.Subtract(TimeSpan.FromHours(order.LatestTrackTimeZone ?? 0))) + { + return; + } } order.IsCompleted = @event.IsCompleted; diff --git a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs index 21ddffc0..9d375716 100644 --- a/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs +++ b/src/SJZY.Track.Application/EventHandlers/TrackUpsertEventHandler.cs @@ -1,10 +1,13 @@ -using DotNetCore.CAP; +using System.Diagnostics; +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.Application.Contract.Services; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Queries; using SJZY.UserCenter.HttpApi.Services; using Volo.Abp.DependencyInjection; @@ -57,15 +60,52 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe @event.TrackCode = mapCode; } - await UpsertTrackAsync(@event); - } - - private async Task UpsertTrackAsync(TrackUpsertEvent @event) - { - // 不存在则新增轨迹,存在则更新 var track = await _trackDetailsRepository.GetFirstOrDefaultAsync(@event.OrderId, @event.TrackCode); - var orderIsCompleted = false; + // step1、upsert es轨迹 + await UpsertTrackAsync(track, @event); + Debug.Assert(track != null, nameof(track) + " != null"); + + // step2、触发轨迹推送事件(异步) + await HandleTrackPushAsync(@event, track); + + // step3、触发订单主表更新事件(异步) + await _capPublisher.PublishAsync(GlobalConst.TrackUpsertAfterUpdateOrderSubscribe, + new TrackUpsertAfterUpdateOrderEvent + { + OrderId = track.OrderId, + IsCompleted = track.IsCompleted, + TrackCode = track.TrackCode, + TrackContent = track.TrackContent, + TrackEnContent = track.TrackEnContent, + TrackPlace = track.TrackPlace, + TrackTime = track.TrackTime, + TrackTimeZone = track.TrackTimeZone + }); + + // step4、根据订单关联关系异步向下刷(异步) + var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId); + foreach (var linkedOrder in linkedOrders) + { + var nextEvent = @event.DeepCopy(); + nextEvent.OrderId = linkedOrder.OrderId; + nextEvent.OrderType = linkedOrder.OrderType; + nextEvent.OrderNo = linkedOrder.OrderNo; + nextEvent.SubSystemId = linkedOrder.SubSystemId; + nextEvent.LatestPushTrackContentId = linkedOrder.LatestPushTrackContentId; + nextEvent.CustomId = linkedOrder.CustomId; + nextEvent.UpSubSystemId = @event.SubSystemId; + await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, nextEvent); + } + } + + /// + /// 不存在则新增轨迹,存在则更新 + /// + /// + /// + private async Task UpsertTrackAsync(TrackDetailsIndex? track, TrackUpsertEvent @event) + { if (track == default) { //todo:可以优化 @@ -73,12 +113,10 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe var trackContent = await _provideQueries.MatchTrackContentAsync(@event.OrderId, @event.TrackCode); if (trackContent == default) { - //throw new BusinessException(message: $"订单:{@event.OrderNo} 所绑定的模板,没有一条内容可以匹配轨迹代码:{@event.TrackCode}"); + // 订单所绑定的模板,没有一条内容可以匹配发生的轨迹 return; } - orderIsCompleted = trackContent.IsCompleted; - track = new TrackDetailsIndex { IndexName = $"{GlobalConst.TrackIndex}-{DateTime.Now:yyyy.MM.dd}", @@ -88,7 +126,8 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe TrackStatus = trackContent.Status, TrackCode = @event.TrackCode, TrackContent = trackContent.Content, - IsCompleted = orderIsCompleted, + TrackContentId = trackContent.Id, + IsCompleted = trackContent.IsCompleted, TrackEnContent = trackContent.EnContent, TrackPlace = @event.TrackPlace, TrackTime = @event.TrackTime!.Value, @@ -97,12 +136,6 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe CreateUser = CurrentUserRequest.CurrentUser.Name, CreateTime = DateTime.Now }; - - // todo:推送只做新增的,更新和删除的不做先 - if (!@event.IsPushCompleted && await _trackPushCacheService.IsPushAsync(@event.CustomId)) - { - //await PushTrack(); - } } else { @@ -114,32 +147,59 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe } await _trackDetailsRepository.UpsertAsync(track); + } - // 触发订单主表更新事件 - await _capPublisher.PublishAsync(GlobalConst.UpdateOrderTrackSubscribe, new UpdateOrderTrackEvent + /// + /// 处理轨迹自动推送 + /// + /// + /// + private async Task HandleTrackPushAsync(TrackUpsertEvent @event, TrackDetailsIndex track) + { + TrackPushContentConfigDto? config; + OptionType optionType = OptionType.修改; + // 推送更新 + if (!track.Id.IsNullOrWhiteSpace()) { - OrderId = track.OrderId, - IsCompleted = orderIsCompleted, - TrackContent = track.TrackContent, - TrackEnContent = track.TrackEnContent, - TrackPlace = track.TrackPlace, - TrackTime = track.TrackTime, - TrackTimeZone = track.TrackTimeZone - }); - - // 根据订单关联关系异步向下刷 - var linkedOrders = await _orderRepository.GetLinkedOrdersAsync(@event.OrderId); - foreach (var linkedOrder in linkedOrders) - { - var nextEvent = @event.DeepCopy(); - nextEvent.OrderId = linkedOrder.OrderId; - nextEvent.OrderType = linkedOrder.OrderType; - nextEvent.OrderNo = linkedOrder.OrderNo; - nextEvent.SubSystemId = linkedOrder.SubSystemId; - nextEvent.IsPushCompleted = linkedOrder.IsPushCompleted; - nextEvent.CustomId = linkedOrder.CustomId; - nextEvent.UpSubSystemId = @event.SubSystemId; - await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, nextEvent); + config = await _trackPushCacheService.GetPushContentConfigAsync( + @event.SubSystemId, @event.CustomId, track.TrackContentId); + if (!config.IsCanUpdate) return; } + else + { + // 推送新增,需要根据上一次的推送 推断 本次推送 是否可行 + config = await _trackPushCacheService.InferNextPushContentOrNullAsync( + @event.SubSystemId, @event.CustomId, @event.LatestPushTrackContentId); + + if (config == null || !config.IsAutoPush) return; + + // 当前发生的轨迹就是要推送的 + if (config.TrackContentId != track.TrackContentId) return; + + optionType = OptionType.新增; + } + + if (config.OrderType != @event.OrderType) return; + + var trackPushEvent = new TrackPushEvent + { + OptionType = optionType, + ServiceProviderCode = config.ServiceProviderCode, + OrderNo = track.OrderNo, + TrackContentId = config.TrackContentId, + TrackStatus = track.TrackStatus, + TrackCode = track.TrackCode, + TrackContent = track.TrackContent, + TrackPlace = track.TrackPlace, + TrackTime = track.TrackTime.AddHours(config.TrackTimeZone ?? track.TrackTimeZone - track.TrackTimeZone), + TrackTimeZone = (float)(config.TrackTimeZone ?? track.TrackTimeZone), + TrackContentCodeValue = config.TrackContentCodeValue, + TrackContentValue = config.TrackContentValue, + TrackEnContentValue = config.TrackEnContentValue, + TrackStatusValue = config.TrackStatusValue, + ExpandFieldsValue = config.ExpandFieldsValue + }; + + await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent); } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/SJZY.Track.Application.csproj b/src/SJZY.Track.Application/SJZY.Track.Application.csproj index 160ca752..e3162402 100644 --- a/src/SJZY.Track.Application/SJZY.Track.Application.csproj +++ b/src/SJZY.Track.Application/SJZY.Track.Application.csproj @@ -8,7 +8,11 @@ - + + + + + diff --git a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs index 51f50f3b..88eb9530 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/OrderService.Link.cs @@ -2,6 +2,7 @@ using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Application.Contract.Events; using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Queries; namespace SJZY.Track.Application.Services.ProvideServices; diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs new file mode 100644 index 00000000..de894ef4 --- /dev/null +++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackPullService.cs @@ -0,0 +1,111 @@ +using Microsoft.AspNetCore.Authorization; +using Newtonsoft.Json; +using SJZY.Expand.ABP.Core; +using SJZY.InterfaceRelay.Application.Contracts; +using SJZY.Track.Application.Contract.Dtos.ProvideServices; +using SJZY.Track.Application.Contract.Dtos.TrackPull; +using SJZY.Track.Application.Contract.Services; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Queries; +using Volo.Abp.Http.Client.DynamicProxying; + +namespace SJZY.Track.Application.Services.ProvideServices; + +/// +/// 轨迹刷新服务 +/// +[ApiExplorerSettings(GroupName = "提供接口")] +[Route("/ProviderService")] +public class TrackPullService : ApplicationService +{ + private readonly IProvideQueries _provideQueries; + private readonly IHttpClientProxy _httpClientProxy; + private readonly ITrackPullCacheService _trackPullCacheService; + + public TrackPullService(IProvideQueries provideQueries, + IHttpClientProxy httpClientProxy, + ITrackPullCacheService trackPullCacheService) + { + _provideQueries = provideQueries; + _httpClientProxy = httpClientProxy; + _trackPullCacheService = trackPullCacheService; + } + + /// + /// 手动刷新轨迹 + /// + /// + /// + [HttpPost("Track/Refresh")] + public async Task RefreshTrackAsync(RefreshTrackInput input) + { + // todo:罚时? + input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空 + + // tips:这里没有区分订单类型,就算的不同类型的单一起刷新了也无所谓 + var orders = await _provideQueries.FindOrderWithServiceProviderAsync(input.OrderNos); + + if (orders.Count == 0) + { + // tips:可能是没有配置、或者所有单都刷完了、或者单不存在 + throw new BusinessException(message: "一个能更新的都没有"); + } + + foreach (var group in orders.GroupBy(x => + new TrackRefreshAttach(x.ServiceProviderId, x.ServiceProviderCode, x.SubSystemId, x.OrderType))) + { + var data = group.Select(x => new + { + x.OrderNo + }).ToList(); + + // 批量获取轨迹 + await _httpClientProxy.Service.BatchForwardThenPushToQueueAsync( + "A012", group.Key.ServiceProviderCode, data, + GlobalConst.TrackRefreshSubscribe, JsonConvert.SerializeObject(group.Key)); + } + + return true; + } + + /// + /// 定时任务刷新轨迹 + /// + /// + [AllowAnonymous] + [HttpPost("Track/RefreshForTask")] + public async Task RefreshForTaskAsync() + { + var configs = await _trackPullCacheService.GetAllPullConfigsAsync(); + foreach (var config in configs) + { + var redisKey = _trackPullCacheService.TrackPullKey(config.SubSystemId, config.ServiceProviderId); + if (await RedisHelper.Client.ExistsAsync(redisKey)) + { + continue; + } + + var orders = await _provideQueries.FindOrderWithServiceProviderAsync(config.ServiceProviderId); + + foreach (var group in orders.GroupBy(x => + new TrackRefreshAttach(x.ServiceProviderId, x.ServiceProviderCode, x.SubSystemId, + x.OrderType))) + { + var data = group.Select(x => new + { + x.OrderNo + }).ToList(); + + // 批量获取轨迹 + await _httpClientProxy.Service.BatchForwardThenPushToQueueAsync( + InterfaceRelayConst.GetTrackInterfaceCode, group.Key.ServiceProviderCode, data, + GlobalConst.TrackRefreshSubscribe, JsonConvert.SerializeObject(group.Key)); + } + + await RedisHelper.Client.SetExAsync(redisKey, config.PullInterval * 60, 1); + } + + + return true; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackPushPullService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackPushPullService.cs deleted file mode 100644 index 2e1dd08b..00000000 --- a/src/SJZY.Track.Application/Services/ProvideServices/TrackPushPullService.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Newtonsoft.Json; -using SJZY.InterfaceRelay.Application.Contracts; -using SJZY.Track.Application.Contract.Dtos.ProvideServices; -using SJZY.Track.Application.Contract.Dtos.TrackPull; -using SJZY.Track.Domain.Aggregates.OrderAggregate; -using Volo.Abp.Http.Client.DynamicProxying; - -namespace SJZY.Track.Application.Services.ProvideServices; - -/// -/// 轨迹推送、拉取服务 -/// -[ApiExplorerSettings(GroupName = "提供接口")] -[Route("/ProviderService")] -public class TrackPushPullService : ApplicationService -{ - private readonly IOrderRepository _orderRepository; - private readonly IHttpClientProxy _httpClientProxy; - - public TrackPushPullService(IOrderRepository orderRepository, - IHttpClientProxy httpClientProxy) - { - _orderRepository = orderRepository; - _httpClientProxy = httpClientProxy; - } - - /// - /// 刷新轨迹 - /// - /// - /// - [HttpPost("Track/Refresh")] - public async Task RefreshTrackAsync(RefreshTrackInput input) - { - if (input.OrderNos.Count == 0) - { - throw new BusinessException(message: "订单号数组不能为空"); - } - - input.OrderNos = input.OrderNos.Distinct().ToList(); - - var orderTemplates = await _orderRepository.GetOrderTemplatesAsync(input.OrderNos); - - foreach (var group in orderTemplates.GroupBy(x => - new TrackRefreshAttach(x.ServiceProviderId, x.ServiceProviderCode, x.SubSystemId, x.OrderType))) - { - var data = group.Select(x => new - { - x.OrderNo - }).ToList(); - - // 批量获取轨迹 - await _httpClientProxy.Service.BatchForwardThenPushToQueueAsync( - "A012", group.Key.ServiceProviderCode, data, - GlobalConst.TrackRefreshSubscribe, JsonConvert.SerializeObject(group.Key)); - } - - return true; - } -} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackPushService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackPushService.cs new file mode 100644 index 00000000..2fee5408 --- /dev/null +++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackPushService.cs @@ -0,0 +1,123 @@ +using DotNetCore.CAP; +using SJZY.Track.Application.Contract.Dtos.ProvideServices; +using SJZY.Track.Application.Contract.Events; +using SJZY.Track.Application.Contract.Services; +using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Enums; +using SJZY.UserCenter.HttpApi.Services; + +namespace SJZY.Track.Application.Services.ProvideServices; + +/// +/// 轨迹推送服务 +/// +[ApiExplorerSettings(GroupName = "提供接口")] +[Route("/ProviderService")] +public class TrackPushService : ApplicationService +{ + private readonly ITrackDetailsRepository _trackDetailsRepository; + private readonly IOrderRepository _orderRepository; + private readonly ITrackPushCacheService _pushCacheService; + private readonly ICapPublisher _capPublisher; + + public TrackPushService(ITrackPushCacheService pushCacheService, + ITrackDetailsRepository trackDetailsRepository + , IOrderRepository orderRepository + , ICapPublisher capPublisher) + { + _pushCacheService = pushCacheService; + _trackDetailsRepository = trackDetailsRepository; + _orderRepository = orderRepository; + _capPublisher = capPublisher; + } + + /// + /// 手工推送轨迹 + /// + /// + /// + [HttpPost("Track/Push")] + public async Task PushTrackAsync(PushTrackInput input) + { + input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空 + + var orders = await _orderRepository.GetListAsync(x => + x.OrderType == input.OrderType && input.OrderNos.Contains(x.OrderNo), x => new + { + x.Id, x.OrderNo, x.SubSystemId, x.CustomId + }); + + if (orders.Count == 0) + { + throw new BusinessException(message: "一个推送配置都不存在"); + } + + var tracks = await _trackDetailsRepository.GetListAsync(input.OrderType, input.OrderNos, input.TrackCode); + + if (tracks.Count == 0) + { + throw new BusinessException(message: "一个能推的轨迹都不存在"); + } + + var res = 0; + + foreach (var order in orders) + { + // 如果没有轨迹,就不需要推 + var track = tracks.FirstOrDefault(x => x.OrderId == order.Id); + if (track == null) continue; + + // 手工推送不推断,直接无脑推 + var config = + await _pushCacheService.GetPushContentConfigAsync(order.SubSystemId, order.CustomId, + track.TrackContentId); + + var trackPushEvent = new TrackPushEvent + { + ServiceProviderCode = config.ServiceProviderCode, + OrderNo = order.OrderNo, + TrackContentId = config.TrackContentId, + TrackStatus = track.TrackStatus, + TrackCode = track.TrackCode, + TrackContent = track.TrackContent, + TrackPlace = track.TrackPlace, + TrackTime = track.TrackTime.AddHours(config.TrackTimeZone ?? + track.TrackTimeZone - track.TrackTimeZone), + TrackTimeZone = (float)(config.TrackTimeZone ?? track.TrackTimeZone), + TrackContentCodeValue = config.TrackContentCodeValue, + TrackContentValue = config.TrackContentValue, + TrackEnContentValue = config.TrackEnContentValue, + TrackStatusValue = config.TrackStatusValue, + ExpandFieldsValue = config.ExpandFieldsValue, + OperationMan = CurrentUserRequest.CurrentUser.Name, + }; + + await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent); + + res++; + } + + return $"即将推送轨迹代码{input.TrackCode}给{res}个订单"; + } + + + /// + /// 定时任务推送预警(》12小时没有推送的) + /// + /// + [HttpPost("Track/PushWarnForTask")] + public async Task PushWarnForTaskAsync() + { + var time = DateTime.Now.Subtract(TimeSpan.FromHours(12)); + var orders = await _orderRepository.GetListAsync(x => + !x.IsCompleted && x.QuestionType == 0 && x.LatestPushTime < time); + + orders.ForEach(x => { x.QuestionType = (int)TrackProblemType.Warn; }); + + await _orderRepository.UpdateRangeAsync(orders, x => new { x.QuestionType }); + + return $"成功将{orders.Select(x => x.OrderNo).JoinAsString(",")}置为预警单"; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs index fbd0fd99..b45d9313 100644 --- a/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs +++ b/src/SJZY.Track.Application/Services/ProvideServices/TrackService.cs @@ -4,6 +4,7 @@ using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Queries; namespace SJZY.Track.Application.Services.ProvideServices; @@ -41,7 +42,7 @@ public partial class TrackService : ApplicationService, ITrackService var order = await _orderRepository.GetFirstAsync(x => x.OrderType == input.OrderType && x.OrderNo == input.OrderNo, x => new { - x.Id, x.SubSystemId, x.IsPushCompleted, x.CustomId + x.Id, x.SubSystemId, x.LatestPushTrackContentId, x.CustomId, x.IsCompleted }); if (order == default) { @@ -52,8 +53,9 @@ public partial class TrackService : ApplicationService, ITrackService var @event = ObjectMapper.Map(input); @event.OrderId = order.Id; @event.SubSystemId = order.SubSystemId; - @event.IsPushCompleted = order.IsPushCompleted; + @event.LatestPushTrackContentId = order.LatestPushTrackContentId; @event.CustomId = order.CustomId; + @event.IsCompleted = order.IsCompleted; await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event); return true; } @@ -76,7 +78,7 @@ public partial class TrackService : ApplicationService, ITrackService var orders = await _orderRepository.GetListAsync(x => x.OrderType == input.OrderType && input.OrderNos.Contains(x.OrderNo), x => new { - x.Id, x.OrderNo, x.SubSystemId, x.IsPushCompleted, x.CustomId + x.Id, x.OrderNo, x.SubSystemId, x.LatestPushTrackContentId, x.CustomId }); foreach (var order in orders) @@ -92,7 +94,7 @@ public partial class TrackService : ApplicationService, ITrackService OrderNo = order.OrderNo, OrderId = order.Id, SubSystemId = order.SubSystemId, - IsPushCompleted = order.IsPushCompleted, + LatestPushTrackContentId = order.LatestPushTrackContentId, CustomId = order.CustomId }; await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event); @@ -120,7 +122,7 @@ public partial class TrackService : ApplicationService, ITrackService throw new BusinessException(message: $"订单:{input.OrderNo}不存在"); } - var codes = await _provideQueries.GetCanDeleteTrackCodesAsync(new List(order.Id), input.TrackCodes); + var codes = await _provideQueries.GetCanDeleteTrackCodesAsync(new List { order.Id }, input.TrackCodes); if (codes.Count == 0) { @@ -149,7 +151,7 @@ public partial class TrackService : ApplicationService, ITrackService public async Task BatchDeleteTrackAsync(BatchDeleteTrackInput input) { var orders = await _orderRepository.GetListAsync(x => - x.OrderType == input.OrderType && input.OrderNos.Contains(x.OrderNo) && !x.IsPushCompleted + x.OrderType == input.OrderType && input.OrderNos.Contains(x.OrderNo) , x => new { x.Id, x.SubSystemId diff --git a/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs b/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs index 0e08e188..f25aad89 100644 --- a/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs +++ b/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs @@ -1,120 +1,154 @@ -using SJZY.Track.Application.Contract.Dtos.ProvideServices; -using SJZY.Track.Domain.Aggregates.OrderAggregate; +using System.Diagnostics; +using SJZY.Track.Application.Contract.Dtos.ProvideServices; +using SJZY.Track.Application.Contract.Dtos.TrackOrder; using SJZY.Track.Domain.Aggregates.TrackContentAggregate; using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Aggregates.TrackPushAggregate; using SJZY.Track.Domain.Dtos.Order; using SJZY.Track.Domain.Dtos.TrackTemplate; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; +using SJZY.Track.Domain.Enums; +using SJZY.Track.Domain.Queries; -namespace SJZY.Track.Application.Services.TrackOrders +namespace SJZY.Track.Application.Services.TrackOrders; + +[ApiExplorerSettings(GroupName = "轨迹订单")] +[Route("/Track/Order")] +public class TrackOrderService : ApplicationService { - [ApiExplorerSettings(GroupName = "轨迹订单")] - [Route("/Track/Order")] - public class TrackOrderService : ApplicationService, ITransientDependency + private readonly ITrackOrderQueries _trackOrderQueries; + private readonly ITrackDetailsRepository _trackDetailsRepository; + private readonly ITrackContentRepository _trackContentRepository; + private readonly ITrackPushRecordsRepository _trackPushRecordsRepository; + + public TrackOrderService( + ITrackOrderQueries trackOrderQueries, + ITrackDetailsRepository trackDetailsRepository, + ITrackContentRepository trackContentRepository, + ITrackPushRecordsRepository trackPushRecordsRepository + ) { - private readonly IOrderRepository _orderRepository; - private readonly ITrackDetailsRepository _trackDetailsRepository; - private readonly ITrackContentRepository _trackContentRepository; - - public TrackOrderService( - IOrderRepository orderRepository, - ITrackDetailsRepository trackDetailsRepository, - ITrackContentRepository trackContentRepository - ) - { - this._orderRepository=orderRepository; - this._trackDetailsRepository=trackDetailsRepository; - this._trackContentRepository=trackContentRepository; - } - - #region 轨迹订单明细 - /// - /// 根据轨迹订单id获取轨迹订单明细列表 - /// - /// - /// - [HttpPost("GetDetails")] - public async Task> GetOrderDetails(GetOrderDetailsInput input) - { - var trackDetails = await _trackDetailsRepository.GetListAsync(input.OrderId); - if (!trackDetails.IsNullOrEmpty()) - { - var list = ObjectMapper.Map, List>(trackDetails); - var trackCodes = list.Where(a => !a.Code.IsNullOrWhiteSpace()).Select(a => a.Code).Distinct().ToList(); - - var trackContents = await _trackContentRepository.GetTrackContentAttributeValue(new GetTemplateContentAttributeValueInputVO - { - SubSystemId =input.SubSystemId, - TrackTemplateIds = input.TrackTemplateIds, - TrackCodes=trackCodes - }); - input.TrackTemplateIds =input.TrackTemplateIds.Where(a => a>0).ToList(); - int id = 1; - list.ForEach(a => - { - a.Id = id++; - - var trackContentsOfTemplates = trackContents.Where(b => b.SubSystemId==input.SubSystemId && b.TrackCode==a.Code - && input.TrackTemplateIds.Contains(b.TrackTemplateId)); - GetTemplateContentAttributeValueVO trackContent = null; - var insertData = input.TrackTemplateIds.Intersect(trackContentsOfTemplates.Select(aa => aa.TrackTemplateId)).ToList(); - if (!insertData.IsNullOrEmpty()) - { - trackContent =trackContentsOfTemplates.FirstOrDefault(a => a.TrackTemplateId==insertData.FirstOrDefault()); - } - - if (trackContent!=null) - { - a.IsCanDelete=trackContent.IsCanDelete; - a.IsExternal = trackContent.IsExternal; - } - //else - //{ - // a.IsCanDelete=false; - // a.IsExternal=false; - //} - if (a.TrackTimeZoneValue==0f) - { - a.TrackTimeZone=$"GTM{" "}+00:00"; - } - else - { - // 将小数形式的小时转换为时区偏移量 - int hours = (int)a.TrackTimeZoneValue; // 提取整数部分作为小时 - int minutes = (int)((a.TrackTimeZoneValue - hours) * 60); // 将小数部分乘以 60 转换为分钟 - TimeSpan offset = new TimeSpan(hours, minutes, 0); - string timeZoneStr = offset.ToString(); - string flag = a.TrackTimeZoneValue>0f ? "+" : ""; - a.TrackTimeZone = $"GTM{" "}{flag}{timeZoneStr.RemovePostFix(":00")}"; - } - }); - return list; - } - - return new List(); - } - #endregion - - #region 轨迹订单列表 - /// - /// 获取分页的轨迹订单 - /// - /// - /// - [HttpPost("GetTrackOrderList")] - public async Task> GetPageTrackOrder(GetPageTrackOrderInput input) - { - var vo = ObjectMapper.Map(input); - var pageList = await _orderRepository.GetPageTrackOrder(vo); - var pageResultDto = - ObjectMapper.Map, UnifyPageResultDto>(pageList); - return pageResultDto; - } - #endregion + _trackOrderQueries = trackOrderQueries; + _trackDetailsRepository = trackDetailsRepository; + _trackContentRepository = trackContentRepository; + _trackPushRecordsRepository = trackPushRecordsRepository; } -} + + #region 轨迹订单明细 + + /// + /// 根据轨迹订单id获取轨迹订单明细列表 + /// + /// + /// + [HttpPost("GetDetails")] + public async Task> GetOrderDetails(GetOrderDetailsInput input) + { + var trackDetails = await _trackDetailsRepository.GetListAsync(input.OrderId); + if (!trackDetails.IsNullOrEmpty()) + { + var list = ObjectMapper.Map, List>(trackDetails); + var trackCodes = list.Where(a => !a.Code.IsNullOrWhiteSpace()).Select(a => a.Code).Distinct().ToList(); + + var trackContents = await _trackContentRepository.GetTrackContentAttributeValue( + new GetTemplateContentAttributeValueInputVO + { + SubSystemId = input.SubSystemId, + TrackTemplateIds = input.TrackTemplateIds, + TrackCodes = trackCodes + }); + Debug.Assert(input.TrackTemplateIds != null, "input.TrackTemplateIds != null"); + input.TrackTemplateIds = input.TrackTemplateIds.Where(a => a > 0).ToList(); + int id = 1; + list.ForEach(a => + { + a.Id = id++; + var trackContentsOfTemplates = trackContents.Where(b => b.SubSystemId == input.SubSystemId && + b.TrackCode == a.Code + && input.TrackTemplateIds.Contains( + b.TrackTemplateId)).ToList(); + GetTemplateContentAttributeValueVO? trackContent = null; + var insertData = input.TrackTemplateIds + .Intersect(trackContentsOfTemplates.Select(aa => aa.TrackTemplateId)).ToList(); + if (!insertData.IsNullOrEmpty()) + { + trackContent = + trackContentsOfTemplates.FirstOrDefault(it => + it.TrackTemplateId == insertData.FirstOrDefault()); + } + + if (trackContent != null) + { + a.IsCanDelete = trackContent.IsCanDelete; + a.IsExternal = trackContent.IsExternal; + } + + if (a.TrackTimeZoneValue == 0f) + { + a.TrackTimeZone = "GTM +00:00"; + } + else + { + // 将小数形式的小时转换为时区偏移量 + int hours = (int)a.TrackTimeZoneValue; // 提取整数部分作为小时 + int minutes = (int)((a.TrackTimeZoneValue - hours) * 60); // 将小数部分乘以 60 转换为分钟 + TimeSpan offset = new TimeSpan(hours, minutes, 0); + string timeZoneStr = offset.ToString(); + string flag = a.TrackTimeZoneValue > 0f ? "+" : ""; + a.TrackTimeZone = $"GTM {flag}{timeZoneStr.RemovePostFix(":00")}"; + } + }); + return list; + } + + return new List(); + } + + #endregion + + #region 轨迹订单列表 + + /// + /// 获取分页的轨迹订单 + /// + /// + /// + [HttpPost("GetTrackOrderList")] + public async Task> GetPageTrackOrder(GetPageTrackOrderInput input) + { + var vo = ObjectMapper.Map(input); + var pageList = await _trackOrderQueries.GetPageTrackOrder(vo); + var pageResultDto = + ObjectMapper.Map, UnifyPageResultDto>(pageList); + return pageResultDto; + } + + #endregion + + /// + /// 获取轨迹计数器 + /// + /// + [HttpGet] + public async Task GetTrackCounterAsync() + { + var counts = await _trackOrderQueries.GetTrackProblemCountsAsync(); + + return new GetTrackCounterOutput + { + TotalCount = counts.Sum(x => x.Count), + ErrorCount = counts.FirstOrDefault(x => x.ProblemType == (int)TrackProblemType.Error)?.Count ?? 0, + WarnCount = counts.FirstOrDefault(x => x.ProblemType == (int)TrackProblemType.Warn)?.Count ?? 0, + }; + } + + /// + /// 获取轨迹推送记录 + /// + /// + /// 订单id + [HttpGet] + public async Task> GetTrackPushRecordsAsync(int orderId) + { + return await _trackPushRecordsRepository.GetTrackPushRecordsAsync(orderId); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/TrackPull/TrackPullCacheService.cs b/src/SJZY.Track.Application/Services/TrackPull/TrackPullCacheService.cs index 420c44e6..c5c7f8fd 100644 --- a/src/SJZY.Track.Application/Services/TrackPull/TrackPullCacheService.cs +++ b/src/SJZY.Track.Application/Services/TrackPull/TrackPullCacheService.cs @@ -1,18 +1,22 @@ -using SJZY.Expand.ABP.Core; +using System.Linq.Expressions; +using SJZY.Expand.ABP.Core; using SJZY.Track.Application.Contract.Dtos.TrackPull; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Domain.Aggregates.TrackPullAggregate; +using SJZY.Track.Domain.Consts; using SJZY.Track.Domain.Dtos.TrackPull; -using System.Linq.Expressions; -using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.Services.TrackPull; -public class TrackPullCacheService : ApplicationService, ITrackPullCacheService, ITransientDependency +public class TrackPullCacheService : ApplicationService, ITrackPullCacheService { private readonly ITrackPullConfigRepository _trackPullConfigRepository; - private string RedisKey(int subSystemId, int serviceProviderId) => GlobalConst.TrackPushKeyPrefix + subSystemId + ":" + serviceProviderId; + public string TrackPullKey(int subSystemId, int serviceProviderId) => + $"{GlobalConst.TrackPullKeyPrefix}:{subSystemId}:{serviceProviderId}"; + + public string TrackPullContentKey(int subSystemId, int serviceProviderId) => + $"{GlobalConst.TrackPullContentKeyPrefix}:{subSystemId}:{serviceProviderId}"; public TrackPullCacheService(ITrackPullConfigRepository trackPullConfigRepository) { @@ -20,9 +24,23 @@ public class TrackPullCacheService : ApplicationService, ITrackPullCacheService, } [NonAction] - public async Task GetPullConfigAsync(int subSystemId, int serviceProviderId) + public async Task> GetAllPullConfigsAsync() { - var data = await RedisHelper.Client.GetAsync(RedisKey(subSystemId, serviceProviderId)); + return await _trackPullConfigRepository.GetListAsync(x => true, x => new TrackPullConfigDto + { + SubSystemId = x.SubSystemId, + ServiceProviderId = x.ServiceProviderId, + PullInterval = x.PullInterval + }); + } + + [NonAction] + public async Task GetPullParamWithContentConfigAsync(int subSystemId, + int serviceProviderId) + { + var data = await RedisHelper.Client.GetAsync(TrackPullContentKey( + subSystemId, + serviceProviderId)); data ??= await SetPullConfigAsync(subSystemId: subSystemId, serviceProviderId: serviceProviderId); @@ -30,12 +48,15 @@ public class TrackPullCacheService : ApplicationService, ITrackPullCacheService, } [NonAction] - public async Task SetPullConfigAsync(int? id = null, int? subSystemId = null, int? serviceProviderId = null) + public async Task SetPullConfigAsync(int? id = null, int? subSystemId = null, + int? serviceProviderId = null) { - var data = new TrackPullConfigDto(); + var data = new TrackPullParamWithContentConfigDto(); - Expression> exp = x => - (id == null || x.Id == id) && (id != null || (x.SubSystemId == subSystemId && x.ServiceProviderId == serviceProviderId)); + Expression> exp = x => true; + if (id.HasValue) exp = x => x.Id == id; + else if (subSystemId.HasValue && serviceProviderId.HasValue) + exp = x => x.SubSystemId == subSystemId && x.ServiceProviderId == serviceProviderId; var trackPullConfigEntity = await _trackPullConfigRepository.GetFirstAsync(exp); if (trackPullConfigEntity == null) return data; @@ -45,10 +66,14 @@ public class TrackPullCacheService : ApplicationService, ITrackPullCacheService, var trackPullContentList = await _trackPullConfigRepository.GetContentListCacheAsync(trackPullConfigEntity.Id); if (trackPullContentList.Count == 0) return data; - data.ParamConfig = ObjectMapper.Map(trackPullConfigDetail); - data.ContentConfigs = ObjectMapper.Map, List>(trackPullContentList); + data.ParamConfig = + ObjectMapper.Map(trackPullConfigDetail); + data.ContentConfigs = + ObjectMapper.Map, List>( + trackPullContentList); - await RedisHelper.Client.SetAsync(RedisKey(trackPullConfigEntity.SubSystemId, trackPullConfigEntity.ServiceProviderId), data, 86400); + await RedisHelper.Client.SetAsync( + TrackPullContentKey(trackPullConfigEntity.SubSystemId, trackPullConfigEntity.ServiceProviderId), data); return data; } diff --git a/src/SJZY.Track.Application/Services/TrackPull/TrackPullService.cs b/src/SJZY.Track.Application/Services/TrackPull/TrackPullService.cs index 61f2cb2d..af00b7c6 100644 --- a/src/SJZY.Track.Application/Services/TrackPull/TrackPullService.cs +++ b/src/SJZY.Track.Application/Services/TrackPull/TrackPullService.cs @@ -9,7 +9,6 @@ using SJZY.Track.Domain.Aggregates.TrackPullAggregate; using SJZY.Track.Domain.Dtos.Common; using SJZY.Track.Domain.Dtos.TrackPull; using SqlSugar; -using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.Services.TrackPull; @@ -18,7 +17,7 @@ namespace SJZY.Track.Application.Services.TrackPull; /// [ApiExplorerSettings(GroupName = "轨迹拉取")] [Route("/Track/PullConfig")] -public class TrackPullService : ApplicationService, ITransientDependency +public class TrackPullService : ApplicationService { private readonly IStringLocalizer _stringLocalizer; private readonly ITrackPullConfigRepository _trackPullConfigRepository; @@ -100,52 +99,57 @@ public class TrackPullService : ApplicationService, ITransientDependency switch (input.Options) { case OptionTypeNoNull.新增: + { + var trackPullEntity = ObjectMapper.Map(input); + var trackPullParamsEntity = + ObjectMapper.Map(input); + + int id; + + using (var ts = TransactionScopeHelper.Create()) { - var trackPullEntity = ObjectMapper.Map(input); - var trackPullParamsEntity = ObjectMapper.Map(input); + id = await _trackPullConfigRepository.InsertReturnIdentityAsync(trackPullEntity); - int id = 0; + trackPullParamsEntity.PullOrPushConfigId = id; + await _trackPullConfigRepository.InsertParamsAsync(trackPullParamsEntity); - using (var ts = TransactionScopeHelper.Create()) - { - id = await _trackPullConfigRepository.InsertReturnIdentityAsync(trackPullEntity); - - trackPullParamsEntity.PullOrPushConfigId = id; - await _trackPullConfigRepository.InsertParamsAsync(trackPullParamsEntity); - - ts.Complete(); - } - - await _trackPullCacheService.SetPullConfigAsync(id); + ts.Complete(); } + + await _trackPullCacheService.SetPullConfigAsync(id); + } break; case OptionTypeNoNull.修改: + { + var oldTrackPullEntity = await _trackPullConfigRepository.GetFirstAsync(x => x.Id == input.Id) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); + + var oldTrackPullParamsEntity = + await _trackPullConfigRepository.GetParamsSingleAsync(x => + x.PullOrPushConfigId == input.Id && !x.IsPush); + + ObjectMapper.Map(input, oldTrackPullEntity); + ObjectMapper.Map(input, oldTrackPullParamsEntity); + + using (var ts = TransactionScopeHelper.Create()) { - var oldTrackPullEntity = await _trackPullConfigRepository.GetFirstAsync(x => x.Id == input.Id) ?? throw new BusinessException(message: _stringLocalizer["NotFindData"]); + await _trackPullConfigRepository.UpdateAsync(oldTrackPullEntity); + await _trackPullConfigRepository.UpdateParamsAsync(oldTrackPullParamsEntity); - var oldTrackPullParamsEntity = await _trackPullConfigRepository.GetParamsSingleAsync(x => x.PullOrPushConfigId == input.Id && !x.IsPush); - - ObjectMapper.Map(input, oldTrackPullEntity); - ObjectMapper.Map(input, oldTrackPullParamsEntity); - - using (var ts = TransactionScopeHelper.Create()) - { - await _trackPullConfigRepository.UpdateAsync(oldTrackPullEntity); - await _trackPullConfigRepository.UpdateParamsAsync(oldTrackPullParamsEntity); - - ts.Complete(); - } - - await _trackPullCacheService.SetPullConfigAsync(input.Id); + ts.Complete(); } + + await _trackPullCacheService.SetPullConfigAsync(input.Id); + } break; case OptionTypeNoNull.删除: using (var ts = TransactionScopeHelper.Create()) { await _trackPullConfigRepository.SoftDeleteAsync(x => x.Id == input.Id); - await _trackPullConfigRepository.SoftDeleteParamsAsync(x => x.PullOrPushConfigId == input.Id && !x.IsPush); + await _trackPullConfigRepository.SoftDeleteParamsAsync(x => + x.PullOrPushConfigId == input.Id && !x.IsPush); await _trackPullConfigRepository.SoftDeleteContentAsync(x => x.TrackPullConfigId == input.Id); ts.Complete(); @@ -171,21 +175,32 @@ public class TrackPullService : ApplicationService, ITransientDependency { if (input.Options != OptionTypeNoNull.删除) { - Expression> isContentAnyExp = x => x.TrackPullConfigId == input.TrackPullConfigId; + Expression> isContentAnyExp = x => + x.TrackPullConfigId == input.TrackPullConfigId; if (input.Options == OptionTypeNoNull.修改) isContentAnyExp = isContentAnyExp.And(x => x.Id != input.Id); - if (await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackContentId == input.TrackContentId))) + if (await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackContentId == input.TrackContentId))) throw new BusinessException(message: _stringLocalizer["IsTrackPullContentAny"]); - else if (!input.TrackContentCodeValue.IsNullOrWhiteSpace() && await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackContentCodeValue == input.TrackContentCodeValue))) + else if (!input.TrackContentCodeValue.IsNullOrWhiteSpace() && + await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackContentCodeValue == input.TrackContentCodeValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPullContentCodeValueAny"]); - else if (!input.TrackStatusValue.IsNullOrWhiteSpace() && await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackStatusValue == input.TrackStatusValue))) + else if (!input.TrackStatusValue.IsNullOrWhiteSpace() && + await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackStatusValue == input.TrackStatusValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPullContentStatusValueAny"]); - else if (!input.TrackContentValue.IsNullOrWhiteSpace() && await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackContentValue == input.TrackContentValue))) + else if (!input.TrackContentValue.IsNullOrWhiteSpace() && + await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackContentValue == input.TrackContentValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPullContentValueAny"]); else if (!input.TrackKeywords.IsNullOrEmpty()) { Expression> trackKeywordExp = _ => false; - input.TrackKeywords!.ForEach(item => { trackKeywordExp = trackKeywordExp.Or(x => SqlFunc.SplitIn(x.TrackKeyword, item)); }); + input.TrackKeywords!.ForEach(item => + { + trackKeywordExp = trackKeywordExp.Or(x => SqlFunc.SplitIn(x.TrackKeyword, item)); + }); if (await _trackPullConfigRepository.IsContentAnyAsync(isContentAnyExp.And(trackKeywordExp))) throw new BusinessException(message: _stringLocalizer["IsTrackPullContentKeywordsAny"]); @@ -195,33 +210,38 @@ public class TrackPullService : ApplicationService, ITransientDependency switch (input.Options) { case OptionTypeNoNull.新增: - { - var entity = ObjectMapper.Map(input); + { + var entity = ObjectMapper.Map(input); - await _trackPullConfigRepository.InsertContentAsync(entity); - await _trackPullCacheService.SetPullConfigAsync(input.TrackPullConfigId); - - break; - } - - case OptionTypeNoNull.修改: - { - var oldTrackPullContentEntity = await _trackPullConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? - throw new BusinessException(message: _stringLocalizer["NotFindData"]); - - ObjectMapper.Map(input, oldTrackPullContentEntity); - - await _trackPullConfigRepository.UpdateContentAsync(oldTrackPullContentEntity); - await _trackPullCacheService.SetPullConfigAsync(input.TrackPullConfigId); - - break; - } - - case OptionTypeNoNull.删除: - - await _trackPullConfigRepository.SoftDeleteContentAsync(x => x.Id == input.Id); + await _trackPullConfigRepository.InsertContentAsync(entity); + await _trackPullCacheService.SetPullConfigAsync(input.TrackPullConfigId); break; + } + + case OptionTypeNoNull.修改: + { + var oldTrackPullContentEntity = await _trackPullConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); + + ObjectMapper.Map(input, oldTrackPullContentEntity); + + await _trackPullConfigRepository.UpdateContentAsync(oldTrackPullContentEntity); + await _trackPullCacheService.SetPullConfigAsync(oldTrackPullContentEntity.TrackPullConfigId); + + break; + } + + case OptionTypeNoNull.删除: + { + var oldTrackPullContentEntity = await _trackPullConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); + + await _trackPullConfigRepository.SoftDeleteContentAsync(x => x.Id == input.Id); + await _trackPullCacheService.SetPullConfigAsync(oldTrackPullContentEntity.TrackPullConfigId); + + break; + } default: throw new BusinessException(message: _stringLocalizer[SjzyBasicLocalization.Validation_IsInEnum, diff --git a/src/SJZY.Track.Application/Services/TrackPush/TrackPushCacheService.cs b/src/SJZY.Track.Application/Services/TrackPush/TrackPushCacheService.cs index 62df4046..46155e2e 100644 --- a/src/SJZY.Track.Application/Services/TrackPush/TrackPushCacheService.cs +++ b/src/SJZY.Track.Application/Services/TrackPush/TrackPushCacheService.cs @@ -1,39 +1,101 @@ -using SJZY.Expand.ABP.Core; +using System.Linq.Expressions; +using SJZY.Expand.ABP.Core; +using SJZY.Track.Application.Contract.Dtos.ProvideServices; using SJZY.Track.Application.Contract.Services; using SJZY.Track.Domain.Aggregates.TrackPushAggregate; -using SJZY.Track.Domain.Queries; -using Volo.Abp.DependencyInjection; +using SJZY.Track.Domain.Consts; namespace SJZY.Track.Application.Services.TrackPush; -public class TrackPushCacheService : ITrackPushCacheService, ITransientDependency +public class TrackPushCacheService : ApplicationService, ITrackPushCacheService { - private readonly IBasicQuery _trackPushConfigQuery; + private readonly ITrackPushConfigRepository _trackPushConfigRepository; - private string RedisKey(int customId) => GlobalConst.TrackPushKeyPrefix + customId; + private string TrackPushContentKey(int subSystemId, int customId) => + $"{GlobalConst.TrackPushKeyPrefix}:{subSystemId}:{customId}"; - public TrackPushCacheService(IBasicQuery trackPushConfigQuery) + public TrackPushCacheService(ITrackPushConfigRepository trackPushConfigRepository) { - _trackPushConfigQuery = trackPushConfigQuery; + _trackPushConfigRepository = trackPushConfigRepository; } - public async Task IsPushAsync(int customId) + [NonAction] + public async Task> GetPushContentConfigsAsync(int subSystemId, int customId) { - var isPush = - await RedisHelper.Client.GetAsync(RedisKey(customId)); + var data = await GetPushConfigAsync(subSystemId, customId); - if (isPush == null) + return data.ContentConfigs; + } + + [NonAction] + public async Task GetPushContentConfigAsync(int subSystemId, int customId, + int trackContentId) + { + var data = await GetPushContentConfigsAsync(subSystemId, customId); + + return data.Single(x => x.TrackContentId == trackContentId); + } + + [NonAction] + public async Task InferNextPushContentOrNullAsync(int subSystemId, int customId, + int? trackContentId) + { + var data = await GetPushConfigAsync(subSystemId, customId); + if (!data.IsAutoPush) return null; + + if (trackContentId.HasValue) { - isPush = await _trackPushConfigQuery.GetFirstAsync(x => x.CustomId == customId, - x => x.IsAutoPush); - await RedisHelper.Client.SetAsync(RedisKey(customId), isPush); + if (data.ContentConfigs.Count > 1 && data.ContentConfigs.Any(x => x.TrackContentId == trackContentId)) + { + int index = data.ContentConfigs.FindIndex(x => x.TrackContentId == trackContentId); + if (index == data.ContentConfigs.Count - 1) return null; + int nextIndex = (index + 1) % data.ContentConfigs.Count; // 计算下一个索引,处理最后一个元素的情况 + + return data.ContentConfigs[nextIndex]; + } + + return null; } - return (bool)isPush; + return data.ContentConfigs.FirstOrDefault(); } - public async Task UpdateAsync(int customId, bool isPush) + [NonAction] + public async Task SetPushContentConfigsAsync(int? id = null, int? subSystemId = null, + int? customId = null) { - await RedisHelper.Client.SetAsync(RedisKey(customId), isPush); + var data = new TrackPushConfigDto { ContentConfigs = new() }; + + Expression> exp = x => true; + if (id.HasValue) exp = x => x.Id == id; + else if (subSystemId.HasValue && customId.HasValue) + exp = x => x.SubSystemId == subSystemId && x.CustomId == customId; + + var trackPushConfigEntity = await _trackPushConfigRepository.GetFirstAsync(exp); + if (trackPushConfigEntity == null) return data; + + var trackPushContentList = + await _trackPushConfigRepository.GetContentListAsync(x => x.TrackPushConfigId == trackPushConfigEntity.Id); + if (trackPushContentList.Count == 0) return data; + + trackPushContentList = trackPushContentList.OrderBy(x => x.Sort).ToList(); + + data.IsAutoPush = trackPushConfigEntity.IsAutoPush; + data.ContentConfigs = + ObjectMapper.Map, List>(trackPushContentList); + + await RedisHelper.Client.SetAsync( + TrackPushContentKey(trackPushConfigEntity.SubSystemId, trackPushConfigEntity.CustomId), data); + + return data; + } + + private async Task GetPushConfigAsync(int subSystemId, int customId) + { + var data = await RedisHelper.Client.GetAsync(TrackPushContentKey(subSystemId, customId)); + + data ??= await SetPushContentConfigsAsync(subSystemId: subSystemId, customId: customId); + + return data; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/TrackPush/TrackPushService.cs b/src/SJZY.Track.Application/Services/TrackPush/TrackPushService.cs index 1ecb8f41..712bbc3c 100644 --- a/src/SJZY.Track.Application/Services/TrackPush/TrackPushService.cs +++ b/src/SJZY.Track.Application/Services/TrackPush/TrackPushService.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Localization; +using System.Linq.Expressions; +using Microsoft.Extensions.Localization; using SJZY.Expand.ABP.Core.Localization; using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Track.Application.Contract.Dtos.TrackPush; @@ -9,9 +10,6 @@ using SJZY.Track.Domain.Aggregates.TrackPushAggregate; using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate; using SJZY.Track.Domain.Dtos.Common; using SJZY.Track.Domain.Dtos.TrackPush; -using SqlSugar; -using System.Linq.Expressions; -using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.Services.TrackPush; @@ -20,11 +18,10 @@ namespace SJZY.Track.Application.Services.TrackPush; /// [ApiExplorerSettings(GroupName = "轨迹推送")] [Route("/Track/PushConfig")] -public class TrackPushService : ApplicationService, ITransientDependency +public class TrackPushService : ApplicationService { private readonly IStringLocalizer _stringLocalizer; private readonly ITrackPushConfigRepository _trackPushConfigRepository; - private readonly ITrackTemplateRepository _trackTemplateRepository; private readonly ITrackPullConfigRepository _trackPullConfigRepository; private readonly ITrackPushCacheService _trackPushCacheService; @@ -37,7 +34,6 @@ public class TrackPushService : ApplicationService, ITransientDependency { _stringLocalizer = stringLocalizer; _trackPushConfigRepository = trackPushConfigRepository; - _trackTemplateRepository = trackTemplateRepository; _trackPullConfigRepository = trackPullConfigRepository; _trackPushCacheService = trackPushCacheService; } @@ -59,7 +55,8 @@ public class TrackPushService : ApplicationService, ITransientDependency /// /// [HttpPost("GetContentPage")] - public async Task> GetContentPageAsync([FromBody] GetTrackPushContentPageInputVO input) + public async Task> GetContentPageAsync( + [FromBody] GetTrackPushContentPageInputVO input) { return await _trackPushConfigRepository.GetContentPageAsync(input); } @@ -97,10 +94,11 @@ public class TrackPushService : ApplicationService, ITransientDependency if (input.Options != OptionTypeNoNull.删除) { Expression> isAnyExp = x => - x.SubSystemId == input.SubSystemId && x.CustomId == input.CustomId && x.ServiceProviderId == input.ServiceProviderId; + x.SubSystemId == input.SubSystemId && x.CustomId == input.CustomId; if (input.Options == OptionTypeNoNull.修改) isAnyExp = isAnyExp.And(x => x.Id != input.Id); - if (await _trackPushConfigRepository.IsAnyAsync(isAnyExp)) throw new BusinessException(message: _stringLocalizer["IsTrackPushConfigAny"]); + if (await _trackPushConfigRepository.IsAnyAsync(isAnyExp)) + throw new BusinessException(message: _stringLocalizer["IsTrackPushConfigAny"]); } switch (input.Options) @@ -108,7 +106,8 @@ public class TrackPushService : ApplicationService, ITransientDependency case OptionTypeNoNull.新增: { var trackPushEntity = ObjectMapper.Map(input); - var trackPushParamsEntity = ObjectMapper.Map(input); + var trackPushParamsEntity = + ObjectMapper.Map(input); using (var ts = TransactionScopeHelper.Create()) { @@ -117,8 +116,6 @@ public class TrackPushService : ApplicationService, ITransientDependency trackPushParamsEntity.PullOrPushConfigId = id; await _trackPullConfigRepository.InsertParamsAsync(trackPushParamsEntity); - if (input.IsAutoPush!.Value) await _trackPushCacheService.IsPushAsync(input.CustomId!.Value); - ts.Complete(); } } @@ -126,11 +123,14 @@ public class TrackPushService : ApplicationService, ITransientDependency case OptionTypeNoNull.修改: { - var oldTrackPushEntity = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == input.Id) ?? throw new BusinessException(message: _stringLocalizer["NotFindData"]); + var oldTrackPushEntity = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == input.Id) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); int oldCustomId = oldTrackPushEntity.CustomId; - var oldTrackPushParamsEntity = await _trackPullConfigRepository.GetParamsSingleAsync(x => x.PullOrPushConfigId == input.Id && x.IsPush); + var oldTrackPushParamsEntity = + await _trackPullConfigRepository.GetParamsSingleAsync(x => + x.PullOrPushConfigId == input.Id && x.IsPush); ObjectMapper.Map(input, oldTrackPushEntity); ObjectMapper.Map(input, oldTrackPushParamsEntity); @@ -140,24 +140,24 @@ public class TrackPushService : ApplicationService, ITransientDependency await _trackPushConfigRepository.UpdateAsync(oldTrackPushEntity); await _trackPullConfigRepository.UpdateParamsAsync(oldTrackPushParamsEntity); - await _trackPushCacheService.UpdateAsync(oldCustomId, false); - if (input.IsAutoPush!.Value) await _trackPushCacheService.IsPushAsync(input.CustomId!.Value); - ts.Complete(); } + + if (input.IsAutoPush!.Value) await _trackPushCacheService.SetPushContentConfigsAsync(input.Id); } break; case OptionTypeNoNull.删除: { - var oldTrackPushEntity = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == input.Id) ?? throw new BusinessException(message: _stringLocalizer["NotFindData"]); + var oldTrackPushEntity = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == input.Id) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); using (var ts = TransactionScopeHelper.Create()) { await _trackPushConfigRepository.SoftDeleteAsync(x => x.Id == input.Id); - await _trackPullConfigRepository.SoftDeleteParamsAsync(x => x.PullOrPushConfigId == input.Id && x.IsPush); + await _trackPullConfigRepository.SoftDeleteParamsAsync(x => + x.PullOrPushConfigId == input.Id && x.IsPush); await _trackPushConfigRepository.SoftDeleteContentAsync(x => x.TrackPushConfigId == input.Id); - await _trackPushCacheService.UpdateAsync(oldTrackPushEntity.CustomId, false); ts.Complete(); } @@ -182,18 +182,28 @@ public class TrackPushService : ApplicationService, ITransientDependency { if (input.Options != OptionTypeNoNull.删除) { - Expression> isContentAnyExp = x => x.TrackPushConfigId == input.TrackPushConfigId; + Expression> isContentAnyExp = x => + x.TrackPushConfigId == input.TrackPushConfigId; if (input.Options == OptionTypeNoNull.修改) isContentAnyExp = isContentAnyExp.And(x => x.Id != input.Id); - if (await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackContentId == input.TrackContentId))) + if (await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackContentId == input.TrackContentId))) throw new BusinessException(message: _stringLocalizer["IsTrackPushContentAny"]); - else if (!input.TrackContentCodeValue.IsNullOrWhiteSpace() && await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackContentCodeValue == input.TrackContentCodeValue))) + else if (!input.TrackContentCodeValue.IsNullOrWhiteSpace() && + await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackContentCodeValue == input.TrackContentCodeValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPushContentCodeValueAny"]); - else if (!input.TrackStatusValue.IsNullOrWhiteSpace() && await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackStatusValue == input.TrackStatusValue))) + else if (!input.TrackStatusValue.IsNullOrWhiteSpace() && + await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackStatusValue == input.TrackStatusValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPushContentStatusValueAny"]); - else if (!input.TrackContentValue.IsNullOrWhiteSpace() && await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackContentValue == input.TrackContentValue))) + else if (!input.TrackContentValue.IsNullOrWhiteSpace() && + await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackContentValue == input.TrackContentValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPushContentValueAny"]); - else if (!input.TrackEnContentValue.IsNullOrWhiteSpace() && await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => x.TrackEnContentValue == input.TrackEnContentValue))) + else if (!input.TrackEnContentValue.IsNullOrWhiteSpace() && + await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x => + x.TrackEnContentValue == input.TrackEnContentValue))) throw new BusinessException(message: _stringLocalizer["IsTrackPushEnContentValueAny"]); } @@ -201,40 +211,47 @@ public class TrackPushService : ApplicationService, ITransientDependency { case OptionTypeNoNull.新增: { - int maxSort = await _trackPushConfigRepository.ContentMaxAsync(x => x.Sort, x => x.TrackPushConfigId == input.TrackPushConfigId); + int maxSort = await _trackPushConfigRepository.ContentMaxAsync(x => x.Sort, + x => x.TrackPushConfigId == input.TrackPushConfigId); var entity = ObjectMapper.Map(input); entity.Sort = maxSort + 1; await _trackPushConfigRepository.InsertContentAsync(entity); + await _trackPushCacheService.SetPushContentConfigsAsync(input.TrackPushConfigId); break; } case OptionTypeNoNull.修改: { - var entity = await _trackPushConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? throw new BusinessException(message: _stringLocalizer["NotFindData"]); + var entity = await _trackPushConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); ObjectMapper.Map(input, entity); await _trackPushConfigRepository.UpdateContentAsync(entity); + await _trackPushCacheService.SetPushContentConfigsAsync(entity.TrackPushConfigId); break; } case OptionTypeNoNull.删除: { - var entity = await _trackPushConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? throw new BusinessException(message: _stringLocalizer["NotFindData"]); + var entity = await _trackPushConfigRepository.GetContentByIdAsync(input.Id!.Value) ?? + throw new BusinessException(message: _stringLocalizer["NotFindData"]); using (var ts = TransactionScopeHelper.Create()) { await _trackPushConfigRepository.SoftDeleteContentAsync(x => x.Id == input.Id); - - await _trackPushConfigRepository.UpdateContentAsync(x => x.Sort == x.Sort - 1, x => x.TrackPushConfigId == entity.TrackPushConfigId && x.Sort > entity.Sort); + await _trackPushConfigRepository.UpdateContentAsync(x => x.Sort == x.Sort - 1, + x => x.TrackPushConfigId == entity.TrackPushConfigId && x.Sort > entity.Sort); ts.Complete(); } + await _trackPushCacheService.SetPushContentConfigsAsync(entity.TrackPushConfigId); + break; } @@ -263,7 +280,11 @@ public class TrackPushService : ApplicationService, ITransientDependency item.Sort = input.SortInfo.Single(x => x.Key == item.Id.ToString()).Value; }); - await _trackPushConfigRepository.UpdateContentRangeAsync(trackPushContentEntities); + if (trackPushContentEntities.Count > 0) + { + await _trackPushConfigRepository.UpdateContentRangeAsync(trackPushContentEntities); + await _trackPushCacheService.SetPushContentConfigsAsync(trackPushContentEntities[0].TrackPushConfigId); + } return true; } diff --git a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs index 9e8d59eb..acc0d4de 100644 --- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs +++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/IOrderRepository.cs @@ -11,13 +11,6 @@ public interface IOrderRepository : IBasicRepository /// Task CreateOrderAsync(OrderEntity order); - /// - /// 获取分页的轨迹订单 - /// - /// - /// - Task> GetPageTrackOrder(GetPageTrackOrderInputVO input); - /// /// 更新订单 /// @@ -57,12 +50,4 @@ public interface IOrderRepository : IBasicRepository Task UnLinkByIdsAsync(List linkIds); #endregion - - - /// - /// 获取订单模板列表 - /// - /// - /// - Task> GetOrderTemplatesAsync(List orderNos); } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs index 66f704a3..2553cb31 100644 --- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs +++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs @@ -43,10 +43,16 @@ public class OrderEntity : IFullAuditedBasicEntitys, IAggregateRoot public bool IsCompleted { get; set; } /// - /// 订单是否推送完成(异步维护) + /// 最新推送轨迹内容id(异步维护) /// - [SugarColumn(ColumnName = "IsPushCompleted")] - public bool IsPushCompleted { get; set; } + [SugarColumn(ColumnName = "LatestPushTrackContentId")] + public int? LatestPushTrackContentId { get; set; } + + /// + /// 最新推送时间(异步维护) + /// + [SugarColumn(ColumnName = "LatestPushTime")] + public DateTime? LatestPushTime { get; set; } /// /// 最新轨迹内容(异步维护) @@ -112,13 +118,13 @@ public class OrderEntity : IFullAuditedBasicEntitys, IAggregateRoot /// 问题类型(主数据枚举TrackQuestionType) /// [SugarColumn(ColumnName = "QuestionType")] - public int QuestionType { get; set; } + public int QuestionType { get; set; } /// - /// 问题描述(主数据枚举TrackProblemDescription) + /// 问题描述 /// [SugarColumn(ColumnName = "ProblemDescription")] - public int ProblemDescription { get; set; } + public string? ProblemDescription { get; set; } /// /// 起运港口 diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs index 34cdac01..acd0ed4e 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/ITrackDetailsRepository.cs @@ -10,6 +10,8 @@ public interface ITrackDetailsRepository Task> GetListAsync(int orderType, List orderNos); + Task> GetListAsync(int orderType, List orderNos, string trackCode); + Task<(List list, long total)> GetListAsync(TrackDetailsQueryInput input); Task> GetListAsync(int orderId); @@ -21,8 +23,6 @@ public interface ITrackDetailsRepository /// Task DeleteTrackAsync(int orderId, List trackCodes); - Task?> GetListAsync(List orderIds); - /// /// 获取最近一条发生的轨迹 /// diff --git a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs index d5909320..43721588 100644 --- a/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs +++ b/src/SJZY.Track.Domain/Aggregates/TrackDetailsAggregate/TrackDetailsIndex.cs @@ -1,5 +1,6 @@ using Nest; using SJZY.Expand.ElasticSearch; +using SJZY.Track.Domain.Consts; namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; @@ -31,11 +32,6 @@ public class TrackDetailsIndex : IdBaseIndex /// public string TrackStatus { get; set; } = null!; - /// - /// 原轨迹状态 - /// - public string? OriginTrackStatus { get; set; } - /// /// 轨迹内容代码 /// @@ -47,10 +43,20 @@ public class TrackDetailsIndex : IdBaseIndex public string TrackContent { get; set; } = null!; /// - /// 是否意味着完成 + /// 轨迹内容Id + /// + public int TrackContentId { get; set; } + + /// + /// 这条轨迹是否意味着完成(删除回退需要用到) /// public bool IsCompleted { get; set; } + /// + /// 原轨迹状态 + /// + public string? OriginTrackStatus { get; set; } + /// /// 原轨迹内容 /// diff --git a/src/SJZY.Track.Domain/Aggregates/TrackPushAggregate/ITrackPushRecordsRepository.cs b/src/SJZY.Track.Domain/Aggregates/TrackPushAggregate/ITrackPushRecordsRepository.cs new file mode 100644 index 00000000..e8115b13 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/TrackPushAggregate/ITrackPushRecordsRepository.cs @@ -0,0 +1,18 @@ +namespace SJZY.Track.Domain.Aggregates.TrackPushAggregate; + +public interface ITrackPushRecordsRepository +{ + /// + /// 添加推送记录 + /// + /// + /// + Task AddAsync(TrackPushRecordIndex index); + + /// + /// 获取轨迹推送记录 + /// + /// + /// + Task> GetTrackPushRecordsAsync(int orderId); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/TrackPushAggregate/TrackPushRecordIndex.cs b/src/SJZY.Track.Domain/Aggregates/TrackPushAggregate/TrackPushRecordIndex.cs new file mode 100644 index 00000000..0d178b45 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/TrackPushAggregate/TrackPushRecordIndex.cs @@ -0,0 +1,100 @@ +using Nest; +using SJZY.Expand.ElasticSearch; +using SJZY.Track.Domain.Consts; + +namespace SJZY.Track.Domain.Aggregates.TrackPushAggregate; + +[ElasticsearchType(RelationName = GlobalConst.TrackPushRecordsIndex)] +public class TrackPushRecordIndex : IdBaseIndex +{ + /// + /// 索引名称 + /// + public string IndexName { get; set; } = null!; + + /// + /// 订单Id + /// + public int OrderId { get; set; } + + /// + /// 接口通请求Id + /// + public Guid RequestId { get; set; } + + /// + /// 信息 + /// + public string Message { get; set; } = null!; + + /// + /// 操作类型 + /// + public string OptionType { get; set; } = null!; + + /// + /// 轨迹状态 + /// + public string TrackStatus { get; set; } = null!; + + /// + /// 轨迹内容代码 + /// + public string TrackCode { get; set; } = null!; + + /// + /// 轨迹内容 + /// + public string TrackContent { get; set; } = null!; + + /// + /// 轨迹发生地 + /// + public string TrackPlace { get; set; } = null!; + + /// + /// 轨迹发生时间 + /// + public DateTime TrackTime { get; set; } + + /// + /// 轨迹发生时区 + /// + public float TrackTimeZone { get; set; } + + /// + /// 是否成功 + /// + public bool IsSuccess { get; set; } + + /// + /// 轨迹代码参数值 + /// + public string? TrackContentCodeValue { get; set; } + + /// + /// 轨迹内容参数值 + /// + public string? TrackContentValue { get; set; } + + /// + /// 轨迹内容英文参数值 + /// + public string? TrackEnContentValue { get; set; } + + /// + /// 轨迹状态参数值 + /// + public string? TrackStatusValue { get; set; } + + /// + /// 扩展字段参数值 + /// + public string? ExpandFieldsValue { get; set; } + + /// 创建人 + public string? CreateUser { get; set; } + + /// 创建时间 + public DateTime CreateTime { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs new file mode 100644 index 00000000..3dd246c4 --- /dev/null +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs @@ -0,0 +1,14 @@ +namespace SJZY.Track.Domain.Consts; + +public partial class GlobalConst +{ + /// + /// 轨迹明细 es索引名称(模板) + /// + public const string TrackIndex = "sjzy_track_details"; + + /// + /// 轨迹推送记录 es索引名称(模板) + /// + public const string TrackPushRecordsIndex = "sjzy_track_push_records"; +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs new file mode 100644 index 00000000..d9dfd74b --- /dev/null +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.MQ.cs @@ -0,0 +1,39 @@ +namespace SJZY.Track.Domain.Consts; + +public partial class GlobalConst +{ + /// + /// 轨迹新增/更新 + /// + public const string TrackUpsertSubscribe = "SJZY.Track.TrackUpsert"; + + /// + /// 轨迹删除 + /// + public const string TrackDeleteSubscribe = "SJZY.Track.TrackDelete"; + + /// + /// 接口通批量轨迹刷新 + /// + public const string TrackRefreshSubscribe = "SJZY.Track.TrackRefresh"; + + /// + /// 轨迹推送 + /// + public const string TrackPushSubscribe = "SJZY.Track.TrackPush"; + + /// + /// 轨迹新增/更新后触发更新订单主表 + /// + public const string TrackUpsertAfterUpdateOrderSubscribe = "SJZY.Track.TrackUpsertAfterUpdateOrder"; + + /// + /// 轨迹推送后触发更新订单主表 + /// + public const string TrackPushAfterUpdateOrderSubscribe = "SJZY.Traack.TrackPushAfterUpdateOrder"; + + /// + /// 关联订单后补轨迹 + /// + public const string OrderLinkAfterFillTrack = "SJZY.Track.OrderLinkAfterFillTrack"; +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs new file mode 100644 index 00000000..e2ca18ae --- /dev/null +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs @@ -0,0 +1,24 @@ +namespace SJZY.Track.Domain.Consts; + +public partial class GlobalConst +{ + /// + /// 轨迹要推送的客户redis key前缀 + /// + public const string TrackPushKeyPrefix = "TrackPush"; + + /// + /// 轨迹推送内容配置redis key前缀 + /// + public const string TrackPushContentKeyPrefix = "TrackPushContent"; + + /// + /// 轨迹拉取配置信息redis key前缀 + /// + public const string TrackPullKeyPrefix = "TrackPull"; + + /// + /// 轨迹拉取配置信息redis key前缀 + /// + public const string TrackPullContentKeyPrefix = "TrackPullContent"; +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Consts/InterfaceRelayConst.cs b/src/SJZY.Track.Domain/Consts/InterfaceRelayConst.cs new file mode 100644 index 00000000..24743a5b --- /dev/null +++ b/src/SJZY.Track.Domain/Consts/InterfaceRelayConst.cs @@ -0,0 +1,27 @@ +namespace SJZY.Track.Domain.Consts; + +/// +/// 接口通常量 +/// +public class InterfaceRelayConst +{ + /// + /// 接口通成功代码 + /// + public const string SuccessCode = "200"; + + /// + /// 获取轨迹接口代码 + /// + public const string GetTrackInterfaceCode = "A012"; + + /// + /// 推送轨迹接口代码 + /// + public const string PushTrackInterfaceCode = "A024"; + + /// + /// 更新轨迹接口代码 + /// + public const string TrackUpdateInterfaceCode = "A040"; +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Order/GetPageTrackOrderInputVO.cs b/src/SJZY.Track.Domain/Dtos/Order/GetPageTrackOrderInputVO.cs index 20589812..5f164841 100644 --- a/src/SJZY.Track.Domain/Dtos/Order/GetPageTrackOrderInputVO.cs +++ b/src/SJZY.Track.Domain/Dtos/Order/GetPageTrackOrderInputVO.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SJZY.Track.Domain.Dtos.Order +namespace SJZY.Track.Domain.Dtos.Order { public class GetPageTrackOrderInputVO : PageInfoInput { @@ -13,17 +7,11 @@ namespace SJZY.Track.Domain.Dtos.Order /// public int SubSystemId { get; set; } - ///// - ///// 单号 - ///// - //public List? OrderNos { get; set; } - /// - /// 当tab选中 0 默认不传 1 直接写死传值 [1,4] 2 传 [2,4] + /// 当tab选中 0 全部 1 异常 2 警告 /// public int TabType { get; set; } - /// /// 订单类型 /// @@ -34,10 +22,15 @@ namespace SJZY.Track.Domain.Dtos.Order /// public int? CustomerId { get; set; } + ///// + ///// 单号 + ///// + //public string? OrderNos { get; set; } + /// /// 单号 /// - public string? OrderNos { get; set; } + public List? OrderNos { get; set; } /// /// 创建时间开始 @@ -93,7 +86,7 @@ namespace SJZY.Track.Domain.Dtos.Order /// /// 客户id /// - public int CustomerId { get; set; } + public int CustomerId { get; set; } ///// ///// 订单明细(json) @@ -133,7 +126,7 @@ namespace SJZY.Track.Domain.Dtos.Order /// /// 子系统 /// - public string SubSystem { get; set; } + public string? SubSystem { get; set; } /// /// 子系统id @@ -154,15 +147,5 @@ namespace SJZY.Track.Domain.Dtos.Order /// 问题类型名称 /// public string? QuestionTypeName { get; set; } - - /// - /// 问题描述(主数据枚举TrackProblemDescription) - /// - public int ProblemDescription { get; set; } - - /// - /// 问题描述名称 - /// - public string? ProblemDescriptionName { get; set; } } -} +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Order/GetTrackCounterVO.cs b/src/SJZY.Track.Domain/Dtos/Order/GetTrackCounterVO.cs new file mode 100644 index 00000000..67cc8496 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Order/GetTrackCounterVO.cs @@ -0,0 +1,14 @@ +namespace SJZY.Track.Domain.Dtos.Order; + +public class GetTrackCounterVO +{ + /// + /// 问题类型 + /// + public int ProblemType { get; set; } + + /// + /// 总条数 + /// + public int Count { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Order/LinkedOrderVO.cs b/src/SJZY.Track.Domain/Dtos/Order/LinkedOrderVO.cs index c0344880..2e0ffbed 100644 --- a/src/SJZY.Track.Domain/Dtos/Order/LinkedOrderVO.cs +++ b/src/SJZY.Track.Domain/Dtos/Order/LinkedOrderVO.cs @@ -6,7 +6,7 @@ public class LinkedOrderVO /// 关联订单id /// public int OrderId { get; set; } - + /// /// 订单号 /// @@ -21,14 +21,19 @@ public class LinkedOrderVO /// 子系统id /// public int SubSystemId { get; set; } - + /// - /// 订单是否推送完成(异步维护) + /// 最新推送轨迹内容id(异步维护) /// - public bool IsPushCompleted { get; set; } - + public int? LatestPushTrackContentId { get; set; } + /// /// 客户id /// public int CustomId { get; set; } + + /// + /// 订单是否完成 + /// + public bool IsCompleted { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Order/OrderTemplateVO.cs b/src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs similarity index 87% rename from src/SJZY.Track.Domain/Dtos/Order/OrderTemplateVO.cs rename to src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs index 6fe7d2b5..df193e03 100644 --- a/src/SJZY.Track.Domain/Dtos/Order/OrderTemplateVO.cs +++ b/src/SJZY.Track.Domain/Dtos/Order/OrderWithServiceProviderVO.cs @@ -1,6 +1,6 @@ namespace SJZY.Track.Domain.Dtos.Order; -public class OrderTemplateVO +public class OrderWithServiceProviderVO { public string OrderNo { get; set; } = null!; @@ -9,8 +9,6 @@ public class OrderTemplateVO /// public int OrderType { get; set; } - public int TemplateId { get; set; } - public int ServiceProviderId { get; set; } /// diff --git a/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs b/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs index adb51944..e0213b5e 100644 --- a/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs +++ b/src/SJZY.Track.Domain/Dtos/TrackDetails/MatchTrackContentDto.cs @@ -2,6 +2,11 @@ public class MatchTrackContentDto { + /// + /// 轨迹内容id + /// + public int Id { get; set; } + /// /// 轨迹内容 /// diff --git a/src/SJZY.Track.Domain/Enums/OrderType.cs b/src/SJZY.Track.Domain/Enums/OrderType.cs new file mode 100644 index 00000000..79a97c52 --- /dev/null +++ b/src/SJZY.Track.Domain/Enums/OrderType.cs @@ -0,0 +1,18 @@ +using System.ComponentModel; + +namespace SJZY.Track.Domain.Enums; + +public enum OrderType +{ + [Description("干线提单")] + 干线提单 = 1, + + [Description("小包运单")] + 小包运单 = 2, + + [Description("箱/袋单")] + 箱袋单 = 3, + + [Description("FBA订单")] + FBA订单 = 4, +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Enums/TrackProblemType.cs b/src/SJZY.Track.Domain/Enums/TrackProblemType.cs new file mode 100644 index 00000000..92369b84 --- /dev/null +++ b/src/SJZY.Track.Domain/Enums/TrackProblemType.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace SJZY.Track.Domain.Enums; + +[Flags] +public enum TrackProblemType +{ + /// + /// 没问题 + /// + [Description("无")] + None = 0, + + /// + /// 异常 + /// + [Description("异常")] + Error = 1, + + /// + /// 预警 + /// + [Description("预警")] + Warn = 2, +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/GlobalConst.cs b/src/SJZY.Track.Domain/GlobalConst.cs deleted file mode 100644 index 629149a8..00000000 --- a/src/SJZY.Track.Domain/GlobalConst.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace SJZY.Track.Domain; - -public class GlobalConst -{ - /// - /// 轨迹明细 es索引名称 - /// - public const string TrackIndex = "sjzy_track_details"; - - /// - /// 轨迹新增/更新 mq订阅名称 - /// - public const string TrackUpsertSubscribe = "SJZY.Track.TrackUpsert"; - - /// - /// 轨迹删除 mq订阅名称 - /// - public const string TrackDeleteSubscribe = "SJZY.Track.TrackDelete"; - - /// - /// 接口通批量轨迹刷新 mq订阅名称 - /// - public const string TrackRefreshSubscribe = "SJZY.Track.TrackRefresh"; - - /// - /// 轨迹新增/更新后触发更新订单轨迹 mq订阅名称 - /// - public const string UpdateOrderTrackSubscribe = "SJZY.Track.UpdateOrderTrack"; - - /// - /// 轨迹删除后触发更新订单轨迹 mq订阅名称 - /// - public const string DeleteTrackAfterUpdateOrderSubscribe = "SJZY.Track.DeleteTrackAfterUpdateOrder"; - - /// - /// 关联订单后补轨迹 mq订阅名称 - /// - public const string OrderLinkAfterFillTrack = "SJZY.Track.OrderLinkAfterFillTrack"; - - /// - /// 轨迹要推送的客户redis key前缀 - /// - public const string TrackPushKeyPrefix = "TrackPush:"; - - /// - /// 轨迹拉取配置信息redis key前缀 - /// - public const string TrackPullConfigInfoKeyPrefix = "TrackPullConfigInfo:"; -} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Queries/IProvideQueries.cs b/src/SJZY.Track.Domain/Queries/IProvideQueries.cs index a3f8450c..2795df48 100644 --- a/src/SJZY.Track.Domain/Queries/IProvideQueries.cs +++ b/src/SJZY.Track.Domain/Queries/IProvideQueries.cs @@ -48,4 +48,18 @@ public interface IProvideQueries /// /// Task> MapTrackCodesAsync(int upSubSystemId, int subSystemId, params string[] trackCodes); + + /// + /// 根据订单模板找对应服务商 + /// + /// + /// + Task> FindOrderWithServiceProviderAsync(List orderNos); + + /// + /// 获取服务商下所有单(未完成的) + /// + /// + /// + Task> FindOrderWithServiceProviderAsync(int serviceProvider); } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Queries/ITrackOrderQueries.cs b/src/SJZY.Track.Domain/Queries/ITrackOrderQueries.cs new file mode 100644 index 00000000..b521d97d --- /dev/null +++ b/src/SJZY.Track.Domain/Queries/ITrackOrderQueries.cs @@ -0,0 +1,19 @@ +using SJZY.Track.Domain.Dtos.Order; + +namespace SJZY.Track.Domain.Queries; + +public interface ITrackOrderQueries +{ + /// + /// 获取分页的轨迹订单 + /// + /// + /// + Task> GetPageTrackOrder(GetPageTrackOrderInputVO input); + + /// + /// 获取轨迹各个问题数 + /// + /// + Task> GetTrackProblemCountsAsync(); +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs index a84a28f5..5bf07b06 100644 --- a/src/SJZY.Track.Repository/Queries/ProvideQueries.cs +++ b/src/SJZY.Track.Repository/Queries/ProvideQueries.cs @@ -6,6 +6,7 @@ using SJZY.Track.Domain.Dtos.Order; using SJZY.Track.Domain.Dtos.TrackDetails; using SJZY.Track.Domain.Dtos.TrackTemplate; using SJZY.Track.Domain.Queries; +using SJZY.Track.Domain.VEntities; namespace SJZY.Track.Repository.Queries; @@ -70,6 +71,7 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, .Where((x, a, b) => x.OrderId == orderId && b.Code == code) .Select((x, a, b, c) => new MatchTrackContentDto { + Id = b.Id, Content = b.Content, EnContent = b.EnContent, Status = c.Status, @@ -104,4 +106,39 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, .Select(x => x.TrackContentCode) .ToListAsync(); } + + + public async Task> FindOrderWithServiceProviderAsync(List orderNos) + { + return await Context.Queryable() + .LeftJoin((a, b) => a.Id == b.OrderId) + .LeftJoin((a, b, c) => b.ServiceProviderId == c.Id) + .Where(a => !a.IsCompleted && orderNos.Contains(a.OrderNo)) + .Select((a, b, c) => new OrderWithServiceProviderVO + { + OrderNo = a.OrderNo, + OrderType = a.OrderType, + ServiceProviderId = b.ServiceProviderId, + ServiceProviderCode = c.Code, + SubSystemId = a.SubSystemId + }) + .ToListAsync(); + } + + public async Task> FindOrderWithServiceProviderAsync(int serviceProvider) + { + return await Context.Queryable() + .RightJoin((a, b) => a.Id == b.OrderId) + .LeftJoin((a, b, c) => b.ServiceProviderId == c.Id) + .Where((a, b) => b.ServiceProviderId == serviceProvider && !a.IsCompleted) + .Select((a, b, c) => new OrderWithServiceProviderVO + { + OrderNo = a.OrderNo, + OrderType = a.OrderType, + ServiceProviderId = b.ServiceProviderId, + ServiceProviderCode = c.Code, + SubSystemId = a.SubSystemId + }) + .ToListAsync(); + } } \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Queries/TrackOrderQueries.cs b/src/SJZY.Track.Repository/Queries/TrackOrderQueries.cs new file mode 100644 index 00000000..8d9d2504 --- /dev/null +++ b/src/SJZY.Track.Repository/Queries/TrackOrderQueries.cs @@ -0,0 +1,95 @@ +using SJZY.Track.Domain.Aggregates.OrderAggregate; +using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate; +using SJZY.Track.Domain.Dtos.Order; +using SJZY.Track.Domain.Queries; +using SJZY.Track.Domain.VEntities; +using SJZY.Track.Repository.VData.Entitys; + +namespace SJZY.Track.Repository.Queries; + +public class TrackOrderQueries : ISugarRepository, ITrackOrderQueries, + ITransientDependency +{ + public ISqlSugarClient Context { get; set; } + + public TrackOrderQueries() + { + Context = SqlsugarScopeBasic.GetContextSafely("default"); + } + + /// + /// 获取分页的轨迹订单 + /// + /// + /// + public async Task> GetPageTrackOrder(GetPageTrackOrderInputVO input) + { + var pageList = await Context.Queryable() + .LeftJoin((a, b) => a.CustomId == b.Id && b.IsDeleted == false) + .LeftJoin((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false) + .WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId) + .WhereIF(!input.OrderNos.IsNullOrEmpty(), (a, b, c) => input.OrderNos!.Contains(a.OrderNo)) + .WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue, + (a, b, c) => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd) + .WhereIF(input.CreateTimeStart.HasValue && (!input.CreateTimeEnd.HasValue), + (a, b, c) => a.CreateTime >= input.CreateTimeStart) + .WhereIF((!input.CreateTimeStart.HasValue) && input.CreateTimeEnd.HasValue, + (a, b, c) => a.CreateTime <= input.CreateTimeEnd) + .WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId) + .WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType) + .WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType) + .OrderByDescending((a, b, c) => a.CreateTime) + .Select((a, b, c) => new TrackOrderVO + { + Id = a.Id, + OrderNumber = a.OrderNo, + OrderType = a.OrderType, + QuestionType = a.QuestionType, + CustomerShortName = b.Abbreviation, + CustomerCode = b.Code, + CustomerId = a.CustomId, + NewestTrackContent = a.LatestTrackContent, + NewestTrackEnContent = a.LatestTrackEnContent, + NewestTrackPlace = a.LatestTrackPlace, + NewestTrackTime = a.LatestTrackTime, + IsFinish = a.IsCompleted, + CreateTime = a.CreateTime, + SubSystem = c.CnName, + SubSystemId = c.Id + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + + if (pageList.List.Any()) + { + //查询也需要最新的轨迹 + var orderIds = pageList.List.Select(a => a.Id).ToList(); + //查询轨迹模版 + var trackTemplateList = await Context.Queryable() + .LeftJoin((a, b) => a.TrackTemplateId == b.Id) + .Where((a, b) => orderIds.Contains(a.OrderId)) + .Select((a, b) => new { a.OrderId, b.Name, TemplateId = b.Id }) + .ToListAsync(); + pageList.List.ForEach(a => + { + a.TrackTemplateNames = trackTemplateList.Where(b => b.OrderId == a.Id).Select(x => x.Name) + .JoinAsString(","); + a.TrackTemplateIds = trackTemplateList.Where(b => b.OrderId == a.Id).Where(b => b.TemplateId > 0) + .Select(x => x.TemplateId).ToList(); + }); + } + + return pageList; + } + + public async Task> GetTrackProblemCountsAsync() + { + return await Context.Queryable() + .GroupBy(x => x.QuestionType) + .Select(x => new GetTrackCounterVO + { + ProblemType = x.QuestionType, + Count = SqlFunc.AggregateCount(1) + }) + .ToListAsync(); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs index e160ec0b..26a8ed2b 100644 --- a/src/SJZY.Track.Repository/Repositories/OrderRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/OrderRepository.cs @@ -1,25 +1,11 @@ using SJZY.Track.Domain; using SJZY.Track.Domain.Aggregates.OrderAggregate; -using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; -using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate; using SJZY.Track.Domain.Dtos.Order; -using SJZY.Track.Domain.VEntities; -using SJZY.Track.Repository.VData.Entitys; -using SqlSugar; namespace SJZY.Track.Repository.Repositories; public class OrderRepository : BasicRepository, IOrderRepository, ITransientDependency { - private readonly ITrackDetailsRepository _trackDetailsRepository; - - public OrderRepository( - ITrackDetailsRepository trackDetailsRepository - ) - { - this._trackDetailsRepository = trackDetailsRepository; - } - public async Task CreateOrderAsync(OrderEntity order) { using var tran = TransactionHelper.GetReadCommitted(); @@ -80,8 +66,9 @@ public class OrderRepository : BasicRepository, IOrderRepository, I OrderType = b.OrderType, OrderNo = b.OrderNo, SubSystemId = b.SubSystemId, - IsPushCompleted = b.IsPushCompleted, - CustomId = b.CustomId + LatestPushTrackContentId = b.LatestPushTrackContentId, + CustomId = b.CustomId, + IsCompleted = b.IsCompleted }) .ToListAsync(); } @@ -97,185 +84,4 @@ public class OrderRepository : BasicRepository, IOrderRepository, I } #endregion - - #region 轨迹订单明细 - - ///// - ///// 根据轨迹订单id获取轨迹明细列表 - ///// - ///// - ///// - //public async Task> GetOrderDetails(GetOrderDetailsInputVO input) - //{ - // return null; - //} - - #endregion - - #region 轨迹订单分页 - - /// - /// 获取分页的轨迹订单 - /// - /// - /// - public async Task> GetPageTrackOrder(GetPageTrackOrderInputVO input) - { - List orderNoList = new List(); - List questionTypeIds = new List(); - int ques = 0; - if (!input.OrderNos.IsNullOrWhiteSpace()) - { - orderNoList = input.OrderNos.Split(new char[] { ',', ',', ':', ':' }).ToList(); - } - if (input.TabType==1) - { - questionTypeIds= new List { 1, 4 }; - ques = questionTypeIds.Sum(); - } - else if (input.TabType==2) - { - questionTypeIds= new List { 2, 4 }; - ques = questionTypeIds.Sum(); - } - - var pageList = await Context.Queryable() - .LeftJoin((a, b) => a.CustomId == b.Id && b.IsDeleted == false) - .LeftJoin((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false) - .WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId) - .WhereIF(!orderNoList.IsNullOrEmpty(), (a, b, c) => orderNoList.Contains(a.OrderNo)) - .WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue, - (a, b, c) => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd) - .WhereIF(input.CreateTimeStart.HasValue && (!input.CreateTimeEnd.HasValue), - (a, b, c) => a.CreateTime >= input.CreateTimeStart) - .WhereIF((!input.CreateTimeStart.HasValue) && input.CreateTimeEnd.HasValue, - (a, b, c) => a.CreateTime <= input.CreateTimeEnd) - .WhereIF(input.CustomerId>0, (a, b, c) => a.CustomId==input.CustomerId) - .WhereIF(input.TrackOrderType>0, (a, b, c) => a.OrderType==input.TrackOrderType) - .WhereIF(input.TabType>0 && (!questionTypeIds.IsNullOrEmpty()), (a, b, c) => (a.QuestionType&ques)>0) - .OrderByDescending((a, b, c) => a.CreateTime) - .Select((a, b, c) => new TrackOrderVO - { - Id = a.Id, - OrderNumber = a.OrderNo, - OrderType = a.OrderType, - OrderTypeName = SqlFunc.IF(a.OrderType == 1).Return("干线提单").ElseIF(a.OrderType == 2).Return("小包运单") - .ElseIF(a.OrderType == 3) - .Return("箱/袋单").ElseIF(a.OrderType == 4).Return("FBA订单").End(""), - CustomerShortName = b.Abbreviation, - CustomerCode = b.Code, - CustomerId = a.CustomId, - QuestionType = a.QuestionType, - QuestionTypeName = SqlFunc.IF(a.QuestionType == 1).Return("异常").ElseIF(a.QuestionType == 2).Return("预警").End(""), - ProblemDescription = a.ProblemDescription, - ProblemDescriptionName =SqlFunc.IF(a.ProblemDescription == 1).Return("推送异常").ElseIF(a.ProblemDescription == 2).Return("推送预警").End(""), - //TrackTemplateNames = SqlFunc.Subqueryable() - // .LeftJoin((aa, bb) => aa.TrackTemplateId == bb.Id) - // .Where((aa, bb) => a.Id == aa.OrderId).SelectStringJoin((aa, bb) => bb.Name, ","), - - //TrackTemplateIds = SqlFunc.Subqueryable() - // .LeftJoin((aa, bb) => aa.TrackTemplateId == bb.Id) - // .Where((aa, bb) => a.Id == aa.OrderId).SelectStringJoin((aa, bb) => bb.Id, ","), - NewestTrackContent = a.LatestTrackContent, - NewestTrackEnContent = a.LatestTrackEnContent, - NewestTrackPlace = a.LatestTrackPlace, - NewestTrackTime = a.LatestTrackTime, - IsFinish = a.IsCompleted, - CreateTime = a.CreateTime, - SubSystem = c.CnName, - SubSystemId = c.Id - }) - .ToPagedListAsync(input.PageIndex, input.PageSize); - - if (pageList.List.Any()) - { - //查询也需要最新的轨迹 - var orderIds = pageList.List.Select(a => a.Id).ToList(); - //查询轨迹模版 - var trackTemplateList = await Context.Queryable() - .LeftJoin((a, b) => a.TrackTemplateId == b.Id) - .Where((a, b) => orderIds.Contains(a.OrderId)) - .Select((a, b) => new { OrderId = a.OrderId, Name = b.Name, TemplateId = b.Id }) - .ToListAsync(); - var esTrackDetails = await _trackDetailsRepository.GetListAsync(orderIds); - pageList.List.ForEach(a => - { - var esDetails = esTrackDetails?.Where(b => b.OrderId == a.Id).OrderByDescending(b => b.TrackTime); - var trackDetail = esDetails?.FirstOrDefault(); - if (trackDetail != null) - { - if (trackDetail.TrackContent != a.NewestTrackContent) - { - a.NewestTrackContent = trackDetail.TrackContent; - } - - if (trackDetail.TrackEnContent != a.NewestTrackEnContent) - { - a.NewestTrackEnContent = trackDetail.TrackEnContent; - } - - if (trackDetail.TrackPlace != a.NewestTrackPlace) - { - a.NewestTrackPlace = trackDetail.TrackPlace; - } - - if (trackDetail.TrackTime != a.NewestTrackTime) - { - a.NewestTrackTime = trackDetail.TrackTime; - } - } - - a.TrackTemplateNames = trackTemplateList.Where(b => b.OrderId == a.Id).Select(a => a.Name) - .JoinAsString(","); - a.TrackTemplateIds = trackTemplateList.Where(b => b.OrderId == a.Id).Where(b => b.TemplateId>0).Select(a => a.TemplateId).ToList(); - }); - } - - - #region 暂时注释 - - //if (pageList.List.Any()) - //{ - // var orderIds = pageList.List.Select(a => a.Id); - // //查询轨迹模版 - - - // var trackTemplateList = await Context.Queryable() - // .LeftJoin((a, b) => a.TrackTemplateId==b.Id) - // .Where((a, b) => orderIds.Contains(a.OrderId)) - // .Select((a, b) => new { OrderId = a.OrderId, Name = b.Name }) - // .ToListAsync(); - - // pageList.List.ForEach(a => - // { - // var templateListOfOrderId = trackTemplateList.Where(b => b.OrderId== a.Id); - // a.TrackTemplateNames = templateListOfOrderId.Select(c => c.Name).JoinAsString(","); - // }); - //} - - #endregion - - return pageList; - } - - #endregion - - - public async Task> GetOrderTemplatesAsync(List orderNos) - { - return await Context.Queryable() - .LeftJoin((a, b) => a.Id == b.OrderId) - .LeftJoin((a, b, c) => b.ServiceProviderId == c.Id) - .Where(a => orderNos.Contains(a.OrderNo)) - .Select((a, b, c) => new OrderTemplateVO - { - OrderNo = a.OrderNo, - OrderType = a.OrderType, - TemplateId = b.TrackTemplateId, - ServiceProviderId = b.ServiceProviderId, - ServiceProviderCode = c.Code, - SubSystemId = a.SubSystemId - }) - .ToListAsync(); - } } \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs index 7609c5a6..360f2a88 100644 --- a/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs @@ -83,7 +83,7 @@ public class TrackContentRepository : BasicRepository, ITrac CreateUser = e.Name, UpdateTime = a.UpdateTime, UpdateUser = f.Name, - IsFinish= a.IsCompleted + IsFinish = a.IsCompleted }) .ToPagedListAsync(input.PageIndex, input.PageSize); @@ -97,21 +97,21 @@ public class TrackContentRepository : BasicRepository, ITrac public async Task> GetTrackContentAttributeValue(GetTemplateContentAttributeValueInputVO input) { var list = await Context.Queryable() - .LeftJoin((a, b) => a.Id==b.TrackContentId&& b.TrackTemplateId>0 && b.IsDeleted==false) - .LeftJoin((a, b, c) => b.TrackTemplateId==c.Id&& c.IsDeleted==false) - .WhereIF(!input.TrackCodes.IsNullOrEmpty(), (a, b, c) => input.TrackCodes.Contains(a.Code)) - .WhereIF(input.SubSystemId>0, (a, b, c) => a.SubSystemId==input.SubSystemId) - .WhereIF(!input.TrackTemplateIds.IsNullOrEmpty(), (a, b, c) => input.TrackTemplateIds.Contains(c.Id)) - .Where((a, b, c) => c.Id>0) + .LeftJoin((a, b) => a.Id == b.TrackContentId && b.TrackTemplateId > 0 && b.IsDeleted == false) + .LeftJoin((a, b, c) => b.TrackTemplateId == c.Id && c.IsDeleted == false) + .WhereIF(!input.TrackCodes.IsNullOrEmpty(), (a, b, c) => input.TrackCodes!.Contains(a.Code)) + .WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId) + .WhereIF(!input.TrackTemplateIds.IsNullOrEmpty(), (a, b, c) => input.TrackTemplateIds!.Contains(c.Id)) + .Where((a, b, c) => c.Id > 0) //.OrderByIF(!input.TrackTemplateIds.IsNullOrEmpty(), (a, b, c) => SqlFunc.IIF(input.TrackTemplateIds.Contains(a.Id), SqlFunc.DateAdd(SqlFunc.GetDate(), 1), c.CreateTime), OrderByType.Desc) .Select((a, b, c) => new GetTemplateContentAttributeValueVO { - IsCanDelete=b.IsCanDelete, - IsExternal=b.IsExternal, - SubSystemId= a.SubSystemId, - TrackCode= a.Code, - TrackContenId= a.Id, - TrackTemplateId=c.Id + IsCanDelete = b.IsCanDelete, + IsExternal = b.IsExternal, + SubSystemId = a.SubSystemId, + TrackCode = a.Code, + TrackContenId = a.Id, + TrackTemplateId = c.Id }).ToListAsync(); return list; @@ -125,9 +125,9 @@ public class TrackContentRepository : BasicRepository, ITrac public async Task GetTemplateIsExist(int trackContentId) { //var trackTemplateContents = await _trackTemplateContentBasicQuery.GetListAsync(a => a.TrackContentId == input.Id); - var trackContentEntities = await Context.Queryable().LeftJoin((a, b) => a.Id==b.TrackContentId && b.IsDeleted==false) - .LeftJoin((a, b, c) => b.TrackTemplateId==c.Id&& c.IsDeleted==false) - .Where((a, b, c) => a.Id==trackContentId) + var trackContentEntities = await Context.Queryable().LeftJoin((a, b) => a.Id == b.TrackContentId && b.IsDeleted == false) + .LeftJoin((a, b, c) => b.TrackTemplateId == c.Id && c.IsDeleted == false) + .Where((a, b, c) => a.Id == trackContentId) .Select((a, b, c) => new { TrackContentId = a.Id, @@ -135,7 +135,7 @@ public class TrackContentRepository : BasicRepository, ITrac }) .ToListAsync(); - if (trackContentEntities.Any(a => a.TemplateId>0)) + if (trackContentEntities.Any(a => a.TemplateId > 0)) { return true; } diff --git a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs index 8bc2739d..f50d7ebb 100644 --- a/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs +++ b/src/SJZY.Track.Repository/Repositories/TrackDetailsRepository.cs @@ -87,6 +87,32 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract> GetListAsync(int orderType, List orderNos, string trackCode) + { + if (orderNos.Count < 1) return new List(); + + var data = await Context.SearchAsync(x => x + .Source(s => s.Includes(fd => fd + .Field(f => f.OrderNo) + .Field(f => f.TrackStatus) + .Field(f => f.TrackCode) + .Field(f => f.TrackContent) + .Field(f => f.TrackPlace) + .Field(f => f.TrackTime) + .Field(f => f.TrackTimeZone) + )) + .Query(q => + q.Terms(t => t + .Field(f => f.OrderNo.Suffix("keyword")) + .Terms(orderNos)) + && q.Term(f => f.OrderType, orderType) + && q.Term(f => f.TrackCode.Suffix("keyword"), trackCode) + ) + ); + + return data.Documents.ToList(); + } + public async Task> GetListAsync(int orderId) { var data = await Context.SearchAsync(x => x @@ -134,11 +160,12 @@ internal class TrackDetailsRepository : ElasticSearchContextAbstract DeleteTrackAsync(int orderId, List trackCodes) { var r = await Context.DeleteByQueryAsync(x => x - .Query( - q => - q.Term(t => t.OrderId, orderId) - && q.Term(t => t.IsCanDelete, true) - && q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))) + .Query( + q => + q.Term(t => t.OrderId, orderId) + && q.Term(t => t.IsCanDelete, true) + && q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))) + .Refresh() // 可选:立即刷新索引使更改立即可见 ); if (!r.IsValid) diff --git a/src/SJZY.Track.Repository/Repositories/TrackPushRecordsRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackPushRecordsRepository.cs new file mode 100644 index 00000000..c1bb968f --- /dev/null +++ b/src/SJZY.Track.Repository/Repositories/TrackPushRecordsRepository.cs @@ -0,0 +1,41 @@ +using Nest; +using SJZY.Expand.ABP.Core.Logger; +using SJZY.Expand.ElasticSearch.Services; +using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate; +using SJZY.Track.Domain.Aggregates.TrackPushAggregate; + +namespace SJZY.Track.Repository.Repositories; + +public class TrackPushRecordsRepository : ElasticSearchContextAbstract, ITrackPushRecordsRepository, + ITransientDependency +{ + public TrackPushRecordsRepository(ConnectionFactory connectionFactory) : base(connectionFactory) + { + } + + public async Task AddAsync(TrackPushRecordIndex index) + { + // 按天写入es + var r = await Context.IndexAsync(index, request => request + .Index(index.IndexName) + //.Refresh(Refresh.True) // 可选:立即刷新索引使更改立即可见 + ); + + if (!r.IsValid) + { + LogHelper.Error($"轨迹推送记录写入es失败,原因:{r.DebugInformation}。"); + } + } + + public async Task> GetTrackPushRecordsAsync(int orderId) + { + var data = await Context.SearchAsync(x => x + .Query(q => + q.Term(t => t.OrderId, orderId) + ) + .Size(1000) + .Sort(s => s.Field(f => f.CreateTime, SortOrder.Descending))); + + return data.Documents.ToList(); + } +} \ No newline at end of file