add-params:增加新增修改轨迹新扩展信息参数,目的是为了修改扩展信息

fix:完善轨迹新增/修改验证
This commit is contained in:
hardstylewyl 2025-04-11 17:19:37 +08:00
parent dd1d041e3f
commit 581de918bc
5 changed files with 124 additions and 80 deletions

View File

@ -30,7 +30,9 @@ public class BatchUpsertTrackInput : OrderNosInfo
public DateTime TrackTime { get; set; }
/// <summary>
/// 更改后的轨迹发生时间,无需更改保持为空
/// 新的轨迹发生时间
/// 如果是新增,那么优先级高于TrackTime
/// 如果要修改TrackTime,请同时传递TrackTime(旧的用于匹配),和NewTrackTime
/// </summary>
public DateTime? NewTrackTime { get; set; }
@ -39,7 +41,7 @@ public class BatchUpsertTrackInput : OrderNosInfo
/// </summary>
// [Required]
// [Range(-12, 12)]
public float TrackTimeZone { get; set; }
public float? TrackTimeZone { get; set; }
/// <summary>
/// 客户是否可见
@ -136,6 +138,13 @@ public class BatchUpsertTrackInput : OrderNosInfo
/// </summary>
public string? Extra { get; set; }
/// <summary>
/// 新的扩展信息,
/// 如果是新增,那么优先级高于Extra
/// 如果要修改Extra,请同时传递Extra(用于匹配旧的)和NewExtra
/// </summary>
public string? NewExtra { get; set; }
/// <summary>
/// 是否强制推送
/// </summary>

View File

@ -35,7 +35,9 @@ public class UpsertTrackInput : OrderNoInfo
public DateTime TrackTime { get; set; }
/// <summary>
/// 更改后的轨迹发生时间,无需更改保持为空
/// 新的轨迹发生时间
/// 如果是新增,那么优先级高于TrackTime
/// 如果要修改TrackTime,请同时传递TrackTime(旧的用于匹配),和NewTrackTime
/// </summary>
public DateTime? NewTrackTime { get; set; }
@ -145,6 +147,13 @@ public class UpsertTrackInput : OrderNoInfo
/// </summary>
public string? Extra { get; set; }
/// <summary>
/// 新的扩展信息,
/// 如果是新增,那么优先级高于Extra
/// 如果要修改Extra,请同时传递Extra(用于匹配旧的)和NewExtra
/// </summary>
public string? NewExtra { get; set; }
/// <summary>
/// 是否强制推送
/// </summary>

View File

@ -55,7 +55,9 @@ public class TrackUpsertEvent
public DateTime TrackTime { get; set; }
/// <summary>
/// 更改后的轨迹发生时间,无需更改保持为空
/// 新的轨迹发生时间
/// 如果是新增,那么优先级高于TrackTime
/// 如果要修改TrackTime,请同时传递TrackTime(旧的用于匹配),和NewTrackTime
/// </summary>
public DateTime? NewTrackTime { get; set; }
@ -162,6 +164,13 @@ public class TrackUpsertEvent
/// </summary>
public string? Extra { get; set; }
/// <summary>
/// 新的扩展信息,
/// 如果是新增,那么优先级高于Extra
/// 如果要修改Extra,请同时传递Extra(用于匹配旧的)和NewExtra
/// </summary>
public string? NewExtra { get; set; }
/// <summary>
/// 是否强制推送
/// </summary>

View File

