Merge branch 'S06' into test

This commit is contained in:
hardstylewyl 2025-01-10 15:58:29 +08:00
commit 63ec1e06ca
22 changed files with 447 additions and 214 deletions

View File

@ -120,6 +120,11 @@ public class BatchUpsertTrackInput : OrderNosInfo
[Range(-12, 12)] [Range(-12, 12)]
public float? DestinationTimeZone { get; set; } public float? DestinationTimeZone { get; set; }
/// <summary>
/// 重复的情况下,用什么比较
/// </summary>
public string? CompareFields { get; set; }
/// <summary> /// <summary>
/// 扩展信息字段,用与轨迹推送的附加字段 /// 扩展信息字段,用与轨迹推送的附加字段
/// </summary> /// </summary>

View File

@ -129,6 +129,11 @@ public class UpsertTrackInput : OrderNoInfo
/// </summary> /// </summary>
public int OptionUserId { get; set; } public int OptionUserId { get; set; }
/// <summary>
/// 重复的情况下,用什么比较
/// </summary>
public string? CompareFields { get; set; }
/// <summary> /// <summary>
/// 扩展信息字段,用与轨迹推送的附加字段 /// 扩展信息字段,用与轨迹推送的附加字段
/// </summary> /// </summary>

View File

@ -44,10 +44,15 @@ public class EditTrackPushConfigInput
/// </summary> /// </summary>
public bool? IsAllPush { get; set; } public bool? IsAllPush { get; set; }
/// <summary>
/// 是否全量推送
/// </summary>
public bool? IsAllPushWithLatest { get; set; }
/// <summary> /// <summary>
/// 时间格式枚举 /// 时间格式枚举
/// </summary> /// </summary>
public int DateTimeFormatType { get; set; } public int? DateTimeFormatType { get; set; } = 0;
/// <summary> /// <summary>
/// 日期时间格式模板 /// 日期时间格式模板

View File

@ -17,6 +17,11 @@ public class TrackPushContentConfigDto
/// </summary> /// </summary>
public bool IsAllPush { get; set; } public bool IsAllPush { get; set; }
/// <summary>
/// 是否全量推送(最新轨迹)
/// </summary>
public bool IsAllPushWithLatest { get; set; }
/// <summary> /// <summary>
/// 是否支持删除 /// 是否支持删除
/// </summary> /// </summary>

View File

@ -19,15 +19,3 @@ public class TrackUpdateInput
public string Log { get; set; } public string Log { get; set; }
} }
public class TrackItem
{
public string Location { get; set; } = null!;
public string Date { get; set; }
public double TimeZone { get; set; }
public string? Description { get; set; }
public string? DescriptionCn { get; set; }
public string? Code { get; set; }
public string? Status { get; set; }
public string? Extra { get; set; }
}

View File

@ -29,8 +29,9 @@ public class TrackPushRecordDto
/// <summary> /// <summary>
/// 接口通请求Id /// 接口通请求Id
/// 在请求接口通前被拦截,就不会有请求Id
/// </summary> /// </summary>
public Guid RequestId { get; set; } public Guid? RequestId { get; set; }
/// <summary> /// <summary>
/// 信息 /// 信息

View File

@ -27,8 +27,9 @@ public class TrackPushCompletedEvent
/// <summary> /// <summary>
/// 接口通请求Id /// 接口通请求Id
/// 在请求接口通前被拦截,就不会有请求Id
/// </summary> /// </summary>
public Guid RequestId { get; set; } public Guid? RequestId { get; set; }
/// <summary> /// <summary>
/// 信息 /// 信息

View File

@ -80,6 +80,11 @@ public struct SystemPushStruct
/// </summary> /// </summary>
public float TrackTimeZone { get; set; } public float TrackTimeZone { get; set; }
/// <summary>
/// 重复的情况下,用什么比较
/// </summary>
public string? CompareFields { get; set; }
/// <summary> /// <summary>
/// 扩展信息字段,用与轨迹推送的附加字段 /// 扩展信息字段,用与轨迹推送的附加字段
/// </summary> /// </summary>

View File

@ -146,6 +146,11 @@ public class TrackUpsertEvent
/// </summary> /// </summary>
public float? DestinationTimeZone { get; set; } public float? DestinationTimeZone { get; set; }
/// <summary>
/// 重复的情况下,用什么比较
/// </summary>
public string? CompareFields { get; set; }
/// <summary> /// <summary>
/// 扩展信息字段,用与轨迹推送的附加字段 /// 扩展信息字段,用与轨迹推送的附加字段
/// </summary> /// </summary>

View File

@ -5,7 +5,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
<Version>7.0.12</Version> <Version>7.0.14</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -26,5 +26,11 @@ public interface IBroadcastingService : ITransientDependency
/// 轨迹推送完成广播(推送完成回调) /// 轨迹推送完成广播(推送完成回调)
/// </summary> /// </summary>
/// <param name="log"></param> /// <param name="log"></param>
void TrackPushCompletedPublicTopicAsync(TrackPushRecordDto log); void TrackPushCompletedPublicTopic(TrackPushRecordDto log);
/// <summary>
/// 轨迹推送失败广播(推送前置被拦截,或调用接口通失败)
/// </summary>
/// <param name="log"></param>
void TrackPushFailedPubilcTopic(TrackPushRecordDto log);
} }

View File

