perf:对于空值使用 -- 填充处理

fix:运输时效预警
 - 修复累计运输时间计算错误
 - 修复运输预警明细的已超时状态被忽略
This commit is contained in:
hardstylewyl 2025-03-20 14:32:33 +08:00
parent 9615b6257e
commit 7f938c5a7d
8 changed files with 66 additions and 35 deletions

View File

@ -13,7 +13,7 @@ public class GetWarningRuleInput
/// <summary> /// <summary>
/// 关键字(kpi/客户名称 模糊) /// 关键字(kpi/客户名称 模糊)
/// </summary> /// </summary>
public string? KeyWord { get; set; } public string? Keywords { get; set; }
/// <summary> /// <summary>
/// 是否启用(留null查全部) /// 是否启用(留null查全部)

View File

@ -33,7 +33,6 @@ public class CompleteWarningService : ApplicationService
private readonly ICompleteWarningHandler _completeWarningHandler; private readonly ICompleteWarningHandler _completeWarningHandler;
private readonly ITrackStatusRepository _trackStatusRepository; private readonly ITrackStatusRepository _trackStatusRepository;
public CompleteWarningService(IWarningRuleRepository warningRuleRepository, IWarningDetailsEsRepository warningDetailsEsRepository, ITrackDetailsEsRepository trackDetailsEsRepository, ICompleteWarningHandler completeWarningHandler, ITrackStatusRepository trackStatusRepository, IOrderRepository orderRepository, IVSystemQueries vSystemQueries, IVExternalSubjectQueries vExternalSubjectQueries) public CompleteWarningService(IWarningRuleRepository warningRuleRepository, IWarningDetailsEsRepository warningDetailsEsRepository, ITrackDetailsEsRepository trackDetailsEsRepository, ICompleteWarningHandler completeWarningHandler, ITrackStatusRepository trackStatusRepository, IOrderRepository orderRepository, IVSystemQueries vSystemQueries, IVExternalSubjectQueries vExternalSubjectQueries)
{ {
_warningRuleRepository = warningRuleRepository; _warningRuleRepository = warningRuleRepository;
@ -87,7 +86,7 @@ public class CompleteWarningService : ApplicationService
WarningId = x.WarningId, WarningId = x.WarningId,
OrderTypes = BuildOrderTypes(x), OrderTypes = BuildOrderTypes(x),
CheckPointTrackStatusId = x.CheckPointTrackStatusId, CheckPointTrackStatusId = x.CheckPointTrackStatusId,
CheckPointTrackStatus = trackStatusDict.GetValueOrDefault(x.CheckPointTrackStatusId), CheckPointTrackStatus = trackStatusDict.GetValueOrDefault(x.CheckPointTrackStatusId, GlobalConst.EmptyString),
RequireTrackStatus = BuildRequireTrackStatus(x), RequireTrackStatus = BuildRequireTrackStatus(x),
NotifyUsers = TextJsonHelper.Deserialize<List<NotifyUserDto>>(x.NotifyUsers)! NotifyUsers = TextJsonHelper.Deserialize<List<NotifyUserDto>>(x.NotifyUsers)!
}); });
@ -102,7 +101,7 @@ public class CompleteWarningService : ApplicationService
Statuses = g.Select(id => new TrackStatusDto Statuses = g.Select(id => new TrackStatusDto
{ {
TrackStatusId = id, TrackStatusId = id,
TrackStatus = trackStatusDict.GetValueOrDefault(id) TrackStatus = trackStatusDict.GetValueOrDefault(id, GlobalConst.EmptyString)
}).ToList() }).ToList()
}).ToList(); }).ToList();
} }
@ -113,7 +112,7 @@ public class CompleteWarningService : ApplicationService
.Select(x => new OrderTypeDto .Select(x => new OrderTypeDto
{ {
OrderType = x, OrderType = x,
OrderTypeName = orderTypeDict.GetValueOrDefault(x.ToString()) OrderTypeName = orderTypeDict.GetValueOrDefault(x.ToString(), GlobalConst.EmptyString)
}).ToList(); }).ToList();
} }
} }
@ -173,14 +172,14 @@ public class CompleteWarningService : ApplicationService
{ {
EsId = x.Id, EsId = x.Id,
SubSystemId = x.SubSystemId, SubSystemId = x.SubSystemId,
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId), SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId, GlobalConst.EmptyString),
OrderType = x.OrderType, OrderType = x.OrderType,
OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString()), OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString(), GlobalConst.EmptyString),
OrderId = x.OrderId, OrderId = x.OrderId,
OrderNo = x.OrderNo, OrderNo = x.OrderNo,
Status = x.Status, Status = x.Status,
CustomId = x.CustomId, CustomId = x.CustomId,
CustomName = customDict.GetValueOrDefault(x.CustomId), CustomName = customDict.GetValueOrDefault(x.CustomId, GlobalConst.EmptyString),
MissingTrackStatus = BuildMissingTrackStatus(x.MissingTrackStatusIds), MissingTrackStatus = BuildMissingTrackStatus(x.MissingTrackStatusIds),
LatestTrackStatus = orderIdTrack?.TrackStatus, LatestTrackStatus = orderIdTrack?.TrackStatus,
LatestTrackContent = orderIdTrack?.TrackContent, LatestTrackContent = orderIdTrack?.TrackContent,

