track/src/SJZY.Track.Application/Services/ForewarningServices/ForewarningNotifyService.cs
2024-07-31 18:21:23 +08:00

141 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 用于处理预警通知
/// </summary>
public class ForewarningNotifyService : IForewarningNotifyService, ITransientDependency
{
private readonly IForewarningCacheService _cacheService;
private readonly IWarningQueries _warningQueries;
public ForewarningNotifyService(IForewarningCacheService cacheService, IWarningQueries warningQueries)
{
_cacheService = cacheService;
_warningQueries = warningQueries;
}
/// <summary>
/// 创建预警通知
/// </summary>
/// <param name="dto">创建预警通知需要的订单信息</param>
/// <returns>创建的通知总量,0表示没有规则</returns>
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<ForewarningRuleCacheEntry> MatchRule(List<ForewarningRuleCacheEntry> rules,
WarningOrderDto order)
{
var res = new List<ForewarningRuleCacheEntry>();
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();
}
}