Merge branch 'S06' into test
This commit is contained in:
commit
ad98219dc7
@ -32,7 +32,7 @@ public class UpsertTrackInput : OrderNoInfo
|
|||||||
/// 轨迹发生时间
|
/// 轨迹发生时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required]
|
||||||
public DateTime? TrackTime { get; set; }
|
public DateTime TrackTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更改后的轨迹发生时间,无需更改保持为空
|
/// 更改后的轨迹发生时间,无需更改保持为空
|
||||||
|
|||||||
@ -181,7 +181,7 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
throw new BusinessException(message: $"当前轨迹不存在扩展信息,无法利用扩展字段:{@event.CompareFields}");
|
throw new BusinessException(message: $"当前轨迹不存在扩展信息,无法利用扩展字段:{@event.CompareFields}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var extraDict = TextJsonHelper.DeserializeDictionary(x.Extra);
|
var extraDict = TextJsonHelper.DeserializeToDictionary(x.Extra);
|
||||||
if (extraDict == null || !extraDict.TryGetValue(@event.CompareFields, out var compareValue))
|
if (extraDict == null || !extraDict.TryGetValue(@event.CompareFields, out var compareValue))
|
||||||
{
|
{
|
||||||
throw new BusinessException(message: $"请检查拓展字段,为什么找不到比较字段:{@event.CompareFields}");
|
throw new BusinessException(message: $"请检查拓展字段,为什么找不到比较字段:{@event.CompareFields}");
|
||||||
|
|||||||
@ -277,7 +277,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Assert(@event.CompareFields != null, "@event.CompareFields != null");
|
Debug.Assert(@event.CompareFields != null, "@event.CompareFields != null");
|
||||||
var extraDict = TextJsonHelper.DeserializeDictionary(@event.Extra);
|
var extraDict = TextJsonHelper.DeserializeToDictionary(@event.Extra);
|
||||||
if (extraDict == null || !extraDict.TryGetValue(@event.CompareFields, out var compareValue))
|
if (extraDict == null || !extraDict.TryGetValue(@event.CompareFields, out var compareValue))
|
||||||
{
|
{
|
||||||
throw new BusinessException(message: $"请检查拓展字段,为什么找不到比较字段:{@event.CompareFields}");
|
throw new BusinessException(message: $"请检查拓展字段,为什么找不到比较字段:{@event.CompareFields}");
|
||||||
@ -285,7 +285,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
|
|
||||||
existTracks = existTracks.Where(x =>
|
existTracks = existTracks.Where(x =>
|
||||||
{
|
{
|
||||||
var oldExtraDict = TextJsonHelper.DeserializeDictionary(x.Extra);
|
var oldExtraDict = TextJsonHelper.DeserializeToDictionary(x.Extra);
|
||||||
// tips:注意兼容性,历史轨迹的字段可能为空
|
// tips:注意兼容性,历史轨迹的字段可能为空
|
||||||
if (oldExtraDict == null || !oldExtraDict.TryGetValue(@event.CompareFields, out var oldValue))
|
if (oldExtraDict == null || !oldExtraDict.TryGetValue(@event.CompareFields, out var oldValue))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,13 +18,20 @@ public static class TextJsonHelper
|
|||||||
return string.IsNullOrWhiteSpace(json) ? default : System.Text.Json.JsonSerializer.Deserialize<T>(json);
|
return string.IsNullOrWhiteSpace(json) ? default : System.Text.Json.JsonSerializer.Deserialize<T>(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, object?>? DeserializeDictionary(string? dictJsonString)
|
public static Dictionary<string, object?>? DeserializeToDictionary(string? dictJsonString)
|
||||||
{
|
{
|
||||||
return string.IsNullOrWhiteSpace(dictJsonString)
|
return string.IsNullOrWhiteSpace(dictJsonString)
|
||||||
? null
|
? null
|
||||||
: System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object?>>(dictJsonString);
|
: System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object?>>(dictJsonString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JsonElement? DeserializeToJsonElement(string? dictJsonString)
|
||||||
|
{
|
||||||
|
return string.IsNullOrWhiteSpace(dictJsonString)
|
||||||
|
? null
|
||||||
|
: System.Text.Json.JsonSerializer.Deserialize<JsonElement>(dictJsonString);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取JsonElement字符串表达的值
|
/// 获取JsonElement字符串表达的值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -158,7 +165,7 @@ public static class TextJsonHelper
|
|||||||
/// <param name="b"></param>
|
/// <param name="b"></param>
|
||||||
/// <param name="fieldName"></param>
|
/// <param name="fieldName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool EqByJsonElementField(object a, object b, string fieldName)
|
public static bool EqByJsonElementField(object? a, object? b, string fieldName)
|
||||||
{
|
{
|
||||||
if (a is not JsonElement aJsonElement || b is not JsonElement bJsonElement)
|
if (a is not JsonElement aJsonElement || b is not JsonElement bJsonElement)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -47,156 +47,6 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
_trackDetailsEsRepository = trackDetailsEsRepository;
|
_trackDetailsEsRepository = trackDetailsEsRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 新增、更新轨迹(存在就更新)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="BusinessException"></exception>
|
|
||||||
[HttpPost("Track/Upsert")]
|
|
||||||
public async Task<UnifyResultDto> UpsertTrackAsync(UpsertTrackInput input)
|
|
||||||
{
|
|
||||||
// todo: 代码太长了
|
|
||||||
var order = await _orderRepository.GetFirstAsync(x =>
|
|
||||||
x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo,
|
|
||||||
x => new
|
|
||||||
{
|
|
||||||
x.Id,
|
|
||||||
x.CustomId
|
|
||||||
});
|
|
||||||
if (order == default)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"订单:{input.OrderNo}不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GlobalConst.SupportTrackSources.Contains(input.Source))
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: "轨迹来源是必须的");
|
|
||||||
}
|
|
||||||
|
|
||||||
//要求时间在当前时间的前后100年之间内
|
|
||||||
bool ValidateTrackTime(DateTime? d) => (d != null && d < DateTime.Now.AddYears(-100) || d > DateTime.Now.AddYears(100));
|
|
||||||
if (ValidateTrackTime(input.TrackTime) || ValidateTrackTime(input.NewTrackTime) || ValidateTrackTime(input.EstimatedDeliveryDate))
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: "轨迹时间不合法");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((input.EstimatedDeliveryDate.HasValue == false && input.DestinationTimeZone.HasValue) ||
|
|
||||||
(input.EstimatedDeliveryDate.HasValue && input.DestinationTimeZone.HasValue == false))
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: "【预计签收时间】和【签收地时区】必须同时输入");
|
|
||||||
}
|
|
||||||
|
|
||||||
//当修改时,如果为来源为外部提供商则不允许修改
|
|
||||||
if (!input.IsAdd && input.Source == (int) TrackSourceEnum.ExternalServiceProvide)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: "来源为外部服务商轨迹不允许修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
var trackContent = await _trackContentRepository.GetByCodeAsync(input.SubSystemId, input.TrackCode);
|
|
||||||
if (trackContent == default)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"轨迹代码:{input.TrackCode}轨迹内容不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
//指示是否为手动操作
|
|
||||||
var manualOperation = input.Source == (int) TrackSourceEnum.Artificial;
|
|
||||||
|
|
||||||
//不允许手动创建
|
|
||||||
if (manualOperation && input.IsAdd && !trackContent.IsAllowManuallyCreate)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"轨迹代码:{input.TrackCode}不允许手动创建");
|
|
||||||
}
|
|
||||||
|
|
||||||
//不允许手动更新
|
|
||||||
if (manualOperation && !input.IsAdd && !trackContent.IsAllowManuallyUpdate)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"轨迹代码:{input.TrackCode}不允许手动更新");
|
|
||||||
}
|
|
||||||
|
|
||||||
//如果传递了esId并且是修改操作则使用esid
|
|
||||||
var tracks = (!string.IsNullOrWhiteSpace(input.EsId) && !input.IsAdd)
|
|
||||||
? await _trackDetailsEsRepository.GetDataByIds(new[] { input.EsId })
|
|
||||||
: (await _trackDetailsEsRepository.GetListAsync(new[] { order.Id }, input.TrackCode, true))
|
|
||||||
.Where(x => x.TrackTime == input.TrackTime)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
//根据比较字段选出所需的轨迹
|
|
||||||
if (!string.IsNullOrWhiteSpace(input.CompareFields))
|
|
||||||
{
|
|
||||||
var a = input.TrackCode + TextJsonHelper.ExtractValue(input.Extra, input.CompareFields);
|
|
||||||
tracks = tracks.Where(x => string.Equals(a,
|
|
||||||
x.TrackCode + TextJsonHelper.ExtractValue(x.Extra, input.CompareFields!))).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo:es落盘延迟是不确定的
|
|
||||||
//当为更新操作时发现更新的数目为0进行重试操作
|
|
||||||
if (!input.IsAdd && tracks.Count == 0)
|
|
||||||
{
|
|
||||||
var curRetryCount = 0;
|
|
||||||
var success = false;
|
|
||||||
while (!success && curRetryCount < GlobalConst.MaxUpdateTrackRetryCount)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tracks = (await _trackDetailsEsRepository.GetListAsync(new[] { order.Id }, input.TrackCode, true))
|
|
||||||
.Where(x => x.TrackTime == input.TrackTime)
|
|
||||||
.ToList();
|
|
||||||
if (tracks.Count > 0)
|
|
||||||
success = true;
|
|
||||||
// todo: 最大重试次数应该是可配置的,当出现的时候应该有告警,而不是直接给调用方,指数退避 2^N
|
|
||||||
await Task.Delay(300);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
curRetryCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tracks.Count == 0)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"订单:{input.OrderNo},轨迹代码:{input.TrackCode}没有要更新的记录");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//更新轨迹,同一时间存在多条轨迹记录,理由:不清晰到底要修改哪一条或是全部修改
|
|
||||||
if (!input.IsAdd && tracks.Count > 1)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"订单:{input.OrderNo},轨迹代码:{input.TrackCode}存在多条记录,不允许修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
|
|
||||||
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
|
|
||||||
{
|
|
||||||
//todo:保留之前的方式(FBA在用) 后续可能去除
|
|
||||||
userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync(input.OptionUserId);
|
|
||||||
|
|
||||||
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
|
|
||||||
//TODO: log || ex
|
|
||||||
throw new BusinessException(message: $"调用用户中心,获取用户信息失败:{userInfo.Msg}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var name = userInfo.Data.UserName;
|
|
||||||
|
|
||||||
// 新增/更新轨迹
|
|
||||||
var @event = ObjectMapper.Map<UpsertTrackInput, TrackUpsertEvent>(input);
|
|
||||||
@event.SubSystemId = input.SubSystemId;
|
|
||||||
@event.CustomId = order.CustomId;
|
|
||||||
@event.OrderIdentifiers = new[]
|
|
||||||
{
|
|
||||||
new OrderIdentifier
|
|
||||||
{
|
|
||||||
OrderId = order.Id,
|
|
||||||
OrderNo = input.OrderNo,
|
|
||||||
OrderType = input.OrderType,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@event.OperationMan = name;
|
|
||||||
await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event);
|
|
||||||
return new UnifyResultDto(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除轨迹
|
/// 删除轨迹
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -375,7 +225,7 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
throw new BusinessException(message: "轨迹extra为空无法使用比较字段比较,请检查轨迹");
|
throw new BusinessException(message: "轨迹extra为空无法使用比较字段比较,请检查轨迹");
|
||||||
}
|
}
|
||||||
|
|
||||||
var extraDict = TextJsonHelper.DeserializeDictionary(y.Extra);
|
var extraDict = TextJsonHelper.DeserializeToDictionary(y.Extra);
|
||||||
if (extraDict!.TryGetValue(input.CompareFields!, out var compareValueJsonElement))
|
if (extraDict!.TryGetValue(input.CompareFields!, out var compareValueJsonElement))
|
||||||
return TextJsonHelper.EqJsonElementAndObject(compareValueJsonElement, input.CompareValue);
|
return TextJsonHelper.EqJsonElementAndObject(compareValueJsonElement, input.CompareValue);
|
||||||
|
|
||||||
@ -403,8 +253,76 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
return new UnifyResultDto(true, true);
|
return new UnifyResultDto(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增、更新轨迹(存在就更新)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="BusinessException"></exception>
|
||||||
|
[HttpPost("Track/Upsert")]
|
||||||
|
public async Task<UnifyResultDto> UpsertTrackAsync(UpsertTrackInput input)
|
||||||
|
{
|
||||||
|
var order = await _orderRepository.GetFirstAsync(x =>
|
||||||
|
x.SubSystemId == input.SubSystemId
|
||||||
|
&& x.OrderType == input.OrderType
|
||||||
|
&& x.OrderNo == input.OrderNo,
|
||||||
|
x => new
|
||||||
|
{
|
||||||
|
x.Id,
|
||||||
|
x.OrderNo,
|
||||||
|
x.CustomId
|
||||||
|
});
|
||||||
|
if (order == default)
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: $"订单:{input.OrderNo}不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入参数的静态规则检查
|
||||||
|
// 轨迹内容上的约束检查
|
||||||
|
// 更新轨迹时是否可以匹配到轨迹的检查
|
||||||
|
await TrackUpsertValidation(input.IsAdd,
|
||||||
|
input.SubSystemId,
|
||||||
|
order.Id,
|
||||||
|
order.OrderNo,
|
||||||
|
input.TrackCode,
|
||||||
|
input.Source,
|
||||||
|
input.TrackTime,
|
||||||
|
input.NewTrackTime,
|
||||||
|
input.EstimatedDeliveryDate,
|
||||||
|
input.DestinationTimeZone,
|
||||||
|
input.Extra,
|
||||||
|
input.CompareFields);
|
||||||
|
|
||||||
|
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
|
||||||
|
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
|
||||||
|
{
|
||||||
|
//todo:保留之前的方式(FBA在用) 后续可能去除
|
||||||
|
userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync(input.OptionUserId);
|
||||||
|
|
||||||
|
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
|
||||||
|
throw new BusinessException(message: $"调用用户中心,获取用户信息失败:{userInfo.Msg}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = userInfo.Data.UserName;
|
||||||
|
|
||||||
|
// 新增/更新轨迹
|
||||||
|
var @event = ObjectMapper.Map<UpsertTrackInput, TrackUpsertEvent>(input);
|
||||||
|
@event.SubSystemId = input.SubSystemId;
|
||||||
|
@event.CustomId = order.CustomId;
|
||||||
|
@event.OrderIdentifiers = new[]
|
||||||
|
{
|
||||||
|
new OrderIdentifier
|
||||||
|
{
|
||||||
|
OrderId = order.Id,
|
||||||
|
OrderNo = input.OrderNo,
|
||||||
|
OrderType = input.OrderType,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@event.OperationMan = name;
|
||||||
|
await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event);
|
||||||
|
return new UnifyResultDto(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
// todo:代码封装性太差了,拆小一点
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 批量新增、更新轨迹
|
/// 批量新增、更新轨迹
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -416,8 +334,9 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
{
|
{
|
||||||
input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空
|
input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空
|
||||||
var orders = await _orderRepository.GetListAsync(x =>
|
var orders = await _orderRepository.GetListAsync(x =>
|
||||||
x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType &&
|
x.SubSystemId == input.SubSystemId
|
||||||
input.OrderNos.Contains(x.OrderNo),
|
&& x.OrderType == input.OrderType
|
||||||
|
&& input.OrderNos.Contains(x.OrderNo),
|
||||||
x => new
|
x => new
|
||||||
{
|
{
|
||||||
x.Id,
|
x.Id,
|
||||||
@ -430,94 +349,26 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
throw new BusinessException(message: "订单一个都不存在");
|
throw new BusinessException(message: "订单一个都不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GlobalConst.SupportTrackSources.Contains(input.Source))
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: "轨迹来源是必须的");
|
|
||||||
}
|
|
||||||
|
|
||||||
//当修改时,如果为来源为外部提供商则不允许修改
|
|
||||||
if (!input.IsAdd && input.Source == (int) TrackSourceEnum.ExternalServiceProvide)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: "来源为外部服务商轨迹不允许修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验主体:批量新增只选取第一条订单进行校验
|
// 校验主体:批量新增只选取第一条订单进行校验
|
||||||
//【新增】存在指定轨迹的内容,进行更新覆盖(只处理一条的情况,并且决定权交给用户),不存在直接插入即可
|
//【新增】存在指定轨迹的内容,进行更新覆盖(只处理一条的情况,并且决定权交给用户),不存在直接插入即可
|
||||||
//【更新】存在指定轨迹的内容(匹配到多条则不处理)
|
//【更新】存在指定轨迹的内容(匹配到多条则不处理)
|
||||||
var order = orders.First();
|
var order = orders.First();
|
||||||
|
|
||||||
//要求时间在当前时间的前后100年之间内
|
// 输入参数的静态规则检查
|
||||||
bool ValidateTrackTime(DateTime? d) => (d != null && d < DateTime.Now.AddYears(-100) || d > DateTime.Now.AddYears(100));
|
// 轨迹内容上的约束检查
|
||||||
if (ValidateTrackTime(input.TrackTime) || ValidateTrackTime(input.NewTrackTime) || ValidateTrackTime(input.EstimatedDeliveryDate))
|
// 更新轨迹时是否可以匹配到轨迹的检查
|
||||||
{
|
await TrackUpsertValidation(input.IsAdd,
|
||||||
throw new BusinessException(message: "轨迹时间不合法");
|
input.SubSystemId,
|
||||||
}
|
order.Id,
|
||||||
|
order.OrderNo,
|
||||||
if ((input.EstimatedDeliveryDate.HasValue == false && input.DestinationTimeZone.HasValue) ||
|
input.TrackCode,
|
||||||
(input.EstimatedDeliveryDate.HasValue && input.DestinationTimeZone.HasValue == false))
|
input.Source,
|
||||||
{
|
input.TrackTime,
|
||||||
throw new BusinessException(message: "【预计签收时间】和【签收地时区】必须同时输入");
|
input.NewTrackTime,
|
||||||
}
|
input.EstimatedDeliveryDate,
|
||||||
|
input.DestinationTimeZone,
|
||||||
var trackContent = await _trackContentRepository.GetByCodeAsync(input.SubSystemId, input.TrackCode);
|
input.Extra,
|
||||||
if (trackContent == default)
|
input.CompareFields);
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"轨迹代码:{input.TrackCode}轨迹内容不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
//指示是否为手动操作
|
|
||||||
var manualOperation = input.Source == (int) TrackSourceEnum.Artificial;
|
|
||||||
|
|
||||||
//不允许手动创建
|
|
||||||
if (manualOperation && input.IsAdd && !trackContent.IsAllowManuallyCreate)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"轨迹代码:{input.TrackCode}不允许手动创建");
|
|
||||||
}
|
|
||||||
|
|
||||||
//不允许手动更新
|
|
||||||
if (manualOperation && !input.IsAdd && !trackContent.IsAllowManuallyUpdate)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"轨迹代码:{input.TrackCode}不允许手动更新");
|
|
||||||
}
|
|
||||||
|
|
||||||
var tracks = (await _trackDetailsEsRepository.GetListAsync(new[] { order.Id }, input.TrackCode, true))
|
|
||||||
.Where(x => x.TrackTime == input.TrackTime)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// todo:这块代码抽出去
|
|
||||||
//当为更新操作时发现更新的数目为0进行重试操作
|
|
||||||
if (!input.IsAdd && tracks.Count == 0)
|
|
||||||
{
|
|
||||||
var curRetryCount = 0;
|
|
||||||
var success = false;
|
|
||||||
while (!success && curRetryCount < GlobalConst.MaxUpdateTrackRetryCount)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tracks = (await _trackDetailsEsRepository.GetListAsync(new[] { order.Id }, input.TrackCode, true))
|
|
||||||
.Where(x => x.TrackTime == input.TrackTime)
|
|
||||||
.ToList();
|
|
||||||
if (tracks.Count > 0)
|
|
||||||
success = true;
|
|
||||||
await Task.Delay(300);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
curRetryCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tracks.Count == 0)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"订单:[{string.Join(",", input.OrderNos)}],轨迹代码:{input.TrackCode}没有要更新的记录");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新轨迹,同一时间存在多条轨迹记录,理由:不清晰到底要修改哪一条或是全部修改
|
|
||||||
if (!input.IsAdd && tracks.Count > 1)
|
|
||||||
{
|
|
||||||
throw new BusinessException(message: $"订单:{order.OrderNo},轨迹代码:{input.TrackCode}存在多条记录,不允许修改");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户name
|
// 获取用户name
|
||||||
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
|
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
|
||||||
@ -572,4 +423,158 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
|
|
||||||
return new UnifyResultDto(true, true);
|
return new UnifyResultDto(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//在轨迹更新主流程之前的前置检查
|
||||||
|
private async Task TrackUpsertValidation(
|
||||||
|
bool isAdd,
|
||||||
|
int subSystemId,
|
||||||
|
int orderId,
|
||||||
|
string orderNo,
|
||||||
|
string trackCode,
|
||||||
|
int source,
|
||||||
|
DateTime trackTime,
|
||||||
|
DateTime? newTrackTime,
|
||||||
|
DateTime? estimatedDeliveryDate,
|
||||||
|
float? destinationTimeZone,
|
||||||
|
string? extra,
|
||||||
|
string? compareFields
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#region 静态规则检查
|
||||||
|
|
||||||
|
// 约束轨迹来源只能选取 1-外部 2-内部 3-手动
|
||||||
|
if (!GlobalConst.SupportTrackSources.Contains(source))
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: "轨迹来源是必须的,1:外部服务商 2:内部系统 3:人工操作");
|
||||||
|
}
|
||||||
|
|
||||||
|
//当修改时,如果为来源为外部提供商则不允许修改
|
||||||
|
if (!isAdd && source == (int) TrackSourceEnum.ExternalServiceProvide)
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: "来源为外部服务商轨迹不允许修改");
|
||||||
|
}
|
||||||
|
|
||||||
|
//要求时间在当前时间的前后100年之间内
|
||||||
|
bool ValidateTrackTime(DateTime? d) => (d != null && d < DateTime.Now.AddYears(-100) || d > DateTime.Now.AddYears(100));
|
||||||
|
if (ValidateTrackTime(trackTime) || ValidateTrackTime(newTrackTime) || ValidateTrackTime(estimatedDeliveryDate))
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: "轨迹时间不合法");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((estimatedDeliveryDate.HasValue == false && destinationTimeZone.HasValue) ||
|
||||||
|
(estimatedDeliveryDate.HasValue && destinationTimeZone.HasValue == false))
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: "【预计签收时间】和【签收地时区】必须同时输入");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(compareFields) && string.IsNullOrWhiteSpace(extra))
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: "当输入了【轨迹对比字段】则轨迹扩展是必须的的");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 轨迹内容中的配置规则检查
|
||||||
|
|
||||||
|
var trackContent = await _trackContentRepository.GetByCodeAsync(subSystemId, trackCode);
|
||||||
|
if (trackContent == default)
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: $"轨迹代码:{trackCode}轨迹内容不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
//指示是否为手动操作
|
||||||
|
var manualOperation = source == (int) TrackSourceEnum.Artificial;
|
||||||
|
|
||||||
|
//不允许手动创建
|
||||||
|
if (manualOperation && isAdd && !trackContent.IsAllowManuallyCreate)
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: $"轨迹代码:{trackCode}不允许手动创建");
|
||||||
|
}
|
||||||
|
|
||||||
|
//不允许手动更新
|
||||||
|
if (manualOperation && !isAdd && !trackContent.IsAllowManuallyUpdate)
|
||||||
|
{
|
||||||
|
throw new BusinessException(message: $"轨迹代码:{trackCode}不允许手动更新");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
//轨迹新增,不允许重复的轨迹提前拦截
|
||||||
|
if (isAdd)
|
||||||
|
{
|
||||||
|
//允许重复,跳过检查
|
||||||
|
if (trackContent.IsRepeatable) return;
|
||||||
|
//找到这个订单的这个轨迹code的所有轨迹
|
||||||
|
var tracks = await QueryAndFilterAsync(orderId, trackCode, trackTime, extra, compareFields);
|
||||||
|
if (tracks.Count > 0)
|
||||||
|
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:{trackCode}不允许重复创建轨迹");
|
||||||
|
}
|
||||||
|
//针对于轨迹更新检查
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//找到这个订单的这个轨迹code的所有轨迹,
|
||||||
|
var tracks = await RetryQueryTrackAsync(orderId, trackCode, trackTime, extra, compareFields);
|
||||||
|
//不存在需要更新的轨迹
|
||||||
|
if (tracks.Count == 0)
|
||||||
|
throw new BusinessException(message: $"订单:[{orderNo}],轨迹代码:{trackCode}没有要更新的记录");
|
||||||
|
|
||||||
|
//更新轨迹,同一时间存在多条轨迹记录,理由:不清晰到底要修改哪一条或是全部修改
|
||||||
|
if (tracks.Count > 1)
|
||||||
|
throw new BusinessException(message: $"订单:{orderNo},轨迹代码:{trackCode}存在多条记录,不允许修改");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重试查询轨迹,直到存在符合要求的轨迹,或者超过最大重试次数
|
||||||
|
private async Task<List<TrackDetailsIndex>> RetryQueryTrackAsync(int orderId, string trackCode, DateTime trackTime, string? extra, string? compareFields)
|
||||||
|
{
|
||||||
|
var tracks = await QueryAndFilterAsync(orderId, trackCode, trackTime, extra, compareFields);
|
||||||
|
if (tracks.Count > 0)
|
||||||
|
return tracks;
|
||||||
|
|
||||||
|
//重试阶段
|
||||||
|
var curRetryCount = 0;
|
||||||
|
while (curRetryCount < GlobalConst.MaxUpdateTrackRetryCount) //tips:后续将最大重试次数提出到配置中
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tracks = await QueryAndFilterAsync(orderId, trackCode, trackTime, extra, compareFields);
|
||||||
|
if (tracks.Count > 0)
|
||||||
|
return tracks;
|
||||||
|
//指数退避等待
|
||||||
|
var delay = TimeSpan.FromMilliseconds(Math.Pow(2, curRetryCount) * 150); // 150ms, 300ms, 600ms, ...
|
||||||
|
await Task.Delay(delay);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
curRetryCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//超过最大重试次数还没找到
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
//查询并按比较字段过滤轨迹,当比较字段为空时则使用轨迹发生时间过滤
|
||||||
|
//tips:后续进行投影缩参优化
|
||||||
|
private async Task<List<TrackDetailsIndex>> QueryAndFilterAsync(int orderId1, string trackCode1, DateTime trackTime1, string? extra1, string? compareFields1)
|
||||||
|
{
|
||||||
|
var tracks1 = await _trackDetailsEsRepository.GetListAsync(new[] { orderId1 }, trackCode1, true);
|
||||||
|
//无比较字段时使用轨迹时间参与过滤(兼容老版本)
|
||||||
|
if (string.IsNullOrWhiteSpace(compareFields1))
|
||||||
|
{
|
||||||
|
return tracks1.Where(x => x.TrackTime == trackTime1).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks1.Where(x =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(x.Extra))
|
||||||
|
throw new BusinessException(message: "轨迹extra为空无法使用比较字段比较,请检查轨迹");
|
||||||
|
|
||||||
|
var extraJsonElement = TextJsonHelper.DeserializeToJsonElement(x.Extra);
|
||||||
|
var inputExtraJsonElement = TextJsonHelper.DeserializeToJsonElement(extra1);
|
||||||
|
|
||||||
|
return TextJsonHelper.EqByJsonElementField(extraJsonElement, inputExtraJsonElement, compareFields1);
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user