View File

@ -112,7 +112,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
orderDetails.ForEach(x => orderDetails.ForEach(x =>
{ {
x.Status = TransportWarningStatus.已关闭.GetHashCode(); x.Status = TransportWarningStatus.已关闭.GetHashCode();
x.CumulativeTimeSpan = DateTime.Now.Subtract(x.StartTrackTime).Milliseconds; //tips:完成态缓存累计运输时间 x.CumulativeTimeSpan = (long)DateTime.Now.Subtract(x.StartTrackTime).TotalMilliseconds; //tips:完成态缓存累计运输时间
}); });
orderTasks.ForEach(x => x.IsClosed = true); orderTasks.ForEach(x => x.IsClosed = true);
needUpdateDetails.AddRange(orderDetails); needUpdateDetails.AddRange(orderDetails);
@ -174,7 +174,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
details.ForEach(x => details.ForEach(x =>
{ {
x.Status = TransportWarningStatus.已关闭.GetHashCode(); x.Status = TransportWarningStatus.已关闭.GetHashCode();
x.CumulativeTimeSpan = DateTime.Now.Subtract(x.StartTrackTime).Milliseconds; //tips:完成态缓存累计运输时间 x.CumulativeTimeSpan = (long)DateTime.Now.Subtract(x.StartTrackTime).TotalMilliseconds; //tips:完成态缓存累计运输时间
}); });
needUpdateDetails.AddRange(details); needUpdateDetails.AddRange(details);
continue; continue;
@ -378,11 +378,11 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
// 修改为完成态 // 修改为完成态
if (detail.Status == TransportWarningStatus.即将超时.GetHashCode()) if (detail.Status == TransportWarningStatus.即将超时.GetHashCode())
detail.Status = TransportWarningStatus.已完成.GetHashCode(); detail.Status = TransportWarningStatus.已完成.GetHashCode();
if (detail.Status == TransportWarningStatus.已超时.GetHashCode()) if (detail.CalcStatus() == TransportWarningStatus.已超时.GetHashCode())
detail.Status = TransportWarningStatus.超时完成.GetHashCode(); detail.Status = TransportWarningStatus.超时完成.GetHashCode();
// 维护累计运输时间(由于变更为终止态,此时为最后一次变更) // 维护累计运输时间(由于变更为终止态,此时为最后一次变更)
detail.CumulativeTimeSpan = DateTime.Now.Subtract(detail.StartTrackTime).Milliseconds; detail.CumulativeTimeSpan = (long)DateTime.Now.Subtract(detail.StartTrackTime).TotalMilliseconds;
// 填充终止状态轨迹信息 // 填充终止状态轨迹信息
detail.EndTrackContentId = earliestTrack.TrackContentId; detail.EndTrackContentId = earliestTrack.TrackContentId;
@ -1070,11 +1070,11 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
if (waningRules.Count == 0) return; //不存在启用的规则主体,直接全部关闭 if (waningRules.Count == 0) return; //不存在启用的规则主体,直接全部关闭
// 构建规则主体id和版本号字典,稍后用于填充明细的版本号 // 构建规则主体id和版本号字典,稍后用于填充明细的版本号
var ruleVersionDict = waningRules.ToDictionary(x => x.Id, x => x.Version); var ruleDict = waningRules.ToDictionary(x => x.Id);
// 选出任务中规则条目id,要求订单存在,主体存在并启用 // 选出任务中规则条目id,要求订单存在,主体存在并启用
var ruleItemIds = tasks var ruleItemIds = tasks
.Where(x => orderDict.ContainsKey(x.OrderId) && ruleVersionDict.ContainsKey(x.WarningId)) .Where(x => orderDict.ContainsKey(x.OrderId) && ruleDict.ContainsKey(x.WarningId))
.Select(x => x.WarningSceneRuleItemId) .Select(x => x.WarningSceneRuleItemId)
.ToHashSet(); .ToHashSet();
if (ruleItemIds.Count == 0) return; if (ruleItemIds.Count == 0) return;
@ -1145,13 +1145,34 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
var endTrackStatusIds = addDetails.Select(x => x.EndTrackStatusId).ToHashSet(); var endTrackStatusIds = addDetails.Select(x => x.EndTrackStatusId).ToHashSet();
var trackStatusIdNameDict = await _trackStatusRepository.GetTrackStatusIdNameDictAsync(endTrackStatusIds); var trackStatusIdNameDict = await _trackStatusRepository.GetTrackStatusIdNameDictAsync(endTrackStatusIds);
// 获取场景字典
var sceneIds = addDetails.Select(x => x.WarningSceneId).ToHashSet();
var scenes = await _warningRuleRepository.GetTransportSceneAsync(x =>
sceneIds.Contains(x.Id)
);
var sceneDict = scenes.ToDictionary(x => x.Id);
// 获取区域字典
Dictionary<int, RuleAreaEntity> areaDict = null;
var areaIds = scenes.Where(x => x.AreaId.HasValue).Select(x => x.AreaId.Value!).ToHashSet();
if (areaIds.Count > 0)
{
var areas = await _kpiAreaRepository.GetListAsync(x => areaIds.Contains(x.Id));
areaDict = areas.ToDictionary(x => x.Id);
}
// 6.生成预警明细,手动赋予EsId,规则版本号,截止轨迹状态名称 // 6.生成预警明细,手动赋予EsId,规则版本号,截止轨迹状态名称
addDetails.ForEach(x => addDetails.ForEach(x =>
{ {
x.Id = Guid.NewGuid().ToString("N"); x.Id = Guid.NewGuid().ToString("N");
x.Version = ruleVersionDict[x.WarningId]; //一定存在
x.EndTrackStatus = trackStatusIdNameDict.GetValueOrDefault(x.EndTrackStatusId) x.EndTrackStatus = trackStatusIdNameDict.GetValueOrDefault(x.EndTrackStatusId)
?? $"不存在id:[{x.EndTrackStatusId}]轨迹状态"; ?? $"不存在id:[{x.EndTrackStatusId}]轨迹状态";
var rule = ruleDict[x.WarningId]; //一定存在
var scene = sceneDict[x.WarningSceneId]; //一定存在
x.Version = rule.Version;
x.WarningName = rule.Name;
x.WarningRuleDescription = x.GetWarningRuleDescription(scene, ruleItemDict[x.WarningSceneRuleItemId], areaDict?.GetValueOrDefault(scene.AreaId ?? 0));
}); });
await _warningDetailsEsRepository.BulkInsertTransportWarningDetailsAsync(addDetails); await _warningDetailsEsRepository.BulkInsertTransportWarningDetailsAsync(addDetails);

