temp
This commit is contained in:
parent
1513bb4964
commit
6b211d8f7f
@ -0,0 +1,29 @@
|
||||
namespace SJZY.Track.Application.Contract.Dtos.Forewarning;
|
||||
|
||||
public class AreaCacheEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// 国家或地区
|
||||
/// </summary>
|
||||
public string Country { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 省份
|
||||
/// </summary>
|
||||
public string? Province { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 城市
|
||||
/// </summary>
|
||||
public string? City { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始邮编
|
||||
/// </summary>
|
||||
public string? LeftPostcode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 截止邮编
|
||||
/// </summary>
|
||||
public string? RightPostcode { get; set; }
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
namespace SJZY.Track.Application.Contract.Dtos.Forewarning;
|
||||
|
||||
public class ForewarningRuleCacheEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// 自增主键
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预警id
|
||||
/// </summary>
|
||||
public int WarningId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时效(小时) e.g. 24
|
||||
/// </summary>
|
||||
public float TotalTimeSpan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提醒的时间(小时) e.g. 9 10 11..
|
||||
/// </summary>
|
||||
public float WarnTimeSpan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提醒次数 e.g. 3 2 1
|
||||
/// </summary>
|
||||
public int WarnCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 起始轨迹状态id
|
||||
/// </summary>
|
||||
public int StartTrackStatusId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终止轨迹状态id
|
||||
/// </summary>
|
||||
public int EndTrackStatusId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货物类型
|
||||
/// </summary>
|
||||
public string? CargoType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 月份
|
||||
/// </summary>
|
||||
public List<int>? Months { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 区域
|
||||
/// </summary>
|
||||
public List<AreaCacheEntry>? AreaId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否中转
|
||||
/// </summary>
|
||||
public bool? IsTransit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 起运港口
|
||||
/// </summary>
|
||||
public string? LeavePort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 产品编码
|
||||
/// </summary>
|
||||
public string? ProductCode { get; set; }
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
using SJZY.Track.Application.Contract.Dtos.Forewarning;
|
||||
|
||||
namespace SJZY.Track.Application.Contract.Services;
|
||||
|
||||
public interface IForewarningCacheService
|
||||
{
|
||||
Task<List<ForewarningRuleCacheEntry>> GetRulesAsync(int subSystemId);
|
||||
}
|
||||
@ -13,14 +13,14 @@ public interface IForewarningNotifyService
|
||||
/// </summary>
|
||||
/// <param name="order">预警订单模型。</param>
|
||||
/// <returns>创建操作的结果,以整数形式返回。</returns>
|
||||
Task WarningCalculateAsync(List<ForewarningOrderModel> order);
|
||||
Task WarningCalculateAsync(List<WarningOrderDto> order);
|
||||
|
||||
/// <summary>
|
||||
/// 删除预警通知。
|
||||
/// </summary>
|
||||
/// <param name="order">预警订单模型。</param>
|
||||
/// <returns>删除操作的结果,以整数形式返回。</returns>
|
||||
Task<int> DeleteForewarningNotify(ForewarningOrderModel order);
|
||||
Task<int> DeleteForewarningNotify(WarningOrderDto order);
|
||||
|
||||
/// <summary>
|
||||
/// 发送通知。
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
|
||||
using SJZY.Track.Domain.Dtos.Forewarning;
|
||||
|
||||
namespace SJZY.Track.Application.Contract.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 定义了与规则因子缓存相关的服务接口。
|
||||
/// </summary>
|
||||
public interface IRuleFactorCacheService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取所有因子收集的规则。
|
||||
/// </summary>
|
||||
/// <returns>规则数组。</returns>
|
||||
Task<ForewarningRuleItem[]> GetAllFactorCollect();
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有规则因子。
|
||||
/// </summary>
|
||||
/// <returns>规则因子实体列表。</returns>
|
||||
Task<List<RuleFactor>> GetAllRuleFactor();
|
||||
|
||||
/// <summary>
|
||||
/// 清除因子缓存。
|
||||
/// </summary>
|
||||
void ClearFactorCache();
|
||||
|
||||
/// <summary>
|
||||
/// 清除规则缓存。
|
||||
/// </summary>
|
||||
void ClearRuleCache();
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
return new WarningOrderDto
|
||||
{
|
||||
Id = order.Id,
|
||||
TrackStatusId = trackStatusId,
|
||||
SubSystemId = order.SubSystemId,
|
||||
CustomerId = order.CustomId,
|
||||
|
||||
private int? DetermineMonthBasedOnOrderDetails(OrderEntity order)
|
||||
{
|
||||
// Implement logic to determine Month
|
||||
return default;
|
||||
}
|
||||
CargoType = order.CargoType,
|
||||
Month = order.CreateTime.Month,
|
||||
IsTransit = order.IsTransit,
|
||||
LeavePort = order.LeavePort,
|
||||
ProductCode = order.ProductCode,
|
||||
|
||||
private int? DetermineAreaBasedOnOrderDetails(OrderEntity order)
|
||||
{
|
||||
// Implement logic to determine Area
|
||||
return default;
|
||||
ArrivalCountry = order.ArrivalCountry,
|
||||
ArrivalProvince = order.ArrivalProvince,
|
||||
ArrivalCity = order.ArrivalCity,
|
||||
ArrivalPostCode = order.ArrivalPostCode,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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<List<ForewarningRuleCacheEntry>> GetRulesAsync(int subSystemId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@ -14,15 +14,13 @@ namespace SJZY.Track.Application.Services.ForewarningServices;
|
||||
/// </summary>
|
||||
public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency
|
||||
{
|
||||
private IRuleFactorCacheService _ruleFactorCache;
|
||||
IReadOnlyDictionary<string, List<ForewarningRuleItem>> _ruleGroupDict;
|
||||
IReadOnlyDictionary<string, List<RuleFactor>> _factorDict;
|
||||
private IReadOnlyDictionary<int, ForewarningRuleItem> _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
|
||||
/// </summary>
|
||||
/// <param name="order">创建预警通知需要的订单信息</param>
|
||||
/// <returns>创建的通知总量,0表示没有规则</returns>
|
||||
public async Task WarningCalculateAsync(List<ForewarningOrderModel> order)
|
||||
public async Task WarningCalculateAsync(List<WarningOrderDto> order)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除预警通知
|
||||
/// </summary>
|
||||
/// <param name="order">订单信息</param>
|
||||
/// <returns>清理的行数</returns>
|
||||
public async Task<int> DeleteForewarningNotify(ForewarningOrderModel order)
|
||||
public Task<int> DeleteForewarningNotify(WarningOrderDto order)
|
||||
{
|
||||
var rules = GetRule(order);
|
||||
if (rules == null || rules.Count == 0)
|
||||
return 0;
|
||||
|
||||
var willDeleteMembers = new List<string>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取规则
|
||||
/// </summary>
|
||||
/// <param name="rule"></param>
|
||||
/// <returns></returns>
|
||||
private List<ForewarningRuleItem> 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<ForewarningRuleItem>();
|
||||
|
||||
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<int> ExecuteRule(List<ForewarningRuleItem> rules, int orderId)
|
||||
{
|
||||
var members = new List<ZMember>();
|
||||
@ -162,71 +116,4 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
||||
var result = new RuleNotifyValue(ruleItem.Id, orderId, sort, ruleItem.TrackEnd);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private List<string> GetForewarningKeys(List<RuleFactor> factors, IForewarningFactorValue rule)
|
||||
{
|
||||
var keys = new List<string>();
|
||||
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("未知的规则类型");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
namespace SJZY.Track.Domain.Dtos.Forewarning;
|
||||
|
||||
public class ForewarningOrderModel:IForewarningFactorValue
|
||||
public class WarningOrderDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单id
|
||||
@ -20,8 +20,6 @@ public class ForewarningOrderModel:IForewarningFactorValue
|
||||
|
||||
public int? Month { get; set; }
|
||||
|
||||
public int? Area { get; set; }
|
||||
|
||||
public bool? IsTransit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -30,4 +28,24 @@ public class ForewarningOrderModel:IForewarningFactorValue
|
||||
public string? LeavePort { get; set; }
|
||||
|
||||
public string? ProductCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目的城市
|
||||
/// </summary>
|
||||
public string ArrivalCity { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 目的国家
|
||||
/// </summary>
|
||||
public string ArrivalCountry { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 到达邮编
|
||||
/// </summary>
|
||||
public string? ArrivalPostCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 到达州省
|
||||
/// </summary>
|
||||
public string? ArrivalProvince { get; set; }
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user