@ -158,6 +158,7 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
} }
} }
// todo:多个相同code的轨迹删除,也需要考虑??
private async Task<List<TrackDetailsIndex>> DeleteTrackAsync(TrackDeleteEvent @event) private async Task<List<TrackDetailsIndex>> DeleteTrackAsync(TrackDeleteEvent @event)
{ {
List<int> orderIds; List<int> orderIds;

View File

@ -1,3 +1,4 @@
using System.Text.Json;
using DotNetCore.CAP; using DotNetCore.CAP;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -10,7 +11,6 @@ using SJZY.Track.Application.Helpers;
using SJZY.Track.Application.Options; using SJZY.Track.Application.Options;
using SJZY.Track.Application.Track2InterfaceRelay; using SJZY.Track.Application.Track2InterfaceRelay;
using SJZY.Track.Domain.Aggregates.OrderAggregate; using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackPushAggregate; using SJZY.Track.Domain.Aggregates.TrackPushAggregate;
using SJZY.Track.Domain.Enums; using SJZY.Track.Domain.Enums;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -23,23 +23,25 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
private readonly IHttpClientProxy<IInterfaceForwardServiceV2> _httpClientProxy; private readonly IHttpClientProxy<IInterfaceForwardServiceV2> _httpClientProxy;
private readonly IOptionsMonitor<InterfaceRelayParamsConfigOptions> _options; private readonly IOptionsMonitor<InterfaceRelayParamsConfigOptions> _options;
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly ITrackPushCacheService _trackPushCacheService; private readonly ITrackPushCacheService _trackPushCacheService;
private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository; private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository;
private readonly IBroadcastingService _broadcastingService;
private List<OrderEntity> _orders = null!; private List<OrderEntity> _orders = null!;
private List<TrackPushContentConfigDto> _pushConfigs = null!; private List<TrackPushContentConfigDto> _pushConfigs = null!;
public TrackPushEventHandler(IHttpClientProxy<IInterfaceForwardServiceV2> httpClientProxy, public TrackPushEventHandler(IHttpClientProxy<IInterfaceForwardServiceV2> httpClientProxy,
IOrderRepository orderRepository, ITrackPushCacheService trackPushCacheService, IOrderRepository orderRepository,
ITrackDetailsEsRepository trackDetailsEsRepository, ITrackPushRecordEsRepository trackPushRecordEsRepository, ITrackPushCacheService trackPushCacheService,
IOptionsMonitor<InterfaceRelayParamsConfigOptions> options) ITrackPushRecordEsRepository trackPushRecordEsRepository,
IOptionsMonitor<InterfaceRelayParamsConfigOptions> options,
IBroadcastingService broadcastingService)
{ {
_httpClientProxy = httpClientProxy; _httpClientProxy = httpClientProxy;
_orderRepository = orderRepository; _orderRepository = orderRepository;
_trackPushCacheService = trackPushCacheService; _trackPushCacheService = trackPushCacheService;
_trackDetailsEsRepository = trackDetailsEsRepository;
_trackPushRecordEsRepository = trackPushRecordEsRepository; _trackPushRecordEsRepository = trackPushRecordEsRepository;
_options = options; _options = options;
_broadcastingService = broadcastingService;
} }
[CapSubscribe(GlobalConst.TrackPushSubscribe, Group = GlobalConst.TrackPushSubscribe)] [CapSubscribe(GlobalConst.TrackPushSubscribe, Group = GlobalConst.TrackPushSubscribe)]
@ -93,25 +95,50 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
private async Task DoPushAsync(TrackPushEvent @event) private async Task DoPushAsync(TrackPushEvent @event)
{ {
// todo: 轨迹中台推送逻辑致使的未推送,也需要广播到mq,告知业务系统缘故
var items = new List<TrackPushInput>(); var items = new List<TrackPushInput>();
TrackPushContentConfigDto? config; TrackPushContentConfigDto? config;
var isSystemPush = @event.OperationMan == null; var isSystemPush = @event.OperationMan == null;
if (isSystemPush && !@event.ForcedPush) if (isSystemPush && !@event.ForcedPush)
{ {
config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode);
foreach (var order in _orders) foreach (var order in _orders)
{ {
if (order.QuestionType == (int) TrackProblemType.Error) continue; // 系统不推异常单,只能人工操作 if (config == null)
// 强制推送只需直接查出配置 {
if (@event.ForcedPush) TrackPushFailedPublicTopic($"没有在推送映射配置中找到关于轨迹代码[{@event.TrackCode}]的配置", @event, order);
config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode); return;
}
// 系统不推异常单,只能人工操作
if (order.QuestionType == (int) TrackProblemType.Error)
{
TrackPushFailedPublicTopic("系统不推异常单,只能人工操作", @event, order);
continue;
}
// 推送新增,需要根据上一次的推送 推断 本次推送 是否可行,为了约束顺序 // 推送新增,需要根据上一次的推送 推断 本次推送 是否可行,为了约束顺序
else var (resultConfig, nextCode) = GetValidPushConfigAsync(_pushConfigs, order.LatestPushTrackCode, @event.TrackCode);
config = GetValidPushConfigAsync(_pushConfigs, order.LatestPushTrackCode, @event.TrackCode); if (resultConfig == null)
if (config == null) continue; {
TrackPushFailedPublicTopic($"推送顺序异常,下一个要推送的应为[{nextCode}]", @event, order);
continue;
}
config = resultConfig;
// 是否自动推送 // 是否自动推送
if (!config.IsAutoPush) continue; if (!config.IsAutoPush)
{
TrackPushFailedPublicTopic($"没有设置为自动推送,如果要推送请手动推送", @event, order);
continue;
}
// 配置的类型如何和订单类型不一致则不允许推送 // 配置的类型如何和订单类型不一致则不允许推送
if (config.OrderType != order.OrderType) continue; if (config.OrderType != order.OrderType)
{
TrackPushFailedPublicTopic($"订单类型{order.OrderType}和配置中的订单类型[{config.OrderType}]不一致,不能推送", @event, order);
continue;
}
var log = new TrackPushRecordIndex var log = new TrackPushRecordIndex
{ {
@ -129,33 +156,49 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
IsToMq = @event.IsToMq, IsToMq = @event.IsToMq,
Extra = @event.SystemPushInfo.Extra Extra = @event.SystemPushInfo.Extra
}; };
var item = await BuiltPushItem(config, log, @event.SystemPushInfo.Extra); var item = await BuiltPushItem(config, log, @event.SystemPushInfo.CompareFields);
item.Log = JsonConvert.SerializeObject(log); item.Log = JsonConvert.SerializeObject(log);
items.Add(item); items.Add(item);
} }
} }
// 手工或强制推送,不会校验已推和顺序问题,因为可能是更新 // 手工或强制推送,不会校验已推和顺序问题,因为可能是更新
else else
{ {
config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode); config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode);
if (config == null) return;
foreach (var order in _orders) foreach (var order in _orders)
{ {
if (config is { IsAllPush: true }) if (config == null)
{ {
// 强制推送只需直接查出配置 TrackPushFailedPublicTopic($"没有在推送映射配置中找到关于轨迹代码[{@event.TrackCode}]的配置", @event, order);
if (@event.ForcedPush) return;
config = _pushConfigs.FirstOrDefault(x => x.TrackCode == @event.TrackCode); }
// 推断 本次推送 是否可行
else if (config is { IsAllPush: true })
config = GetValidPushConfigAsync(_pushConfigs, order.LatestPushTrackCode, @event.TrackCode); {
// 非强制推送需要 推断 本次推送 是否可行
if (!@event.ForcedPush)
{
var (resultConfig, nextCode) = GetValidPushConfigAsync(_pushConfigs, order.LatestPushTrackCode, @event.TrackCode);
if (resultConfig == null)
{
TrackPushFailedPublicTopic($"推送顺序异常,下一个要推送的应为[{nextCode}]", @event, order);
continue;
}
config = resultConfig;
}
// tips:强制推送直接使用配置
} }
if (config == null) continue;
//配置的类型如何和订单类型不一致则不允许推送 //配置的类型如何和订单类型不一致则不允许推送
if (config.OrderType != order.OrderType) continue; if (config.OrderType != order.OrderType)
{
TrackPushFailedPublicTopic($"订单类型{order.OrderType}和配置中的订单类型[{config.OrderType}]不一致,不能推送", @event, order);
continue;
}
var log = new TrackPushRecordIndex var log = new TrackPushRecordIndex
{ {
@ -173,7 +216,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
IsToMq = @event.IsToMq, IsToMq = @event.IsToMq,
Extra = @event.SystemPushInfo.Extra Extra = @event.SystemPushInfo.Extra
}; };
var item = await BuiltPushItem(config, log, @event.SystemPushInfo.Extra); var item = await BuiltPushItem(config, log, @event.SystemPushInfo.CompareFields);
item.Log = JsonConvert.SerializeObject(log); item.Log = JsonConvert.SerializeObject(log);
items.Add(item); items.Add(item);
} }
@ -193,6 +236,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
if (r.Code != GlobalConst.SuccessCode) if (r.Code != GlobalConst.SuccessCode)
{ {
TrackPushFailedPublicTopic($"轨迹中台调用接口通失败,RequestId: {r.RequestId}; Msg: {r.Msg}", @event, r.RequestId, items.Cast<dynamic>().ToList());
throw new BusinessException(message: $"requestId: {r.RequestId}; serviceProviderCode:{serviceProviderCode} Msg: {r.Msg}"); throw new BusinessException(message: $"requestId: {r.RequestId}; serviceProviderCode:{serviceProviderCode} Msg: {r.Msg}");
} }
} }
@ -207,7 +251,11 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
foreach (var order in _orders) foreach (var order in _orders)
{ {
//配置的类型如何和订单类型不一致则不允许推送 //配置的类型如何和订单类型不一致则不允许推送
if (config.OrderType != order.OrderType) continue; if (config.OrderType != order.OrderType)
{
TrackPushFailedPublicTopic($"订单类型{order.OrderType}和配置中的订单类型[{config.OrderType}]不一致,不能推送", @event, order);
continue;
}
var log = new TrackPushRecordIndex var log = new TrackPushRecordIndex
{ {
@ -225,7 +273,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
IsToMq = @event.IsToMq, IsToMq = @event.IsToMq,
Extra = @event.SystemPushInfo.Extra Extra = @event.SystemPushInfo.Extra
}; };
var item = BuiltUpdateItem(config, log, @event.SystemPushInfo.Extra); var item = BuiltUpdateItem(config, log);
item.Log = JsonConvert.SerializeObject(log); item.Log = JsonConvert.SerializeObject(log);
items.Add(item); items.Add(item);
} }
@ -244,12 +292,13 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
if (r.Code != GlobalConst.SuccessCode) if (r.Code != GlobalConst.SuccessCode)
{ {
TrackPushFailedPublicTopic($"轨迹中台调用接口通失败,RequestId: {r.RequestId}; Msg: {r.Msg}", @event, r.RequestId, items.Cast<dynamic>().ToList());
throw new BusinessException(message: $"requestId: {r.RequestId}; serviceProviderCode:{serviceProviderCode} Msg: {r.Msg}"); throw new BusinessException(message: $"requestId: {r.RequestId}; serviceProviderCode:{serviceProviderCode} Msg: {r.Msg}");
} }
} }
} }
private TrackUpdateInput BuiltUpdateItem(TrackPushContentConfigDto config, TrackPushRecordIndex log, string? extraJson) private TrackUpdateInput BuiltUpdateItem(TrackPushContentConfigDto config, TrackPushRecordIndex log)
{ {
var trackDatetime = log.TrackTime.AddHours(config.TrackTimeZone ?? log.TrackTimeZone - log.TrackTimeZone); var trackDatetime = log.TrackTime.AddHours(config.TrackTimeZone ?? log.TrackTimeZone - log.TrackTimeZone);
var trackDateStr = DateTimeFormat(trackDatetime, config.TrackTimeZone ?? log.TrackTimeZone, config); var trackDateStr = DateTimeFormat(trackDatetime, config.TrackTimeZone ?? log.TrackTimeZone, config);
@ -268,7 +317,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
{ "descriptionCn", config.TrackContentValue }, { "descriptionCn", config.TrackContentValue },
{ "code", config.TrackContentCodeValue }, { "code", config.TrackContentCodeValue },
{ "status", config.TrackStatusValue }, { "status", config.TrackStatusValue },
{ "extra", DeserializeForTextJson<object>(extraJson) } { "extra", DeserializeForTextJson<object>(log.Extra) }
}; };
body.Data.Add(dict); body.Data.Add(dict);
log.PushContent = body.ToJson(); log.PushContent = body.ToJson();
@ -276,7 +325,8 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
return body; return body;
} }
private async Task<TrackPushInput> BuiltPushItem(TrackPushContentConfigDto config, TrackPushRecordIndex log, string? extraJson) private async Task<TrackPushInput> BuiltPushItem(TrackPushContentConfigDto config, TrackPushRecordIndex log,
string? compareFields)
{ {
var trackDatetime = log.TrackTime.AddHours(config.TrackTimeZone ?? log.TrackTimeZone - log.TrackTimeZone); var trackDatetime = log.TrackTime.AddHours(config.TrackTimeZone ?? log.TrackTimeZone - log.TrackTimeZone);
var trackDateStr = DateTimeFormat(trackDatetime, config.TrackTimeZone ?? log.TrackTimeZone, config); var trackDateStr = DateTimeFormat(trackDatetime, config.TrackTimeZone ?? log.TrackTimeZone, config);
@ -285,7 +335,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
{ {
OrderNo = log.OrderNo, OrderNo = log.OrderNo,
}; };
var dict = new Dictionary<string, object?>() var cur = new Dictionary<string, object?>
{ {
// 推真实的发生地和发生时间(时间是计算后的) // 推真实的发生地和发生时间(时间是计算后的)
{ "location", log.TrackPlace }, { "location", log.TrackPlace },
@ -295,9 +345,9 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
{ "descriptionCn", config.TrackContentValue }, { "descriptionCn", config.TrackContentValue },
{ "code", config.TrackContentCodeValue }, { "code", config.TrackContentCodeValue },
{ "status", config.TrackStatusValue }, { "status", config.TrackStatusValue },
{ "extra", DeserializeForTextJson<object>(extraJson) } { "extra", DeserializeForTextJson<object>(log.Extra) }
}; };
body.Data.Add(dict); body.Data.Add(cur);
if (config.IsAllPush) if (config.IsAllPush)
{ {
@ -305,7 +355,23 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
if (history != default) if (history != default)
{ {
body = DeserializeForTextJson<TrackPushInput>(history.PushContent); body = DeserializeForTextJson<TrackPushInput>(history.PushContent);
body!.Data.Add(dict); if (config.IsAllPushWithLatest)
{
var old = body!.Data
.Where(x => x["code"] == cur["code"])
.WhereIf(!compareFields.IsNullOrWhiteSpace(), x =>
{
if (x["extra"] == null || log.Extra == null) return false;
return EqExtraByFieldForTextJson(x["extra"]!, DeserializeForTextJson<JsonElement>(log.Extra)!, compareFields!);
})
.FirstOrDefault();
if (old != null)
{
body.Data.Remove(old);
}
}
body!.Data.Add(cur);
} }
} }
@ -318,7 +384,7 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
/// 根据轨迹代码推断下一个(升序)要推送的内容,如果找不到或者已经是最后一个了 /// 根据轨迹代码推断下一个(升序)要推送的内容,如果找不到或者已经是最后一个了
/// 则查询有没有可交换的推送,没有就返回null /// 则查询有没有可交换的推送,没有就返回null
/// </summary> /// </summary>
private static TrackPushContentConfigDto? GetValidPushConfigAsync(List<TrackPushContentConfigDto> cache, private static (TrackPushContentConfigDto? config, string nextCode) GetValidPushConfigAsync(List<TrackPushContentConfigDto> cache,
string? latestPushTrackCode, string? trackCode) string? latestPushTrackCode, string? trackCode)
{ {
var idx = cache.FindIndex(x => x.TrackCode == latestPushTrackCode); var idx = cache.FindIndex(x => x.TrackCode == latestPushTrackCode);
@ -332,7 +398,10 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
// find swap // find swap
cache.FirstOrDefault(x => x.TrackCode == cache[idx + 1].SwapTrackCode); cache.FirstOrDefault(x => x.TrackCode == cache[idx + 1].SwapTrackCode);
return matched != null && matched.TrackCode == trackCode ? matched : default; //没推完,可能不符合推送顺序
return matched != null && matched.TrackCode == trackCode
? (matched, matched.TrackCode)
: (default, matched?.TrackCode ?? cache[idx + 1].TrackCode);
} }
/// <summary> /// <summary>
@ -364,4 +433,79 @@ public class TrackPushEventHandler : ITransientDependency, ICapSubscribe
{ {
return string.IsNullOrWhiteSpace(json) ? default : System.Text.Json.JsonSerializer.Deserialize<T>(json); return string.IsNullOrWhiteSpace(json) ? default : System.Text.Json.JsonSerializer.Deserialize<T>(json);
} }
//比较扩展中的某个字段的相等性
private bool EqExtraByFieldForTextJson(object a, object b, string fieldName)
{
if (a is not JsonElement aJsonElement || b is not JsonElement bJsonElement)
return false;
if (aJsonElement.TryGetProperty(fieldName, out var aValue)
&& bJsonElement.TryGetProperty(fieldName, out var bValue))
{
return aValue.ToString() == bValue.ToString();
}
return false;
}
//轨迹推送失败(被拦截)
private void TrackPushFailedPublicTopic(
string failedMessage,
TrackPushEvent @event,
OrderEntity order)
{
_broadcastingService.TrackPushFailedPubilcTopic(new TrackPushRecordDto
{
//还没请求接口通
RequestId = null,
IsSuccess = false,
Message = failedMessage,
OperationMan = @event.OperationMan,
PushTime = DateTime.Now,
OptionType = @event.OptionType.ToString(),
IsManualPush = @event.OperationMan != null,
//还没到构建推送内容那一步就被拦截
PushContent = string.Empty,
OrderNo = order.OrderNo,
TrackStatus = @event.SystemPushInfo.TrackStatus,
TrackContent = @event.SystemPushInfo.TrackStatus,
TrackTimeZone = @event.SystemPushInfo.TrackTimeZone,
TrackTime = @event.SystemPushInfo.TrackTime,
TrackPlace = @event.SystemPushInfo.TrackPlace,
TrackCode = @event.TrackCode,
Extra = @event.SystemPushInfo.Extra,
});
}
//轨迹推送失败(请求接口通)
private void TrackPushFailedPublicTopic(
string failedMessage,
TrackPushEvent @event,
Guid requestId,
List<dynamic> pushOrUpdateInputs)
{
foreach (var pushInput in pushOrUpdateInputs)
{
_broadcastingService.TrackPushFailedPubilcTopic(new TrackPushRecordDto
{
RequestId = requestId,
IsSuccess = false,
Message = failedMessage,
OperationMan = @event.OperationMan,
PushTime = DateTime.Now,
OptionType = @event.OptionType.ToString(),
IsManualPush = @event.OperationMan != null,
PushContent = SerializeForTextJson(pushInput),
OrderNo = pushInput.OrderNo,
TrackStatus = @event.SystemPushInfo.TrackStatus,
TrackContent = @event.SystemPushInfo.TrackStatus,
TrackTimeZone = @event.SystemPushInfo.TrackTimeZone,
TrackTime = @event.SystemPushInfo.TrackTime,
TrackPlace = @event.SystemPushInfo.TrackPlace,
TrackCode = @event.TrackCode,
Extra = @event.SystemPushInfo.Extra,
});
}
}
} }