View File

@ -82,7 +82,7 @@ public class ReturnWarningService : ApplicationService
var id = int.Parse(x); var id = int.Parse(x);
return new TrackStatusDto return new TrackStatusDto
{ {
TrackStatus = trackStatusDict.GetValueOrDefault(id), TrackStatus = trackStatusDict.GetValueOrDefault(id, GlobalConst.EmptyString),
TrackStatusId = id TrackStatusId = id
}; };
}).ToList(); }).ToList();
@ -124,14 +124,14 @@ public class ReturnWarningService : ApplicationService
{ {
EsId = x.Id, EsId = x.Id,
SubSystemId = x.SubSystemId, SubSystemId = x.SubSystemId,
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId), SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId, GlobalConst.EmptyString),
OrderType = x.OrderType, OrderType = x.OrderType,
OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString()), OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString(), GlobalConst.EmptyString),
OrderId = x.OrderId, OrderId = x.OrderId,
OrderNo = x.OrderNo, OrderNo = x.OrderNo,
Status = x.Status, Status = x.Status,
CustomId = x.CustomId, CustomId = x.CustomId,
CustomName = customDict.GetValueOrDefault(x.CustomId), CustomName = customDict.GetValueOrDefault(x.CustomId, GlobalConst.EmptyString),
// 轨迹信息 // 轨迹信息
TrackStatus = x.TrackStatus, TrackStatus = x.TrackStatus,
TrackCode = x.TrackCode, TrackCode = x.TrackCode,

