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>
/// 关键字(kpi/客户名称 模糊)
/// </summary>
public string? KeyWord { get; set; }
public string? Keywords { get; set; }
/// <summary>
/// 是否启用(留null查全部)

View File

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

View File

@ -112,7 +112,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
orderDetails.ForEach(x =>
{
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);
needUpdateDetails.AddRange(orderDetails);
@ -174,7 +174,7 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
details.ForEach(x =>
{
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);
continue;
@ -378,11 +378,11 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
// 修改为完成态
if (detail.Status == TransportWarningStatus.即将超时.GetHashCode())
detail.Status = TransportWarningStatus.已完成.GetHashCode();
if (detail.Status == TransportWarningStatus.已超时.GetHashCode())
if (detail.CalcStatus() == 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;
@ -1070,11 +1070,11 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
if (waningRules.Count == 0) return; //不存在启用的规则主体,直接全部关闭
// 构建规则主体id和版本号字典,稍后用于填充明细的版本号
var ruleVersionDict = waningRules.ToDictionary(x => x.Id, x => x.Version);
var ruleDict = waningRules.ToDictionary(x => x.Id);
// 选出任务中规则条目id,要求订单存在,主体存在并启用
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)
.ToHashSet();
if (ruleItemIds.Count == 0) return;
@ -1145,13 +1145,34 @@ public class TransportWarningHandler : ITransportWarningHandler, ITransientDepen
var endTrackStatusIds = addDetails.Select(x => x.EndTrackStatusId).ToHashSet();
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,规则版本号,截止轨迹状态名称
addDetails.ForEach(x =>
{
x.Id = Guid.NewGuid().ToString("N");
x.Version = ruleVersionDict[x.WarningId]; //一定存在
x.EndTrackStatus = trackStatusIdNameDict.GetValueOrDefault(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);

View File

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

View File

@ -151,9 +151,9 @@ public class TransportWarningService : ApplicationService
{
Id = x.Id,
StartTrackStatusId = x.StartTrackStatusId,
StartTrackStatus = trackStatusDict.GetValueOrDefault(x.StartTrackStatusId),
StartTrackStatus = trackStatusDict.GetValueOrDefault(x.StartTrackStatusId, GlobalConst.EmptyString),
EndTrackStatusId = x.EndTrackStatusId,
EndTrackStatus = trackStatusDict.GetValueOrDefault(x.EndTrackStatusId),
EndTrackStatus = trackStatusDict.GetValueOrDefault(x.EndTrackStatusId, GlobalConst.EmptyString),
TransportTimeSpan = x.TransportTimeSpan,
StartTrackWarningTimeSpan = x.StartTrackWarningTimeSpan,
NotifyUsers = x.NotifyUsers.ToObject<List<NotifyUserDto>>()
@ -208,13 +208,13 @@ public class TransportWarningService : ApplicationService
{
EsId = x.Id,
SubSystemId = x.SubSystemId,
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId),
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId, GlobalConst.EmptyString),
CustomId = x.CustomId,
CustomName = customDict.GetValueOrDefault(x.CustomId),
CustomName = customDict.GetValueOrDefault(x.CustomId, GlobalConst.EmptyString),
OrderId = x.OrderId,
OrderNo = x.OrderNo,
OrderType = x.OrderType,
OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString()),
OrderTypeName = orderTypeDict.GetValueOrDefault(x.OrderType.ToString(), GlobalConst.EmptyString),
NotifyUserNames = ToUserNames(x.NotifyUsers),
// 最新轨迹 (不冗余)
@ -239,9 +239,10 @@ public class TransportWarningService : ApplicationService
WarningRuleDescription = x.WarningRuleDescription,
// 累计运输时间
CumulativeTimeSpan = FormatCumulativeTimeSpan(x.CumulativeTimeSpan),
CumulativeTimeSpan = FormatCumulativeTimeSpan(x),
Status = x.Status,
// 状态动态计算
Status = x.CalcStatus(),
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}分钟";
}
@ -302,6 +306,7 @@ public class TransportWarningService : ApplicationService
var sorted = postBo.Months.Split('/').Select(int.Parse).OrderBy(x => x).ToList();
postBo.Months = string.Join('/', sorted);
}
// 更新或者新增
var id = await _warningRuleRepository.UpsertTransportSceneReturnIdAsync(postBo.ToEntity());

View File

@ -38,7 +38,7 @@ public class WarningService : ApplicationService
[HttpPost("GetWarningRule")]
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)
return new UnifyResultDto<List<WarningRuleDto>>(true, new List<WarningRuleDto>());
@ -63,9 +63,9 @@ public class WarningService : ApplicationService
{
Id = x.Id,
SubSystemId = x.SubSystemId,
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId),
SubSystemName = subSystemDict.GetValueOrDefault(x.SubSystemId, GlobalConst.EmptyString),
CustomId = x.CustomId,
CustomName = customDict.GetValueOrDefault(x.CustomId),
CustomName = customDict.GetValueOrDefault(x.CustomId, GlobalConst.EmptyString),
Name = x.Name,
IsEnabled = x.IsEnabled,
WarningType = x.WarningType,

View File

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

View File

@ -75,12 +75,12 @@ public class WarningRuleRepository : BasicRepository<WarningRuleEntity>, IWarnin
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>()
.WhereIF(subsystemId.HasValue, x => x.SubSystemId == subsystemId!.Value)
// 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(warningType.HasValue, x => x.WarningType == warningType!.Value)
.ToListAsync();