View File

@ -1,4 +1,7 @@
using System.Diagnostics;
using System.Text.Json;
using DotNetCore.CAP; using DotNetCore.CAP;
using Microsoft.Extensions.Logging;
using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Events; using SJZY.Track.Application.Contract.Events;
@ -20,6 +23,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
private readonly IProvideQueries _provideQueries; private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository; private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly IBroadcastingService _broadcastingService; private readonly IBroadcastingService _broadcastingService;
private readonly ILogger<TrackUpsertEventHandler> _logger;
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository; private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
public TrackUpsertEventHandler( public TrackUpsertEventHandler(
@ -28,7 +32,8 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
IProvideQueries provideQueries, IProvideQueries provideQueries,
ITrackDetailsEsRepository trackDetailsEsRepository, ITrackDetailsEsRepository trackDetailsEsRepository,
IOrderOperationRecordEsRepository orderOperationRecordEsRepository, IOrderOperationRecordEsRepository orderOperationRecordEsRepository,
IBroadcastingService broadcastingService) IBroadcastingService broadcastingService,
ILogger<TrackUpsertEventHandler> logger)
{ {
_orderRepository = orderRepository; _orderRepository = orderRepository;
_capPublisher = capPublisher; _capPublisher = capPublisher;
@ -36,6 +41,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
_trackDetailsEsRepository = trackDetailsEsRepository; _trackDetailsEsRepository = trackDetailsEsRepository;
_orderOperationRecordEsRepository = orderOperationRecordEsRepository; _orderOperationRecordEsRepository = orderOperationRecordEsRepository;
_broadcastingService = broadcastingService; _broadcastingService = broadcastingService;
_logger = logger;
} }
[CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)] [CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)]
@ -216,6 +222,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
TrackPlace = @event.TrackPlace, TrackPlace = @event.TrackPlace,
TrackTime = @event.NewTrackTime ?? @event.TrackTime, TrackTime = @event.NewTrackTime ?? @event.TrackTime,
TrackTimeZone = @event.TrackTimeZone, TrackTimeZone = @event.TrackTimeZone,
CompareFields = @event.CompareFields,
Extra = @event.Extra Extra = @event.Extra
}, },
ForcedPush = @event.ForcedPush, ForcedPush = @event.ForcedPush,
@ -232,188 +239,75 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray(); var orderIds = @event.OrderIdentifiers.Select(x => x.OrderId).ToArray();
// important:轨迹code相同,时间、发生地不同的,可能存在多条!! // important:轨迹code相同,时间、发生地不同的,可能存在多条!!
var tracks = await _trackDetailsEsRepository.GetListAsync(orderIds, @event.TrackCode, false); var tracks = await _trackDetailsEsRepository.GetListAsync(orderIds, @event.TrackCode, true);
var insertTracks = new List<TrackDetailsIndex>(); var insertTracks = new List<TrackDetailsIndex>();
var updateTracks = new List<TrackDetailsIndex>(); var updateTracks = new List<TrackDetailsIndex>();
foreach (var order in @event.OrderIdentifiers) foreach (var order in @event.OrderIdentifiers)
{ {
TrackDetailsIndex? track; // fast path: by update with es id case
if (!@event.IsAdd) if (!@event.IsAdd && !string.IsNullOrWhiteSpace(@event.EsId))
{ {
//如果命中了esId var trackById = tracks.FirstOrDefault(x => x.Id == @event.EsId);
track = string.IsNullOrWhiteSpace(@event.EsId) if (trackById != null)
? null
: tracks.FirstOrDefault(x => x.Id == @event.EsId);
if (track != null) goto TipEsIdTrack;
//同一订单同轨迹code同一轨迹时间如果有多条轨迹明细则不允许修改
var existTracks = tracks.Where(x => x.OrderId == order.OrderId
&& x.TrackTime == @event.TrackTime).ToArray();
if (existTracks.Length > 1)
{ {
// 修改轨迹时,订单存在多条轨迹不允许修改 updateTracks.Add(BuiltUpdateTrack(@event, trackById, order, trackContent));
continue;
} }
track = existTracks.FirstOrDefault(); continue;
}
if (track == null) continue; // 不存在不让改 var existTracks = tracks.Where(x => x.OrderId == order.OrderId).ToList();
if (@event.CompareFields.IsNullOrEmpty())
{
existTracks = existTracks.Where(x => x.TrackTime == @event.TrackTime).ToList();
} }
else else
{ {
// 【批量新增】所有可能遇到的场景 Debug.Assert(@event.CompareFields != null, "@event.CompareFields != null");
// 标识:允许重复,不允许重复,零条,一条,多条; var extraDict = GetExtraDictForTextJson(@event.Extra);
// 场景A:允许重复,零条 => 新增 if (extraDict == null || !extraDict.TryGetValue(@event.CompareFields, out var compareValue))
// 场景B:允许重复,一条 => 新增(约束受限新增,否则跳过新增)
// 场景C:允许重复,多条 => 新增(约束受限新增,否则跳过新增)
// 场景D:不允许重复,零条 => 新增
// 场景E:不允许重复,一条 => 跳过
// 场景F:不允许重复,(理想不会出现多条) => 跳过
var existTracks = tracks.Where(x => x.OrderId == order.OrderId).ToArray();
track = existTracks.FirstOrDefault();
//覆盖场景:B,C
if (trackContent.IsRepeatable && existTracks.Length >= 1)
{ {
if (existTracks.Any(x => x.TrackTime == @event.TrackTime)) throw new BusinessException(message: $"请检查拓展字段,为什么找不到比较字段:{@event.CompareFields}");
}
existTracks = existTracks.Where(x =>
{
var oldExtraDict = GetExtraDictForTextJson(x.Extra);
// tips:注意兼容性,历史轨迹的字段可能为空
if (oldExtraDict == null|| !oldExtraDict.TryGetValue(@event.CompareFields, out var oldValue))
{ {
//TrackCode TrackTime联合不能重复 return false;
continue;
} }
// 设置null后面执行新增逻辑 return EqJsonElementObject(oldValue, compareValue);
track = null; }).ToList();
} }
//不允许重复,并且记录大于等于一条,跳过 var track = existTracks.FirstOrDefault();
//覆盖场景:E,F
if (!trackContent.IsRepeatable && existTracks.Length >= 1) if (!@event.IsAdd)
{
if (existTracks.Count > 1)
{ {
// todo: 所有的event handle 多写log,取缔注释,特别是continue,return,这种跳出的地方,方便排查问题
_logger.LogInformation("订单存在多条轨迹不允许修改:{@event}", @event);
continue; continue;
} }
//其余情况:A,D都为新增操作,无需检查数量,track为null执行新增操作 // todo:例如这里
} if (track == null) continue; // 不存在不让改
//通过esId命中了轨迹 updateTracks.Add(BuiltUpdateTrack(@event, track, order, trackContent));
TipEsIdTrack:
if (track == default)
{
track = new TrackDetailsIndex
{
SubSystemId = @event.SubSystemId,
OrderId = order.OrderId,
OrderNo = order.OrderNo,
OrderType = order.OrderType,
TrackCode = @event.TrackCode,
TrackPlace = @event.TrackPlace,
TrackTime = @event.NewTrackTime ?? @event.TrackTime,
TrackTimeZone = @event.TrackTimeZone,
ServiceProviderCode = @event.TrackRefreshData.ServiceProviderCode ?? GlobalConst.EmptyString,
OriginTrackContent = @event.TrackRefreshData.OriginTrackContent ?? GlobalConst.EmptyString,
OriginTrackDataHash = @event.TrackRefreshData.OriginTrackDataHash ?? GlobalConst.EmptyString,
CreateUser = @event.OperationMan ?? GlobalConst.SystemUser,
CreateTime = DateTime.Now,
//来源轨迹内容,第一次新增的时候使用轨迹内容表提供的
TrackStatusId = trackContent.TrackStatusId,
TrackStatus = trackContent.TrackStatus,
TrackStatusCode = trackContent.TrackStatusCode,
//跨子系统?
TrackContentId = trackContent.TrackContentId,
TrackContent = @event.Content ?? trackContent.TrackContent,
TrackEnContent = @event.EnStatus ?? trackContent.TrackEnContent,
//S06新增轨迹明细字段
IsVisibility = @event.IsVisibility,
Source = @event.Source,
Remarks = @event.Remarks ?? GlobalConst.EmptyString,
Files = @event.Files?.Select(x => new FileItem
{
OssKey = x.OssKey,
FileName = x.FileName
}).ToList(),
TrackPlaceCity = @event.TrackPlaceCity ?? GlobalConst.EmptyString,
TrackPlaceCityId = @event.TrackPlaceCityId ?? GlobalConst.NotExistId,
TrackPlaceProvince = @event.TrackPlaceProvince ?? GlobalConst.EmptyString,
TrackPlaceProvinceId = @event.TrackPlaceProvinceId ?? GlobalConst.NotExistId,
TrackPlaceNation = @event.TrackPlaceNation ?? GlobalConst.EmptyString,
TrackPlaceNationId = @event.TrackPlaceNationId ?? GlobalConst.NotExistId,
TrackPlacePostcode = @event.TrackPlacePostcode ?? GlobalConst.EmptyString,
DestinationTimeZone = @event.DestinationTimeZone,
EstimatedDeliveryDate = @event.EstimatedDeliveryDate,
Extra = @event.Extra
};
track.ZeroTrackTime = Math.Abs(track.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1
? track.TrackTime
: track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone));
insertTracks.Add(track);
// 写入操作日志
_ = _orderOperationRecordEsRepository.AddAsync(new OrderOperationRecordIndex
{
OrderId = order.OrderId,
OrderNo = order.OrderNo,
OptionType = OrderOperationType.创建轨迹.ToString(),
Content = track.ToJson(),
CreateUserId = @event.OperationManId,
CreateUserName = @event.OperationMan ?? "",
CreateTime = DateTime.Now
});
} }
else else
{ {
//外部轨迹,轨迹发生地,轨迹发生时间,轨迹发生时区,不允许更改 // 不允许重复轨迹,跳过
if (track.Source != (int) TrackSourceEnum.ExternalServiceProvide) if (!trackContent.IsRepeatable && existTracks.Count > 0) continue;
{
track.TrackPlace = @event.TrackPlace;
track.TrackTime = @event.NewTrackTime ?? @event.TrackTime;
track.TrackTimeZone = @event.TrackTimeZone;
}
track.ZeroTrackTime = Math.Abs(track.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1 insertTracks.Add(BuiltNewTrack(@event, order, trackContent));
? track.TrackTime
: track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone));
track.UpdateUser = @event.OperationMan ?? GlobalConst.SystemUser;
track.UpdateTime = DateTime.Now;
//允许二次修改,在修改了轨迹内容后进行修改轨迹操作,如果输入的轨迹内容则以输入为准
//跨子系统?
track.TrackContent = @event.Content ?? trackContent.TrackContent;
track.TrackEnContent = @event.EnStatus ?? trackContent.TrackEnContent;
//S06新增
track.IsVisibility = @event.IsVisibility;
track.Remarks = @event.Remarks ?? GlobalConst.EmptyString;
track.Files = @event.Files?.Select(x => new FileItem
{
OssKey = x.OssKey,
FileName = x.FileName
}).ToList();
track.TrackPlaceCity = @event.TrackPlaceCity ?? GlobalConst.EmptyString;
track.TrackPlaceCityId = @event.TrackPlaceCityId ?? GlobalConst.NotExistId;
track.TrackPlaceProvince = @event.TrackPlaceProvince ?? GlobalConst.EmptyString;
track.TrackPlaceProvinceId = @event.TrackPlaceProvinceId ?? GlobalConst.NotExistId;
track.TrackPlaceNation = @event.TrackPlaceNation ?? GlobalConst.EmptyString;
track.TrackPlaceNationId = @event.TrackPlaceNationId ?? GlobalConst.NotExistId;
track.TrackPlacePostcode = @event.TrackPlacePostcode ?? GlobalConst.EmptyString;
track.DestinationTimeZone = @event.DestinationTimeZone;
track.EstimatedDeliveryDate = @event.EstimatedDeliveryDate;
track.Extra = @event.Extra;
updateTracks.Add(track);
// 写入操作日志
_ = _orderOperationRecordEsRepository.AddAsync(new OrderOperationRecordIndex
{
OrderId = order.OrderId,
OrderNo = order.OrderNo,
OptionType = OrderOperationType.修改轨迹.ToString(),
Content = track.ToJson(),
CreateUserId = @event.OperationManId,
CreateUserName = @event.OperationMan ?? "",
CreateTime = DateTime.Now
});
} }
canNextOrderIds.Add(order.OrderId); canNextOrderIds.Add(order.OrderId);
@ -427,4 +321,144 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
return insertTracks; return insertTracks;
} }
private TrackDetailsIndex BuiltUpdateTrack(TrackUpsertEvent @event, TrackDetailsIndex track, OrderIdentifier order,
TrackContentVO trackContent)
{
//外部轨迹,轨迹发生地,轨迹发生时间,轨迹发生时区,不允许更改
if (track.Source != (int) TrackSourceEnum.ExternalServiceProvide)
{
track.TrackPlace = @event.TrackPlace;
track.TrackTime = @event.NewTrackTime ?? @event.TrackTime;
track.TrackTimeZone = @event.TrackTimeZone;
}
track.ZeroTrackTime = Math.Abs(track.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1
? track.TrackTime
: track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone));
track.UpdateUser = @event.OperationMan ?? GlobalConst.SystemUser;
track.UpdateTime = DateTime.Now;
//允许二次修改,在修改了轨迹内容后进行修改轨迹操作,如果输入的轨迹内容则以输入为准
//跨子系统?
track.TrackContent = @event.Content ?? trackContent.TrackContent;
track.TrackEnContent = @event.EnStatus ?? trackContent.TrackEnContent;
//S06新增
track.IsVisibility = @event.IsVisibility;
track.Remarks = @event.Remarks ?? GlobalConst.EmptyString;
track.Files = @event.Files?.Select(x => new FileItem
{
OssKey = x.OssKey,
FileName = x.FileName
}).ToList();
track.TrackPlaceCity = @event.TrackPlaceCity ?? GlobalConst.EmptyString;
track.TrackPlaceCityId = @event.TrackPlaceCityId ?? GlobalConst.NotExistId;
track.TrackPlaceProvince = @event.TrackPlaceProvince ?? GlobalConst.EmptyString;
track.TrackPlaceProvinceId = @event.TrackPlaceProvinceId ?? GlobalConst.NotExistId;
track.TrackPlaceNation = @event.TrackPlaceNation ?? GlobalConst.EmptyString;
track.TrackPlaceNationId = @event.TrackPlaceNationId ?? GlobalConst.NotExistId;
track.TrackPlacePostcode = @event.TrackPlacePostcode ?? GlobalConst.EmptyString;
track.DestinationTimeZone = @event.DestinationTimeZone;
track.EstimatedDeliveryDate = @event.EstimatedDeliveryDate;
track.Extra = @event.Extra;
// todo:如果后面写es异常了,这里日志不就不准了,这里应该和写轨迹一样,做成批量的,放到写完轨迹只会写日志
// 写入操作日志
_ = _orderOperationRecordEsRepository.AddAsync(new OrderOperationRecordIndex
{
OrderId = order.OrderId,
OrderNo = order.OrderNo,
OptionType = OrderOperationType.修改轨迹.ToString(),
Content = track.ToJson(),
CreateUserId = @event.OperationManId,
CreateUserName = @event.OperationMan ?? "",
CreateTime = DateTime.Now
});
return track;
}
private TrackDetailsIndex BuiltNewTrack(TrackUpsertEvent @event, OrderIdentifier order, TrackContentVO trackContent)
{
var track = new TrackDetailsIndex
{
SubSystemId = @event.SubSystemId,
OrderId = order.OrderId,
OrderNo = order.OrderNo,
OrderType = order.OrderType,
TrackCode = @event.TrackCode,
TrackPlace = @event.TrackPlace,
TrackTime = @event.NewTrackTime ?? @event.TrackTime,
TrackTimeZone = @event.TrackTimeZone,
ServiceProviderCode = @event.TrackRefreshData.ServiceProviderCode ?? GlobalConst.EmptyString,
OriginTrackContent = @event.TrackRefreshData.OriginTrackContent ?? GlobalConst.EmptyString,
OriginTrackDataHash = @event.TrackRefreshData.OriginTrackDataHash ?? GlobalConst.EmptyString,
CreateUser = @event.OperationMan ?? GlobalConst.SystemUser,
CreateTime = DateTime.Now,
//来源轨迹内容,第一次新增的时候使用轨迹内容表提供的
TrackStatusId = trackContent.TrackStatusId,
TrackStatus = trackContent.TrackStatus,
TrackStatusCode = trackContent.TrackStatusCode,
//跨子系统?
TrackContentId = trackContent.TrackContentId,
TrackContent = @event.Content ?? trackContent.TrackContent,
TrackEnContent = @event.EnStatus ?? trackContent.TrackEnContent,
//S06新增轨迹明细字段
IsVisibility = @event.IsVisibility,
Source = @event.Source,
Remarks = @event.Remarks ?? GlobalConst.EmptyString,
Files = @event.Files?.Select(x => new FileItem
{
OssKey = x.OssKey,
FileName = x.FileName
}).ToList(),
TrackPlaceCity = @event.TrackPlaceCity ?? GlobalConst.EmptyString,
TrackPlaceCityId = @event.TrackPlaceCityId ?? GlobalConst.NotExistId,
TrackPlaceProvince = @event.TrackPlaceProvince ?? GlobalConst.EmptyString,
TrackPlaceProvinceId = @event.TrackPlaceProvinceId ?? GlobalConst.NotExistId,
TrackPlaceNation = @event.TrackPlaceNation ?? GlobalConst.EmptyString,
TrackPlaceNationId = @event.TrackPlaceNationId ?? GlobalConst.NotExistId,
TrackPlacePostcode = @event.TrackPlacePostcode ?? GlobalConst.EmptyString,
DestinationTimeZone = @event.DestinationTimeZone,
EstimatedDeliveryDate = @event.EstimatedDeliveryDate,
Extra = @event.Extra
};
track.ZeroTrackTime = Math.Abs(track.TrackTimeZone - GlobalConst.NoneTrackTimeZone) < 1
? track.TrackTime
: track.TrackTime.Subtract(TimeSpan.FromHours(track.TrackTimeZone));
// todo:如果后面写es异常了,这里日志不就不准了,这里应该和写轨迹一样,做成批量的,放到写完轨迹只会写日志
// 写入操作日志
_ = _orderOperationRecordEsRepository.AddAsync(new OrderOperationRecordIndex
{
OrderId = order.OrderId,
OrderNo = order.OrderNo,
OptionType = OrderOperationType.创建轨迹.ToString(),
Content = track.ToJson(),
CreateUserId = @event.OperationManId,
CreateUserName = @event.OperationMan ?? "",
CreateTime = DateTime.Now
});
return track;
}
private Dictionary<string, object?>? GetExtraDictForTextJson(string? extraStr)
{
return string.IsNullOrWhiteSpace(extraStr)
? null
: System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object?>>(extraStr);
}
private bool EqJsonElementObject(object? a, object? b)
{
if (a is JsonElement aJsonElement && b is JsonElement bJsonElement)
{
return aJsonElement.ToString() == bJsonElement.ToString();
}
return false;
}
} }