View File

@ -151,9 +151,9 @@ public class TransportWarningService : ApplicationService
{ {
Id = x.Id, Id = x.Id,
StartTrackStatusId = x.StartTrackStatusId, StartTrackStatusId = x.StartTrackStatusId,
StartTrackStatus = trackStatusDict.GetValueOrDefault(x.StartTrackStatusId), StartTrackStatus = trackStatusDict.GetValueOrDefault(x.StartTrackStatusId, GlobalConst.EmptyString),
EndTrackStatusId = x.EndTrackStatusId, EndTrackStatusId = x.EndTrackStatusId,
EndTrackStatus = trackStatusDict.GetValueOrDefault(x.EndTrackStatusId), EndTrackStatus = trackStatusDict.GetValueOrDefault(x.EndTrackStatusId, GlobalConst.EmptyString),
TransportTimeSpan = x.TransportTimeSpan, TransportTimeSpan = x.TransportTimeSpan,
StartTrackWarningTimeSpan = x.StartTrackWarningTimeSpan, StartTrackWarningTimeSpan = x.StartTrackWarningTimeSpan,
NotifyUsers = x.NotifyUsers.ToObject<List<NotifyUserDto>>() NotifyUsers = x.NotifyUsers.ToObject<List<NotifyUserDto>>()
@ -208,13 +208,13 @@ public class TransportWarningService : ApplicationService
{ {
EsId = x.Id, EsId = x.Id,
SubSystemId = x.SubSystemId, SubSystemId = x.SubSystemId,
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId), SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId, GlobalConst.EmptyString),
CustomId = x.CustomId, CustomId = x.CustomId,
CustomName = customDict.GetValueOrDefault(x.CustomId), CustomName = customDict.GetValueOrDefault(x.CustomId, GlobalConst.EmptyString),
OrderId = x.OrderId, OrderId = x.OrderId,
OrderNo = x.OrderNo, OrderNo = x.OrderNo,
OrderType = x.OrderType, OrderType = x.OrderType,
OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString()), OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString(), GlobalConst.EmptyString),
NotifyUserNames = ToUserNames(x.NotifyUsers), NotifyUserNames = ToUserNames(x.NotifyUsers),
// 最新轨迹 (不冗余) // 最新轨迹 (不冗余)
@ -239,9 +239,10 @@ public class TransportWarningService : ApplicationService
WarningRuleDescription = x.WarningRuleDescription, WarningRuleDescription = x.WarningRuleDescription,
// 累计运输时间 // 累计运输时间
CumulativeTimeSpan = FormatCumulativeTimeSpan(x.CumulativeTimeSpan), CumulativeTimeSpan = FormatCumulativeTimeSpan(x),
Status = x.Status, // 状态动态计算
Status = x.CalcStatus(),
CreateTime = x.CreateTime CreateTime = x.CreateTime
}; };
}); });
@ -269,9 +270,12 @@ public class TransportWarningService : ApplicationService
} }
// 格式化累计运输时间为文本形式 // 格式化累计运输时间为文本形式
string FormatCumulativeTimeSpan(long cumulativeTimeSpan) string FormatCumulativeTimeSpan(TransportWarningDetailsIndex detail)
{ {
var timeSpan = TimeSpan.FromMilliseconds(cumulativeTimeSpan); // 如果是完成态则直接取缓存的累计运输时间
var timeSpan = detail.CanCompleted()
? TimeSpan.FromMilliseconds(detail.CumulativeTimeSpan)
: DateTime.Now.Subtract(detail.StartTrackTime);
return $"{timeSpan.Days:00}天{timeSpan.Hours:00}小时{timeSpan.Minutes:00}分钟"; return $"{timeSpan.Days:00}天{timeSpan.Hours:00}小时{timeSpan.Minutes:00}分钟";
} }
@ -302,6 +306,7 @@ public class TransportWarningService : ApplicationService
var sorted = postBo.Months.Split('/').Select(int.Parse).OrderBy(x => x).ToList(); var sorted = postBo.Months.Split('/').Select(int.Parse).OrderBy(x => x).ToList();
postBo.Months = string.Join('/', sorted); postBo.Months = string.Join('/', sorted);
} }
// 更新或者新增 // 更新或者新增
var id = await _warningRuleRepository.UpsertTransportSceneReturnIdAsync(postBo.ToEntity()); var id = await _warningRuleRepository.UpsertTransportSceneReturnIdAsync(postBo.ToEntity());

