diff --git a/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs index b6632dea..8293c2fb 100644 --- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs +++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs @@ -13,7 +13,7 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa private readonly IOrderRepository _orderRepository; private readonly IForewarningNotifyService _forewarningNotifyService; - public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository, + public TrackChangeAfterUpdateOrderEventHandler(IOrderRepository orderRepository, IForewarningNotifyService forewarningNotifyService) { _orderRepository = orderRepository; @@ -23,19 +23,7 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa [CapSubscribe(GlobalConst.TrackChangeAfterUpdateOrderSubscribe)] public async Task ConsumerAsync(TrackChangeAfterUpdateOrderEvent @event) { - var orders = await _orderRepository.GetListAsync(x => @event.OrderIds.Contains(x.Id), - x => new OrderEntity - { - Id = x.Id, - IsCompleted = x.IsCompleted, - LatestTrackContent = x.LatestTrackContent, - LatestTrackEnContent = x.LatestTrackEnContent, - LatestTrackPlace = x.LatestTrackPlace, - LatestTrackTime = x.LatestTrackTime, - LatestTrackTimeZone = x.LatestTrackTimeZone, - ArrivalCountry = x.ArrivalCountry, - ArrivalCity = x.ArrivalCity, - }); + var orders = await _orderRepository.GetListAsync(x => @event.OrderIds.Contains(x.Id), x => MapOrderSummary(x)); if (orders.Count == 0) return; @@ -70,41 +58,78 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa x.IsCompleted, x.LatestTrackContent, x.LatestTrackEnContent, x.LatestTrackPlace, x.LatestTrackTime, x.LatestTrackTimeZone }); + + // 预警计算 + WarningCalculationAsync(orders); } - private ForewarningOrderModel OrderToForewarningOrderModel(OrderEntity order) -{ - return new ForewarningOrderModel + private Task WarningCalculationAsync(List orders) { - Id = order.Id, - Track = DetermineTrackBasedOnOrderDetails(order), - SystemId = order.SubSystemId, - CustomerId = order.CustomId, - CargoType = order.CargoType, - Month = order.CreateTime.Month, - Area = DetermineAreaBasedOnOrderDetails(order), - IsTransit = order.IsTransit, - DeparturePort = order.LeavePort, - ProductCode = order.ProductCode - }; -} + var forewarningOrderModels = orders.Select(OrderToForewarningOrderModel).ToList(); + + return Task.CompletedTask; + } + + private OrderEntity MapOrderSummary(OrderEntity x) + { + return new OrderEntity + { + Id = x.Id, + + // 轨迹 + IsCompleted = x.IsCompleted, + LatestTrackContent = x.LatestTrackContent, + LatestTrackEnContent = x.LatestTrackEnContent, + LatestTrackPlace = x.LatestTrackPlace, + LatestTrackTime = x.LatestTrackTime, + LatestTrackTimeZone = x.LatestTrackTimeZone, + + // 因素 + CargoType = x.CargoType, + CreateTime = x.CreateTime, + ArrivalCountry = x.ArrivalCountry, + ArrivalProvince = x.ArrivalProvince, + ArrivalCity = x.ArrivalCity, + ArrivalPostCode = x.ArrivalPostCode, + IsTransit = x.IsTransit, + LeavePort = x.LeavePort, + ProductCode = x.ProductCode + }; + } + + 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.IsTransit, + LeavePort = 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 DetermineTrackBasedOnOrderDetails(OrderEntity order) + { + // Implement logic to determine Track + return default; + } -private int? DetermineMonthBasedOnOrderDetails(OrderEntity order) -{ - // Implement logic to determine Month - 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; -} + 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/ForewarningHelper.cs b/src/SJZY.Track.Application/Helpers/ForewarningHelper.cs index cfdc5cfb..c85ef3db 100644 --- a/src/SJZY.Track.Application/Helpers/ForewarningHelper.cs +++ b/src/SJZY.Track.Application/Helpers/ForewarningHelper.cs @@ -1,3 +1,5 @@ +using System.Dynamic; +using Nest; using Newtonsoft.Json.Linq; using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Track.Application.Contract.Dtos.Forewarning; @@ -30,7 +32,7 @@ public class ForewarningHelper throw new BusinessException(message: "轨迹状态区间或因素列表为空"); } - var rules = Enumerable.Repeat(new WarningRuleEntity(), len).ToList(); + var rules = Enumerable.Range(0, len).Select(_ => new WarningRuleEntity()).ToList(); var repeat = len / statusSpans.Count; @@ -41,7 +43,7 @@ public class ForewarningHelper var factorValueCount = factor.FactorValue.Count; // repeat梯度下降,与times成反比关系 - repeat /= factor.FactorValue.Count; + repeat /= factorValueCount; var times = len / repeat / factorValueCount; FillFactor(factor, rules, repeat, times); } @@ -184,4 +186,53 @@ public class ForewarningHelper }).ToList() }; } + + public static List DynamicCalcRuleList(List rules, List factors) + { + var dynamicList = new List(); + + foreach (var rule in rules) + { + dynamic dynamicRule = new ExpandoObject(); + var dynamicRuleDict = (IDictionary)dynamicRule; + + dynamicRuleDict[nameof(Id)] = rule.Id; + dynamicRuleDict[nameof(rule.StartTrackStatus)] = rule.StartTrackStatus; + dynamicRuleDict[nameof(rule.EndTrackStatus)] = rule.EndTrackStatus; + + foreach (var factor in factors) + { + switch (factor) + { + case RuleFactorType.CargoType: + dynamicRuleDict[nameof(rule.CargoType)] = rule.CargoType; + break; + case RuleFactorType.Months: + dynamicRuleDict[nameof(rule.Months)] = rule.Months; + break; + case RuleFactorType.Areas: + dynamicRuleDict[nameof(rule.Area)] = rule.Area; + break; + case RuleFactorType.IsTransit: + dynamicRuleDict[nameof(rule.IsTransit)] = rule.IsTransit; + break; + case RuleFactorType.LeavePort: + dynamicRuleDict[nameof(rule.LeavePort)] = rule.LeavePort; + break; + case RuleFactorType.ProductCode: + dynamicRuleDict[nameof(rule.ProductCode)] = rule.ProductCode; + break; + default: + throw new BusinessException(message: $"不支持的因素:{factor}"); + } + } + + dynamicRuleDict[nameof(rule.TotalTimeSpan)] = rule.TotalTimeSpan; + dynamicRuleDict[nameof(rule.WarnTimeSpan)] = rule.WarnTimeSpan; + dynamicRuleDict[nameof(rule.WarnCount)] = rule.WarnCount; + dynamicList.Add(dynamicRule); + } + + return dynamicList; + } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs index 3beac40f..8aa91e75 100644 --- a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs +++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs @@ -221,7 +221,7 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep case RuleFactorType.CargoType: return rule.CargoType; case RuleFactorType.LeavePort: - return rule.DeparturePort; + return rule.LeavePort; case RuleFactorType.Months: return rule.Month.HasValue ? rule.Month.Value.ToString() : throw new Exception("月份不能为空"); case RuleFactorType.ProductCode: diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs index 6d8a61d4..abe4f846 100644 --- a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs +++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningService.cs @@ -3,6 +3,7 @@ using SJZY.Track.Application.Contract.Dtos.Forewarning; using SJZY.Track.Application.Helpers; using SJZY.Track.Domain.Aggregates.ForewarningAggregate; using SJZY.Track.Domain.Dtos.Forewarning; +using SJZY.Track.Domain.Queries; namespace SJZY.Track.Application.Services.ForewarningServices; @@ -38,6 +39,13 @@ public class ForewarningService : ApplicationService public async Task CreateWarning(CreateWarningInput input) { var warning = ObjectMapper.Map(input); + + if (await _warningRepository.IsAnyAsync(x => + x.SubSystemId == warning.SubSystemId && x.CustomerId == warning.CustomerId && x.Name == warning.Name)) + { + throw new BusinessException(message: "该子系统下的客户已经存在一个同名预警: " + warning.Name); + } + warning.WarningRules = ForewarningHelper.CalcRuleList(input.TrackStatusSpans, input.WarningFactors); warning.WarningFactors = ForewarningHelper.MapFactorEntities(input.WarningFactors); warning.WarningNotifies = ForewarningHelper.MapNotifyEntities(input); @@ -126,18 +134,21 @@ public class ForewarningService : ApplicationService return await _warningRepository.TurnWarningAsync(warning); } - + /// /// 查询预警规则列表 /// /// 预警规则id + /// /// [HttpGet("GetWarningRuleList")] - public async Task> GetWarningRuleListAsync([Required] int warningId) + public async Task> GetWarningRuleListAsync([Required] int warningId, [FromServices] IBasicQuery factorQuery) { + var factors = await factorQuery.GetListAsync(x => x.WarningId == warningId, x => x.Type); var rules = await _warningRepository.GetWarningRuleListAsync(warningId); - - return rules; + + var dynamicList = ForewarningHelper.DynamicCalcRuleList(rules, factors); + return dynamicList; } /// diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs index c44d633f..8dbd7ae5 100644 --- a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs @@ -16,7 +16,7 @@ public class ForewarningOrderModel:IForewarningFactorValue public int CustomerId { get; set; } - public string CargoType { get; set; } + public string? CargoType { get; set; } public int? Month { get; set; } @@ -24,7 +24,10 @@ public class ForewarningOrderModel:IForewarningFactorValue public bool? IsTransit { get; set; } - public string DeparturePort { get; set; } + /// + /// 起运港 + /// + public string? LeavePort { get; set; } - public string ProductCode { get; set; } + public string? ProductCode { get; set; } } \ No newline at end of file diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRuleItem.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRuleItem.cs index ef550296..9e03f6c2 100644 --- a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRuleItem.cs +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningRuleItem.cs @@ -13,12 +13,12 @@ public record struct ForewarningRuleItem:IForewarningFactorValue public int Count { get; set; } public int TrackStart { get; set; } public int TrackEnd { get; set; } - public string CargoType { 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? LeavePort { get; set; } + public string? ProductCode { get; set; } public string Conect { get; set; } diff --git a/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs index 4ace20ac..11dae2ce 100644 --- a/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/IForewarningFactorValue.cs @@ -2,7 +2,7 @@ namespace SJZY.Track.Domain.Dtos.Forewarning; public interface IForewarningFactorValue { - public string CargoType { get; set; } + public string? CargoType { get; set; } public int? Month { get; set; } @@ -10,7 +10,7 @@ public interface IForewarningFactorValue public bool? IsTransit { get; set; } - public string DeparturePort { get; set; } + public string? LeavePort { get; set; } - public string ProductCode { get; set; } + public string? ProductCode { get; set; } } \ No newline at end of file