diff --git a/src/SJZY.Track.Application.Contract/Dtos/Forewarning/AreaCacheEntry.cs b/src/SJZY.Track.Application.Contract/Dtos/Forewarning/AreaCacheEntry.cs new file mode 100644 index 00000000..1e87ff17 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/Forewarning/AreaCacheEntry.cs @@ -0,0 +1,29 @@ +namespace SJZY.Track.Application.Contract.Dtos.Forewarning; + +public class AreaCacheEntry +{ + /// + /// 国家或地区 + /// + public string Country { get; set; } = null!; + + /// + /// 省份 + /// + 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.Application.Contract/Dtos/Forewarning/ForewarningRuleCacheEntry.cs b/src/SJZY.Track.Application.Contract/Dtos/Forewarning/ForewarningRuleCacheEntry.cs new file mode 100644 index 00000000..09ab3e1d --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Dtos/Forewarning/ForewarningRuleCacheEntry.cs @@ -0,0 +1,69 @@ +namespace SJZY.Track.Application.Contract.Dtos.Forewarning; + +public class ForewarningRuleCacheEntry +{ + /// + /// 自增主键 + /// + public int Id { get; set; } + + /// + /// 预警id + /// + public int WarningId { get; set; } + + /// + /// 时效(小时) e.g. 24 + /// + public float TotalTimeSpan { get; set; } + + /// + /// 提醒的时间(小时) e.g. 9 10 11.. + /// + public float WarnTimeSpan { get; set; } + + /// + /// 提醒次数 e.g. 3 2 1 + /// + public int WarnCount { get; set; } + + /// + /// 起始轨迹状态id + /// + public int StartTrackStatusId { get; set; } + + /// + /// 终止轨迹状态id + /// + public int EndTrackStatusId { get; set; } + + /// + /// 货物类型 + /// + public string? CargoType { get; set; } + + /// + /// 月份 + /// + public List? Months { get; set; } + + /// + /// 区域 + /// + public List? AreaId { get; set; } + + /// + /// 是否中转 + /// + public bool? IsTransit { get; set; } + + /// + /// 起运港口 + /// + public string? LeavePort { get; set; } + + /// + /// 产品编码 + /// + public string? ProductCode { get; set; } +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Services/IForewarningCacheService.cs b/src/SJZY.Track.Application.Contract/Services/IForewarningCacheService.cs new file mode 100644 index 00000000..ce6550f1 --- /dev/null +++ b/src/SJZY.Track.Application.Contract/Services/IForewarningCacheService.cs @@ -0,0 +1,8 @@ +using SJZY.Track.Application.Contract.Dtos.Forewarning; + +namespace SJZY.Track.Application.Contract.Services; + +public interface IForewarningCacheService +{ + Task> GetRulesAsync(int subSystemId); +} \ No newline at end of file diff --git a/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs b/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs index 58dcd995..8830f610 100644 --- a/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs +++ b/src/SJZY.Track.Application.Contract/Services/IForewarningNotifyService.cs @@ -13,14 +13,14 @@ public interface IForewarningNotifyService /// /// 预警订单模型。 /// 创建操作的结果,以整数形式返回。 - Task WarningCalculateAsync(List order); + Task WarningCalculateAsync(List order); /// /// 删除预警通知。 /// /// 预警订单模型。 /// 删除操作的结果,以整数形式返回。 - Task DeleteForewarningNotify(ForewarningOrderModel order); + Task DeleteForewarningNotify(WarningOrderDto order); /// /// 发送通知。 diff --git a/src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs b/src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs deleted file mode 100644 index fb1f742b..00000000 --- a/src/SJZY.Track.Application.Contract/Services/IRuleFactorCacheService.cs +++ /dev/null @@ -1,32 +0,0 @@ -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/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs b/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs index f5766880..0b657f6c 100644 --- a/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs +++ b/src/SJZY.Track.Application/CAP/EventHandlers/TrackChangeAfterUpdateOrderEventHandler.cs @@ -67,67 +67,59 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa }); // 预警计算 - var warningOrders = orders.Select(order => new ForewarningOrderModel - { - Id = order.Id, - TrackStatusId = @event.TrackStatusId, - SubSystemId = order.SubSystemId, - CustomerId = order.CustomId, - CargoType = order.CargoType, - Month = order.CreateTime.Month, - Area = DetermineAreaBasedOnOrderDetails(order), - IsTransit = order.IsTransit, - LeavePort = order.LeavePort, - ProductCode = order.ProductCode - }).ToList(); + var warningOrders = orders.Select(order => MapWarningOrderDto(order, @event.TrackStatusId)).ToList(); + _forewarningNotifyService.WarningCalculateAsync(warningOrders); } - private OrderEntity MapOrderSummary(OrderEntity x) + private OrderEntity MapOrderSummary(OrderEntity order) { return new OrderEntity { - Id = x.Id, - SubSystemId = x.SubSystemId, - CustomId = x.CustomId, + Id = order.Id, + SubSystemId = order.SubSystemId, + CustomId = order.CustomId, // 轨迹 - IsCompleted = x.IsCompleted, - LatestTrackContent = x.LatestTrackContent, - LatestTrackEnContent = x.LatestTrackEnContent, - LatestTrackPlace = x.LatestTrackPlace, - LatestTrackTime = x.LatestTrackTime, - LatestTrackTimeZone = x.LatestTrackTimeZone, + IsCompleted = order.IsCompleted, + LatestTrackContent = order.LatestTrackContent, + LatestTrackEnContent = order.LatestTrackEnContent, + LatestTrackPlace = order.LatestTrackPlace, + LatestTrackTime = order.LatestTrackTime, + LatestTrackTimeZone = order.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 + CargoType = order.CargoType, + CreateTime = order.CreateTime, + ArrivalCountry = order.ArrivalCountry, + ArrivalProvince = order.ArrivalProvince, + ArrivalCity = order.ArrivalCity, + ArrivalPostCode = order.ArrivalPostCode, + 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) + + private WarningOrderDto MapWarningOrderDto(OrderEntity order, int trackStatusId) { - // 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; + return new WarningOrderDto + { + Id = order.Id, + TrackStatusId = trackStatusId, + SubSystemId = order.SubSystemId, + CustomerId = order.CustomId, + + CargoType = order.CargoType, + Month = order.CreateTime.Month, + IsTransit = order.IsTransit, + LeavePort = order.LeavePort, + ProductCode = order.ProductCode, + + ArrivalCountry = order.ArrivalCountry, + ArrivalProvince = order.ArrivalProvince, + ArrivalCity = order.ArrivalCity, + ArrivalPostCode = order.ArrivalPostCode, + }; } } \ No newline at end of file diff --git a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningCacheService.cs b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningCacheService.cs new file mode 100644 index 00000000..289f3bbf --- /dev/null +++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningCacheService.cs @@ -0,0 +1,13 @@ +using SJZY.Track.Application.Contract.Dtos.Forewarning; +using SJZY.Track.Application.Contract.Services; +using Volo.Abp.DependencyInjection; + +namespace SJZY.Track.Application.Services.ForewarningServices; + +public class ForewarningCacheService: IForewarningCacheService, ISingletonDependency +{ + public Task> GetRulesAsync(int subSystemId) + { + throw new NotImplementedException(); + } +} \ 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 c097ff7c..f4b2c418 100644 --- a/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs +++ b/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs @@ -14,15 +14,13 @@ 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) + public ForewarningNotifyService(INotifyService notifyService) { - _ruleFactorCache = ruleFactorCache; _notifyService = notifyService; } @@ -31,31 +29,14 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep /// /// 创建预警通知需要的订单信息 /// 创建的通知总量,0表示没有规则 - public async Task WarningCalculateAsync(List order) + public async Task WarningCalculateAsync(List order) { throw new NotImplementedException(); } - /// - /// 清除预警通知 - /// - /// 订单信息 - /// 清理的行数 - public async Task DeleteForewarningNotify(ForewarningOrderModel order) + public Task DeleteForewarningNotify(WarningOrderDto 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; + throw new NotImplementedException(); } public void SendNotification(int intervalMinute) @@ -96,33 +77,6 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep return members; } - /// - /// 获取规则 - /// - /// - /// - private List GetRule(ForewarningOrderModel order) - { - if (!_factorDict.TryGetValue(GetFactorKey(order.CustomerId, order.SubSystemId), out var factors)) - { - return null; - } - - var keys = GetForewarningKeys(factors, order); - var result = new List(); - - foreach (var item in keys) - { - if (!_ruleGroupDict.TryGetValue(item, out var rules)) - continue; - - var allRules = rules.Where(val => val.TrackStart <= order.TrackStatusId && val.TrackEnd >= order.TrackStatusId); - result.AddRange(allRules); - } - - return result; - } - private async ValueTask ExecuteRule(List rules, int orderId) { var members = new List(); @@ -162,71 +116,4 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep var result = new RuleNotifyValue(ruleItem.Id, orderId, sort, ruleItem.TrackEnd); return result.ToString(); } - - private List 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() - { - // todo:缓存设计有问题 重构 120s 10w 30w 3000k/s - 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.LeavePort: - return rule.LeavePort; - case RuleFactorType.Months: - 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.Domain/Dtos/Forewarning/ForewarningOrderModel.cs b/src/SJZY.Track.Domain/Dtos/Forewarning/WarningOrderDto.cs similarity index 56% rename from src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs rename to src/SJZY.Track.Domain/Dtos/Forewarning/WarningOrderDto.cs index 3767abcb..4cdc5a91 100644 --- a/src/SJZY.Track.Domain/Dtos/Forewarning/ForewarningOrderModel.cs +++ b/src/SJZY.Track.Domain/Dtos/Forewarning/WarningOrderDto.cs @@ -1,6 +1,6 @@ namespace SJZY.Track.Domain.Dtos.Forewarning; -public class ForewarningOrderModel:IForewarningFactorValue +public class WarningOrderDto { /// /// 订单id @@ -20,8 +20,6 @@ public class ForewarningOrderModel:IForewarningFactorValue public int? Month { get; set; } - public int? Area { get; set; } - public bool? IsTransit { get; set; } /// @@ -30,4 +28,24 @@ public class ForewarningOrderModel:IForewarningFactorValue public string? LeavePort { get; set; } public string? ProductCode { get; set; } + + /// + /// 目的城市 + /// + public string ArrivalCity { get; set; } = null!; + + /// + /// 目的国家 + /// + public string ArrivalCountry { get; set; } = null!; + + /// + /// 到达邮编 + /// + public string? ArrivalPostCode { get; set; } + + /// + /// 到达州省 + /// + public string? ArrivalProvince { get; set; } } \ No newline at end of file