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>
|
/// </summary>
|
||||||
/// <param name="order">预警订单模型。</param>
|
/// <param name="order">预警订单模型。</param>
|
||||||
/// <returns>创建操作的结果,以整数形式返回。</returns>
|
/// <returns>创建操作的结果,以整数形式返回。</returns>
|
||||||
Task WarningCalculateAsync(List<ForewarningOrderModel> order);
|
Task WarningCalculateAsync(List<WarningOrderDto> order);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除预警通知。
|
/// 删除预警通知。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="order">预警订单模型。</param>
|
/// <param name="order">预警订单模型。</param>
|
||||||
/// <returns>删除操作的结果,以整数形式返回。</returns>
|
/// <returns>删除操作的结果,以整数形式返回。</returns>
|
||||||
Task<int> DeleteForewarningNotify(ForewarningOrderModel order);
|
Task<int> DeleteForewarningNotify(WarningOrderDto order);
|
||||||
|
|
||||||
/// <summary>
|
/// <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
|
var warningOrders = orders.Select(order => MapWarningOrderDto(order, @event.TrackStatusId)).ToList();
|
||||||
{
|
|
||||||
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();
|
|
||||||
_forewarningNotifyService.WarningCalculateAsync(warningOrders);
|
_forewarningNotifyService.WarningCalculateAsync(warningOrders);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OrderEntity MapOrderSummary(OrderEntity x)
|
private OrderEntity MapOrderSummary(OrderEntity order)
|
||||||
{
|
{
|
||||||
return new OrderEntity
|
return new OrderEntity
|
||||||
{
|
{
|
||||||
Id = x.Id,
|
Id = order.Id,
|
||||||
SubSystemId = x.SubSystemId,
|
SubSystemId = order.SubSystemId,
|
||||||
CustomId = x.CustomId,
|
CustomId = order.CustomId,
|
||||||
|
|
||||||
// 轨迹
|
// 轨迹
|
||||||
IsCompleted = x.IsCompleted,
|
IsCompleted = order.IsCompleted,
|
||||||
LatestTrackContent = x.LatestTrackContent,
|
LatestTrackContent = order.LatestTrackContent,
|
||||||
LatestTrackEnContent = x.LatestTrackEnContent,
|
LatestTrackEnContent = order.LatestTrackEnContent,
|
||||||
LatestTrackPlace = x.LatestTrackPlace,
|
LatestTrackPlace = order.LatestTrackPlace,
|
||||||
LatestTrackTime = x.LatestTrackTime,
|
LatestTrackTime = order.LatestTrackTime,
|
||||||
LatestTrackTimeZone = x.LatestTrackTimeZone,
|
LatestTrackTimeZone = order.LatestTrackTimeZone,
|
||||||
|
|
||||||
// 因素
|
// 因素
|
||||||
CargoType = x.CargoType,
|
CargoType = order.CargoType,
|
||||||
CreateTime = x.CreateTime,
|
CreateTime = order.CreateTime,
|
||||||
ArrivalCountry = x.ArrivalCountry,
|
ArrivalCountry = order.ArrivalCountry,
|
||||||
ArrivalProvince = x.ArrivalProvince,
|
ArrivalProvince = order.ArrivalProvince,
|
||||||
ArrivalCity = x.ArrivalCity,
|
ArrivalCity = order.ArrivalCity,
|
||||||
ArrivalPostCode = x.ArrivalPostCode,
|
ArrivalPostCode = order.ArrivalPostCode,
|
||||||
IsTransit = x.IsTransit,
|
IsTransit = order.IsTransit,
|
||||||
LeavePort = x.LeavePort,
|
LeavePort = order.LeavePort,
|
||||||
ProductCode = x.ProductCode
|
ProductCode = order.ProductCode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder methods for deriving or converting values. You'll need to implement these based on your specific logic.
|
private WarningOrderDto MapWarningOrderDto(OrderEntity order, int trackStatusId)
|
||||||
private int DetermineTrackBasedOnOrderDetails(OrderEntity order)
|
|
||||||
{
|
{
|
||||||
// Implement logic to determine Track
|
return new WarningOrderDto
|
||||||
return default;
|
{
|
||||||
}
|
Id = order.Id,
|
||||||
|
TrackStatusId = trackStatusId,
|
||||||
|
SubSystemId = order.SubSystemId,
|
||||||
|
CustomerId = order.CustomId,
|
||||||
|
|
||||||
private int? DetermineMonthBasedOnOrderDetails(OrderEntity order)
|
CargoType = order.CargoType,
|
||||||
{
|
Month = order.CreateTime.Month,
|
||||||
// Implement logic to determine Month
|
IsTransit = order.IsTransit,
|
||||||
return default;
|
LeavePort = order.LeavePort,
|
||||||
}
|
ProductCode = order.ProductCode,
|
||||||
|
|
||||||
private int? DetermineAreaBasedOnOrderDetails(OrderEntity order)
|
ArrivalCountry = order.ArrivalCountry,
|
||||||
{
|
ArrivalProvince = order.ArrivalProvince,
|
||||||
// Implement logic to determine Area
|
ArrivalCity = order.ArrivalCity,
|
||||||
return default;
|
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>
|
/// </summary>
|
||||||
public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency
|
public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency
|
||||||
{
|
{
|
||||||
private IRuleFactorCacheService _ruleFactorCache;
|
|
||||||
IReadOnlyDictionary<string, List<ForewarningRuleItem>> _ruleGroupDict;
|
IReadOnlyDictionary<string, List<ForewarningRuleItem>> _ruleGroupDict;
|
||||||
IReadOnlyDictionary<string, List<RuleFactor>> _factorDict;
|
IReadOnlyDictionary<string, List<RuleFactor>> _factorDict;
|
||||||
private IReadOnlyDictionary<int, ForewarningRuleItem> _rules;
|
private IReadOnlyDictionary<int, ForewarningRuleItem> _rules;
|
||||||
readonly INotifyService _notifyService;
|
readonly INotifyService _notifyService;
|
||||||
|
|
||||||
public ForewarningNotifyService(IRuleFactorCacheService ruleFactorCache, INotifyService notifyService)
|
public ForewarningNotifyService(INotifyService notifyService)
|
||||||
{
|
{
|
||||||
_ruleFactorCache = ruleFactorCache;
|
|
||||||
_notifyService = notifyService;
|
_notifyService = notifyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,31 +29,14 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="order">创建预警通知需要的订单信息</param>
|
/// <param name="order">创建预警通知需要的订单信息</param>
|
||||||
/// <returns>创建的通知总量,0表示没有规则</returns>
|
/// <returns>创建的通知总量,0表示没有规则</returns>
|
||||||
public async Task WarningCalculateAsync(List<ForewarningOrderModel> order)
|
public async Task WarningCalculateAsync(List<WarningOrderDto> order)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public Task<int> DeleteForewarningNotify(WarningOrderDto order)
|
||||||
/// 清除预警通知
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="order">订单信息</param>
|
|
||||||
/// <returns>清理的行数</returns>
|
|
||||||
public async Task<int> DeleteForewarningNotify(ForewarningOrderModel order)
|
|
||||||
{
|
{
|
||||||
var rules = GetRule(order);
|
throw new NotImplementedException();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendNotification(int intervalMinute)
|
public void SendNotification(int intervalMinute)
|
||||||
@ -96,33 +77,6 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
return members;
|
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)
|
private async ValueTask<int> ExecuteRule(List<ForewarningRuleItem> rules, int orderId)
|
||||||
{
|
{
|
||||||
var members = new List<ZMember>();
|
var members = new List<ZMember>();
|
||||||
@ -162,71 +116,4 @@ public class ForewarningNotifyService : IForewarningNotifyService, ITransientDep
|
|||||||
var result = new RuleNotifyValue(ruleItem.Id, orderId, sort, ruleItem.TrackEnd);
|
var result = new RuleNotifyValue(ruleItem.Id, orderId, sort, ruleItem.TrackEnd);
|
||||||
return result.ToString();
|
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;
|
namespace SJZY.Track.Domain.Dtos.Forewarning;
|
||||||
|
|
||||||
public class ForewarningOrderModel:IForewarningFactorValue
|
public class WarningOrderDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 订单id
|
/// 订单id
|
||||||
@ -20,8 +20,6 @@ public class ForewarningOrderModel:IForewarningFactorValue
|
|||||||
|
|
||||||
public int? Month { get; set; }
|
public int? Month { get; set; }
|
||||||
|
|
||||||
public int? Area { get; set; }
|
|
||||||
|
|
||||||
public bool? IsTransit { get; set; }
|
public bool? IsTransit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,4 +28,24 @@ public class ForewarningOrderModel:IForewarningFactorValue
|
|||||||
public string? LeavePort { get; set; }
|
public string? LeavePort { get; set; }
|
||||||
|
|
||||||
public string? ProductCode { 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