From 895e12762d545e189bb8e4226474cec123655312 Mon Sep 17 00:00:00 2001 From: "DESKTOP-S2TSHMH\\BSI" Date: Wed, 24 Jul 2024 08:54:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A2=84=E8=AD=A6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dtos/ProvideServices/UpdateOrderInput.cs | 15 ++ .../SJZY.Track.Application.Contract.csproj | 3 + .../Services/IForewarningNotifyService.cs | 30 +++ .../Services/IKpiAreaCacheService.cs | 6 + .../Services/INotifyService.cs | 6 + .../Services/IRuleFactorCacheService.cs | 32 +++ .../AutoMapper/ForewarningMapperProfile.cs | 48 ++++ ...TrackChangeAfterUpdateOrderEventHandler.cs | 43 +++- .../Helpers/ForewarningFactorHelper.cs | 58 +++++ .../SJZY.Track.Application.csproj | 4 + .../ForewarningNotifyService.cs | 236 ++++++++++++++++++ .../ForewarningServices/ForewarningService.cs | 128 ++++++++++ .../KpiAreaCacheService.cs | 46 ++++ .../ForewarningServices/KpiAreaService.cs | 131 ++++++++++ .../RuleFactorCacheService.cs | 195 +++++++++++++++ .../Services/Notifies/NotifyService.cs | 12 + .../Forewarning/CreateRuleFactorValidation.cs | 33 +++ .../Forewarning/FactorItemDtoValidator.cs | 6 + .../Forewarning/RuleTrackStateDtoValidator.cs | 15 ++ .../ForewarningAggregate/FactorItemModel.cs | 16 ++ .../ForewarningAggregate/IForewarningList.cs | 8 + .../IRuleCollectRepository.cs | 13 + .../IRuleFactorRepository.cs | 10 + .../ForewarningAggregate/IRuleRepository.cs | 12 + .../ForewarningAggregate/RuleAreaEntity.cs | 6 + .../ForewarningAggregate/RuleCollectEntity.cs | 110 ++++++++ .../ForewarningAggregate/RuleEntity.cs | 60 +++++ .../ForewarningAggregate/RuleFactorEntity.cs | 55 ++++ .../RuleTrackStateModel.cs | 24 ++ .../Aggregates/KPIAreaAggregate.cs | 6 + .../KPIAreaAggregate/IKpiAreaRepository.cs | 68 +++++ .../KPIAreaAggregate/RuleAreaEntity.cs | 50 ++++ .../KPIAreaAggregate/RuleAreaInfoEntity.cs | 71 ++++++ .../Aggregates/OrderAggregate/OrderEntity.cs | 18 ++ .../Consts/GlobalConst.ES.cs | 5 + .../Consts/GlobalConst.Redis.cs | 15 ++ .../Forewarning/AddRuleAreaInfoRequest.cs | 20 ++ .../Dtos/Forewarning/AreaDto.cs | 9 + .../Dtos/Forewarning/AreaInfoDto.cs | 35 +++ .../Dtos/Forewarning/CreateRuleAreaRequest.cs | 18 ++ .../Dtos/Forewarning/CreateRuleRequest.cs | 65 +++++ .../Dtos/Forewarning/FactorItemDto.cs | 16 ++ .../Dtos/Forewarning/ForewarningOrderModel.cs | 30 +++ .../Dtos/Forewarning/ForewarningRule.cs | 26 ++ .../Forewarning/IForewarningFactorValue.cs | 16 ++ .../Dtos/Forewarning/KpiAreaInfo.cs | 6 + .../Forewarning/ModifyTimelinessRequest.cs | 34 +++ .../Dtos/Forewarning/QueryAreaInfoRequest.cs | 6 + .../Dtos/Forewarning/QueryAreaRequest.cs | 14 ++ .../Forewarning/QueryForewarningRequest.cs | 24 ++ .../QueryForewarningRuleRequest.cs | 19 ++ .../Dtos/Forewarning/RuleCollectDto.cs | 22 ++ .../Dtos/Forewarning/RuleCollectRequest.cs | 7 + .../Dtos/Forewarning/RuleFactor.cs | 37 +++ .../Dtos/Forewarning/RuleInfoModel.cs | 42 ++++ .../Dtos/Forewarning/RuleNotifyValue.cs | 40 +++ .../Dtos/Forewarning/RuleTrackStateDto.cs | 24 ++ .../Forewarning/UpdateRuleAreaInfoRequest.cs | 22 ++ .../Dtos/Forewarning/UpdateRuleAreaRequest.cs | 17 ++ src/SJZY.Track.Domain/Enums/RuleFactorType.cs | 38 +++ .../SJZY.Track.Domain.csproj | 5 + .../Repositories/KpiAreaInfoRepository.cs | 6 + .../Repositories/KpiAreaRepository.cs | 103 ++++++++ .../Repositories/RuleCollectRepository.cs | 50 ++++ .../Repositories/RuleFactorRepository.cs | 53 ++++ .../Repositories/RuleRepository.cs | 53 ++++ 66 files changed, 2450 insertions(+), 1 deletion(-) create mode 100644 src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs create mode 100644 src/SJZY.Track.Application.Contract/Services/IKpiAreaCacheService.cs create mode 100644 src/SJZY.Track.Application.Contract/Services/INotifyService.cs create mode 100644 src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs create mode 100644 src/SJZY.Track.Application/AutoMapper/ForewarningMapperProfile.cs create mode 100644 src/SJZY.Track.Application/Helpers/ForewarningFactorHelper.cs create mode 100644 src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs create mode 100644 src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs create mode 100644 src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaCacheService.cs create mode 100644 src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaService.cs create mode 100644 src/SJZY.Track.Application/Services/ForewarningServices/RuleFactorCacheService.cs create mode 100644 src/SJZY.Track.Application/Services/Notifies/NotifyService.cs create mode 100644 src/SJZY.Track.Application/Validations/Forewarning/CreateRuleFactorValidation.cs create mode 100644 src/SJZY.Track.Application/Validations/Forewarning/FactorItemDtoValidator.cs create mode 100644 src/SJZY.Track.Application/Validations/Forewarning/RuleTrackStateDtoValidator.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/FactorItemModel.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IForewarningList.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleCollectRepository.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleFactorRepository.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleRepository.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleAreaEntity.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleCollectEntity.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleEntity.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleFactorEntity.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleTrackStateModel.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/IKpiAreaRepository.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaEntity.cs create mode 100644 src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaInfoEntity.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/AddRuleAreaInfoRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/AreaDto.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/AreaInfoDto.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleAreaRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/FactorItemDto.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRule.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/KpiAreaInfo.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/ModifyTimelinessRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaInfoRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRuleRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectDto.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/RuleFactor.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/RuleInfoModel.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/RuleNotifyValue.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/RuleTrackStateDto.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaInfoRequest.cs create mode 100644 src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaRequest.cs create mode 100644 src/SJZY.Track.Domain/Enums/RuleFactorType.cs create mode 100644 src/SJZY.Track.Repository/Repositories/KpiAreaInfoRepository.cs create mode 100644 src/SJZY.Track.Repository/Repositories/KpiAreaRepository.cs create mode 100644 src/SJZY.Track.Repository/Repositories/RuleCollectRepository.cs create mode 100644 src/SJZY.Track.Repository/Repositories/RuleFactorRepository.cs create mode 100644 src/SJZY.Track.Repository/Repositories/RuleRepository.cs diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/UpdateOrderInput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/UpdateOrderInput.cs index ebb47f17..14e2fdc3 100644 --- a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/UpdateOrderInput.cs +++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/UpdateOrderInput.cs @@ -51,4 +51,19 @@ public class UpdateOrderInput : OrderNoInfo /// 订单航班信息 /// public List FlightInfos { get; set; } = new(); + + /// + /// 货物类型 + /// + public string? CargoType { get; set; } + + /// + /// 是否转运 + /// + public bool? IsTransfer { get; set; } + + /// + /// 产品编码 + /// + public string? ProductCode { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/SJZY.Track.Application.Contract.csproj b/src/SJZY.Track.Application.Contract/SJZY.Track.Application.Contract.csproj index 7a7f7902..f2e2a7a3 100644 --- a/src/SJZY.Track.Application.Contract/SJZY.Track.Application.Contract.csproj +++ b/src/SJZY.Track.Application.Contract/SJZY.Track.Application.Contract.csproj @@ -12,5 +12,8 @@ + + + diff --git a/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs b/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs new file mode 100644 index 00000000..f76891a1 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs @@ -0,0 +1,30 @@ +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Application.Contract.Services; + +/// +/// 预警通知服务接口定义。 +/// 提供创建、删除预警通知和发送通知的功能。 +/// +public interface IForewarningNotifyService +{ + /// + /// 创建预警通知。 + /// + /// 预警订单模型。 + /// 创建操作的结果,以整数形式返回。 + Task CreateForewarningNotify(ForewarningOrderModel order); + + /// + /// 删除预警通知。 + /// + /// 预警订单模型。 + /// 删除操作的结果,以整数形式返回。 + Task DeleteForewarningNotify(ForewarningOrderModel order); + + /// + /// 发送通知。 + /// + /// 通知间隔时间,以分钟为单位。 + void SendNotification(int intervalMinute); +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Services/IKpiAreaCacheService.cs b/src/SJZY.Track.Application.Contract/Services/IKpiAreaCacheService.cs new file mode 100644 index 00000000..5713a2d8 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Services/IKpiAreaCacheService.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Application.Contract.Services; + +public interface IKpiAreaCacheService +{ + +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Services/INotifyService.cs b/src/SJZY.Track.Application.Contract/Services/INotifyService.cs new file mode 100644 index 00000000..54b8a368 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Services/INotifyService.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Application.Contract.Services; + +public interface INotifyService +{ + void SendNotification(string body); +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs b/src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs new file mode 100644 index 00000000..41eb2171 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs @@ -0,0 +1,32 @@ +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Application.Contract.Services; + +/// +/// 定义了与规则因子缓存相关的服务接口。 +/// +public interface IRuleFactorCacheService +{ + /// + /// 获取所有因子收集的规则。 + /// + /// 规则数组。 + Task GetAllFactorCollect(); + + /// + /// 获取所有规则因子。 + /// + /// 规则因子实体列表。 + Task> GetAllRuleFactor(); + + /// + /// 清除因子缓存。 + /// + void ClearFactorCache(); + + /// + /// 清除规则缓存。 + /// + void ClearRuleCache(); +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/AutoMapper/ForewarningMapperProfile.cs b/src/SJZY.Track.Application/AutoMapper/ForewarningMapperProfile.cs new file mode 100644 index 00000000..b905d38d --- /dev/null +++ b/src/SJZY.Track.Application/AutoMapper/ForewarningMapperProfile.cs @@ -0,0 +1,48 @@ +using AutoMapper; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Application.AutoMapper; + +public class ForewarningMapperProfile :Profile +{ + public ForewarningMapperProfile() + { + CreateMap(MemberList.None); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(MemberList.None); + CreateMap(MemberList.None) + .ForMember(dest => dest.Country, opt => opt.MapFrom(src => src.Country)) + .ForMember(dest => dest.Province, opt => opt.MapFrom(src => src.Province)) + .ForMember(dest => dest.City, opt => opt.MapFrom(src => src.City)) + .ForMember(dest => dest.LeftPostcode, opt => opt.MapFrom(src => src.LeftPostCode)) + .ForMember(dest => dest.RightPostcode, opt => opt.MapFrom(src => src.RightPostCode)) + .ForMember(dest => dest.AreaId, opt => opt.MapFrom(src => src.AreaId)); + + CreateMap(MemberList.None) + .ForMember(dest => dest.SubSystemId, opt => opt.MapFrom(src => src.SystemId)) + .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name)); + + CreateMap(MemberList.None) + .ForMember(dest => dest.Country, opt => opt.MapFrom(src => src.Country)) + .ForMember(dest => dest.Province, opt => opt.MapFrom(src => src.Province)) + .ForMember(dest => dest.City, opt => opt.MapFrom(src => src.City)) + .ForMember(dest => dest.LeftPostcode, opt => opt.MapFrom(src => src.LeftPostCode)) + .ForMember(dest => dest.RightPostcode, opt => opt.MapFrom(src => src.RightPostCode)); + + CreateMap(MemberList.None) + .ForMember(dest => dest.RuleId, opt => opt.MapFrom(src => src.RuleId)) + .ForMember(dest => dest.Tracks, opt => opt.MapFrom(src => src.Tracks)) + .ForMember(dest => dest.FactorItems, opt => opt.MapFrom(src => src.FactorItems)) + .ForMember(dest => dest.CargoTypes, opt => opt.MapFrom(src => src.CargoTypes)) + .ForMember(dest => dest.Months, opt => opt.MapFrom(src => src.Months.Select(m => m.ToString()))) + .ForMember(dest => dest.IsTransit, opt => opt.MapFrom(src => src.IsTransit.Select(i => i == 1))) + .ForMember(dest => dest.Areas, opt => opt.MapFrom(src => src.Areas)) + .ForMember(dest => dest.DeparturePorts, opt => opt.MapFrom(src => src.DeparturePorts)) + .ForMember(dest => dest.ProductCodes, opt => opt.MapFrom(src => src.ProductCodes)); + + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs index c8f184ae..7a371e49 100644 --- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs +++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs @@ -1,8 +1,10 @@ using DotNetCore.CAP; 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.Dtos.Forewarning; using Volo.Abp.DependencyInjection; namespace SJZY.Track.Application.CAP.EventHandlers; @@ -11,12 +13,15 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa { private readonly IOrderRepository _orderRepository; private readonly ITrackDetailsRepository _trackDetailsRepository; + private readonly IForewarningNotifyService _forewarningNotifyService; public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository, - ITrackDetailsRepository trackDetailsRepository) + ITrackDetailsRepository trackDetailsRepository, + IForewarningNotifyService forewarningNotifyService) { _orderRepository = orderRepository; _trackDetailsRepository = trackDetailsRepository; + _forewarningNotifyService = forewarningNotifyService; } [CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)] @@ -68,4 +73,40 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa x.LatestTrackTimeZone }); } + + private ForewarningOrderModel OrderToForewarningOrderModel(OrderEntity order) +{ + return new ForewarningOrderModel + { + Id = order.Id, + Track = DetermineTrackBasedOnOrderDetails(order), + SystemId = order.SubSystemId, + CustomerId = order.CustomId, + CargoType = order.CargoType, + Month = order.CreateTime.Month, + Area = DetermineAreaBasedOnOrderDetails(order), + IsTransit = order.IsTransfer, + DeparturePort = order.LeavePort, + ProductCode = order.ProductCode + }; +} + +// Placeholder methods for deriving or converting values. You'll need to implement these based on your specific logic. +private int DetermineTrackBasedOnOrderDetails(OrderEntity order) +{ + // Implement logic to determine Track + return default; +} + +private int? DetermineMonthBasedOnOrderDetails(OrderEntity order) +{ + // Implement logic to determine Month + return default; +} + +private int? DetermineAreaBasedOnOrderDetails(OrderEntity order) +{ + // Implement logic to determine Area + return default; +} } \ No newline at end of file diff --git a/src/SJZY.Track.Application/Helpers/ForewarningFactorHelper.cs b/src/SJZY.Track.Application/Helpers/ForewarningFactorHelper.cs new file mode 100644 index 00000000..c88ec276 --- /dev/null +++ b/src/SJZY.Track.Application/Helpers/ForewarningFactorHelper.cs @@ -0,0 +1,58 @@ +using JetBrains.Annotations; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +namespace SJZY.Track.Application.Helpers; + +public class ForewarningFactorHelper +{ + public static RuleCollectEntity[] GetFactorItem([NotNull]RuleFactorEntity ruleFactors) + { + var total = Factorial(ruleFactors); + var ruleCollect = AllocateFactor(total,ruleFactors.RuleId); + Assignment(ruleCollect,total,ruleFactors.CargoTypes,(item,value)=>item.CargoType=value); + Assignment(ruleCollect,total,ruleFactors.Months,(item,value)=>item.Month=value); + Assignment(ruleCollect,total,ruleFactors.Areas,(item,value)=>item.Area=value); + Assignment(ruleCollect,total,ruleFactors.IsTransit,(item,value)=>item.IsTransit=value); + Assignment(ruleCollect,total,ruleFactors.DeparturePorts,(item,value)=>item.DeparturePort=value); + Assignment(ruleCollect,total,ruleFactors.ProductCodes,(item,value)=>item.ProductCode=value); + return ruleCollect.ToArray(); + } + + private static void Assignment(Span ruleCollect,int total,IReadOnlyList values,Action action) + { + if (values.Count == 0) + { + return; + } + + var segment = total / values.Count; + for(int index=0;index AllocateFactor(int total,int ruleId) + { + + Span factors = new RuleCollectEntity[total]; + for (int index = 0; index < total; index++) + { + factors[index] = new RuleCollectEntity() + { + RuleId = ruleId + }; + } + return factors; + } + + internal static int Factorial(RuleFactorEntity ruleFactors) + { + return ruleFactors.CargoTypes.Count*ruleFactors.Months.Count*ruleFactors.Areas.Count*ruleFactors.IsTransit.Count*ruleFactors.DeparturePorts.Count*ruleFactors.ProductCodes.Count; + } +} \ 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 378f50c7..011dd0d7 100644 --- a/src/SJZY.Track.Application/SJZY.Track.Application.csproj +++ b/src/SJZY.Track.Application/SJZY.Track.Application.csproj @@ -29,4 +29,8 @@ + + + + diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs new file mode 100644 index 00000000..d692dad5 --- /dev/null +++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs @@ -0,0 +1,236 @@ +using FreeRedis; +using NetTaste; +using SJZY.Expand.ABP.Core; +using SJZY.Track.Application.Contract.Services; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Dtos.Forewarning; +using SJZY.Track.Domain.Enums; +using SqlSugar; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.Services.ForewarningServices; + +/// +/// 单例服务,用于处理预警通知 +/// +public class ForewarningNotifyService:IForewarningNotifyService,ITransientDependency +{ + private IRuleFactorCacheService _ruleFactorCache; + IReadOnlyDictionary> _ruleGroupDict; + IReadOnlyDictionary> _factorDict; + private IReadOnlyDictionary _rules; + readonly INotifyService _notifyService; + + public ForewarningNotifyService(IRuleFactorCacheService ruleFactorCache, INotifyService notifyService) + { + _ruleFactorCache = ruleFactorCache; + _notifyService = notifyService; + } + + /// + /// 创建预警通知 + /// + /// 创建预警通知需要的订单信息 + /// 创建的通知总量,0表示没有规则 + public async Task CreateForewarningNotify(ForewarningOrderModel order) + { + var rules = GetRule(order); + if (rules == null || rules.Count == 0) + return 0; + + return await ExecuteRule(rules,order.Id); + } + + /// + /// 清除预警通知 + /// + /// 订单信息 + /// 清理的行数 + public async Task DeleteForewarningNotify(ForewarningOrderModel order) + { + var rules = GetRule(order); + if (rules == null || rules.Count == 0) + return 0; + + var willDeleteMembers = new List(); + foreach (var rule in rules) + { + var allRuleNotities= DeleteNotifyValue(rule, order.Id); + willDeleteMembers.AddRange(allRuleNotities); + } + + await RedisHelper.Client.ZRemAsync(GlobalConst.ForewarningNotifyKeyPrefix, willDeleteMembers.ToArray()); + return willDeleteMembers.Count; + } + + public void SendNotification(int intervalMinute) + { + var currentTimestamp = GetTimestamp(DateTime.Now); + var notifyMembers = RedisHelper.Client.ZRangeByScore(GlobalConst.ForewarningNotifyKeyPrefix, 0, currentTimestamp); + if (notifyMembers == null || notifyMembers.Length == 0) + return; + + var notifyValues = notifyMembers.Select(val => new RuleNotifyValue(val)); + foreach (var notifyValue in notifyValues) + { + if(!_rules.TryGetValue(notifyValue.RuleId, out var rule)) + continue; + + //todo 发送通知 + _notifyService.SendNotification(""); + } + } + + public void ClearCache() + { + _ruleGroupDict = null; + _factorDict = null; + _rules = null; + } + + private List DeleteNotifyValue(ForewarningRule rule,int orderId) + { + var members = new List(); + for(var index=0;index + /// 获取规则 + /// + /// + /// + private List GetRule(ForewarningOrderModel order) + { + if (!_factorDict.TryGetValue(GetFactorKey(order.CustomerId, order.SystemId), out var factors)) + { + return null; + } + + var keys = GetForewarningKeys(factors, order); + var result = new List< ForewarningRule>(); + + foreach (var item in keys) + { + if (!_ruleGroupDict.TryGetValue(item, out var rules)) + continue; + + var allRules = rules.Where(val=>val.TrackStart <= order.Track && val.TrackEnd >= order.Track); + result.AddRange(allRules); + } + + return result; + } + + private async ValueTask ExecuteRule(List rules,int orderId) + { + var members = new List(); + foreach (var rule in rules) + { + var notifys = ExecuteRule(rule,orderId); + members.AddRange(notifys); + } + + await RedisHelper.Client.ZAddAsync(GlobalConst.ForewarningNotifyKeyPrefix, members.ToArray()); + return members.Count; + } + + private List ExecuteRule(ForewarningRule rule,int orderId) + { + var members = new List(); + var intervalMinute = 60 * ((rule.Timeliness - rule.Remind) / rule.Count);// 间隔多少分钟 + + for(var index=0;index GetForewarningKeys(List factors, IForewarningFactorValue rule) + { + var keys = new List(); + foreach (var factor in factors) + { + var key = GetRuleKey(rule, factor); + keys.Add(key); + } + + return keys; + } + + private async Task Init() + { + var allFactorCollect = await _ruleFactorCache.GetAllFactorCollect(); + var factors = await _ruleFactorCache.GetAllRuleFactor(); + var factorsMap = factors.GroupBy(val=>val.RuleId) + .ToDictionary(val=>val.Key,val=>val.First()); + + _rules = allFactorCollect.ToDictionary(val => val.Id); + + _factorDict = factors.GroupBy(val => GetFactorKey(val.CustomerId,val.SystemId)) + .ToDictionary(val=>val.Key,val=>val.ToList()); + + _ruleGroupDict = allFactorCollect.GroupBy(x => GetRuleKey(x, factorsMap[x.RuleId])) + .ToDictionary(val => val.Key, val => val.ToList()); + } + + private string GetFactorKey(int customerId,int systemId) + { + return $"{customerId}:{systemId}"; + } + + private string GetRuleKey(IForewarningFactorValue rule,RuleFactor factors) + { + var key = ""; + foreach (var factorItem in factors.FactorItems) + { + key+=GetFactorValue(factorItem,rule); + } + + return key; + } + + private string GetFactorValue(FactorItemModel factorItem, IForewarningFactorValue rule) + { + switch (factorItem.FactorType) + { + case RuleFactorType.Areas: + return rule.Area.HasValue ? rule.Area.Value.ToString() : throw new Exception("区域不能为空"); + case RuleFactorType.CargoType: + return rule.CargoType; + case RuleFactorType.DeparturePort: + return rule.DeparturePort; + case RuleFactorType.Month: + return rule.Month.HasValue ? rule.Month.Value.ToString() : throw new Exception("月份不能为空"); + case RuleFactorType.ProductCode: + return rule.ProductCode; + case RuleFactorType.IsTransit: + return rule.IsTransit.HasValue ? "1" : "0"; + // Add additional cases for other RuleFactorTypes as needed + default: + throw new Exception("未知的规则类型"); + } + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs new file mode 100644 index 00000000..2f660c83 --- /dev/null +++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs @@ -0,0 +1,128 @@ +using System.Diagnostics.CodeAnalysis; +using AutoMapper; +using SJZY.Track.Application.Helpers; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; +using SqlSugar; + +namespace SJZY.Track.Application.Services.ForewarningServices; + +[ApiExplorerSettings(GroupName = "预警服务")] +[Route("/ForewarningService")] +public class ForewarningService: ApplicationService +{ + readonly IRuleRepository _ruleRepository; + IRuleFactorRepository _ruleFactorRepository; + private IRuleCollectRepository _ruleCollectRepository; + + public ForewarningService(IRuleRepository ruleRepository + ,IRuleFactorRepository ruleFactorRepository + , IRuleCollectRepository ruleCollectRepository) + { + _ruleRepository = ruleRepository; + _ruleFactorRepository = ruleFactorRepository; + _ruleCollectRepository = ruleCollectRepository; + } + + /// + /// 创建预警模板,存在则更新 + /// + /// + /// + [HttpPost("ModifyForewarning")] + public async ValueTask ModifyForewarning(CreateRuleFactorRequest input) + { + var factors = ObjectMapper.Map(input); + var ruleCollects = ForewarningFactorHelper.GetFactorItem(factors); + + //todo 原子性没有保证,后续可能需要调整 + if (input.RuleId > 0) + { + await _ruleFactorRepository.DeleteByIdAsync(input.RuleId.ToString()); + } + + if (input.RuleId > 0) + { + var ruleTemplate = await _ruleRepository.GetFirstAsync(val=>val.Id == input.RuleId); + if (ruleTemplate == null) + return new UnifyResultDto(false,"规则不存在"); + + ruleTemplate.Name = input.Name; + ruleTemplate.CustomId = input.CustomId; + + await _ruleFactorRepository.IndexDocumentAsync(factors); + await _ruleRepository.UpdateForewarning(ruleTemplate, ruleCollects); + return new UnifyResultDto(true,"保存成功"); + } + + var newRuleTemplate = ObjectMapper.Map(input); + var ruleTemplateId = await _ruleRepository.CreateForewarning(newRuleTemplate, ruleCollects); + factors.Id = ruleTemplateId.ToString(); + return new UnifyResultDto(true,"保存成功"); + } + + /// + /// 修改时效 + /// + [HttpPost("ModifyTimeliness")] + public async ValueTask ModifyTimeliness(ModifyTimelinessRequest input) + { + var ruleIds = input.Items.Select(val=>val.Id).ToList(); + var ruleCollect = await _ruleCollectRepository.GetListAsync(val => ruleIds.Contains(val.Id) && val.RuleId == input.RuleId); + if (ruleCollect == null|| ruleCollect.Count == 0) + throw new BusinessException(message:"规则不存在"); + + var ruleMaps = ruleCollect.ToDictionary(val => val.Id); + var notModifyList = new List(); + foreach (var item in input.Items) + { + if (!ruleMaps.TryGetValue(item.Id, out var rule)) + { + notModifyList.Add(item.Id); + continue; + } + + rule.Remind= item.Remind; + rule.Timeliness = item.Timeliness; + rule.Count = item.Count; + } + + await _ruleCollectRepository.UpdateRangeAsync(ruleCollect,val=>val.RuleId==input.RuleId); + + if (notModifyList.Count > 0) + return new UnifyResultDto(true, $"更新成功,规则{string.Join(",", notModifyList)}不存在"); + + return new UnifyResultDto(true, "更新成功"); + } + + /// + /// 查询预警模板列表 + /// + /// + [HttpPost("QueryForewarning")] + public async Task QueryForewarning(QueryForewarningRequest input) + { + var result = await _ruleRepository.QueryForewarning(input); + return new UnifyResultDto(true, result); + } + + /// + /// 查询预警规则列表 + /// + [HttpPost("QueryForewarningRules")] + public async Task QueryForewarningRules(QueryForewarningRuleRequest input) + { + var result = await _ruleCollectRepository.QueryForewarningRule(input); + return new UnifyResultDto(true, result); + } + + /// + /// 发送预警通知 + /// + [HttpPost("SendForewarningNotification")] + public void SendForewarningNotification() + { + + } + +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaCacheService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaCacheService.cs new file mode 100644 index 00000000..65accbcf --- /dev/null +++ b/src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaCacheService.cs @@ -0,0 +1,46 @@ +using SJZY.Expand.ABP.Core; +using SJZY.Track.Application.Contract.Services; +using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Dtos.Forewarning; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.Services.ForewarningServices; + +public class KpiAreaCacheService:IKpiAreaCacheService,ITransientDependency +{ + IKpiAreaRepository _kpiAreaRepository; + const string GlobalKpiAreaLockKey = "KpiAreaCacheService_GlobalLock"; + + public KpiAreaCacheService(IKpiAreaRepository kpiAreaRepository) + { + _kpiAreaRepository = kpiAreaRepository; + } + + private string GetKey(int systemId, string country) + { + return $"{GlobalConst.KpiAreaKeyPrefix}:{systemId}:{country}"; + } + + public async Task GetKpiArea(int systemId, string country) + { + var key = GetKey(systemId, country); + var result = RedisHelper.Client.Get(key); + if (result == null) + { + using (var globalLock = RedisHelper.Client.Lock(GlobalKpiAreaLockKey, 10)) + { + result = RedisHelper.Client.Get(key); + if (result != null) return; + + //todo 转换成KpiAreaInfo + var kpiArea =await _kpiAreaRepository.GetAllAreaInfos(); + if (kpiArea == null) + { + return; + } + RedisHelper.Client.Set(key, kpiArea, TimeSpan.FromSeconds(20)); + } + } + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaService.cs new file mode 100644 index 00000000..f87b3109 --- /dev/null +++ b/src/SJZY.Track.Application/Services/ForewarningServices/KpiAreaService.cs @@ -0,0 +1,131 @@ +using AutoMapper; +using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; +using SqlSugar; + +namespace SJZY.Track.Application.Services.ForewarningServices; + +[ApiExplorerSettings(GroupName = "预警服务")] +[Route("/ForewarningService")] +public class KpiAreaService : ApplicationService +{ + readonly IKpiAreaRepository _ruleAreaRepository; + + public KpiAreaService(IKpiAreaRepository ruleAreaRepository ) + { + _ruleAreaRepository = ruleAreaRepository; + } + + /// + /// 创建分区 + /// + /// + /// 分区id + [HttpPost("KpiArea/CreateKpiArea")] + public async ValueTask CreateKpiArea(CreateRuleAreaRequest input) + { + var ruleAreaEntity = ObjectMapper.Map(input); + var areaId = await _ruleAreaRepository.CreateAreaAsync(ruleAreaEntity); + return new UnifyResultDto(true,areaId, "创建成功"); + } + + /// + /// 添加区域信息 + /// + /// + /// 区域id + [HttpPost("KpiArea/AddAreaInfo")] + public async ValueTask AddAreaInfoAsync(AddRuleAreaInfoRequest input) + { + var ruleAreaEntity = ObjectMapper.Map(input); + var ruleInfoId = await _ruleAreaRepository.AddAreaInfoAsync(ruleAreaEntity); + return new UnifyResultDto(true,ruleInfoId, "添加成功"); + } + + /// + /// 删除分区 + /// + /// 分区id + /// + [HttpDelete("KpiArea/DeleteKpiArea")] + public async ValueTask DeleteKpiArea(int id) + { + await _ruleAreaRepository.DeleteArea(id); + return new UnifyResultDto(true, "删除成功"); + } + + /// + /// 删除分区信息 + /// + /// 分区信息id + /// + [HttpDelete("KpiArea/DeleteKpiAreaInfo")] + public async ValueTask DeleteKpiAreaInfo(int id) + { + await _ruleAreaRepository.DeleteAreaInfo(id); + return new UnifyResultDto(true, "删除成功"); + } + + /// + /// 更新区域信息 + /// + /// + /// + [HttpPost("KpiArea/ModifyKpiArea")] + public async Task ModifyKpiArea(UpdateRuleAreaRequest input) + { + if(input.Id<=0) + return new UnifyResultDto(false,"id不能为空"); + + var ruleArea =await _ruleAreaRepository.GetFirstAsync(val=>val.Id==input.Id); + if(ruleArea==null) + return new UnifyResultDto(false,"未找到该区域"); + + ruleArea.Name = input.Name; + await _ruleAreaRepository.UpdateAsync(ruleArea); + return new UnifyResultDto(true,"更新成功"); + } + + /// + /// 更新区域信息 + /// + /// + /// + [HttpPost("KpiArea/ModifyKpiAreaInfo")] + public async Task ModifyKpiAreaInfo(UpdateRuleAreaInfoRequest input) + { + if(input.Id<=0) + return new UnifyResultDto(false,"id不能为空"); + + //todo 测试不存在id的情况 + RuleAreaInfoEntity areaInfo = await _ruleAreaRepository.GetAreaInfoById(input.Id); + if(areaInfo==null) + return new UnifyResultDto(false,"未找到该区域信息"); + + var ruleAreaEntity = ObjectMapper.Map(input,areaInfo); + await _ruleAreaRepository.UpdateAreaInfoAsync(ruleAreaEntity); + return new UnifyResultDto(true,"更新成功"); + } + + /// + /// 查询分区列表 + /// + /// + /// + [HttpPost("KpiArea/GetKpiAreas")] + public async Task> GetKpiAreas(QueryAreaRequest input) + { + return await _ruleAreaRepository.GetAreas(input); + } + + /// + /// 查询分区列表 + /// + /// + /// + [HttpPost("KpiArea/GetKpiAreaInfos")] + public async Task> GetKpiAreaInfos(QueryAreaInfoRequest query) + { + return await _ruleAreaRepository.GetAreaInfos(query); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/RuleFactorCacheService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/RuleFactorCacheService.cs new file mode 100644 index 00000000..6b7ffcb4 --- /dev/null +++ b/src/SJZY.Track.Application/Services/ForewarningServices/RuleFactorCacheService.cs @@ -0,0 +1,195 @@ +using SJZY.Expand.ABP.Core; +using SJZY.Track.Application.Contract.Services; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Consts; +using SJZY.Track.Domain.Dtos.Forewarning; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.Services.ForewarningServices; + +public class RuleFactorCacheService:IRuleFactorCacheService,ITransientDependency +{ + private const string GlobalFactorLockKey = "RuleFactorCacheService_GlobalLock"; + private const string GlobalRuleLockKey = "RuleFactorCacheService_GlobalLock"; + readonly IRuleFactorRepository _ruleFactorRepository; + readonly IRuleCollectRepository _ruleCollectRepository; + readonly IRuleRepository _ruleRepository; + + public RuleFactorCacheService(IRuleFactorRepository ruleFactorRepository, + IRuleCollectRepository ruleCollectRepository, IRuleRepository ruleRepository) + { + _ruleFactorRepository = ruleFactorRepository; + _ruleCollectRepository = ruleCollectRepository; + _ruleRepository = ruleRepository; + } + + private string GetKey() + { + return $"{GlobalConst.RuleFactorKeyPrefix}:allFactor"; + } + + private string GetRuleKey() + { + return $"{GlobalConst.RuleFactorKeyPrefix}:allRule"; + } + + /// + /// 获取所有规则数据 + /// + /// + [NonAction] + public async Task GetAllFactorCollect() + { + + var key = GetRuleKey(); + var result =await RedisHelper.Client.GetAsync(key); + if (result == null) + { + using (var globalLock = RedisHelper.Client.Lock(GlobalRuleLockKey, 10)) + { + result =await RedisHelper.Client.GetAsync(key); + if (result != null) return result; + + var ruleCollect = await _ruleCollectRepository.GetListAsync(val => true); + if (ruleCollect == null || ruleCollect.Count == 0) + { + ForewarningRule[] rules = new ForewarningRule[0]; + await RedisHelper.Client.SetAsync(key,rules , TimeSpan.FromSeconds(20)); + return result; + } + + var ruleList = ruleCollect.SelectMany(RuleEntityToRule); + await RedisHelper.Client.SetAsync(key, ruleList); + return result; + } + } + + return result; + } + + /// + /// 获取所有因素数据 + /// + /// 获取所有因素,返回值可能为空 + [NonAction] + public async Task> GetAllRuleFactor() + { + var key = GetKey(); + var result =await RedisHelper.Client.GetAsync>(key); + if (result == null) + { + using (var globalLock = RedisHelper.Client.Lock(GlobalFactorLockKey, 10)) + { + result =await RedisHelper.Client.GetAsync>(key); + if (result != null) return result; + + result = await GenerateAllRuleFactor(); + if (result == null || result.Count == 0) + { + await RedisHelper.Client.SetAsync(key,new List() , TimeSpan.FromSeconds(20)); + return result; + } + + await RedisHelper.Client.SetAsync(key, result); + return result; + } + } + + return result; + } + + [NonAction] + public void ClearFactorCache() + { + RedisHelper.Client.DelAsync(GetKey()); + } + + [NonAction] + public void ClearRuleCache() + { + RedisHelper.Client.DelAsync(GetRuleKey()); + } + + private async Task> GenerateAllRuleFactor() + { + var factors =await _ruleFactorRepository.GetAllList(); + var ruleTemplate =await _ruleRepository.GetListAsync(val => true); + var ruleMap = ruleTemplate.ToDictionary(val => val.Id); + var result = new List(); + foreach (var item in factors) + { + if(!ruleMap.TryGetValue(item.RuleId,out var rule)) + continue; + var ruleFactors = EntityToRuleFactor(item, rule); + result.AddRange(ruleFactors); + } + + return result; + } + + private ForewarningRule[] RuleEntityToRule(RuleCollectEntity entity) + { + var result = RuleCollectToRule(entity); + if (string.IsNullOrEmpty(entity.Month)) + { + return new ForewarningRule[] { result }; + } + + var months = entity.Month.Split('/'); + var rules = new List(months.Length); + + foreach (var month in months) + { + if (int.TryParse(month, out int monthInt)) + { + var rule = result; + rule.Month = monthInt; + rules.Add(rule); + } + } + + return rules.ToArray(); + } + + private ForewarningRule RuleCollectToRule(RuleCollectEntity entity) + { + return new ForewarningRule + { + Id = entity.Id, + RuleId = entity.RuleId, + Remind = entity.Remind, + Timeliness = entity.Timeliness, + Count = entity.Count, + TrackStart = entity.TrackStart, + TrackEnd = entity.TrackEnd, + CargoType = entity.CargoType, + Month = null, + Area = entity.Area, + IsTransit = entity.IsTransit, + DeparturePort = entity.DeparturePort, + ProductCode = entity.ProductCode + }; + } + + private List EntityToRuleFactor(RuleFactorEntity entity,RuleEntity ruleTemplate) + { + List result = new List(); + foreach (var track in entity.Tracks) + { + var item = new RuleFactor() + { + CustomerId = ruleTemplate.CustomId, + RuleId = ruleTemplate.Id, + NotifyUser = track.NotifyUser, + NotifyTemplate = track.NotifyTemplate, + FactorItems = entity.FactorItems, + End = track.End, + Start = track.Start, + SystemId = ruleTemplate.SubSystemId + }; + result.Add(item); + } + + return result; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/Notifies/NotifyService.cs b/src/SJZY.Track.Application/Services/Notifies/NotifyService.cs new file mode 100644 index 00000000..9365fbc9 --- /dev/null +++ b/src/SJZY.Track.Application/Services/Notifies/NotifyService.cs @@ -0,0 +1,12 @@ +using SJZY.Track.Application.Contract.Services; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.Services.Notifies; + +public class NotifyService:INotifyService, ITransientDependency +{ + public void SendNotification(string body) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Validations/Forewarning/CreateRuleFactorValidation.cs b/src/SJZY.Track.Application/Validations/Forewarning/CreateRuleFactorValidation.cs new file mode 100644 index 00000000..0b3fe50a --- /dev/null +++ b/src/SJZY.Track.Application/Validations/Forewarning/CreateRuleFactorValidation.cs @@ -0,0 +1,33 @@ +using FluentValidation; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Application.Validations.Forewarning; + +public class CreateRuleFactorValidation : AbstractValidator +{ + public CreateRuleFactorValidation() + { + RuleForEach(x => x.Tracks).SetValidator(new RuleTrackStateDtoValidator()); + RuleFor(x => x.FactorItems).NotNull().WithMessage("FactorItems cannot be null."); + + RuleFor(x => x.CargoTypes).NotEmpty().WithMessage("CargoTypes cannot be empty."); + RuleForEach(x => x.CargoTypes).NotEmpty().WithMessage("CargoType cannot be empty."); + + RuleFor(x => x.Months).NotEmpty().WithMessage("Months cannot be empty."); + RuleForEach(x => x.Months) + .ForEach(val=>val.Must(t=>t>0)) + .WithMessage("Each month array must have 12 elements."); + + RuleFor(x => x.IsTransit).NotEmpty().WithMessage("IsTransit cannot be empty."); + RuleForEach(x => x.IsTransit).InclusiveBetween(0, 1).WithMessage("IsTransit must be 0 or 1."); + + RuleFor(x => x.Areas).NotEmpty().WithMessage("Areas cannot be empty."); + RuleForEach(x => x.Areas).GreaterThan(0).WithMessage("Area must be greater than 0."); + + RuleFor(x => x.DeparturePorts).NotEmpty().WithMessage("DeparturePorts cannot be empty."); + RuleForEach(x => x.DeparturePorts).NotEmpty().WithMessage("DeparturePort cannot be empty."); + + RuleFor(x => x.ProductCodes).NotEmpty().WithMessage("ProductCodes cannot be empty."); + RuleForEach(x => x.ProductCodes).NotEmpty().WithMessage("ProductCode cannot be empty."); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Validations/Forewarning/FactorItemDtoValidator.cs b/src/SJZY.Track.Application/Validations/Forewarning/FactorItemDtoValidator.cs new file mode 100644 index 00000000..368e5d63 --- /dev/null +++ b/src/SJZY.Track.Application/Validations/Forewarning/FactorItemDtoValidator.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Application.Validations.Forewarning; + +public class FactorItemDtoValidator +{ + +} \ No newline at end of file diff --git a/src/SJZY.Track.Application/Validations/Forewarning/RuleTrackStateDtoValidator.cs b/src/SJZY.Track.Application/Validations/Forewarning/RuleTrackStateDtoValidator.cs new file mode 100644 index 00000000..6de8c9b6 --- /dev/null +++ b/src/SJZY.Track.Application/Validations/Forewarning/RuleTrackStateDtoValidator.cs @@ -0,0 +1,15 @@ +using FluentValidation; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Application.Validations.Forewarning; + +public class RuleTrackStateDtoValidator : AbstractValidator +{ + public RuleTrackStateDtoValidator() + { + RuleFor(x => x.Start).GreaterThanOrEqualTo(0).WithMessage("Start must be greater than or equal to 0."); + RuleFor(x => x.End).GreaterThanOrEqualTo(0).WithMessage("End must be greater than or equal to 0."); + RuleFor(x => x.NotifyUser).NotEmpty().WithMessage("NotifyUser cannot be empty."); + RuleFor(x => x.NotifyTemplate).NotEmpty().WithMessage("NotifyTemplate cannot be empty."); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/FactorItemModel.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/FactorItemModel.cs new file mode 100644 index 00000000..7df7f7f2 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/FactorItemModel.cs @@ -0,0 +1,16 @@ +using SJZY.Track.Domain.Enums; + +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public class FactorItemModel +{ + /// + /// Gets or sets the sort order. + /// + public int Sort { get; set; } + + /// + /// Gets or sets the type of the rule factor. + /// + public RuleFactorType FactorType { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IForewarningList.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IForewarningList.cs new file mode 100644 index 00000000..ae0406fe --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IForewarningList.cs @@ -0,0 +1,8 @@ +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public interface IForewarningList +{ + void AddForewarning(int score,int id); + + void DeleteForewarning(int score,int id); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleCollectRepository.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleCollectRepository.cs new file mode 100644 index 00000000..b48a7186 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleCollectRepository.cs @@ -0,0 +1,13 @@ +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public interface IRuleCollectRepository:IBasicRepository +{ + /// + /// 查询分页 + /// + /// + /// + Task> QueryForewarningRule(QueryForewarningRuleRequest input); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleFactorRepository.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleFactorRepository.cs new file mode 100644 index 00000000..38b32ef7 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleFactorRepository.cs @@ -0,0 +1,10 @@ +using SJZY.Expand.ElasticSearch.Services; + +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public interface IRuleFactorRepository:IElasticsearchClientService +{ + Task> GetFactorByIdsAsync(int[] ruleIds); + + Task> GetAllList(); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleRepository.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleRepository.cs new file mode 100644 index 00000000..04a32139 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/IRuleRepository.cs @@ -0,0 +1,12 @@ +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public interface IRuleRepository:IBasicRepository +{ + Task CreateForewarning(RuleEntity rule, RuleCollectEntity[] factorList); + + Task UpdateForewarning(RuleEntity rule, RuleCollectEntity[] factorList); + + Task> QueryForewarning(QueryForewarningRequest input); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleAreaEntity.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleAreaEntity.cs new file mode 100644 index 00000000..c6325956 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleAreaEntity.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public class RuleAreaEntity +{ + +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleCollectEntity.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleCollectEntity.cs new file mode 100644 index 00000000..ba4648e2 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleCollectEntity.cs @@ -0,0 +1,110 @@ +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +[SugarTable("t_rule_collect")] +public class RuleCollectEntity : IAggregateRoot,ICloneable +{ + /// + /// 自增主键 + /// + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + [SugarColumn(ColumnName = "RuleId")] + public int RuleId { get; set; } + + /// + /// 提醒的时间(小时) + /// + [SugarColumn(ColumnName = "Remind")] + public float Remind { get; set; } + + /// + /// 时效(小时) + /// + [SugarColumn(ColumnName = "Timeliness")] + public float Timeliness { get; set; } + + /// + /// 提醒次数 + /// + [SugarColumn(ColumnName = "Count")] + public int Count { get; set; } + + /// + /// 起始轨迹 + /// + [SugarColumn(ColumnName = "TrackStart", IsNullable = false)] + public int TrackStart { get; set; } + + /// + /// 终止轨迹 + /// + [SugarColumn(ColumnName = "TrackEnd", IsNullable = false)] + public int TrackEnd { get; set; } + + /// + /// 货物类型 + /// + [SugarColumn(ColumnName = "CargoType", Length = 64)] + public string CargoType { get; set; } + + /// + /// 月份 + /// + [SugarColumn(ColumnName = "Month", Length = 25)] + public string Month { get; set; } + + /// + /// 区域 + /// + [SugarColumn(ColumnName = "Area")] + public int? Area { get; set; } + + /// + /// 是否中转 + /// + [SugarColumn(ColumnName = "IsTransit")] + public bool? IsTransit { get; set; } + + /// + /// 起运港口 + /// + [SugarColumn(ColumnName = "DeparturePort")] + public string DeparturePort { get; set; } + + /// + /// 产品编码 + /// + [SugarColumn(ColumnName = "ProductCode")] + public string ProductCode { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "CreateUserId")] + public int CreateUserId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "CreateTime")] + public DateTime CreateTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "UpdateUserId")] + public int UpdateUserId { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "UpdateTime")] + public DateTime UpdateTime { get; set; } + + public object Clone() + { + var clone = this.MemberwiseClone(); + return clone; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleEntity.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleEntity.cs new file mode 100644 index 00000000..15439fbf --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleEntity.cs @@ -0,0 +1,60 @@ +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +[SugarTable("t_rule")] +public class RuleEntity:IAggregateRoot +{ + /// + /// 自增主键 + /// + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + + /// + /// 子系统id + /// + [SugarColumn(ColumnName = "SubSystemId")] + public int SubSystemId { get; set; } + + /// + /// 客户id + /// + [SugarColumn(ColumnName = "CustomId")] + public int CustomId { get; set; } + + /// + /// 规则模板名称,KPI名称 + /// + [SugarColumn(ColumnName = "Name", Length = 64)] + public string Name { get; set; } + + /// + /// 规则模板名称,KPI名称 + /// + [SugarColumn(ColumnName = "CustomName", Length = 64)] + public string CustomName { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "CreateUserId")] + public int CreateUserId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "CreateTime")] + public DateTime CreateTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "UpdateUserId", IsNullable = false)] + public int UpdateUserId { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "UpdateTime", IsNullable = false)] + public DateTime UpdateTime { get; set; } + +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleFactorEntity.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleFactorEntity.cs new file mode 100644 index 00000000..b356b062 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleFactorEntity.cs @@ -0,0 +1,55 @@ +using Nest; +using SJZY.Expand.ElasticSearch; +using SJZY.Track.Domain.Consts; + +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +[ElasticsearchType(RelationName = GlobalConst.RuleFactorIndex)] +public class RuleFactorEntity:IdBaseIndex +{ + /// + /// RuleId 表的id + /// + [Keyword(Index = true)] + public int RuleId { get; set; } + + /// + /// 获取或设置规则跟踪状态实体的列表。 + /// + public List Tracks { get; set; } + + /// + /// 获取或设置因素项模型的列表。 + /// + public List FactorItems { get; set; } + + /// + /// 获取或设置货物类型的列表。 + /// + public List CargoTypes { get; set; } + + /// + /// 获取或设置月份的列表。 + /// + public List Months { get; set; } + + /// + /// 获取或设置是否中转的列表。 + /// + public List IsTransit { get; set; } + + /// + /// 获取或设置区域的列表。 + /// + public List Areas { get; set; } + + /// + /// 获取或设置起运港口的列表。 + /// + public List DeparturePorts { get; set; } + + /// + /// 获取或设置产品编号的列表。 + /// + public List ProductCodes { get; set; } +} diff --git a/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleTrackStateModel.cs b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleTrackStateModel.cs new file mode 100644 index 00000000..554d1e2c --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/ForewarningAggregate/RuleTrackStateModel.cs @@ -0,0 +1,24 @@ +namespace SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +public class RuleTrackStateModel +{ + /// + /// Gets or sets the start track value. + /// + public int Start { get; set; } + + /// + /// Gets or sets the end track value. + /// + public int End { get; set; } + + /// + /// Gets or sets the user to notify. + /// + public string NotifyUser { get; set; } + + /// + /// Gets or sets the notification template. + /// + public string NotifyTemplate { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate.cs b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate.cs new file mode 100644 index 00000000..353b4ebc --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Domain.Aggregates; + +public class KPIAreaAggregate +{ + +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/IKpiAreaRepository.cs b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/IKpiAreaRepository.cs new file mode 100644 index 00000000..cc1d5168 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/IKpiAreaRepository.cs @@ -0,0 +1,68 @@ +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Domain.Aggregates.KPIAreaAggregate; + +public interface IKpiAreaRepository:IBasicRepository +{ + /// + /// 创建分区 + /// + /// + /// + ValueTask CreateAreaAsync(RuleAreaEntity entity); + + /// + /// 添加分区信息 + /// + /// + /// + ValueTask AddAreaInfoAsync(RuleAreaInfoEntity entity); + + /// + /// 删除分区信息 + /// + /// 分区信息id + /// + Task DeleteAreaInfo(int areaInfoId); + + /// + /// 删除分区 + /// + /// 分区id + /// + ValueTask DeleteArea(int areaId); + + /// + /// 更新区域信息 + /// + /// + /// + Task UpdateAreaInfoAsync(RuleAreaInfoEntity entity); + + /// + /// 获得分区 + /// + /// + /// + Task> GetAreas(QueryAreaRequest query); + + /// + /// 获取分区信息 + /// + /// + /// + Task> GetAreaInfos(QueryAreaInfoRequest query); + + /// + /// 获取分区信息通过id + /// + /// + /// + Task GetAreaInfoById(int id); + + /// + /// 获取所有区域信息 + /// + /// + Task> GetAllAreaInfos(); +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaEntity.cs b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaEntity.cs new file mode 100644 index 00000000..2f404cea --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaEntity.cs @@ -0,0 +1,50 @@ +namespace SJZY.Track.Domain.Aggregates.KPIAreaAggregate; + +[SugarTable("t_rule_area", TableDescription = "KPI分区主表")] +public class RuleAreaEntity : IAggregateRoot +{ + /// + /// 自增主键 + /// + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "自增主键")] + public int Id { get; set; } + + /// + /// 子系统id + /// + [SugarColumn(ColumnName = "SubSystemId", ColumnDescription = "子系统id")] + public int SubSystemId { get; set; } + + /// + /// 分区名称KPI名称 + /// + [SugarColumn(ColumnName = "Name", Length = 64, ColumnDescription = "分区名称KPI名称")] + public string Name { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "CreateUserId", ColumnDescription = "创建人")] + public int CreateUserId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "CreateTime", ColumnDescription = "创建时间")] + public DateTime CreateTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "UpdateUserId", ColumnDescription = "更新人")] + public int UpdateUserId { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "UpdateTime", ColumnDescription = "更新时间")] + public DateTime UpdateTime { get; set; } + + [SugarColumn(IsIgnore = true)] + public List AreaInfos { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaInfoEntity.cs b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaInfoEntity.cs new file mode 100644 index 00000000..66b28382 --- /dev/null +++ b/src/SJZY.Track.Domain/Aggregates/KPIAreaAggregate/RuleAreaInfoEntity.cs @@ -0,0 +1,71 @@ +namespace SJZY.Track.Domain.Aggregates.KPIAreaAggregate; + +[SugarTable("t_rule_area_info", TableDescription = "kpi 区域子表")] +public class RuleAreaInfoEntity : IEntity +{ + /// + /// 自增主键 + /// + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "自增主键")] + public int Id { get; set; } + + /// + /// t_rule_area 表id + /// + [SugarColumn(ColumnName = "AreaId", ColumnDescription = "t_rule_area 表id")] + public int AreaId { get; set; } + + /// + /// 国家或地区 + /// + [SugarColumn(ColumnName = "Country", Length = 128, ColumnDescription = "国家或地区")] + public string Country { get; set; } + + /// + /// 州或者省份 + /// + [SugarColumn(ColumnName = "Province", Length = 128, IsNullable = true, ColumnDescription = "州或者省份")] + public string Province { get; set; } + + /// + /// 城市 + /// + [SugarColumn(ColumnName = "City", Length = 128, IsNullable = true, ColumnDescription = "城市")] + public string City { get; set; } + + /// + /// 起始邮编 + /// + [SugarColumn(ColumnName = "LeftPostcode", Length = 10, IsNullable = true, ColumnDescription = "起始邮编")] + public string LeftPostcode { get; set; } + + /// + /// 截止邮编 + /// + [SugarColumn(ColumnName = "RightPostcode", Length = 10, IsNullable = true, ColumnDescription = "截止邮编")] + public string RightPostcode { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "CreateUserId", ColumnDescription = "创建人")] + public int CreateUserId { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "CreateTime", ColumnDescription = "创建时间")] + public DateTime CreateTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "UpdateUserId", IsNullable = false, ColumnDescription = "更新人")] + public int UpdateUserId { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "UpdateTime", IsNullable = false, ColumnDescription = "更新时间")] + public DateTime UpdateTime { get; set; } +} \ 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 e0f19389..9a7c4597 100644 --- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs +++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs @@ -131,6 +131,24 @@ public class OrderEntity : IFullAuditedBasicEntitys, IAggregateRoot /// [SugarColumn(ColumnName = "LeavePort")] public string? LeavePort { get; set; } + + /// + /// 起运港口 + /// + [SugarColumn(ColumnName = "CargoType")] + public string? CargoType { get; set; } + + /// + /// 起运港口 + /// + [SugarColumn(ColumnName = "IsTransfer")] + public bool? IsTransfer { get; set; } + + /// + /// 起运港口 + /// + [SugarColumn(ColumnName = "ProductCode")] + public string? ProductCode { get; set; } [SugarColumn(IsIgnore = true)] public List OrderFlights { get; set; } [SugarColumn(IsIgnore = true)] public List OrderTemplates { get; set; } diff --git a/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs b/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs index 3dd246c4..baf25867 100644 --- a/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.ES.cs @@ -11,4 +11,9 @@ public partial class GlobalConst /// 轨迹推送记录 es索引名称(模板) /// public const string TrackPushRecordsIndex = "sjzy_track_push_records"; + + /// + /// 预警规则 es索引名称(模板) + /// + public const string RuleFactorIndex = "sjzy_rule_factor"; } \ 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 index e2ca18ae..dcaf7a35 100644 --- a/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs +++ b/src/SJZY.Track.Domain/Consts/GlobalConst.Redis.cs @@ -21,4 +21,19 @@ public partial class GlobalConst /// 轨迹拉取配置信息redis key前缀 /// public const string TrackPullContentKeyPrefix = "TrackPullContent"; + + /// + /// 规则因素缓存redis key前缀 + /// + public const string RuleFactorKeyPrefix = "RuleFactor"; + + /// + /// 预警通知redis key前缀 + /// + public const string ForewarningNotifyKeyPrefix = "ForewarningNotity"; + + /// + /// kpi区域redis key前缀 + /// + public const string KpiAreaKeyPrefix = "KpiArea"; } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/AddRuleAreaInfoRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/AddRuleAreaInfoRequest.cs new file mode 100644 index 00000000..789dd29f --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/AddRuleAreaInfoRequest.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class AddRuleAreaInfoRequest +{ + [Required] + public string Country { get; set; } + + public string? Province { get; set; } + + public string? City { get; set; } + + public string? LeftPostCode { get; set; } + + public string? RightPostCode { get; set; } + + [Required] + public int AreaId { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/AreaDto.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/AreaDto.cs new file mode 100644 index 00000000..d0703d4a --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/AreaDto.cs @@ -0,0 +1,9 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class AreaDto +{ + public int Id { get; set; } + public int SubSystemId { get; set; } + public string Name { get; set; } + public DateTime UpdateTime { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/AreaInfoDto.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/AreaInfoDto.cs new file mode 100644 index 00000000..9ac65e86 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/AreaInfoDto.cs @@ -0,0 +1,35 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleAreaInfoDto +{ + /// + /// 分区信息id + /// + public int Id { get; set; } + + /// + /// 分区id + /// + public int AreaId { get; set; } + + /// + /// 国家或地区 + /// + public string Country { get; set; } + + /// + /// 省份 + /// + public string Province { get; set; } + + /// + /// 城市 + /// + public string City { get; set; } + + /// + /// 开始邮编 + /// + public string LeftPostcode { get; set; } + public string RightPostcode { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleAreaRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleAreaRequest.cs new file mode 100644 index 00000000..a3801625 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleAreaRequest.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class CreateRuleAreaRequest +{ + /// + /// 系统id + /// + [Required] + public int SystemId { get; set; } + + /// + /// 名称 + /// + [Required] + public string Name { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleRequest.cs new file mode 100644 index 00000000..68199b0f --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/CreateRuleRequest.cs @@ -0,0 +1,65 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning +{ + public class CreateRuleFactorRequest + { + /// + /// RuleId 表的id,小于0 表示创建新的规则 + /// + public int RuleId { get; set; } + + /// + /// 模板名称 + /// + public string Name { get; set; } + + /// + /// 子系统id + /// + public int SubSystemId { get; set; } + + /// + /// 客户id + /// + public int CustomId { get; set; } + + /// + /// 获取或设置规则跟踪状态实体的列表。 + /// + public List Tracks { get; set; } + + /// + /// 获取或设置因素项模型的列表。 + /// + public List FactorItems { get; set; } + + /// + /// 获取或设置货物类型的列表。 + /// + public List CargoTypes { get; set; } + + /// + /// 获取或设置月份的列表。 + /// + public List Months { get; set; } + + /// + /// 获取或设置是否中转的列表。 + /// + public List IsTransit { get; set; } + + /// + /// 获取或设置区域的列表。 + /// + public List Areas { get; set; } + + /// + /// 获取或设置起运港口的列表。 + /// + public List DeparturePorts { get; set; } + + /// + /// 获取或设置产品编号的列表。 + /// + public List ProductCodes { get; set; } + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/FactorItemDto.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/FactorItemDto.cs new file mode 100644 index 00000000..9360d491 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/FactorItemDto.cs @@ -0,0 +1,16 @@ +using SJZY.Track.Domain.Enums; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class FactorItemDto +{ + /// + /// Gets or sets the sort order. + /// + public int Sort { get; set; } + + /// + /// Gets or sets the type of the rule factor. + /// + public RuleFactorType FactorType { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs new file mode 100644 index 00000000..c44d633f --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs @@ -0,0 +1,30 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class ForewarningOrderModel:IForewarningFactorValue +{ + /// + /// 订单id + /// + public int Id { get; set; } + + /// + /// 当前轨迹状态 + /// + public int Track { get; set; } + + public int SystemId { get; set; } + + public int CustomerId { get; set; } + + public string CargoType { get; set; } + + public int? Month { get; set; } + + public int? Area { get; set; } + + public bool? IsTransit { get; set; } + + public string DeparturePort { get; set; } + + public string ProductCode { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRule.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRule.cs new file mode 100644 index 00000000..b8499e64 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRule.cs @@ -0,0 +1,26 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public record struct ForewarningRule:IForewarningFactorValue +{ + public int Id { get; set; } + + public int CustomerId { get; set; } + + public int SystemId { get; set; } + public int RuleId { get; set; } + public float Remind { get; set; } + public float Timeliness { get; set; } + public int Count { get; set; } + public int TrackStart { get; set; } + public int TrackEnd { get; set; } + public string CargoType { get; set; } + public int? Month { get; set; } + public int? Area { get; set; } + public bool? IsTransit { get; set; } + public string DeparturePort { get; set; } + public string ProductCode { get; set; } + + public string Conect { get; set; } + + public string Template { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs new file mode 100644 index 00000000..4ace20ac --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs @@ -0,0 +1,16 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public interface IForewarningFactorValue +{ + public string CargoType { get; set; } + + public int? Month { get; set; } + + public int? Area { get; set; } + + public bool? IsTransit { get; set; } + + public string DeparturePort { get; set; } + + public string ProductCode { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/KpiAreaInfo.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/KpiAreaInfo.cs new file mode 100644 index 00000000..a9273783 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/KpiAreaInfo.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class KpiAreaInfo +{ + +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/ModifyTimelinessRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/ModifyTimelinessRequest.cs new file mode 100644 index 00000000..8b023cac --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/ModifyTimelinessRequest.cs @@ -0,0 +1,34 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class ModifyTimelinessRequest +{ + public List Items { get; set; } + + /// + /// 规则模板id + /// + public int RuleId { get; set; } +} + +public class TimelinessDto +{ + /// + /// 时效 + /// + public float Timeliness { get; set; } + + /// + /// 提醒时效 + /// + public float Remind { get; set; } + + /// + /// 提醒次数 + /// + public int Count { get; set; } + + /// + /// 规则id + /// + public int Id { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaInfoRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaInfoRequest.cs new file mode 100644 index 00000000..196a65bf --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaInfoRequest.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class QueryAreaInfoRequest: PageInfoInput +{ + public int AreaId { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaRequest.cs new file mode 100644 index 00000000..31befffd --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryAreaRequest.cs @@ -0,0 +1,14 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class QueryAreaRequest:PageInfoInput +{ + /// + /// 分区名称 + /// + public string? Name { get; set; } + + /// + /// 子系统id + /// + public int? SystemId { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRequest.cs new file mode 100644 index 00000000..5bb9fea1 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRequest.cs @@ -0,0 +1,24 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class QueryForewarningRequest: PageInfoInput +{ + /// + /// 子系统id + /// + public int? SystemId { get; set; } + + /// + /// 客户或者模板名称 + /// + public string? KeyWord { get; set; } + + /// + /// 排序方式,不填不排序 + /// + public string? SortField { get; set; } + + /// + /// 排序方式 + /// + public bool IsAsc { get; set; } = false; +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRuleRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRuleRequest.cs new file mode 100644 index 00000000..0014a95a --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/QueryForewarningRuleRequest.cs @@ -0,0 +1,19 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class QueryForewarningRuleRequest: PageInfoInput +{ + /// + /// kpi 预警规则模板id + /// + public int RuleId { get; set; } + + /// + /// 排序方式,不填不排序 + /// + public string? SortField { get; set; } + + /// + /// 排序方式 + /// + public bool IsAsc { get; set; } = false; +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectDto.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectDto.cs new file mode 100644 index 00000000..4cce0e58 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectDto.cs @@ -0,0 +1,22 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleCollectDto +{ + public int Id { get; set; } + public int RuleId { get; set; } + public float Remind { get; set; } + public float Timeliness { get; set; } + public int Count { get; set; } + public int TrackStart { get; set; } + public int TrackEnd { get; set; } + public string CargoType { get; set; } + public string Month { get; set; } + public int? Area { get; set; } + public bool? IsTransit { get; set; } + public string DeparturePort { get; set; } + public string ProductCode { get; set; } + public int CreateUserId { get; set; } + public DateTime CreateTime { get; set; } + public int UpdateUserId { get; set; } + public DateTime UpdateTime { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectRequest.cs new file mode 100644 index 00000000..b4b1fadd --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleCollectRequest.cs @@ -0,0 +1,7 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleCollectRequest +{ + public string Name { get; set; } + +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/RuleFactor.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleFactor.cs new file mode 100644 index 00000000..add12997 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleFactor.cs @@ -0,0 +1,37 @@ +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleFactor +{ + public int RuleId { get; set; } + + public int SystemId { get; set; } + + public int CustomerId { get; set; } + + /// + /// Gets or sets the start track value. + /// + public int Start { get; set; } + + /// + /// Gets or sets the end track value. + /// + public int End { get; set; } + + /// + /// Gets or sets the user to notify. + /// + public string NotifyUser { get; set; } + + /// + /// Gets or sets the notification template. + /// + public string NotifyTemplate { get; set; } + + /// + /// 获取或设置因素项模型的列表。 + /// + public List FactorItems { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/RuleInfoModel.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleInfoModel.cs new file mode 100644 index 00000000..93644080 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleInfoModel.cs @@ -0,0 +1,42 @@ +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Enums; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleInfoModel +{ + /// + /// 获取或设置因素项模型的列表。 + /// + public FactorItemModel FactorItems { get; set; } + + /// + /// 获取或设置货物类型的列表。 + /// + public string CargoTypes { get; set; } + + /// + /// 获取或设置月份的列表。 + /// + public short Months { get; set; } + + /// + /// 获取或设置是否中转的列表。 + /// + public bool? IsTransit { get; set; } + + /// + /// 获取或设置区域的列表。 + /// + public int Areas { get; set; } + + /// + /// 获取或设置起运港口的列表。 + /// + public string DeparturePorts { get; set; } + + /// + /// 获取或设置产品编号的列表。 + /// + public string ProductCodes { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/RuleNotifyValue.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleNotifyValue.cs new file mode 100644 index 00000000..eda39cc7 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleNotifyValue.cs @@ -0,0 +1,40 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleNotifyValue +{ + public int RuleId { get; set; } + + public int OrderId { get; set; } + + /// + /// 第几次通知 + /// + public int Count { get; set; } + + /// + /// 结束轨迹状态 + /// + public int TrackEnd { get; set; } + + public RuleNotifyValue(int ruleId, int orderId, int count, int trackEnd) + { + RuleId = ruleId; + OrderId = orderId; + Count = count; + TrackEnd = trackEnd; + } + + public RuleNotifyValue(string notifyValue) + { + var values = notifyValue.Split(':'); + RuleId = int.Parse(values[0]); + OrderId = int.Parse(values[1]); + Count = int.Parse(values[2]); + TrackEnd = int.Parse(values[3]); + } + + public override string ToString() + { + return $"{RuleId}:{OrderId}:{Count}:{TrackEnd}"; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/RuleTrackStateDto.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleTrackStateDto.cs new file mode 100644 index 00000000..52abd1fa --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/RuleTrackStateDto.cs @@ -0,0 +1,24 @@ +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class RuleTrackStateDto +{ + /// + /// Gets or sets the start track value. + /// + public int Start { get; set; } + + /// + /// Gets or sets the end track value. + /// + public int End { get; set; } + + /// + /// Gets or sets the user to notify. + /// + public string NotifyUser { get; set; } + + /// + /// Gets or sets the notification template. + /// + public string NotifyTemplate { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaInfoRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaInfoRequest.cs new file mode 100644 index 00000000..c6f52158 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaInfoRequest.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class UpdateRuleAreaInfoRequest +{ + /// + /// 分区信息id + /// + public int Id { get; set; } + + [Required] + public string Country { get; set; } + + public string? Province { get; set; } + + public string? City { get; set; } + + public string? LeftPostCode { get; set; } + + public string? RightPostCode { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaRequest.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaRequest.cs new file mode 100644 index 00000000..f0bac318 --- /dev/null +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/UpdateRuleAreaRequest.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; + +namespace SJZY.Track.Domain.Dtos.Forewarning; + +public class UpdateRuleAreaRequest +{ + /// + /// 名称 + /// + [Required] + public string Name { get; set; } + + /// + /// 分区id + /// + public int Id { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Enums/RuleFactorType.cs b/src/SJZY.Track.Domain/Enums/RuleFactorType.cs new file mode 100644 index 00000000..64d32839 --- /dev/null +++ b/src/SJZY.Track.Domain/Enums/RuleFactorType.cs @@ -0,0 +1,38 @@ +namespace SJZY.Track.Domain.Enums; + + +/// +/// 枚举表示不同类型的规则因素。 +/// +public enum RuleFactorType +{ + /// + /// 表示货物类型。 + /// + CargoType, + + /// + /// 表示月份。 + /// + Month, + + /// + /// 表示分区或区域。 + /// + Areas, + + /// + /// 指示货物是否中转。 + /// + IsTransit, + + /// + /// 表示起运港口。 + /// + DeparturePort, + + /// + /// 表示产品编号。 + /// + ProductCode +} \ No newline at end of file diff --git a/src/SJZY.Track.Domain/SJZY.Track.Domain.csproj b/src/SJZY.Track.Domain/SJZY.Track.Domain.csproj index d086d460..ea3705c5 100644 --- a/src/SJZY.Track.Domain/SJZY.Track.Domain.csproj +++ b/src/SJZY.Track.Domain/SJZY.Track.Domain.csproj @@ -11,5 +11,10 @@ + + + + + diff --git a/src/SJZY.Track.Repository/Repositories/KpiAreaInfoRepository.cs b/src/SJZY.Track.Repository/Repositories/KpiAreaInfoRepository.cs new file mode 100644 index 00000000..de1e628d --- /dev/null +++ b/src/SJZY.Track.Repository/Repositories/KpiAreaInfoRepository.cs @@ -0,0 +1,6 @@ +namespace SJZY.Track.Repository.Repositories; + +public class KpiAreaInfoRepository +{ + +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/KpiAreaRepository.cs b/src/SJZY.Track.Repository/Repositories/KpiAreaRepository.cs new file mode 100644 index 00000000..601821e5 --- /dev/null +++ b/src/SJZY.Track.Repository/Repositories/KpiAreaRepository.cs @@ -0,0 +1,103 @@ +using SJZY.Track.Domain; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Aggregates.KPIAreaAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Repository.Repositories; + +public class KpiAreaRepository:BasicRepository ,IKpiAreaRepository,ITransientDependency +{ + public async ValueTask CreateAreaAsync(RuleAreaEntity entity) + { + return await InsertReturnIdentityAsync(entity); + } + + public async ValueTask AddAreaInfoAsync(RuleAreaInfoEntity entity) + { + return await Context.Insertable(entity).ExecuteReturnIdentityAsync(); + } + + public async ValueTask DeleteArea(int areaId) + { + using var transaction = TransactionHelper.GetReadCommitted(); + await DeleteByIdAsync(areaId); + await Context.Deleteable().Where(x => x.AreaId == areaId).ExecuteCommandAsync(); + transaction.Complete(); + } + + public Task DeleteAreaInfo(int areaInfoId) + { + return Context.Deleteable().Where(val=>val.Id==areaInfoId).ExecuteCommandAsync(); + } + + public Task UpdateAreaInfoAsync(RuleAreaInfoEntity entity) + { + return Context.Updateable(entity).ExecuteCommandAsync(); + } + + /// + /// 获取分区 + /// + /// + /// + public async Task> GetAreas(QueryAreaRequest query) + { + var queryable = Context.Queryable(); + if (!string.IsNullOrEmpty(query.Name)) + { + queryable = queryable.Where(x => x.Name.Contains(query.Name)); + } + + if (query.SystemId.HasValue) + { + queryable = queryable.Where(x => x.SubSystemId == query.SystemId.Value); + } + + return await queryable.OrderBy(x => x.Id, OrderByType.Desc) + .Select(val=>new AreaDto() + { + Id = val.Id, + Name = val.Name, + SubSystemId = val.SubSystemId, + UpdateTime = val.CreateTime + }) + .ToPagedListAsync(query.PageIndex, query.PageSize); + } + + /// + /// 获得分区信息 + /// + /// + /// + public async Task> GetAreaInfos(QueryAreaInfoRequest query) + { + var queryable = Context.Queryable(); + queryable = queryable.Where(x => x.AreaId == query.AreaId); + return await queryable.OrderBy(x => x.Id, OrderByType.Desc) + .Select(val=>new RuleAreaInfoDto() + { + Id = val.Id, + AreaId = val.AreaId, + City = val.City, + Country = val.Country, + LeftPostcode = val.LeftPostcode, + RightPostcode = val.RightPostcode, + Province = val.Province + }) + .ToPagedListAsync(query.PageIndex, query.PageSize); + } + + public Task GetAreaInfoById(int id) + { + return Context.Queryable().FirstAsync(val => val.Id == id); + } + + /// + /// 获取所有区域信息 + /// + /// + public Task> GetAllAreaInfos() + { + return Context.Queryable().ToListAsync(); + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/RuleCollectRepository.cs b/src/SJZY.Track.Repository/Repositories/RuleCollectRepository.cs new file mode 100644 index 00000000..250eedf1 --- /dev/null +++ b/src/SJZY.Track.Repository/Repositories/RuleCollectRepository.cs @@ -0,0 +1,50 @@ +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Repository.Repositories; + +public class RuleCollectRepository: BasicRepository, IRuleCollectRepository,ITransientDependency +{ + /// + /// 查询预警规则分页信息 + /// + /// + /// + public Task> QueryForewarningRule(QueryForewarningRuleRequest input) + { + var query = Context.Queryable() + .Where(val => val.RuleId == input.RuleId); + + if (!string.IsNullOrEmpty(input.SortField)) + { + query = query.OrderByPropertyName(input.SortField, input.IsAsc ? OrderByType.Asc : OrderByType.Desc); + } + + return query.Select(val=>MapToDto(val)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + } + + private RuleCollectDto MapToDto(RuleCollectEntity entity) + { + return new RuleCollectDto() + { + Id = entity.Id, + RuleId = entity.RuleId, + Remind = entity.Remind, + Timeliness = entity.Timeliness, + Count = entity.Count, + TrackStart = entity.TrackStart, + TrackEnd = entity.TrackEnd, + CargoType = entity.CargoType, + Month = entity.Month, + Area = entity.Area, + IsTransit = entity.IsTransit, + DeparturePort = entity.DeparturePort, + ProductCode = entity.ProductCode, + CreateUserId = entity.CreateUserId, + CreateTime = entity.CreateTime, + UpdateUserId = entity.UpdateUserId, + UpdateTime = entity.UpdateTime + }; + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/RuleFactorRepository.cs b/src/SJZY.Track.Repository/Repositories/RuleFactorRepository.cs new file mode 100644 index 00000000..b9492f28 --- /dev/null +++ b/src/SJZY.Track.Repository/Repositories/RuleFactorRepository.cs @@ -0,0 +1,53 @@ +using Nest; +using SJZY.Expand.ElasticSearch.Services; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; + +namespace SJZY.Track.Repository.Repositories; + +public class RuleFactorRepository:ElasticSearchContextAbstract, IRuleFactorRepository, + ITransientDependency +{ + public RuleFactorRepository(ConnectionFactory connectionFactory) : base(connectionFactory) + { + } + + public async Task CreateAsync(RuleFactorEntity entity) + { + await IndexDocumentAsync(entity); + } + + public async Task> GetFactorByIdsAsync(int[] ruleIds) + { + var response = await Context.SearchAsync(s => s.Query(q => q.Terms(t => t.Field(f => f.RuleId).Terms(ruleIds)))); + int num = response.ApiCall.HttpStatusCode ?? throw new Exception("数据查询失败,原因:" + response.DebugInformation); + switch (num) + { + case 200: + return response.Documents.ToList(); + case 404: + return new List(); + default: + throw new Exception($"数据查询失败,http status: {num},原因:{response.DebugInformation}"); + } + } + + /// + /// 获取所有数据 + /// + /// + /// + public async Task> GetAllList() + { + var response = await Context.SearchAsync(); + int num = response.ApiCall.HttpStatusCode ?? throw new Exception("数据查询失败,原因:" + response.DebugInformation); + switch (num) + { + case 200: + return response.Documents.ToList(); + case 404: + return new List(); + default: + throw new Exception($"数据查询失败,http status: {num},原因:{response.DebugInformation}"); + } + } +} \ No newline at end of file diff --git a/src/SJZY.Track.Repository/Repositories/RuleRepository.cs b/src/SJZY.Track.Repository/Repositories/RuleRepository.cs new file mode 100644 index 00000000..4867ab3f --- /dev/null +++ b/src/SJZY.Track.Repository/Repositories/RuleRepository.cs @@ -0,0 +1,53 @@ +using SJZY.Track.Domain; +using SJZY.Track.Domain.Aggregates.ForewarningAggregate; +using SJZY.Track.Domain.Dtos.Forewarning; + +namespace SJZY.Track.Repository.Repositories; + +public class RuleRepository:BasicRepository ,IRuleRepository,ITransientDependency +{ + public async Task CreateForewarning(RuleEntity rule, RuleCollectEntity[] factorList) + { + using var tran = TransactionHelper.GetReadCommitted(); + + var ruleId = await InsertReturnIdentityAsync(rule); + foreach (var item in factorList) + { + item.RuleId = ruleId; + } + await Context.Insertable(factorList).ExecuteCommandAsync(); + tran.Complete(); + return ruleId; + } + + public async Task UpdateForewarning(RuleEntity rule,RuleCollectEntity[] factorList) + { + using var tran = TransactionHelper.GetReadCommitted(); + await UpdateAsync(rule); + await Context.Deleteable().Where(x=>x.RuleId==rule.Id).ExecuteCommandAsync(); + await Context.Insertable(factorList).ExecuteCommandAsync(); + tran.Complete(); + } + + /// + /// 查询预警模板分页信息 + /// + /// + /// + public Task> QueryForewarning(QueryForewarningRequest input) + { + var query = Context.Queryable() + .WhereIF(input.SystemId.HasValue,val=>val.SubSystemId == input.SystemId) + .WhereIF(string.IsNullOrEmpty(input.KeyWord), val=> val.CustomName.Contains(input.KeyWord)||val.Name.Contains(input.KeyWord)); + + if (!string.IsNullOrEmpty(input.SortField)) + { + query = query.OrderByPropertyName(input.SortField, input.IsAsc ? OrderByType.Asc : OrderByType.Desc); + } + + return query.ToPagedListAsync(input.PageIndex, input.PageSize); + } + + + +} \ No newline at end of file