@ -289,55 +289,26 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
var existTracks = tracks.Where(x => x.OrderId == order.OrderId).ToList();
if (@event.CompareFields.IsNullOrEmpty())
// tips:如果没传时区则使用+8兜底进行过滤
var timezone = Math.Abs(@event.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 0.01f ? 8.0f : @event.TrackTimeZone;
// 根据时间过滤
existTracks = @event.IsAdd
? existTracks.Where(x => x.GetUtc0TrackTime() == (@event.NewTrackTime ?? @event.TrackTime).Subtract(TimeSpan.FromHours(timezone))).ToList()
: existTracks.Where(x =>
x.GetUtc0TrackTime() == @event.TrackTime.Subtract(TimeSpan.FromHours(timezone))
// 修改了并且修改了时间
|| (@event.NewTrackTime != null && x.GetUtc0TrackTime() == @event.NewTrackTime.Value.Subtract(TimeSpan.FromHours(timezone)))
).ToList();
// 根据扩展信息过滤
existTracks = @event.IsAdd
? existTracks.Where(x => x.Extra == (@event.NewExtra ?? @event.Extra)).ToList()
: existTracks.Where(x => x.Extra == @event.Extra || x.Extra == @event.NewExtra).ToList();
if (@event.IsAdd)
{
existTracks = existTracks.Where(x => x.TrackTime == @event.TrackTime).ToList();
}
else
{
Debug.Assert(@event.CompareFields != null, "@event.CompareFields != null");
var extraDict = TextJsonHelper.DeserializeToDictionary(@event.Extra);
if (extraDict == null || !extraDict.TryGetValue(@event.CompareFields, out var compareValue))
{
throw new BusinessException(message: $"请检查拓展字段,为什么找不到比较字段:{@event.CompareFields}");
}
existTracks = existTracks.Where(x =>
{
var oldExtraDict = TextJsonHelper.DeserializeToDictionary(x.Extra);
// tips:注意兼容性,历史轨迹的字段可能为空
if (oldExtraDict == null || !oldExtraDict.TryGetValue(@event.CompareFields, out var oldValue))
{
return false;
}
return TextJsonHelper.EqJsonElement(oldValue, compareValue);
}).ToList();
}
var track = existTracks.FirstOrDefault();
if (!@event.IsAdd)
{
if (existTracks.Count > 1)
{
_logger.LogInformation("订单存在多条轨迹不允许修改:{@event}", @event);
continue;
}
if (track == null)
{
_logger.LogInformation("订单不存在轨迹不允许修改:{@event}", @event);
continue; // 不存在不让改
}
updateTracks.Add(BuiltUpdateTrack(@event, track, order, trackContent));
operationRecords.Add(BuildOrderOperationRecord(@event, track, order));
}
else
{
// 不允许重复轨迹,跳过
if (!trackContent.IsRepeatable && existTracks.Count > 0)
if (existTracks.Count > 0)
{
_logger.LogInformation("订单已经存在不允许重复的轨迹,不允许重复添加:{@event}", @event);
continue;
@ -345,6 +316,26 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
insertTracks.Add(BuiltNewTrack(@event, order, trackContent));
}
else
{
// 不存在不让改
if (existTracks.Count == 0)
{
_logger.LogInformation("订单不存在轨迹,不允许修改:{@event}", @event);
continue;
}
if (existTracks.Count > 1)
{
_logger.LogInformation("订单存在多条轨迹不允许修改:{@event}", @event);
continue;
}
var track = existTracks.First();
updateTracks.Add(BuiltUpdateTrack(@event, track, order, trackContent));
operationRecords.Add(BuildOrderOperationRecord(@event, track, order));
}
canNextOrderIds.Add(order.OrderId);
}
@ -406,7 +397,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
track.TrackPlacePostcode = @event.TrackPlacePostcode ?? GlobalConst.EmptyString;
track.DestinationTimeZone = @event.DestinationTimeZone;
track.EstimatedDeliveryDate = @event.EstimatedDeliveryDate;
track.Extra = @event.Extra;
track.Extra = @event.NewExtra ?? @event.Extra;
return track;
}
@ -456,7 +447,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
TrackPlacePostcode = @event.TrackPlacePostcode ?? GlobalConst.EmptyString,
DestinationTimeZone = @event.DestinationTimeZone,
EstimatedDeliveryDate = @event.EstimatedDeliveryDate,
Extra = @event.Extra
Extra = @event.NewExtra ?? @event.Extra,
};
track.ZeroTrackTime = Math.Abs(track.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http;
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Application.Contract.Services.ProvideServices;
using SJZY.Track.Application.Helpers;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
@ -289,10 +290,12 @@ public partial class TrackService : ApplicationService, ITrackService
input.TrackCode,
input.Source,
input.TrackTime,
input.TrackTimeZone ?? 8.0f, //没传时区默认使用+8参与过滤
input.NewTrackTime,
input.EstimatedDeliveryDate,
input.DestinationTimeZone,
input.Extra,
input.NewExtra,
input.CompareFields);
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
@ -308,6 +311,7 @@ public partial class TrackService : ApplicationService, ITrackService
var name = userInfo.Data.UserName;
// 新增/更新轨迹
input.TrackTimeZone ??= GlobalConst.NoneTrackTimeZone; //时区为空使用一个特殊值填充
var @event = ObjectMapper.Map<UpsertTrackInput, TrackUpsertEvent>(input);
@event.SubSystemId = input.SubSystemId;
@event.CustomId = order.CustomId;
@ -366,10 +370,12 @@ public partial class TrackService : ApplicationService, ITrackService
input.TrackCode,
input.Source,
input.TrackTime,
input.TrackTimeZone ?? 8.0f, //没传时区默认使用+8参与过滤
input.NewTrackTime,
input.EstimatedDeliveryDate,
input.DestinationTimeZone,
input.Extra,
input.NewExtra,
input.CompareFields);
// 获取用户name
@ -397,7 +403,7 @@ public partial class TrackService : ApplicationService, ITrackService
TrackPlace = input.TrackPlace,
TrackTime = input.TrackTime,
NewTrackTime = input.NewTrackTime,
TrackTimeZone = input.TrackTimeZone,
TrackTimeZone = input.TrackTimeZone ?? GlobalConst.NoneTrackTimeZone, //时区为空使用一个特殊值填充
OperationMan = userInfo.Data.UserName,
OperationManId = userInfo.Data.UserId,
IsVisibility = input.IsVisibility,
@ -418,6 +424,7 @@ public partial class TrackService : ApplicationService, ITrackService
DestinationTimeZone = input.DestinationTimeZone,
CompareFields = input.CompareFields,
Extra = input.Extra,
NewExtra = input.NewExtra,
ForcedPush = input.ForcedPush,
IsToMq = input.IsToMq,
};
@ -436,10 +443,12 @@ public partial class TrackService : ApplicationService, ITrackService
string trackCode,
int source,
DateTime trackTime,
float trackTimezone,
DateTime? newTrackTime,
DateTime? estimatedDeliveryDate,
float? destinationTimeZone,
string? extra,
string? newExtra,
string? compareFields
)
{
@ -505,10 +514,8 @@ public partial class TrackService : ApplicationService, ITrackService
//轨迹新增,不允许重复的轨迹提前拦截
if (isAdd)
{
//允许重复,跳过检查
if (trackContent.IsRepeatable) return;
//找到这个订单的这个轨迹code的所有轨迹
var tracks = await RetryQueryTrackAsync(orderId, trackCode, trackTime, extra, compareFields, trackContent.IsRepeatable);
var tracks = await RetryQueryTrackAsync(isAdd, orderId, trackCode, trackTime, trackTimezone, newTrackTime, extra, newExtra, compareFields, trackContent.IsRepeatable);
if (tracks.Count > 0)
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:{trackCode}不允许重复创建轨迹");
}
@ -516,21 +523,45 @@ public partial class TrackService : ApplicationService, ITrackService
else
{
//找到这个订单的这个轨迹code的所有轨迹,
var tracks = await RetryQueryTrackAsync(orderId, trackCode, trackTime, extra, compareFields, trackContent.IsRepeatable);
//不存在需要更新的轨迹
var tracks = await RetryQueryTrackAsync(isAdd, orderId, trackCode, trackTime, trackTimezone, newTrackTime, extra, newExtra, compareFields, trackContent.IsRepeatable);
// 不存在需要更新的轨迹
if (tracks.Count == 0)
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:[{trackCode}]没有要更新的记录");
//更新轨迹,同一时间存在多条轨迹记录,理由:不清晰到底要修改哪一条或是全部修改
// 更新轨迹,同一时间存在多条轨迹记录,理由:不清晰到底要修改哪一条或是全部修改
if (tracks.Count > 1)
{
if (newTrackTime.HasValue && tracks.Any(track => DateTimeHelper.ConvertUtc0Compare(track.TrackTime, track.TrackTimeZone, newTrackTime.Value, trackTimezone) == 0))
{
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:[{trackCode}]和现存轨迹时间重复,不允许修改,请检查轨迹NewTrackTime");
}
if (!string.IsNullOrWhiteSpace(extra) && tracks.Any(track => string.Equals(track.Extra, newExtra)))
{
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:[{trackCode}]和现存轨迹Extra重复,不允许修改,请检查轨迹NewExtra");
}
throw new BusinessException(message: $"订单:{orderNo},轨迹代码:[{trackCode}]存在多条记录,不允许修改");
}
var track = tracks.First();
if (DateTimeHelper.ConvertUtc0Compare(track.TrackTime, track.TrackTimeZone, trackTime, trackTimezone) != 0)
{
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:[{trackCode}]找不到要更新的记录,不允许修改,请检查轨迹TrackTime");
}
if (!string.Equals(track.Extra, extra))
{
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:[{trackCode}]找不到要更新的记录,不允许修改,请检查轨迹Extra");
}
}
}
// 重试查询轨迹,直到存在符合要求的轨迹,或者超过最大重试次数
private async Task<List<TrackDetailsIndex>> RetryQueryTrackAsync(int orderId, string trackCode, DateTime trackTime, string? extra, string? compareFields, bool isRepeatable)
private async Task<List<TrackDetailsIndex>> RetryQueryTrackAsync(bool isAdd, int orderId, string trackCode, DateTime trackTime, float trackTimezone, DateTime? newTrackTime, string? extra, string? newExtra, string? compareFields, bool isRepeatable)
{
var tracks = await QueryAndFilterAsync(orderId, trackCode, trackTime, extra, compareFields, isRepeatable);
var tracks = await QueryAndFilterAsync(isAdd, orderId, trackCode, trackTime, trackTimezone, newTrackTime, extra, newExtra, compareFields, isRepeatable);
if (tracks.Count > 0)
return tracks;
@ -540,7 +571,7 @@ public partial class TrackService : ApplicationService, ITrackService
{
try
{
tracks = await QueryAndFilterAsync(orderId, trackCode, trackTime, extra, compareFields, isRepeatable);
tracks = await QueryAndFilterAsync(isAdd, orderId, trackCode, trackTime, trackTimezone, newTrackTime, extra, newExtra, compareFields, isRepeatable);
if (tracks.Count > 0)
return tracks;
//指数退避等待
@ -559,28 +590,23 @@ public partial class TrackService : ApplicationService, ITrackService
//查询并按比较字段过滤轨迹,当比较字段为空时则使用轨迹发生时间过滤
//tips:后续进行投影缩参优化
private async Task<List<TrackDetailsIndex>> QueryAndFilterAsync(int orderId, string trackCode, DateTime trackTime, string? extra, string? compareFields, bool isRepeatable)
private async Task<List<TrackDetailsIndex>> QueryAndFilterAsync(bool isAdd, int orderId, string trackCode, DateTime trackTime, float trackTimezone, DateTime? newTrackTime, string? extra, string? newExtra, string? compareFields, bool isRepeatable)
{
var tracks = await _trackDetailsEsRepository.GetListAsync(new[] { orderId }, trackCode, true);
// 如果不允许重复,则直接返回
if (!isRepeatable) return tracks;
//无比较字段时使用轨迹时间参与过滤(兼容老版本)
if (string.IsNullOrWhiteSpace(compareFields))
{
return tracks.Where(x => x.TrackTime == trackTime).ToList();
}
tracks = isAdd
? tracks.Where(x => x.GetUtc0TrackTime() == (newTrackTime ?? trackTime).Subtract(TimeSpan.FromHours(trackTimezone))).ToList()
: tracks.Where(x =>
x.GetUtc0TrackTime() == trackTime.Subtract(TimeSpan.FromHours(trackTimezone))
// 修改了并且修改了时间
|| (newTrackTime != null && x.GetUtc0TrackTime() == newTrackTime.Value.Subtract(TimeSpan.FromHours(trackTimezone)))
).ToList();
return tracks.Where(x =>
{
if (string.IsNullOrWhiteSpace(x.Extra))
throw new BusinessException(message: "轨迹extra为空无法使用比较字段比较,请检查轨迹");
var extraJsonElement = TextJsonHelper.DeserializeToJsonElement(x.Extra);
var inputExtraJsonElement = TextJsonHelper.DeserializeToJsonElement(extra);
return TextJsonHelper.EqByJsonElementField(extraJsonElement, inputExtraJsonElement, compareFields);
})
.ToList();
return isAdd
? tracks.Where(x => x.Extra == (newExtra ?? extra)).ToList()
: tracks.Where(x => x.Extra == extra || x.Extra == newExtra).ToList();
}
}