View File

@ -70,7 +70,7 @@ public class TrackPushCompletedEventHandler : ITransientDependency, IRabbitHandl
// 推送广播 // 推送广播
if (log.IsToMq) if (log.IsToMq)
_broadcastingService.TrackPushCompletedPublicTopicAsync(BuildDto(log)); _broadcastingService.TrackPushCompletedPublicTopic(BuildDto(log));
// 往es 写推送日志 // 往es 写推送日志
await _trackPushRecordEsRepository.AddAsync(log); await _trackPushRecordEsRepository.AddAsync(log);

View File

@ -86,7 +86,7 @@ public class BroadcastingService : IBroadcastingService
/// </summary> /// </summary>
/// <param name="log"></param> /// <param name="log"></param>
/// <returns></returns> /// <returns></returns>
public void TrackPushCompletedPublicTopicAsync(TrackPushRecordDto log) public void TrackPushCompletedPublicTopic(TrackPushRecordDto log)
{ {
var data = new TrackPushCompletedEvent var data = new TrackPushCompletedEvent
{ {
@ -111,4 +111,10 @@ public class BroadcastingService : IBroadcastingService
_rabbitClientBus.Publish(GlobalConst.TrackPushExchange, $"TrackPush.{log.SubSystemCode}", _rabbitClientBus.Publish(GlobalConst.TrackPushExchange, $"TrackPush.{log.SubSystemCode}",
Encoding.UTF8.GetBytes(data.ToJson())); Encoding.UTF8.GetBytes(data.ToJson()));
} }
public void TrackPushFailedPubilcTopic(TrackPushRecordDto log)
{
//暂时使用推送完成模型,后续可能会出现有区分度的模型
TrackPushCompletedPublicTopic(log);
}
} }

