using FreeRedis;
using SJZY.Expand.ABP.Core;
using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Application.Contract.Services;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Consts;
using SJZY.Track.Domain.Queries;
using Volo.Abp.DependencyInjection;
namespace SJZY.Track.Application.Services.ForewarningServices;
///
/// 用于处理预警通知
///
public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency
{
private readonly IForewarningCacheService _cacheService;
private readonly IWarningQueries _warningQueries;
public ForewarningNotifyService(IForewarningCacheService cacheService, IWarningQueries warningQueries)
{
_cacheService = cacheService;
_warningQueries = warningQueries;
}
///
/// 创建预警通知
///
/// 创建预警通知需要的订单信息
/// 创建的通知总量,0表示没有规则
public async Task WarningCalculateAsync(WarningDto dto)
{
if (dto.Orders.Count == 0) return;
var rules = await _cacheService.GetRulesAsync(dto.SubSystemId, dto.CustomerId);
if (rules == null || rules.Count == 0) return;
var adds = new List<(int ruleId, int orderId, int cnt, long ts)>();
var dels = new List<(int ruleId, int orderId)>();
foreach (var order in dto.Orders)
{
MatchRule(
rules.Where(rule => rule.StartTrackStatusId == dto.TrackStatusId).ToList(),
order
).ForEach(rule =>
{
var timestamp = GetTimestamp(order.TrackTime.AddMinutes(rule.WarnTimeSpan));
adds.Add((rule.Id, order.Id, rule.WarnCount, timestamp));
});
MatchRule(
rules.Where(rule => rule.EndTrackStatusId == dto.TrackStatusId).ToList(),
order
).ForEach(rule => { dels.Add((rule.Id, order.Id)); });
}
await RedisHelper.Client.HSetAsync(GlobalConst.ForewarningNotifyCntKey,
adds.ToDictionary(x => $"{x.ruleId}_{x.orderId}", x => x.cnt));
await RedisHelper.Client.ZAddAsync(GlobalConst.ForewarningNotifyKey, adds.Select(x =>
{
var entry = new WarningNotifyCacheEntry(x.ruleId, x.orderId);
return new ZMember(entry.ToString(), x.ts);
}).ToArray());
await RedisHelper.Client.HDelAsync(GlobalConst.ForewarningNotifyCntKey,
dels.Select(x => $"{x.ruleId}_{x.orderId}").ToArray());
// await RedisHelper.Client.ZRemAsync(GlobalConst.ForewarningNotifyKey,
// dels.Select(x => $"{x.ruleId}:{x.orderId}").ToArray());
}
private static List MatchRule(List rules,
WarningOrderDto order)
{
var res = new List();
foreach (var rule in rules)
{
if (rule.IsTransit != null)
{
if (order.IsTransit != rule.IsTransit) continue;
}
if (!rule.CargoType.IsNullOrEmpty())
{
if (order.CargoType != rule.CargoType) continue;
}
if (!rule.LeavePort.IsNullOrEmpty())
{
if (order.LeavePort != rule.LeavePort) continue;
}
if (!rule.ProductCode.IsNullOrEmpty())
{
if (order.ProductCode != rule.ProductCode) continue;
}
if (!rule.Months.IsNullOrEmpty())
{
if (!order.Month.IsIn(rule.Months)) continue;
}
if (rule.Area != null)
{
if (order.ArrivalCountry != rule.Area.Country) continue;
if (!rule.Area.LeftPostcode.IsNullOrEmpty() && !rule.Area.RightPostcode.IsNullOrEmpty())
{
// todo: 参考小包的邮编匹配
}
if (!rule.Area.City.IsNullOrEmpty() && order.ArrivalCity != rule.Area.City) continue;
if (!rule.Area.Province.IsNullOrEmpty() && order.ArrivalProvince != rule.Area.Province) continue;
}
res.Add(rule);
}
return res;
}
public async Task SendNotificationAsync()
{
var max = GetTimestamp(DateTime.Now);
var set = await RedisHelper.Client.ZRangeByScoreAsync(GlobalConst.ForewarningNotifyKey, 0, max);
if (set.IsNullOrEmpty()) return;
var entries = set.Select(x => new WarningNotifyCacheEntry(x)).ToList();
var ruleIds = entries.Select(x => x.RuleId).ToList();
var notifyRules = await _warningQueries.GetWarningNotifyRulesAsync(ruleIds);
foreach (var group in notifyRules)
{
}
}
private static long GetTimestamp(DateTime dateTime)
{
return new DateTimeOffset(dateTime).ToUnixTimeSeconds();
}
}