View File

@ -38,7 +38,7 @@ public class WarningService : ApplicationService
[HttpPost("GetWarningRule")] [HttpPost("GetWarningRule")]
public async Task<UnifyResultDto<List<WarningRuleDto>>> GetWarningRule(GetWarningRuleInput input) public async Task<UnifyResultDto<List<WarningRuleDto>>> GetWarningRule(GetWarningRuleInput input)
{ {
var result = await _warningRuleRepository.GetWarningRuleListAsync(input.SubSystemId, input.KeyWord, input.IsEnabled, input.WarningType); var result = await _warningRuleRepository.GetWarningRuleListAsync(input.SubSystemId, input.Keywords, input.IsEnabled, input.WarningType);
if (result.Count == 0) if (result.Count == 0)
return new UnifyResultDto<List<WarningRuleDto>>(true, new List<WarningRuleDto>()); return new UnifyResultDto<List<WarningRuleDto>>(true, new List<WarningRuleDto>());
@ -63,9 +63,9 @@ public class WarningService : ApplicationService
{ {
Id = x.Id, Id = x.Id,
SubSystemId = x.SubSystemId, SubSystemId = x.SubSystemId,
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId), SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId, GlobalConst.EmptyString),
CustomId = x.CustomId, CustomId = x.CustomId,
CustomName = customDict.GetValueOrDefault(x.CustomId), CustomName = customDict.GetValueOrDefault(x.CustomId, GlobalConst.EmptyString),
Name = x.Name, Name = x.Name,
IsEnabled = x.IsEnabled, IsEnabled = x.IsEnabled,
WarningType = x.WarningType, WarningType = x.WarningType,

View File

@ -21,14 +21,18 @@ public sealed class TransportWarningDetailsIndex : IdBaseIndex
public string WarningRuleDescription { get; set; } // 预警规则描述 (场景+场景规则项目构建) public string WarningRuleDescription { get; set; } // 预警规则描述 (场景+场景规则项目构建)
public float TransportTimeSpan { get; set; } //时效 (单位小时),用于计算状态 public float TransportTimeSpan { get; set; } //时效 (单位小时),用于计算状态
public float StartTrackWarningTimeSpan { get; set; } //起始轨迹生成预警时间 (单位小时),用于计算状态 public float StartTrackWarningTimeSpan { get; set; } //起始轨迹生成预警时间 (单位小时),用于计算状态
//public string NotifyModes { get; set; } //通知方式,多个方式(,)分割 eg: 1,2 //public string NotifyModes { get; set; } //通知方式,多个方式(,)分割 eg: 1,2
public string NotifyUsers { get; set; } //通知人Json eg: [{"UserId":1,"UserName":"张三"},{"UserId":2,"UserName":"李四"}] public string NotifyUsers { get; set; } //通知人Json eg: [{"UserId":1,"UserName":"张三"},{"UserId":2,"UserName":"李四"}]
//订单信息 //订单信息
public int SubSystemId { get; set; } //(冗余)子系统Id public int SubSystemId { get; set; } //(冗余)子系统Id
// public string SubSystemName { get; set; } //(冗余)子系统名称 // public string SubSystemName { get; set; } //(冗余)子系统名称
public int CustomId { get; set; } //(冗余)客户Id public int CustomId { get; set; } //(冗余)客户Id
// public string CustomName { get; set; } //冗余 客户简称(用于查询条件) // public string CustomName { get; set; } //冗余 客户简称(用于查询条件)
public int OrderId { get; set; } public int OrderId { get; set; }
public string OrderNo { get; set; } //订单号 public string OrderNo { get; set; } //订单号
@ -68,7 +72,9 @@ public sealed class TransportWarningDetailsIndex : IdBaseIndex
private static readonly ImmutableHashSet<int> CompletedStatus = ImmutableHashSet.Create(3, 4, 5); private static readonly ImmutableHashSet<int> CompletedStatus = ImmutableHashSet.Create(3, 4, 5);
// todo:计算并设置状态,后续维护到vo当中 public bool CanCompleted() => CompletedStatus.Contains(Status);
// tips:计算并设置状态,后续维护到vo当中
public int CalcStatus() public int CalcStatus()
{ {
// 结束态无需计算,直接返回 // 结束态无需计算,直接返回
@ -106,7 +112,7 @@ public sealed class TransportWarningDetailsIndex : IdBaseIndex
res.Append($",{scene.CargoType}"); res.Append($",{scene.CargoType}");
// 月份 (1/3/5/...) // 月份 (1/3/5/...)
if (!string.IsNullOrWhiteSpace(scene.Months)) if (!string.IsNullOrWhiteSpace(scene.Months))
res.Append($",{scene.Months}"); res.Append($",{scene.Months}月份");
// 区域名称 (美国xxx区域) // 区域名称 (美国xxx区域)
if (ruleArea != null) if (ruleArea != null)
res.Append($",{ruleArea.Name}"); res.Append($",{ruleArea.Name}");

View File

@ -75,12 +75,12 @@ public class WarningRuleRepository : BasicRepository<WarningRuleEntity>, IWarnin
return version; return version;
} }
public Task<List<WarningRuleEntity>> GetWarningRuleListAsync(int? subsystemId, string? keyword, bool? isEnabled, int? warningType) public Task<List<WarningRuleEntity>> GetWarningRuleListAsync(int? subsystemId, string? keywords, bool? isEnabled, int? warningType)
{ {
return Context.Queryable<WarningRuleEntity>() return Context.Queryable<WarningRuleEntity>()
.WhereIF(subsystemId.HasValue, x => x.SubSystemId == subsystemId!.Value) .WhereIF(subsystemId.HasValue, x => x.SubSystemId == subsystemId!.Value)
// todo: 客户/kpi名称 改成客户下拉 // todo: 客户/kpi名称 改成客户下拉
.WhereIF(!string.IsNullOrWhiteSpace(keyword), x => x.Name.Contains(keyword!)) .WhereIF(!string.IsNullOrWhiteSpace(keywords), x => x.Name.Contains(keywords!))
.WhereIF(isEnabled.HasValue, x => x.IsEnabled == isEnabled!.Value) .WhereIF(isEnabled.HasValue, x => x.IsEnabled == isEnabled!.Value)
.WhereIF(warningType.HasValue, x => x.WarningType == warningType!.Value) .WhereIF(warningType.HasValue, x => x.WarningType == warningType!.Value)
.ToListAsync(); .ToListAsync();