View File

@ -117,6 +117,7 @@ public class TrackPushService : ApplicationService, ITrackPushService
TrackPlace = track.TrackPlace, TrackPlace = track.TrackPlace,
TrackTime = track.TrackTime, TrackTime = track.TrackTime,
TrackTimeZone = track.TrackTimeZone, TrackTimeZone = track.TrackTimeZone,
// todo: 这里也要改,重复code问题,到底推哪个
Extra = track.Extra Extra = track.Extra
} }
}; };

View File

@ -240,6 +240,8 @@ public partial class TrackService : ApplicationService, ITrackService
throw new BusinessException(message: "存在来源于外部服务商的轨迹,不允许删除"); throw new BusinessException(message: "存在来源于外部服务商的轨迹,不允许删除");
} }
// todo:非必须不用goto,除非是在写算法,业务逻辑理论上都能通过if和方法规避
NO_DELETE_TRACK: NO_DELETE_TRACK:
if (tracks.Count == 0) if (tracks.Count == 0)
{ {
@ -357,6 +359,9 @@ public partial class TrackService : ApplicationService, ITrackService
return new UnifyResultDto(true, true); return new UnifyResultDto(true, true);
} }
// todo:代码封装性太差了,拆小一点
/// <summary> /// <summary>
/// 批量新增、更新轨迹 /// 批量新增、更新轨迹
/// </summary> /// </summary>
@ -436,6 +441,7 @@ public partial class TrackService : ApplicationService, ITrackService
.Where(x => x.TrackTime == input.TrackTime) .Where(x => x.TrackTime == input.TrackTime)
.ToList(); .ToList();
// todo:这块代码抽出去
//当为更新操作时发现更新的数目为0进行重试操作 //当为更新操作时发现更新的数目为0进行重试操作
if (!input.IsAdd && tracks.Count == 0) if (!input.IsAdd && tracks.Count == 0)
{ {
@ -513,6 +519,7 @@ public partial class TrackService : ApplicationService, ITrackService
TrackPlacePostcode = input.TrackPlacePostcode, TrackPlacePostcode = input.TrackPlacePostcode,
EstimatedDeliveryDate = input.EstimatedDeliveryDate, EstimatedDeliveryDate = input.EstimatedDeliveryDate,
DestinationTimeZone = input.DestinationTimeZone, DestinationTimeZone = input.DestinationTimeZone,
CompareFields = input.CompareFields,
Extra = input.Extra, Extra = input.Extra,
ForcedPush = input.ForcedPush, ForcedPush = input.ForcedPush,
IsToMq = input.IsToMq, IsToMq = input.IsToMq,

View File

@ -51,6 +51,7 @@ public class TrackPushCacheService : ITrackPushCacheService, ITransientDependenc
x.Id, x.Id,
x.IsAutoPush, x.IsAutoPush,
x.IsAllPush, x.IsAllPush,
x.IsAllPushWithLatest,
x.IsCanDelete, x.IsCanDelete,
x.IsCanUpdate, x.IsCanUpdate,
x.SubSystemId, x.SubSystemId,
@ -76,6 +77,7 @@ public class TrackPushCacheService : ITrackPushCacheService, ITransientDependenc
IsAutoPush = trackPushConfig.IsAutoPush, IsAutoPush = trackPushConfig.IsAutoPush,
IsCanUpdate = trackPushConfig.IsCanUpdate, IsCanUpdate = trackPushConfig.IsCanUpdate,
IsAllPush = trackPushConfig.IsAllPush, IsAllPush = trackPushConfig.IsAllPush,
IsAllPushWithLatest = trackPushConfig.IsAllPushWithLatest,
IsCanDelete = trackPushConfig.IsCanDelete, IsCanDelete = trackPushConfig.IsCanDelete,
DateTimeFormatType = (int) trackPushConfig.DateTimeFormatType, DateTimeFormatType = (int) trackPushConfig.DateTimeFormatType,
DateTimeFormat = trackPushConfig.DateTimeFormat, DateTimeFormat = trackPushConfig.DateTimeFormat,
@ -89,6 +91,7 @@ public class TrackPushCacheService : ITrackPushCacheService, ITransientDependenc
TrackContentValue = item.TrackContentValue, TrackContentValue = item.TrackContentValue,
TrackEnContentValue = item.TrackEnContentValue, TrackEnContentValue = item.TrackEnContentValue,
TrackTimeZone = item.TrackTimeZone, TrackTimeZone = item.TrackTimeZone,
// todo:废弃字段如果没有外部子系统依赖,可以逐步删除
ExpandFieldsValue = item.ExpandFieldsValue, ExpandFieldsValue = item.ExpandFieldsValue,
}).ToList(); }).ToList();

View File

@ -56,6 +56,12 @@ public class TrackPushConfigEntity : IFullAuditedBasicEntitys, IAggregateRoot
[SugarColumn(ColumnName = "IsAllPush")] [SugarColumn(ColumnName = "IsAllPush")]
public bool IsAllPush { get; set; } public bool IsAllPush { get; set; }
/// <summary>
/// 是否全量推送(最新轨迹)
/// </summary>
[SugarColumn(ColumnName = "IsAllPushWithLatest")]
public bool IsAllPushWithLatest { get; set; }
/// <summary> /// <summary>
/// 日期时间格式类型 /// 日期时间格式类型
/// </summary> /// </summary>

View File

@ -51,6 +51,11 @@ public class GetTrackPushConfigDetailOutputVO
/// </summary> /// </summary>
public bool IsAllPush { get; set; } public bool IsAllPush { get; set; }
/// <summary>
/// 是否全量推送(最新轨迹)
/// </summary>
public bool IsAllPushWithLatest { get; set; }
/// <summary> /// <summary>
/// 时间格式枚举 /// 时间格式枚举
/// </summary> /// </summary>

View File

@ -19,7 +19,7 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
public async Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, string trackCode, public async Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, string trackCode,
bool forUpsert = false) bool forUpsert = false)
{ {
var r = !forUpsert var r = forUpsert
? await Context.SearchAsync<TrackDetailsIndex>(s => s ? await Context.SearchAsync<TrackDetailsIndex>(s => s
.Index(GlobalConst.TrackDetailsIndex) .Index(GlobalConst.TrackDetailsIndex)
.Source() .Source()