Merge remote-tracking branch 'refs/remotes/origin/S06' into test

This commit is contained in:
eli 2024-11-19 17:09:22 +08:00
commit 8cf9ef756a
51 changed files with 2054 additions and 90 deletions

View File

@ -7,7 +7,7 @@
"Apollo": {
"AppId": "SJZY.Track.Configuration",
"Env": "DEV",
"Namespace": "test",
"Namespace": "dev",
"MetaServer": "http://apollo-service-test-apollo-configservice.apollo.svc.cluster.local:8080",
"ConfigServer": [
"http://apollo-service-test-apollo-configservice.apollo.svc.cluster.local:8080"

View File

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class BatchDeleteTrackByEsIdInput
{
/// <summary>
/// 轨迹内容es id,必填
/// </summary>
[MaxLength(500)]
public List<string> TrackContentEsIds { get; set; } = new();
}

View File

@ -35,4 +35,82 @@ public class BatchUpsertTrackInput : OrderNosInfo
[Required]
[Range(-12, 12)]
public float TrackTimeZone { get; set; }
/// <summary>
/// 客户是否可见
/// </summary>
[Required]
public bool IsVisibility { get; set; }
/// <summary>
/// 数据来源:1外部服务商创建,2内部系统创建,3人工创建
/// </summary>
[Required]
public int Source { get; set; }
/// <summary>
/// 轨迹备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 附件集合
/// </summary>
public List<FileItemDto>? Files { get; set; }
/// <summary>
/// 轨迹内容,若为空则取轨迹内容表中该轨迹Code对应的轨迹内容
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 轨迹内容英文,若为空则取轨迹内容表中该轨迹Code对应的轨迹英文内容
/// </summary>
public string? EnStatus { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; }
/// <summary>
/// 轨迹发生地(城市)Id
/// </summary>
public int? TrackPlaceCityId { get; set; }
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; }
/// <summary>
///轨迹发生地(省/州)Id
/// </summary>
public int? TrackPlaceProvinceId { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)Id
/// </summary>
public int? TrackPlaceNationId { get; set; }
/// <summary>
/// 轨迹发生地邮编
/// </summary>
public string? TrackPlacePostcode { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
[Range(-12, 12)]
public float? DestinationTimeZone { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class FileItemDto
{
/// <summary>
/// 文件osskey
/// </summary>
public string OssKey { get; set; }
/// <summary>
/// 文件名称
/// </summary>
public string FileName { get; set; }
}

View File

@ -0,0 +1,19 @@
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class GetDetailTimelineInput
{
/// <summary>
/// 订单编号
/// </summary>
public string OrderNumber { get; set; }
/// <summary>
/// 订单所属子系统id
/// </summary>
public int SystemId { get; set; }
/// <summary>
/// 当前用户登陆子系统id
/// </summary>
public int CurrenUserSystemId { get; set; }
}

View File

@ -0,0 +1,92 @@
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
public class GetDetailTimelineOutput
{
/// <summary>
/// 轨迹编码
/// </summary>
public string TrackCode { get; set; }
/// <summary>
/// 轨迹内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 轨迹英文内容
/// </summary>
public string EnContent { get; set; }
/// <summary>
/// 轨迹发生时间
/// </summary>
public long TrackTime { get; set; }
/// <summary>
/// 轨迹时间前缀
/// </summary>
public string TrackTimePrefix { get; set; }
/// <summary>
/// 轨迹发生时区
/// </summary>
public string TrackTimeZone { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 文件 osskey 集合
/// </summary>
public List<TrackFileItem> Files { get; set; }
/// <summary>
/// 是否高亮
/// </summary>
public bool IsHighlight { get; set; }
/// <summary>
/// 是否显示悬停效果
/// </summary>
public bool IsShowHover { get; set; }
/// <summary>
/// 轨迹发生地
/// </summary>
public string TrackPlace { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; }
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; }
}
public class TrackFileItem
{
/// <summary>
/// 文件osskey
/// </summary>
public string OssKey { get; set; }
/// <summary>
/// 文件名称
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 文件url
/// </summary>
public string Url { get; set; }
}

View File

@ -86,4 +86,54 @@ public class TrackOrderDetailDto
/// 创建人
/// </summary>
public string? CreateUser { get; set; }
/// <summary>
/// 客户是否可见
/// </summary>
public bool IsVisibility { get; set; }
/// <summary>
/// 数据来源:1外部服务商创建,2内部系统创建,3人工创建
/// </summary>
public int Source { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 附件集合
/// </summary>
public List<FileItemDto>? Files { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; }
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; }
/// <summary>
/// 轨迹发生地邮编
/// </summary>
public string? TrackPlacePostcode { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
}

View File

@ -152,4 +152,19 @@ public class TrackOrderDto
///// 问题描述名称
///// </summary>
//public string? ProblemDescriptionName { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
/// <summary>
/// 第三方单号,服务商-轨迹0000000、轨迹服务商-0000000
/// </summary>
public string? ThirdPartyOrderNumber { get; set; }
}

View File

@ -57,6 +57,16 @@ public class UpdateOrderInput : OrderNoInfo
/// </summary>
public string? ProductCode { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
/// <summary>
/// 拉取配置信息
/// </summary>
@ -76,6 +86,11 @@ public class PullConfigInfo
[Required]
public string ServiceCode { get; set; }
/// <summary>
/// api服务商订单号(第三方单号)
/// </summary>
public string? OrderNo { get; set; }
/// <summary>
/// 开始轨迹code
/// </summary>

View File

@ -35,4 +35,82 @@ public class UpsertTrackInput : OrderNoInfo
[Required]
[Range(-12, 12)]
public float? TrackTimeZone { get; set; }
/// <summary>
/// 客户是否可见
/// </summary>
[Required]
public bool IsVisibility { get; set; }
/// <summary>
/// 数据来源:1外部服务商创建,2内部系统创建,3人工创建
/// </summary>
[Required]
public int Source { get; set; }
/// <summary>
/// 轨迹备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 附件集合
/// </summary>
public List<FileItemDto>? Files { get; set; }
/// <summary>
/// 轨迹内容,若为空则取轨迹内容表中该轨迹Code对应的轨迹内容
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 轨迹内容英文,若为空则取轨迹内容表中该轨迹Code对应的轨迹英文内容
/// </summary>
public string? EnStatus { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; }
/// <summary>
/// 轨迹发生地(城市)Id
/// </summary>
public int? TrackPlaceCityId { get; set; }
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; }
/// <summary>
/// 轨迹发生地(省/州)Id
/// </summary>
public int? TrackPlaceProvinceId { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)Id
/// </summary>
public int? TrackPlaceNationId { get; set; }
/// <summary>
/// 轨迹发生地邮编
/// </summary>
public string? TrackPlacePostcode { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
[Range(-12, 12)]
public float? DestinationTimeZone { get; set; }
}

View File

@ -46,6 +46,21 @@ public class EditTrackContentInput
/// 是否对外
/// </summary>
public bool IsExternal { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
public bool IsAllowManuallyCreate { get; set; }
}
public class GetTrackContentDetailDto
@ -104,4 +119,19 @@ public class GetTrackContentDetailDto
/// 是否对外
/// </summary>
public bool IsExternal { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
public bool IsAllowManuallyCreate { get; set; }
}

View File

@ -0,0 +1,25 @@
namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
public class GetAvailableContentInput
{
/// <summary>
/// 子系统id
/// </summary>
public int SystemId { get; set; }
/// <summary>
/// 订单号
/// </summary>
public string? OrderNo { get; set; }
/// <summary>
/// 操作类型 1=创建 2=修改
/// </summary>
public TrackOptionType TrackOptionType { get; set; }
}
public enum TrackOptionType
{
创建 = 1,
修改 = 2
}

View File

@ -0,0 +1,29 @@
namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
public class GetAvailableContentOutput
{
/// <summary>
/// Id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 轨迹内容代码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 轨迹内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 轨迹内容英文
/// </summary>
public string EnContent { get; set; }
/// <summary>
/// 是否对外
/// </summary>
public bool IsExternal { get; set; }
}

View File

@ -89,4 +89,19 @@ public class GetTrackContentListDto
/// 修改人
/// </summary>
public string UpdateUser { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
public bool IsAllowManuallyCreate { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
public class GetTrackContentByCodeInput
{
/// <summary>
/// 子系统id
/// </summary>
public int SystemId { get; set; }
/// <summary>
/// 轨迹内容code
/// </summary>
public string Code { get; set; }
}

View File

@ -0,0 +1,19 @@
namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
public class GetTrackContentByCodeOutput
{
/// <summary>
/// 中文内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 英文内容
/// </summary>
public string EnContent { get; set; }
/// <summary>
/// 是否对外
/// </summary>
public bool IsExternal { get; set; }
}

View File

@ -41,4 +41,14 @@ public class TrackChangeAfterUpdateOrderEvent
/// 时区缺失和发生地缺失标记,1表示时区,2表示发生地,3表示两种
/// </summary>
public int DeficiencyTagValue { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 签收地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
}

View File

@ -0,0 +1,131 @@
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
namespace SJZY.Track.Application.Contract.Events;
public class TrackChangeEto
{
/// <summary>
/// 操作类型:1新增,2删除,3修改
/// </summary>
public int Option { get; set; }
/// <summary>
/// 子系统id
/// </summary>
public int SubSystemId { get; set; }
/// <summary>
/// 单号
/// </summary>
public string OrderNo { get; set; }
/// <summary>
/// 客户id
/// </summary>
public int CustomId { get; set; }
/// <summary>
/// 订单id
/// </summary>
public OrderIdentifier[] OrderIdentifiers { get; set; } = null!;
/// <summary>
/// 操作人
/// </summary>
public string? OperationMan { get; set; }
/// <summary>
/// 轨迹内容代码
/// </summary>
public string TrackCode { get; set; } = null!;
/// <summary>
/// 轨迹内容
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 轨迹内容英文
/// </summary>
public string? EnStatus { get; set; }
/// <summary>
/// 轨迹状态代码
/// </summary>
public string TrackStatusCode { get; set; }
/// <summary>
/// 轨迹发生地
/// </summary>
public string TrackPlace { get; set; } = null!;
/// <summary>
/// 轨迹发生时间
/// </summary>
public DateTime TrackTime { get; set; }
/// <summary>
/// 轨迹发生地时区
/// </summary>
public float TrackTimeZone { get; set; }
/// <summary>
/// 客户是否可见
/// </summary>
public bool IsVisibility { get; set; }
/// <summary>
/// 数据来源:1外部服务商创建,2内部系统创建,3人工创建
/// </summary>
public int Source { get; set; }
/// <summary>
/// 轨迹备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 附件集合
/// </summary>
public List<FileItemDto>? Files { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; }
/// <summary>
/// 轨迹发生地(城市)Id
/// </summary>
public int? TrackPlaceCityId { get; set; }
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; }
/// <summary>
///轨迹发生地(省/州)Id
/// </summary>
public int? TrackPlaceProvinceId { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)Id
/// </summary>
public int? TrackPlaceNationId { get; set; }
/// <summary>
/// 轨迹发生地邮编
/// </summary>
public string? TrackPlacePostcode { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
}

View File

@ -7,6 +7,11 @@ public class TrackDeleteEvent
/// </summary>
public int SubSystemId { get; set; }
/// <summary>
/// es中的id
/// </summary>
public string[] EsIds { get; set; }
/// <summary>
/// 订单ids
/// </summary>
@ -22,6 +27,11 @@ public class TrackDeleteEvent
/// </summary>
public string? OperationMan { get; set; }
/// <summary>
/// 操作人姓名
/// </summary>
public int OperationManId { get; set; }
/// <summary>
/// 已经处理过的订单
/// </summary>

View File

@ -1,3 +1,5 @@
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
namespace SJZY.Track.Application.Contract.Events;
public class TrackUpsertEvent
@ -22,6 +24,11 @@ public class TrackUpsertEvent
/// </summary>
public string? OperationMan { get; set; }
/// <summary>
/// 操作人id
/// </summary>
public int OperationManId { get; set; }
/// <summary>
/// true新增,false更新
/// </summary>
@ -54,6 +61,81 @@ public class TrackUpsertEvent
public TrackRefreshStruct TrackRefreshData { get; set; }
/// <summary>
/// 客户是否可见
/// </summary>
public bool IsVisibility { get; set; }
/// <summary>
/// 数据来源:1外部服务商创建,2内部系统创建,3人工创建
/// </summary>
public int Source { get; set; }
/// <summary>
/// 轨迹备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 附件集合
/// </summary>
public List<FileItemDto>? Files { get; set; }
/// <summary>
/// 轨迹内容,若为空则取轨迹内容表中该轨迹Code对应的轨迹内容
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 轨迹内容英文,若为空则取轨迹内容表中该轨迹Code对应的轨迹英文内容
/// </summary>
public string? EnStatus { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; }
/// <summary>
/// 轨迹发生地(城市)Id
/// </summary>
public int? TrackPlaceCityId { get; set; }
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; }
/// <summary>
///轨迹发生地(省/州)Id
/// </summary>
public int? TrackPlaceProvinceId { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; }
/// <summary>
/// 轨迹发生地(国家/地区)Id
/// </summary>
public int? TrackPlaceNationId { get; set; }
/// <summary>
/// 轨迹发生地邮编
/// </summary>
public string? TrackPlacePostcode { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
public override string ToString()
{
return

View File

@ -33,6 +33,7 @@ public class OrderAutoMapperProfile : Profile
.ForMember(dest => dest.Content, opt => opt.MapFrom(m => m.TrackContent))
.ForMember(dest => dest.EnContent, opt => opt.MapFrom(m => m.TrackEnContent))
.ForMember(dest => dest.TrackTimeZoneValue, opt => opt.MapFrom(m => m.TrackTimeZone));
CreateMap<FileItem, FileItemDto>(MemberList.None);
CreateMap<TrackPushRecordIndex, TrackPushRecordOutput>(MemberList.None);
}

View File

@ -26,6 +26,8 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
return;
}
//指示是否需要更新【预计签收时间】【签收地时区】
var isNeedUpdate = false;
var updateOrders = new List<OrderEntity>();
foreach (var order in orders)
{
@ -55,20 +57,43 @@ public class TrackChangeAfterUpdateOrderEventHandler : ITransientDependency, ICa
order.LatestTrackPlace = @event.TrackPlace;
order.LatestTrackTime = @event.TrackTime;
order.LatestTrackTimeZone = @event.TrackTimeZone;
//当【预计签收时间】【签收地时区】同时存在时则更新主表
if (@event.EstimatedDeliveryDate.HasValue && @event.DestinationTimeZone.HasValue)
{
order.EstimatedDeliveryDate = @event.EstimatedDeliveryDate.Value;
order.DestinationTimeZone = @event.DestinationTimeZone.Value;
isNeedUpdate = true;
}
updateOrders.Add(order);
}
await _orderRepository.UpdateRangeAsync(updateOrders,
x => new
{
x.IsCompleted,
x.LatestTrackContent,
x.LatestTrackEnContent,
x.LatestTrackPlace,
x.LatestTrackTime,
x.LatestTrackTimeZone,
x.DeficiencyTag
});
isNeedUpdate
? x => new
{
x.IsCompleted,
x.LatestTrackContent,
x.LatestTrackEnContent,
x.LatestTrackPlace,
x.LatestTrackTime,
x.LatestTrackTimeZone,
x.DeficiencyTag,
//当标识指示需要更新时添加更新列
x.EstimatedDeliveryDate,
x.DestinationTimeZone
}
: x => new
{
x.IsCompleted,
x.LatestTrackContent,
x.LatestTrackEnContent,
x.LatestTrackPlace,
x.LatestTrackTime,
x.LatestTrackTimeZone,
x.DeficiencyTag,
}
);
}
private async Task<List<OrderEntity>> GetOrdersAsync(int[] orderIds)

View File

@ -1,9 +1,14 @@
using System.Text;
using BSI.Stack.Rabbit;
using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
using SJZY.Track.Domain.Enums;
using SJZY.Track.Domain.Queries;
using Volo.Abp.DependencyInjection;
@ -13,17 +18,29 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
{
private readonly ICapPublisher _capPublisher;
private readonly IOrderRepository _orderRepository;
private readonly ITrackStatusRepository _trackStatusRepository;
private readonly ITrackContentRepository _trackContentRepository;
private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly RabbitClientBus _rabbitClientBus;
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
public TrackDeleteEventHandler(IProvideQueries provideQueries,
IOrderRepository orderRepository, ICapPublisher capPublisher,
ITrackDetailsEsRepository trackDetailsEsRepository)
ITrackDetailsEsRepository trackDetailsEsRepository,
RabbitClientBus rabbitClientBus,
ITrackStatusRepository trackStatusRepository,
ITrackContentRepository trackContentRepository,
IOrderOperationRecordEsRepository orderOperationRecordEsRepository)
{
_provideQueries = provideQueries;
_orderRepository = orderRepository;
_capPublisher = capPublisher;
_trackDetailsEsRepository = trackDetailsEsRepository;
_rabbitClientBus = rabbitClientBus;
_trackStatusRepository = trackStatusRepository;
_trackContentRepository = trackContentRepository;
_orderOperationRecordEsRepository = orderOperationRecordEsRepository;
}
[CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)]
@ -31,7 +48,10 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
{
if (!CanDelete(@event)) return;
await DeleteTrackAsync(@event);
var trackList = await DeleteTrackAsync(@event);
//发布事件
await PublicTrackTopicAsync(@event, trackList);
// 根据订单关联关系异步向下刷(异步)
await DownByOrderLink(@event);
@ -84,12 +104,8 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
private bool CanDelete(TrackDeleteEvent @event)
{
// 系统创建的轨迹不允许删除
if (@event.Visited.IsNullOrEmpty() && @event.OperationMan == GlobalConst.SystemUser)
{
LogHelper.Warn($"系统创建的轨迹不允许被删除:{@event}", true);
return false;
}
if (@event.OrderIds == null)
return true;
// 订单循环关联检测
var dup = @event.Visited.Intersect(@event.OrderIds).ToArray();
@ -102,14 +118,80 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
return true;
}
private async Task DeleteTrackAsync(TrackDeleteEvent @event)
private async Task PublicTrackTopicAsync(TrackDeleteEvent eto, List<TrackDetailsIndex> trackList)
{
// 删除轨迹(删的是同子系统下的单,所以code是统一的)
var tracks = await _trackDetailsEsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes);
if (trackList == null)
return;
var orderIds = await _trackDetailsEsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes);
var statusList = await _trackStatusRepository.GetListAsync(m => m.SubSystemId == eto.SubSystemId);
if (statusList == null)
return;
var contentList = await _trackContentRepository.GetTrackContentBySyetemIdAsync(eto.SubSystemId);
if (contentList == null)
return;
foreach (var dataItem in trackList.GroupBy(m => new
{
m.TrackCode,
m.OrderNo
}))
{
var item = dataItem.First();
var status = statusList.FirstOrDefault(m => m.Code == item.TrackStatusCode);
if (status == null || !status.IsToMq)
continue;
var content = contentList.FirstOrDefault(m => m.TrackContentCode == item.TrackCode);
var data = new TrackChangeEto()
{
OrderIdentifiers = dataItem.Select(m => new OrderIdentifier
{
OrderId = m.OrderId,
OrderNo = m.OrderNo,
OrderType = m.OrderType
}).ToArray(),
TrackStatusCode = item.TrackStatusCode,
TrackCode = item.TrackCode,
OperationMan = eto.OperationMan,
SubSystemId = eto.SubSystemId,
Option = 2
};
_rabbitClientBus.Publish(GlobalConst.TrackChangeExchange, $"TrackChange.{content.SubSystemCode}", Encoding.UTF8.GetBytes(data.ToJson()));
}
}
private async Task<List<TrackDetailsIndex>> DeleteTrackAsync(TrackDeleteEvent @event)
{
List<int> orderIds;
List<TrackDetailsIndex> tracks;
if (@event.EsIds != null && @event.EsIds.Any()) //根据明确的esid进行删除
{
tracks = await _trackDetailsEsRepository.GetDataByIds(@event.EsIds);
orderIds = tracks.Select(m => m.OrderId).Distinct().ToList();
@event.OrderIds = orderIds.ToArray();
// 外部api获取的轨迹不允许删除
if (tracks.Any(m => m.Source == TrackSourceEnum.ExternalServiceProvide.GetHashCode()))
return tracks;
// 删除轨迹
foreach (var item in tracks)
{
await _trackDetailsEsRepository.DeleteTrackByIdAsync(item.Id, item.IndexName);
}
}
else //原有逻辑,根据轨迹code和订单进行删除
{
// 删除轨迹(删的是同子系统下的单,所以code是统一的)
tracks = await _trackDetailsEsRepository.GetLatestListAsync(@event.OrderIds, @event.TrackCodes);
orderIds = await _trackDetailsEsRepository.DeleteTrackAsync(@event.OrderIds, @event.TrackCodes);
if (orderIds.Count == 0) return tracks;
}
if (orderIds.Count == 0) return;
var orders = await _orderRepository.GetListAsync(x => orderIds.Contains(x.Id),
x => new OrderEntity
@ -121,8 +203,7 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
LatestTrackTime = x.LatestTrackTime,
LatestTrackTimeZone = x.LatestTrackTimeZone,
});
if (orders.Count == 0) return;
if (orders.Count == 0) return tracks;
foreach (var order in orders)
{
@ -146,6 +227,19 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
order.LatestTrackTime = track.TrackTime;
order.LatestTrackTimeZone = track.TrackTimeZone;
}
// 写入操作日志
_ = _orderOperationRecordEsRepository.AddAsync(new OrderOperationRecordIndex
{
OrderId = order.Id,
OrderNo = order.OrderNo,
OptionType = OrderOperationType.删除轨迹.ToString(),
Content = tracks?.Where(m=>m.OrderId == order.Id)?.ToList().ToJson(),
CreateUserId = @event.OperationManId,
CreateUserName = @event.OperationMan ?? "",
CreateTime = DateTime.Now
});
}
await _orderRepository.UpdateRangeAsync(orders,
@ -157,5 +251,7 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
x.LatestTrackTime,
x.LatestTrackTimeZone
});
return tracks;
}
}

View File

@ -1,10 +1,14 @@
using System.Text;
using BSI.Stack.Rabbit;
using DotNetCore.CAP;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Events;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
using SJZY.Track.Domain.Dtos.TrackContents;
using SJZY.Track.Domain.Enums;
using SJZY.Track.Domain.Queries;
using Volo.Abp.DependencyInjection;
using OrderIdentifier = SJZY.Track.Application.Contract.Events.OrderIdentifier;
@ -17,14 +21,23 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
private readonly IOrderRepository _orderRepository;
private readonly IProvideQueries _provideQueries;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly RabbitClientBus _rabbitClientBus;
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
public TrackUpsertEventHandler(IOrderRepository orderRepository, ICapPublisher capPublisher,
IProvideQueries provideQueries, ITrackDetailsEsRepository trackDetailsEsRepository)
public TrackUpsertEventHandler(
IOrderRepository orderRepository,
ICapPublisher capPublisher,
IProvideQueries provideQueries,
ITrackDetailsEsRepository trackDetailsEsRepository,
RabbitClientBus rabbitClientBus,
IOrderOperationRecordEsRepository orderOperationRecordEsRepository)
{
_orderRepository = orderRepository;
_capPublisher = capPublisher;
_provideQueries = provideQueries;
_trackDetailsEsRepository = trackDetailsEsRepository;
_rabbitClientBus = rabbitClientBus;
_orderOperationRecordEsRepository = orderOperationRecordEsRepository;
}
[CapSubscribe(GlobalConst.TrackUpsertSubscribe, Group = GlobalConst.TrackUpsertSubscribe)]
@ -34,13 +47,63 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
if (!CanDelete(@event)) return;
var canNextOrderIds = new List<int>();
await HandleTrackAsync(@event, canNextOrderIds);
var content = await HandleTrackAsync(@event, canNextOrderIds);
// 处理广播事件
PublicTrackTopic(@event, content);
if (canNextOrderIds.Count == 0) return;
// 根据订单关联关系异步向下刷(异步)
await DownByOrderLink(@event, canNextOrderIds);
}
/// <summary>
/// 发送轨迹广播
/// </summary>
/// <param name="eto"></param>
/// <param name="content"></param>
private void PublicTrackTopic(TrackUpsertEvent eto, TrackContentVO? content)
{
// var trackStatus = await _trackStatusRepository.GetFirstAsync(m => m.Code == content.TrackStatusCode);
if (content == null || !content.IsToMq)
return;
var data = new TrackChangeEto()
{
EstimatedDeliveryDate = eto.EstimatedDeliveryDate,
TrackPlacePostcode = eto.TrackPlacePostcode,
TrackPlaceNation = eto.TrackPlaceNation,
TrackPlaceNationId = eto.TrackPlaceNationId,
TrackPlaceProvince = eto.TrackPlaceProvince,
TrackPlaceProvinceId = eto.TrackPlaceProvinceId,
TrackPlaceCity = eto.TrackPlaceCity,
TrackPlaceCityId = eto.TrackPlaceCityId,
Files = eto.Files,
Remarks = eto.Remarks,
Source = eto.Source,
IsVisibility = eto.IsVisibility,
TrackTimeZone = eto.TrackTimeZone,
TrackTime = eto.TrackTime,
TrackPlace = eto.TrackPlace,
TrackStatusCode = content.TrackStatusCode,
EnStatus = eto.EnStatus,
Content = eto.Content,
TrackCode = eto.TrackCode,
OperationMan = eto.OperationMan,
OrderIdentifiers = eto.OrderIdentifiers,
CustomId = eto.CustomId,
SubSystemId = eto.SubSystemId
};
if (eto.IsAdd)
data.Option = 1;
else
data.Option = 3;
_rabbitClientBus.Publish(GlobalConst.TrackChangeExchange, $"TrackChange.{content.SubSystemCode}", Encoding.UTF8.GetBytes(data.ToJson()));
}
private async Task DownByOrderLink(TrackUpsertEvent @event, List<int> canNextOrderIds)
{
// 根据订单关联关系异步向下刷(异步)
@ -125,7 +188,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
return true;
}
private async Task HandleTrackAsync(TrackUpsertEvent @event, List<int> canNextOrderIds)
private async Task<TrackContentVO?> HandleTrackAsync(TrackUpsertEvent @event, List<int> canNextOrderIds)
{
var trackContent = await _provideQueries.GetTrackContentAsync(@event.SubSystemId, @event.TrackCode);
@ -133,12 +196,20 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
{
// 找不到轨迹内容,直接结束
LogHelper.Warn($"找不到轨迹内容:{@event}", true);
return;
return default;
}
//虽然在引发事件之前做了判断,引发之后并不一定立即处理,在此过程中轨迹内容仍然可能被修改,所以要二次进行判断。
//通过来源指示是否为手动操作
var manualOperation = @event.Source == (int) TrackSourceEnum.Artificial;
//轨迹内容标识不允许手动创建的
if (manualOperation && @event.IsAdd && trackContent.IsAllowManuallyCreate == false) return trackContent;
//轨迹内容标识不允许手动更新的
if (manualOperation && !@event.IsAdd && trackContent.IsAllowManuallyUpdate == false) return trackContent;
var insertTracks = await UpsertTrackAsync(@event, canNextOrderIds, trackContent);
if (canNextOrderIds.Count == 0) return;
if (canNextOrderIds.Count == 0) return trackContent;
if (insertTracks.Any())
{
@ -171,6 +242,8 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
TrackPlace = @event.TrackPlace,
TrackTime = @event.TrackTime,
TrackTimeZone = @event.TrackTimeZone,
DestinationTimeZone = @event.DestinationTimeZone,
EstimatedDeliveryDate = @event.EstimatedDeliveryDate
});
// 触发轨迹推送事件(异步)
@ -192,6 +265,8 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
}
};
await _capPublisher.PublishAsync(GlobalConst.TrackPushSubscribe, trackPushEvent);
return trackContent;
}
private async Task<List<TrackDetailsIndex>> UpsertTrackAsync(TrackUpsertEvent @event, List<int> canNextOrderIds,
@ -210,6 +285,7 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
TrackDetailsIndex? track;
if (!@event.IsAdd)
{
//同一订单同轨迹code如果有多条轨迹明细则不允许修改
var existTracks = tracks.Where(x => x.OrderId == order.OrderId).ToArray();
if (existTracks.Length > 1)
{
@ -220,13 +296,44 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
track = existTracks.FirstOrDefault();
if (track == null) continue; // 不存在不让改
//来源与外部服务商不允许修改
if (track.Source == (int) TrackSourceEnum.ExternalServiceProvide) continue;
}
else
{
track = tracks.FirstOrDefault(x =>
x.OrderId == order.OrderId && x.TrackTime == @event.TrackTime && x.TrackPlace == @event.TrackPlace);
// 【批量新增】所有可能遇到的场景
// 标识:允许重复,不允许重复,零条,一条,多条;
// 场景A:允许重复,零条 => 新增
// 场景B:允许重复,一条 => 新增(约束受限新增,否则跳过新增)
// 场景C:允许重复,多条 => 新增(约束受限新增,否则跳过新增)
// 场景D:不允许重复,零条 => 新增
// 场景E:不允许重复,一条 => 跳过
// 场景F:不允许重复,(理想不会出现多条) => 跳过
var existTracks = tracks.Where(x => x.OrderId == order.OrderId).ToArray();
track = existTracks.FirstOrDefault();
if (track != null) continue; // 存在不让创建
//覆盖场景:B,C
if (trackContent.IsRepeatable && existTracks.Length >= 1)
{
if (existTracks.Any(x => x.TrackPlace == @event.TrackPlace && x.TrackTime == @event.TrackTime))
{
//允许重复,出现【轨迹发生地】,【轨迹发生时间】的都重复,则不允许新增
continue;
}
// 设置null后面执行新增逻辑
track = null;
}
//不允许重复,并且记录大于等于一条,跳过
//覆盖场景:E,F
if (!trackContent.IsRepeatable && existTracks.Length >= 1)
{
continue;
}
//其余情况:A,D都为新增操作,无需检查数量,track为null执行新增操作
}
if (track == default)
@ -246,15 +353,47 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
OriginTrackDataHash = @event.TrackRefreshData.OriginTrackDataHash ?? GlobalConst.EmptyString,
CreateUser = @event.OperationMan ?? GlobalConst.SystemUser,
CreateTime = DateTime.Now,
//来源轨迹内容,第一次新增的时候使用轨迹内容表提供的
TrackStatus = trackContent.TrackStatus,
TrackStatusCode = trackContent.TrackStatusCode,
TrackContent = trackContent.TrackContent,
TrackEnContent = trackContent.TrackEnContent
TrackEnContent = 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,
};
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
{
@ -267,7 +406,40 @@ public class TrackUpsertEventHandler : ITransientDependency, ICapSubscribe
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;
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);

View File

@ -10,6 +10,7 @@
<ItemGroup>
<PackageReference Include="BSI.Stack.Rabbit" Version="2.0.9" />
<PackageReference Include="Savorboard.CAP.InMemoryMessageQueue" Version="8.2.1"/>
<PackageReference Include="SJZY.Expand.AliyunOSS" Version="7.0.17" />
<PackageReference Include="SJZY.InterfaceRelay.Application.Contracts" Version="7.2.3"/>
<PackageReference Include="Volo.Abp.Http.Client" Version="7.0.2" />
<PackageReference Include="Volo.Abp.FluentValidation" Version="7.0.2" />

View File

@ -36,6 +36,15 @@ public partial class OrderService : ApplicationService, IOrderService
[HttpPost("Order/Upsert")]
public async Task<UnifyResultDto<IdBaseDto>> UpsertAsync(UpsertOrderInput input)
{
// 校验预计到达时间是否不是同时存在或同时不存在
if ((input.EstimatedDeliveryDate.HasValue && input.DestinationTimeZone.HasValue == false) ||
(input.EstimatedDeliveryDate.HasValue == false && input.DestinationTimeZone.HasValue))
{
throw new BusinessException(message: "【目的地时区】和【预计到达时间】必须同时输入");
}
var currentUser = CurrentUserRequest.CurrentUser;
// 校验订单是否已存在,存在则更新
var order = await _orderRepository.GetFirstAsync(x =>
x.SubSystemId == input.SubSystemId && x.OrderType == input.OrderType && x.OrderNo == input.OrderNo);
@ -48,8 +57,10 @@ public partial class OrderService : ApplicationService, IOrderService
{
OrderId = order.Id,
OrderNo = input.OrderNo,
OptionType = OptionType.修改.ToString(),
OptionType = OrderOperationType.修改订单.ToString(),
Content = input.ToJson(),
CreateUserId = currentUser.UserId,
CreateUserName = currentUser.Name,
};
_ = _orderOperationRecordEsRepository.AddAsync(index);
@ -64,6 +75,7 @@ public partial class OrderService : ApplicationService, IOrderService
order.SubSystemId = input.SubSystemId;
order.OrderFlights = ObjectMapper.Map<List<OrderFlightInfo>, List<OrderFlightEntity>>(input.FlightInfos);
order.OrderPullStatus = BuiltOrderPullStatus(input.PullConfigInfos);
order.OrderPlatformNumbers = BuiltOrderPlatformNumbers(input.PullConfigInfos);
var orderId = await _orderRepository.CreateOrderAsync(order);
@ -72,9 +84,10 @@ public partial class OrderService : ApplicationService, IOrderService
{
OrderId = orderId,
OrderNo = input.OrderNo,
OptionType = OptionType.新增.ToString(),
OptionType = OrderOperationType.创建订单.ToString(),
Content = input.ToJson(),
CreateUserId = CurrentUserRequest.CurrentUser.UserId,
CreateUserId = currentUser.UserId,
CreateUserName = currentUser.Name,
CreateTime = DateTime.Now
};
_ = _orderOperationRecordEsRepository.AddAsync(indexForAdd);
@ -115,6 +128,8 @@ public partial class OrderService : ApplicationService, IOrderService
{
order = ObjectMapper.Map(input, order);
order.OrderFlights = ObjectMapper.Map<List<OrderFlightInfo>, List<OrderFlightEntity>>(input.FlightInfos);
order.OrderPullStatus = BuiltOrderPullStatus(input.PullConfigInfos);
order.OrderPlatformNumbers = BuiltOrderPlatformNumbers(input.PullConfigInfos);
await _orderRepository.UpdateOrderAsync(order);
}
@ -128,6 +143,7 @@ public partial class OrderService : ApplicationService, IOrderService
var status = new OrderPullStatusEntity
{
ServiceProviderCode = x.ServiceCode,
OrderNo = x.OrderNo,
PullStatus = TrackPullStatus.Init,
StartTrackCode = x.StartCode ?? GlobalConst.EmptyString,
EndTrackCode = x.EndCode ?? GlobalConst.EmptyString,
@ -147,4 +163,22 @@ public partial class OrderService : ApplicationService, IOrderService
return status;
}).ToList();
}
private List<OrderPlatformNumberEntity> BuiltOrderPlatformNumbers(List<PullConfigInfo>? pullConfigInfos)
{
if (pullConfigInfos == null) return new List<OrderPlatformNumberEntity>();
return pullConfigInfos.Select(x =>
{
var status = new OrderPlatformNumberEntity
{
//三方单号
OrderNumber = x.OrderNo,
//三方平台名称,目前认为是服务商code
Platform = x.ServiceCode,
};
return status;
}).ToList();
}
}

View File

@ -5,6 +5,7 @@ using SJZY.Track.Application.Contract.Services.ProvideServices;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Enums;
using SJZY.UserCenter.HttpApi.Services;
using Volo.Abp.Http.Client.DynamicProxying;
@ -59,6 +60,47 @@ public partial class TrackService : ApplicationService, ITrackService
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}不允许手动更新");
}
var tracks = await _trackDetailsEsRepository.GetListAsync(new[] { order.Id }, input.TrackCode, true);
//更新轨迹,但存在多条轨迹记录,理由:不清晰到底要修改哪一条或是全部修改
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)
{
@ -112,6 +154,14 @@ public partial class TrackService : ApplicationService, ITrackService
var name = userInfo.Data.UserName;
//删除轨迹约束,只要其中有一条来源是外部的就立即返回错误
var tracks = await _trackDetailsEsRepository
.GetListAsync(new[] { orderId }, input.TrackCodes, TrackSourceEnum.ExternalServiceProvide);
if (tracks.Count > 0)
{
throw new BusinessException(message: "存在来源于外部服务商的轨迹,不允许删除");
}
// 删除轨迹
var @event = new TrackDeleteEvent
{
@ -125,6 +175,48 @@ public partial class TrackService : ApplicationService, ITrackService
return new UnifyResultDto(true, true);
}
/// <summary>
/// 根据esid删除轨迹内容
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("Track/BatchDeleteByEsId")]
public async Task<UnifyResultDto> BatchDeleteTrackByEsIdAsync(BatchDeleteTrackByEsIdInput input)
{
var tracks = await _trackDetailsEsRepository.GetDataByIds(input.TrackContentEsIds.ToArray());
if (tracks == null || tracks.Count == 0)
return new UnifyResultDto(false, "未找到指定id下的轨迹内容");
if (tracks.Any(m => m.Source == TrackSourceEnum.ExternalServiceProvide.GetHashCode()))
return new UnifyResultDto(false, "存在来源于外部服务商的轨迹,不允许删除");
if (tracks.GroupBy(m => m.SubSystemId).Count() > 1)
return new UnifyResultDto(false, "暂不支持跨子系统批量删除");
// 获取用户name
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
{
throw new BusinessException(message: $"调用用户中心,获取用户信息失败:{userInfo.Msg}");
}
// 删除轨迹
var currentUser = CurrentUserRequest.CurrentUser;
var userName = userInfo.Data.UserName;
if (string.IsNullOrEmpty(userName))
userName = (await _orderRepository.GetUserById(currentUser.UserId))?.Name;
var @event = new TrackDeleteEvent
{
EsIds = input.TrackContentEsIds.ToArray(),
SubSystemId = tracks.First().SubSystemId,
OperationMan = userName,
OperationManId = currentUser.UserId
};
await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, @event);
return new UnifyResultDto(true);
}
/// <summary>
/// 批量删除轨迹
@ -153,13 +245,21 @@ public partial class TrackService : ApplicationService, ITrackService
throw new BusinessException(message: $"调用用户中心,获取用户信息失败:{userInfo.Msg}");
}
//删除轨迹约束,只要其中有一条来源是外部的就立即返回错误
var tracks = await _trackDetailsEsRepository
.GetListAsync(orderIds.ToArray(), input.TrackCodes, TrackSourceEnum.ExternalServiceProvide);
if (tracks.Count > 0)
{
throw new BusinessException(message: "存在来源于外部服务商的轨迹,不允许删除");
}
// 删除轨迹
var @event = new TrackDeleteEvent
{
OrderIds = orderIds.ToArray(),
TrackCodes = input.TrackCodes,
SubSystemId = input.SubSystemId,
OperationMan = userInfo.Data.UserName
OperationMan = userInfo.Data.UserName,
};
await _capPublisher.PublishAsync(GlobalConst.TrackDeleteSubscribe, @event);
@ -191,6 +291,57 @@ public partial class TrackService : ApplicationService, ITrackService
throw new BusinessException(message: "订单一个都不存在");
}
//当修改时,如果为来源为外部提供商则不允许修改
if (!input.IsAdd && input.Source == (int) TrackSourceEnum.ExternalServiceProvide)
{
throw new BusinessException(message: "来源为外部服务商轨迹不允许修改");
}
// 校验主体:批量新增只选取第一条订单进行校验
//【新增】存在指定轨迹的内容,进行更新覆盖(只处理一条的情况,并且决定权交给用户),不存在直接插入即可
//【更新】存在指定轨迹的内容(匹配到多条则不处理)
var order = orders.First();
if (input.TrackTime < DateTime.Now.AddYears(-100) || input.TrackTime > DateTime.Now.AddYears(100))
{
throw new BusinessException(message: "轨迹时间不合法");
}
if ((input.EstimatedDeliveryDate.HasValue == false && input.DestinationTimeZone.HasValue) ||
(input.EstimatedDeliveryDate.HasValue && input.DestinationTimeZone.HasValue == false))
{
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}不允许手动更新");
}
var tracks = await _trackDetailsEsRepository.GetListAsync(new[] { order.Id }, input.TrackCode, true);
//更新轨迹,存在多条轨迹记录不允许更改,理由:不清晰到底要修改哪一条或是全部修改
if (!input.IsAdd && tracks.Count > 1)
{
throw new BusinessException(message: $"订单:{order.OrderNo},轨迹代码:{input.TrackCode}存在多条记录,不允许修改");
}
// 获取用户name
var userInfo = await _requestCurrentUserService.Service.GetCurrentUserBasicInfoAsync();
if (userInfo.Code != GlobalConst.SuccessCode || userInfo.Data is null)
@ -216,7 +367,23 @@ public partial class TrackService : ApplicationService, ITrackService
TrackPlace = input.TrackPlace,
TrackTime = input.TrackTime,
TrackTimeZone = input.TrackTimeZone,
OperationMan = userInfo.Data.UserName
OperationMan = userInfo.Data.UserName,
OperationManId = userInfo.Data.UserId,
IsVisibility = input.IsVisibility,
Source = input.Source,
Remarks = input.Remarks,
Files = input.Files,
Content = input.Content,
EnStatus = input.EnStatus,
TrackPlaceCity = input.TrackPlaceCity,
TrackPlaceCityId = input.TrackPlaceCityId,
TrackPlaceProvince = input.TrackPlaceProvince,
TrackPlaceProvinceId = input.TrackPlaceProvinceId,
TrackPlaceNation = input.TrackPlaceNation,
TrackPlaceNationId = input.TrackPlaceNationId,
TrackPlacePostcode = input.TrackPlacePostcode,
EstimatedDeliveryDate = input.EstimatedDeliveryDate,
DestinationTimeZone = input.DestinationTimeZone,
};
await _capPublisher.PublishAsync(GlobalConst.TrackUpsertSubscribe, @event);
}

View File

@ -2,9 +2,12 @@ using System.Linq.Expressions;
using Microsoft.Extensions.Localization;
using SJZY.Expand.ABP.Core.Localization;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
using SJZY.Track.Application.Contract.Dtos.TrackContents;
using SJZY.Track.Application.Localization;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackFlagAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
using SJZY.Track.Domain.Dtos.TrackContents;
@ -23,17 +26,23 @@ public class TrackContentService : ApplicationService
private readonly ITrackContentRepository _trackContentRepository;
private readonly IBasicQuery<TrackFlagEntity> _trackFlagBasicQuery;
private readonly IBasicQuery<TrackStatusEntity> _trackStatusBasicQuery;
private readonly IOrderRepository _orderRepository;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
public TrackContentService(
IStringLocalizer<TrackLocalizationResource> stringLocalizer,
ITrackContentRepository trackContentRepository,
IBasicQuery<TrackStatusEntity> trackStatusBasicQuery,
IBasicQuery<TrackFlagEntity> trackFlagBasicQuery)
IBasicQuery<TrackFlagEntity> trackFlagBasicQuery,
IOrderRepository orderRepository,
ITrackDetailsEsRepository trackDetailsEsRepository)
{
_stringLocalizer = stringLocalizer;
_trackContentRepository = trackContentRepository;
_trackStatusBasicQuery = trackStatusBasicQuery;
_trackFlagBasicQuery = trackFlagBasicQuery;
_orderRepository = orderRepository;
_trackDetailsEsRepository = trackDetailsEsRepository;
}
/// <summary>
@ -96,8 +105,7 @@ public class TrackContentService : ApplicationService
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("GetList")]
public async Task<UnifyPageResultDto<GetTrackContentListDto>> GetPageTrackContent(
GetPageTrackContentInput input)
public async Task<UnifyPageResultDto<GetTrackContentListDto>> GetPageTrackContent(GetPageTrackContentInput input)
{
var vo = ObjectMapper.Map<GetPageTrackContentInput, GetPageTrackContentVO>(input);
var resultDto = await _trackContentRepository.GetPageTrackContent(vo);
@ -181,6 +189,99 @@ public class TrackContentService : ApplicationService
return true;
}
/// <summary>
/// 根据轨迹内容code获取轨迹内容
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("GetTrackContentByCode")]
public async Task<UnifyResultDto<GetTrackContentByCodeOutput>> GetTrackContentByCodeAsync([FromBody] GetTrackContentByCodeInput input)
{
if (input.SystemId <= 0)
return new UnifyResultDto<GetTrackContentByCodeOutput>(false, "子系统Id必须大于等于0");
if (string.IsNullOrEmpty(input.Code))
return new UnifyResultDto<GetTrackContentByCodeOutput>(false, "轨迹内容code不能为空");
var content = await _trackContentRepository.GetByCodeAsync(input.SystemId, input.Code);
if (content == null)
return new UnifyResultDto<GetTrackContentByCodeOutput>(false, "在当前子系统中未找到指定code的轨迹内容");
var res = new UnifyResultDto<GetTrackContentByCodeOutput>(true)
{
Data = new GetTrackContentByCodeOutput
{
Content = content.Content,
EnContent = content.EnContent,
IsExternal = content.IsExternal
}
};
return res;
}
/// <summary>
/// 创建轨迹时获取可用的轨迹内容
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("GetAvailableContent")]
public async Task<UnifyResultDto<List<GetAvailableContentOutput>>> GetAvailableContent(GetAvailableContentInput input)
{
if (input.SystemId <= 0)
return new UnifyResultDto<List<GetAvailableContentOutput>>(false, "系统id需大于0!");
if (string.IsNullOrEmpty(input.OrderNo))
return new UnifyResultDto<List<GetAvailableContentOutput>>(false, "单号不能为空!");
//获取当前订单下已有的轨迹内容
var orderId = await _orderRepository.GetFirstAsync(x => x.OrderNo == input.OrderNo && x.SubSystemId == input.SystemId, x => x.Id);
if (orderId == default)
throw new BusinessException(message: "订单不存在!");
//获取轨迹详情
var trackDetails = await _trackDetailsEsRepository.GetListAsync(orderId);
//获取当前子系统下所有的轨迹内容
var contentList = await _trackContentRepository.GetListBySystemIdAsync(input.SystemId);
if (contentList == null)
throw new BusinessException(message: "当前子系统下未找到任何可用的轨迹内容!");
var res = new UnifyResultDto<List<GetAvailableContentOutput>>(true)
{
Data = new List<GetAvailableContentOutput>()
};
foreach (var item in contentList)
{
//新增时跳过已存在轨迹内容
if (input.TrackOptionType == TrackOptionType.创建 && !item.IsRepeatable && trackDetails?.Any(m => m.TrackCode == item.Code) == true)
continue;
// 修改时跳过不存在轨迹内容
if (input.TrackOptionType == TrackOptionType.修改 && trackDetails != null && trackDetails.All(m => m.TrackCode != item.Code))
continue;
if (!item.IsAllowManuallyCreate && input.TrackOptionType == TrackOptionType.创建) //跳过不允许手动创建的轨迹内容
continue;
if (!item.IsAllowManuallyUpdate && input.TrackOptionType == TrackOptionType.修改) //跳过不允许手动创建的轨迹内容
continue;
res.Data.Add(new GetAvailableContentOutput()
{
IsExternal = item.IsExternal,
EnContent = item.EnContent,
Content = item.Content,
Code = item.Code,
Id = item.Id
});
}
return res;
}
#region 私有方法
private async Task<UnifyResultDto> AddAsync(EditTrackContentInput input)

View File

@ -1,9 +1,11 @@
using SJZY.Expand.AliyunOSS;
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
using SJZY.Track.Application.Contract.Dtos.TrackOrder;
using SJZY.Track.Domain.Aggregates.OrderAggregate;
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Aggregates.TrackPushAggregate;
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
using SJZY.Track.Domain.Dtos.Order;
namespace SJZY.Track.Application.Services.TrackOrders;
@ -18,6 +20,7 @@ public class TrackOrderService : ApplicationService
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
private readonly IOrderRepository _orderRepository;
private readonly ITrackContentRepository _trackContentRepository;
private readonly ITrackStatusRepository _trackStatusRepository;
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
private readonly ITrackPushRecordEsRepository _trackPushRecordEsRepository;
@ -26,13 +29,15 @@ public class TrackOrderService : ApplicationService
ITrackDetailsEsRepository trackDetailsEsRepository,
ITrackContentRepository trackContentRepository,
ITrackPushRecordEsRepository trackPushRecordEsRepository,
IOrderOperationRecordEsRepository orderOperationRecordEsRepository)
IOrderOperationRecordEsRepository orderOperationRecordEsRepository,
ITrackStatusRepository trackStatusRepository)
{
_orderRepository = orderRepository;
_trackDetailsEsRepository = trackDetailsEsRepository;
_trackContentRepository = trackContentRepository;
_trackPushRecordEsRepository = trackPushRecordEsRepository;
_orderOperationRecordEsRepository = orderOperationRecordEsRepository;
_trackStatusRepository = trackStatusRepository;
}
#region 轨迹订单列表
@ -93,7 +98,7 @@ public class TrackOrderService : ApplicationService
int hours = (int) x.TrackTimeZone; // 提取整数部分作为小时
int minutes = (int) ((x.TrackTimeZone - hours) * 60); // 将小数部分乘以 60 转换为分钟
x.TrackGTMTimeZone =
$"GTM {(x.TrackTimeZone >= 0 ? "+" : "-")}{new TimeSpan(hours, minutes, 0).ToString().RemovePostFix(":00")}";
$"GMT {(x.TrackTimeZone >= 0 ? "+" : "-")}{new TimeSpan(hours, minutes, 0).ToString().RemovePostFix(":00")}";
});
return res;
@ -144,7 +149,7 @@ public class TrackOrderService : ApplicationService
{
if (a.TrackTimeZoneValue == 0f)
{
a.TrackTimeZone = "GTM +00:00";
a.TrackTimeZone = "GMT +00:00";
}
else if (Math.Abs(a.TrackTimeZoneValue - GlobalConst.NoneTrackTimeZone) < 1)
{
@ -158,12 +163,121 @@ public class TrackOrderService : ApplicationService
var offset = new TimeSpan(hours, minutes, 0);
var timeZoneStr = offset.ToString();
var flag = a.TrackTimeZoneValue > 0f ? "+" : "";
a.TrackTimeZone = $"GTM {flag}{timeZoneStr.RemovePostFix(":00")}";
a.TrackTimeZone = $"GMT {flag}{timeZoneStr.RemovePostFix(":00")}";
}
});
return list;
}
/// <summary>
/// 按时间轴获取轨迹内容
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("GetDetailTimeline")]
public async Task<UnifyResultDto<List<GetDetailTimelineOutput>>> GetDetailTimeline(GetDetailTimelineInput input)
{
var res = new UnifyResultDto<List<GetDetailTimelineOutput>>(true);
var order = await _orderRepository.GetFirstAsync(m => m.OrderNo == input.OrderNumber);
if (order == null)
return new UnifyResultDto<List<GetDetailTimelineOutput>>(false, "订单不存在");
if (input.SystemId <= 0)
return new UnifyResultDto<List<GetDetailTimelineOutput>>(false, "子系统id不合法");
if (input.CurrenUserSystemId <= 0)
return new UnifyResultDto<List<GetDetailTimelineOutput>>(false, "当前登陆用户子系统id不合法");
var system = await _orderRepository.GetSystemInfoById(input.CurrenUserSystemId);
if (system == null)
return new UnifyResultDto<List<GetDetailTimelineOutput>>(false, "未找到指定id的子系统");
var trackStatus = await _trackStatusRepository.GetListAsync(m => m.SubSystemId == input.SystemId);
if (trackStatus == null)
return new UnifyResultDto<List<GetDetailTimelineOutput>>(false, "未找到子系统下的任何轨迹状态");
var trackContent = await _trackContentRepository.GetListAsync(m => m.SubSystemId == input.SystemId);
if (trackContent == null)
return new UnifyResultDto<List<GetDetailTimelineOutput>>(false, "未找到子系统下的任何轨迹内容");
var trackDetails = await _trackDetailsEsRepository.GetListAsync(order.Id);
res.Data = new List<GetDetailTimelineOutput>();
var isCompleted = false;
foreach (var item in trackDetails)
{
var currentTrackStatus = trackStatus.FirstOrDefault(m => m.Code == item.TrackStatusCode);
var currentTrackContet = trackContent.FirstOrDefault(m => m.Code == item.TrackCode);
//是否完结
if (!isCompleted)
isCompleted = currentTrackStatus is { IsCompleted: true };
//如果是外部系统,且轨迹内容不对外则跳过这条轨迹内容
if (system.SystemProperty == 2 && currentTrackContet != null && !currentTrackContet.IsExternal)
continue;
res.Data.Add(new GetDetailTimelineOutput()
{
IsHighlight = true,
IsShowHover = true,
Remark = item.Remarks == null || item.Remarks == "--" ? "" : item.Remarks,
TrackTimeZone = $"GMT{(item.TrackTimeZone >= 0 ? "+" : "-")}{GetTimeZoneStr(item.TrackTimeZone)}",
TrackTime = ToUnixTimestamp(item.TrackTime),
TrackPlace = item.TrackPlace,
EnContent = item.TrackEnContent,
Files = item.Files == null
? new List<TrackFileItem>()
: item.Files!.Select(m => new TrackFileItem()
{
OssKey = m.OssKey,
FileName = m.FileName,
Url = m.OssKey.GetUrlByKey(),
}).ToList(),
Content = item.TrackContent,
TrackCode = item.TrackCode,
TrackPlaceNation = item.TrackPlaceNation,
TrackPlaceProvince = item.TrackPlaceProvince,
TrackPlaceCity = item.TrackPlaceCity,
});
}
//如果轨迹状态没完结则追加最后一个默认节点
if (!isCompleted)
{
res.Data.Add(new GetDetailTimelineOutput()
{
Content = "签收",
IsHighlight = false,
TrackTimeZone = order.EstimatedDeliveryDate.HasValue ? $"GMT{(order.DestinationTimeZone >= 0 ? "+" : "-")}{order.DestinationTimeZone}" : "",
TrackTime = order.EstimatedDeliveryDate.HasValue ? ToUnixTimestamp(DateTime.Parse(order.EstimatedDeliveryDate.ToString()!)) : 0,
TrackTimePrefix = order.EstimatedDeliveryDate.HasValue ? "预计签收时间:" : "",
});
}
return res;
}
public static long ToUnixTimestamp(DateTime time)
{
var sTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Utc, TimeZoneInfo.Local);
return (long) (time - sTime).TotalMilliseconds;
}
private string GetTimeZoneStr(float timeZone)
{
var time = timeZone.ToString().Split('.');
if (time.Length > 1 && time[1] != "0") //如果时区有小数点
{
return time[0] + ":30";
}
else
{
return time[0] + ":00";
}
}
/// <summary>
/// 根据轨迹id删除单条轨迹
/// </summary>

View File

@ -3,9 +3,11 @@ using DotNetCore.CAP;
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.Configuration;
using RabbitMQ.Client;
using Savorboard.CAP.InMemoryMessageQueue;
using SJZY.Expand.ABP.Core.Localization;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Expand.AliyunOSS;
using SJZY.InterfaceRelay.Application.Contracts;
using SJZY.Track.Application.CAP;
using SJZY.Track.Application.Contract;
@ -49,10 +51,7 @@ public class SjzyTrackApplicationModule : AbpModule
});
//添加虚拟文件系统
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<SjzyTrackApplicationModule>("SJZY.Track.Application");
});
Configure<AbpVirtualFileSystemOptions>(options => { options.FileSets.AddEmbedded<SjzyTrackApplicationModule>("SJZY.Track.Application"); });
//添加多语言
var languageConfig = configuration.GetSection("Language");
@ -81,45 +80,59 @@ public class SjzyTrackApplicationModule : AbpModule
//CAP
context.Services.AddSingleton<ISubscribeExecutor, MySubscribeExecutor>();
context.Services.AddCapTableNameService();
context.Services.AddCap(options =>
if (!System.Diagnostics.Debugger.IsAttached)
{
options.UseMySql(configuration["ConnectionStrings:DefaultConnection"]!);
options.UseRabbitMQ(configure =>
context.Services.AddCap(options =>
{
configure.HostName = configuration["RabbitMQ:HostName"]!;
configure.UserName = configuration["RabbitMQ:UserName"]!;
configure.Password = configuration["RabbitMQ:Password"]!;
configure.Port = configuration.GetValue<int>("RabbitMQ:Port");
configure.BasicQosOptions =
new RabbitMQOptions.BasicQos(configuration.GetValue<ushort>("CAP:PrefetchCount"));
});
options.FailedRetryInterval = configuration.GetValue<int>("CAP:FailedRetryInterval");
options.FailedRetryCount = configuration.GetValue<int>("CAP:FailedRetryCount");
options.SucceedMessageExpiredAfter = configuration.GetValue<int>("CAP:SucceedMessageExpiredAfter");
options.FallbackWindowLookbackSeconds =
configuration.GetValue<int>("CAP:FallbackWindowLookbackSeconds");
options.UseDashboard(dashboardOptions =>
{
dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached
? ""
: configuration["Swagger:JsonUrlPrefix"]!;
});
options.FailedThresholdCallback = faileCalback =>
{
try
options.UseMySql(configuration["ConnectionStrings:DefaultConnection"]!);
options.UseRabbitMQ(configure =>
{
LogHelper.Error($@"
configure.HostName = configuration["RabbitMQ:HostName"]!;
configure.UserName = configuration["RabbitMQ:UserName"]!;
configure.Password = configuration["RabbitMQ:Password"]!;
configure.Port = configuration.GetValue<int>("RabbitMQ:Port");
configure.BasicQosOptions =
new RabbitMQOptions.BasicQos(configuration.GetValue<ushort>("CAP:PrefetchCount"));
});
options.FailedRetryInterval = configuration.GetValue<int>("CAP:FailedRetryInterval");
options.FailedRetryCount = configuration.GetValue<int>("CAP:FailedRetryCount");
options.SucceedMessageExpiredAfter = configuration.GetValue<int>("CAP:SucceedMessageExpiredAfter");
options.FallbackWindowLookbackSeconds =
configuration.GetValue<int>("CAP:FallbackWindowLookbackSeconds");
options.UseDashboard(dashboardOptions =>
{
dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached
? ""
: configuration["Swagger:JsonUrlPrefix"]!;
});
options.FailedThresholdCallback = faileCalback =>
{
try
{
LogHelper.Error($@"
|-CAP失败回调事件:
|-处理类型:{(faileCalback.MessageType == DotNetCore.CAP.Messages.MessageType.Subscribe ? "消费消息达到最大重试次数,需要开发人员介入" : "生产消息推送失败")}
|-头部信息:{faileCalback.Message.Headers.ToJson()}");
}
catch (Exception ex)
{
LogHelper.Error("【严重】CAP失败回调事件发生未处理异常" + ex);
}
};
}).AddSubscribeFilter<CapFilter>();
}
catch (Exception ex)
{
LogHelper.Error("【严重】CAP失败回调事件发生未处理异常" + ex);
}
};
}).AddSubscribeFilter<CapFilter>();
}
else
{
//是本地调试环境,用内存存储和内存队列
context.Services.AddCap(capOptions =>
{
capOptions.UseInMemoryStorage();
capOptions.UseInMemoryMessageQueue();
capOptions.UseDashboard();
}).AddSubscribeFilter<CapFilter>();
Console.WriteLine("-- 当前为VS本地环境,用内存存储和内存队列");
}
context.Services.AddRabbitBoot(options =>
@ -141,6 +154,17 @@ public class SjzyTrackApplicationModule : AbpModule
o.QueueBind(GlobalConst.TrackRefreshSubscribe, GlobalConst.InterfaceRelayExchange,
GlobalConst.TrackRefreshSubscribe);
}
},
new()
{
//广播轨迹
Queue = GlobalConst.TrackRefreshSubscribe,
FetchCount = configuration.GetValue<ushort>("TrackApp:TrackRefreshFetchCount"),
FailedRequeue = false,
Declaration = o =>
{
o.ExchangeDeclare(GlobalConst.TrackChangeExchange, ExchangeType.Topic, true);
}
}
};
}, typeof(SjzyTrackApplicationModule).Assembly);
@ -148,6 +172,16 @@ public class SjzyTrackApplicationModule : AbpModule
context.Services.Configure<TrackAppOptions>(configuration.GetSection("TrackApp"));
context.Services.Configure<InterfaceRelayParamsConfigOptions>(
configuration.GetSection("InterfaceRelayParamsConfig"));
//注册阿里云OSS服务
context.Services.AddAliOSS(option =>
{
option.AccessKeyId = configuration["OSS:AccessKeyId"];
option.AccessKeySecret = configuration["OSS:AccessKeySecret"];
option.Endpoint = configuration["OSS:Endpoint"];
option.BucketName = configuration["OSS:BucketName"];
option.ReturnHttpsUrl = true;
});
}
public override void PreConfigureServices(ServiceConfigurationContext context)

View File

@ -1,4 +1,5 @@
using SJZY.Track.Domain.Dtos.Order;
using SJZY.Track.Domain.VEntities;
namespace SJZY.Track.Domain.Aggregates.OrderAggregate;
@ -131,4 +132,18 @@ public interface IOrderRepository : IBasicRepository<OrderEntity>
Task<int> UpdateOrderPullConfigForServiceProviderAsync(UpdateOrderPullConfigsInputVo inputVo);
#endregion
/// <summary>
/// 根据id获取子系统信息
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<VSystemEntity> GetSystemInfoById(int id);
/// <summary>
/// 根据id获取员工姓名
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<VUserEntity> GetUserById(int id);
}

View File

@ -168,10 +168,25 @@ public class OrderEntity : IFullAuditedBasicEntitys, IAggregateRoot
[SugarColumn(ColumnName = "ArrivalProvince")]
public string? ArrivalProvince { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
[SugarColumn(ColumnName = "EstimatedDeliveryDate")]
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
[SugarColumn(ColumnName = "DestinationTimeZone")]
public float? DestinationTimeZone { get; set; }
[SugarColumn(IsIgnore = true)] public List<OrderFlightEntity> OrderFlights { get; set; }
[SugarColumn(IsIgnore = true)] public List<OrderPullStatusEntity> OrderPullStatus { get; set; }
[Navigate(NavigateType.OneToMany, nameof(OrderPlatformNumberEntity.OrderId))]
[SugarColumn(IsIgnore = true)] public List<OrderPlatformNumberEntity> OrderPlatformNumbers { get; set; }
public void ResetTrackInfo()
{
IsCompleted = false;

View File

@ -40,8 +40,22 @@ public class OrderOperationRecordIndex : IdBaseIndex
/// </summary>
public int CreateUserId { get; set; }
/// <summary>
/// 创建人姓名
/// </summary>
public string CreateUserName { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
}
public enum OrderOperationType
{
创建订单 = 1,
修改订单 = 2,
创建轨迹 = 3,
修改轨迹 = 4,
删除轨迹 = 5
}

View File

@ -0,0 +1,32 @@
namespace SJZY.Track.Domain.Aggregates.OrderAggregate;
/// <summary>
/// 外部单号关联表
/// </summary>
[SugarTable("t_order_platform_number")]
public class OrderPlatformNumberEntity : IFullAuditedBasicEntitys, IEntity
{
/// <summary>
/// 自增主键
/// </summary>
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
/// <summary>
/// 订单id
/// </summary>
[SugarColumn(ColumnName = "OrderId")]
public int OrderId { get; set; }
/// <summary>
/// 外部单号
/// </summary>
[SugarColumn(ColumnName = "OrderNumber")]
public string? OrderNumber { get; set; }
/// <summary>
/// 平台名称
/// </summary>
[SugarColumn(ColumnName = "Platform")]
public string? Platform { get; set; }
}

View File

@ -18,6 +18,12 @@ public class OrderPullStatusEntity : ICreateBaicEntity, IUpdateBasicEntity, IEnt
[SugarColumn(ColumnName = "OrderId")]
public int OrderId { get; set; }
/// <summary>
/// api服务商订单号(第三方单号)
/// </summary>
[SugarColumn(ColumnName = "OrderNo")]
public string? OrderNo { get; set; }
/// <summary>
/// 服务商code
/// </summary>

View File

@ -26,4 +26,7 @@ public interface ITrackContentRepository : IBasicRepository<TrackContentEntity>
Expression<Func<TrackContentMapEntity, bool>> whereExpression);
Task<bool> GetTemplateIsExist(int trackContentId);
Task<TrackContentEntity> GetByCodeAsync(int systemId, string code);
Task<List<TrackContentEntity>> GetListBySystemIdAsync(int systemId);
Task<List<TrackContentVO>> GetTrackContentBySyetemIdAsync(int subSystemId);
}

View File

@ -36,6 +36,12 @@ public class TrackContentEntity : IFullAuditedBasicEntitys, IAggregateRoot
[SugarColumn(ColumnName = "SubSystemId")]
public int SubSystemId { get; set; }
/// <summary>
/// 子系统名称
/// </summary>
[SugarColumn(IsIgnore = true)]
public string SubSystem { get; set; }
/// <summary>
/// 轨迹标记id,多个逗号分隔
/// </summary>
@ -53,4 +59,22 @@ public class TrackContentEntity : IFullAuditedBasicEntitys, IAggregateRoot
/// </summary>
[SugarColumn(ColumnName = "IsExternal")]
public bool IsExternal { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
[SugarColumn(ColumnName = "IsRepeatable")]
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
[SugarColumn(ColumnName = "IsAllowManuallyUpdate")]
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
[SugarColumn(ColumnName = "IsAllowManuallyCreate")]
public bool IsAllowManuallyCreate { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
public class FileItem
{
/// <summary>
/// 文件osskey
/// </summary>
public string OssKey { get; set; }
/// <summary>
/// 文件名称
/// </summary>
public string FileName { get; set; }
}

View File

@ -1,4 +1,5 @@
using SJZY.Expand.ElasticSearch.Services;
using SJZY.Track.Domain.Enums;
namespace SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
@ -22,7 +23,10 @@ public interface ITrackDetailsEsRepository : IElasticsearchClientService<TrackDe
Task<List<TrackDetailsIndex>> GetListAsync(int orderId);
Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, List<string> trackCodes, TrackSourceEnum source);
Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes);
Task DeleteTrackByIdAsync(string id, string indexName);
Task<List<TrackDetailsIndex>> GetDataByIds(string[] ids);
}

View File

@ -37,6 +37,11 @@ public class TrackDetailsIndex : IdBaseIndex
/// </summary>
public string TrackStatus { get; set; } = GlobalConst.EmptyString;
/// <summary>
/// 轨迹状态code
/// </summary>
public string TrackStatusCode { get; set; } = GlobalConst.EmptyString;
/// <summary>
/// 轨迹内容代码
/// </summary>
@ -106,4 +111,69 @@ public class TrackDetailsIndex : IdBaseIndex
/// 修改时间
/// </summary>
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 客户是否可见
/// </summary>
public bool IsVisibility { get; set; }
/// <summary>
/// 数据来源:1外部服务商创建,2内部系统创建,3人工创建
/// </summary>
public int Source { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remarks { get; set; } = GlobalConst.EmptyString;
/// <summary>
/// 附件集合
/// </summary>
public List<FileItem>? Files { get; set; }
/// <summary>
/// 轨迹发生地(城市)
/// </summary>
public string? TrackPlaceCity { get; set; } = GlobalConst.EmptyString;
/// <summary>
/// 轨迹发生地(城市)Id
/// </summary>
public int? TrackPlaceCityId { get; set; } = GlobalConst.NotExistId;
/// <summary>
/// 轨迹发生地(省/州)
/// </summary>
public string? TrackPlaceProvince { get; set; } = GlobalConst.EmptyString;
/// <summary>
///轨迹发生地(省/州)Id
/// </summary>
public int? TrackPlaceProvinceId { get; set; } = GlobalConst.NotExistId;
/// <summary>
/// 轨迹发生地(国家/地区)
/// </summary>
public string? TrackPlaceNation { get; set; } = GlobalConst.EmptyString;
/// <summary>
/// 轨迹发生地(国家/地区)Id
/// </summary>
public int? TrackPlaceNationId { get; set; } = GlobalConst.NotExistId;
/// <summary>
/// 轨迹发生地邮编
/// </summary>
public string? TrackPlacePostcode { get; set; } = GlobalConst.EmptyString;
/// <summary>
/// 预计签收时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 签收地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
}

View File

@ -51,4 +51,11 @@ public partial class GlobalConst
/// 预警计算任务
/// </summary>
public const string TrackWarningCalcSubscribe = "SJZY.Track.TrackWarningCalc";
/// <summary>
/// 轨迹变更通知交换机
/// </summary>
public const string TrackChangeExchange = "sjzy.track.on_track_change_ex";
}

View File

@ -7,6 +7,7 @@ public partial class GlobalConst
public const int ChunkSize = 100;
public const int SafelyLimit = 10000;
public const int NormalLimit = 10000;
public const int NotExistId = -9999;
public const float NoneTrackTimeZone = 99999;

View File

@ -68,6 +68,7 @@ public class TrackOrderVO
/// </summary>
public string? OrderNumber { get; set; }
/// <summary>
/// 客户简称
/// </summary>
@ -137,4 +138,19 @@ public class TrackOrderVO
/// 问题类型名称
/// </summary>
public string? QuestionTypeName { get; set; }
/// <summary>
/// 预计到达时间
/// </summary>
public DateTime? EstimatedDeliveryDate { get; set; }
/// <summary>
/// 目的地时区
/// </summary>
public float? DestinationTimeZone { get; set; }
/// <summary>
/// 第三方单号,服务商-轨迹0000000、轨迹服务商-0000000
/// </summary>
public string? ThirdPartyOrderNumber { get; set; }
}

View File

@ -89,4 +89,19 @@ public class GetTrackContentListVO
/// 修改人
/// </summary>
public string UpdateUser { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
public bool IsAllowManuallyCreate { get; set; }
}

View File

@ -56,4 +56,18 @@ public class GetTrackContentDetailVO
/// 是否对外
/// </summary>
public bool IsExternal { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
public bool IsAllowManuallyCreate { get; set; }
}

View File

@ -31,4 +31,34 @@ public class TrackContentVO
/// 是否完成态
/// </summary>
public bool IsCompleted { get; set; }
/// <summary>
/// 轨迹状态代码
/// </summary>
public string TrackStatusCode { get; set; }
/// <summary>
/// 是否可重复
/// </summary>
public bool IsRepeatable { get; set; }
/// <summary>
/// 是否允许手动修改
/// </summary>
public bool IsAllowManuallyUpdate { get; set; }
/// <summary>
/// 是否允许手动创建
/// </summary>
public bool IsAllowManuallyCreate { get; set; }
/// <summary>
/// 是否广播
/// </summary>
public bool IsToMq { get; set; }
/// <summary>
/// 轨迹内容code
/// </summary>
public string TrackContentCode { get; set; }
}

View File

@ -0,0 +1,24 @@
using System.ComponentModel;
namespace SJZY.Track.Domain.Enums;
/// <summary>
/// 轨迹来源
/// </summary>
public enum TrackSourceEnum
{
/// <summary>
/// 外部服务商创建
/// </summary>
[Description("外部服务商创建")] ExternalServiceProvide = 1,
/// <summary>
/// 内部系统创建
/// </summary>
[Description("内部系统创建")] InternalService = 2,
/// <summary>
/// 人工创建
/// </summary>
[Description("人工创建")] Artificial = 3,
}

View File

@ -45,7 +45,8 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
&& b.StartTime <= DateTime.Now && b.EndTime >= DateTime.Now)
.Select((a, b, c) => new OrderWithServiceProviderVO
{
OrderNo = a.OrderNo,
//优先使用第三方的订单号,为空时才使用主单号
OrderNo = b.OrderNo ?? a.OrderNo,
OrderType = a.OrderType,
SubSystemId = a.SubSystemId,
ServiceProviderCode = b.ServiceProviderCode,
@ -65,7 +66,8 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
b.EndTime >= DateTime.Now)
.Select((a, b) => new OrderWithServiceProviderVO
{
OrderNo = a.OrderNo,
//优先使用第三方的订单号,为空时才使用主单号
OrderNo = b.OrderNo ?? a.OrderNo,
OrderType = a.OrderType,
SubSystemId = a.SubSystemId,
ServiceProviderCode = b.ServiceProviderCode
@ -87,9 +89,14 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
SubSystemCode = z.Key,
TrackStatusId = x.TrackStatusId,
TrackStatus = y.Status,
TrackStatusCode = y.Code,
TrackContent = x.Content,
TrackEnContent = x.EnContent,
IsCompleted = y.IsCompleted,
IsRepeatable = x.IsRepeatable,
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
IsToMq = y.IsToMq,
})
.FirstAsync();
}

View File

@ -12,11 +12,14 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
{
public async Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input)
{
//查询完去重
var pageList = await Context.Queryable<OrderEntity>()
.Includes(a => a.OrderPlatformNumbers)
.LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false)
.LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false)
.LeftJoin<OrderPlatformNumberEntity>((a, b, c, d) => a.Id == d.OrderId && d.IsDeleted == false)
.WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId)
.WhereIF(!input.OrderNos.IsNullOrEmpty(), (a, b, c) => input.OrderNos!.Contains(a.OrderNo))
.WhereIF(!input.OrderNos.IsNullOrEmpty(), (a, b, c, d) => input.OrderNos!.Contains(a.OrderNo) || input.OrderNos!.Contains(d.OrderNumber))
.WhereIF(input.CreateTimeStart.HasValue && input.CreateTimeEnd.HasValue,
(a, b, c) => a.CreateTime >= input.CreateTimeStart && a.CreateTime <= input.CreateTimeEnd)
.WhereIF(input.CreateTimeStart.HasValue && (!input.CreateTimeEnd.HasValue),
@ -28,6 +31,7 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
.WhereIF(input.TabType > 0, (a, b, c) => a.QuestionType == input.TabType)
.WhereIF(input.TabType == (int) TrackProblemType.Warn, (a, b, c) => !a.IsCompleted)
.OrderByDescending((a, b, c) => a.CreateTime)
.Distinct()
.Select((a, b, c) => new TrackOrderVO
{
Id = a.Id,
@ -44,7 +48,10 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
IsFinish = a.IsCompleted,
CreateTime = a.CreateTime,
SubSystem = c.CnName,
SubSystemId = c.Id
SubSystemId = c.Id,
DestinationTimeZone = a.DestinationTimeZone,
EstimatedDeliveryDate = a.EstimatedDeliveryDate,
ThirdPartyOrderNumber = BuildThirdPartyOrderNumber(a.OrderPlatformNumbers)
})
.ToPagedListAsync(input.PageIndex, input.PageSize);
@ -60,6 +67,8 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
await Context.Insertable(order.OrderFlights).ExecuteCommandAsync();
order.OrderPullStatus.ForEach(x => x.OrderId = orderId);
await Context.Insertable(order.OrderPullStatus).ExecuteCommandAsync();
order.OrderPlatformNumbers.ForEach(x => x.OrderId = orderId);
await Context.Insertable(order.OrderPlatformNumbers).ExecuteCommandAsync();
tran.Complete();
@ -90,6 +99,13 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
// 更新订单模板
await Context.Deleteable<OrderPullStatusEntity>().Where(x => x.OrderId == order.Id).ExecuteCommandAsync();
order.OrderPullStatus.ForEach(x => x.OrderId = order.Id);
await Context.Insertable(order.OrderPullStatus).ExecuteCommandAsync();
// 更新订单三方关联
await Context.Deleteable<OrderPlatformNumberEntity>().Where(x => x.OrderId == order.Id).ExecuteCommandAsync();
order.OrderPlatformNumbers.ForEach(x => x.OrderId = order.Id);
await Context.Insertable(order.OrderPlatformNumbers).ExecuteCommandAsync();
// 更新订单航班
await Context.Deleteable<OrderFlightEntity>().Where(x => x.OrderId == order.Id).ExecuteCommandAsync();
@ -163,6 +179,16 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
return res.Select(x => (x.Key, x.Id)).ToList();
}
public Task<VSystemEntity> GetSystemInfoById(int id)
{
return Context.Queryable<VSystemEntity>().FirstAsync(m => m.IsDeleted == false && m.Id == id);
}
public Task<VUserEntity> GetUserById(int id)
{
return Context.Queryable<VUserEntity>().FirstAsync(m => m.IsDeleted == false && m.Id == id);
}
private int UpdateOrderQuestionType(int questionType, IEnumerable<int> ids)
{
var idsString = string.Join(",", ids);
@ -174,6 +200,20 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
});
}
/// <summary>
/// 拼接多个三方单号,默认使用分隔符默认(、)
/// 第三方单号,服务商-轨迹0000000、轨迹服务商-0000000
/// </summary>
/// <param name="orderPlatformNumberEntities"></param>
/// <returns></returns>
private static string BuildThirdPartyOrderNumber(List<OrderPlatformNumberEntity> orderPlatformNumberEntities)
{
const string separator = "、";
var thirdPartyOrderNumbers = orderPlatformNumberEntities
.Select(x => $"{x.Platform}-{x.OrderNumber}").ToList();
return string.Join(separator, thirdPartyOrderNumbers);
}
#region 订单关联
public async Task<List<LinkedOrderVO>> GetLinkedOrdersAsync(int[] orderIds)

View File

@ -33,6 +33,9 @@ public class TrackContentRepository : BasicRepository<TrackContentEntity>, ITrac
EnContent = a.EnContent,
TrackFlagId = a.TrackFlagId,
IsExternal = a.IsExternal,
IsRepeatable = a.IsRepeatable,
IsAllowManuallyUpdate = a.IsAllowManuallyUpdate,
IsAllowManuallyCreate = a.IsAllowManuallyCreate
})
.Mapper(x => { x.TrackFlagIds = x.TrackFlagId?.Split(',').Select(int.Parse).ToList(); })
.FirstAsync();
@ -80,6 +83,9 @@ public class TrackContentRepository : BasicRepository<TrackContentEntity>, ITrac
CreateUser = e.Name,
UpdateTime = a.UpdateTime,
UpdateUser = f.Name,
IsRepeatable = a.IsRepeatable,
IsAllowManuallyUpdate = a.IsAllowManuallyUpdate,
IsAllowManuallyCreate = a.IsAllowManuallyCreate
})
.ToPagedListAsync(input.PageIndex, input.PageSize);
@ -113,7 +119,6 @@ public class TrackContentRepository : BasicRepository<TrackContentEntity>, ITrac
return false;
}
public async Task<UnifyPageResultDto<GetTrackContentMapPageOutputVO>> GetMapPageAsync(
GetTrackContentMapPageInputVO input)
{
@ -220,4 +225,50 @@ public class TrackContentRepository : BasicRepository<TrackContentEntity>, ITrac
return await Context.Updateable<TrackContentMapEntity>().SetColumns(columns).Where(whereExpression)
.ExecuteCommandAsync() > 0;
}
public Task<TrackContentEntity> GetByCodeAsync(int systemId, string code)
{
return Context.Queryable<TrackContentEntity>().FirstAsync(m => m.SubSystemId == systemId && m.Code == code);
}
public Task<List<TrackContentEntity>> GetListBySystemIdAsync(int systemId)
{
return Context.Queryable<TrackContentEntity>()
.Where(content => content.SubSystemId == systemId && !content.IsDeleted)
.Select((content) => new TrackContentEntity
{
Id = content.Id,
Code = content.Code,
IsExternal = content.IsExternal,
EnContent = content.EnContent,
Content = content.Content,
IsRepeatable = content.IsRepeatable,
IsAllowManuallyCreate = content.IsAllowManuallyCreate,
IsAllowManuallyUpdate = content.IsAllowManuallyUpdate,
})
.ToListAsync();
}
public Task<List<TrackContentVO>> GetTrackContentBySyetemIdAsync(int subSystemId)
{
return Context.Queryable<TrackContentEntity>()
.LeftJoin<TrackStatusEntity>((x, y) => x.TrackStatusId == y.Id)
.LeftJoin<VSystemEntity>((x, y, z) => x.SubSystemId == z.Id)
.Where(x => x.SubSystemId == subSystemId)
.Select((x, y, z) => new TrackContentVO
{
SubSystemCode = z.Key,
TrackStatusId = x.TrackStatusId,
TrackStatus = y.Status,
TrackStatusCode = y.Code,
TrackContent = x.Content,
TrackContentCode = x.Code,
TrackEnContent = x.EnContent,
IsCompleted = y.IsCompleted,
IsRepeatable = x.IsRepeatable,
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
IsToMq = y.IsToMq,
}).ToListAsync();
}
}

View File

@ -3,6 +3,7 @@ using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Expand.ElasticSearch.Services;
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
using SJZY.Track.Domain.Consts;
using SJZY.Track.Domain.Enums;
namespace SJZY.Track.Repository.Repositories;
@ -145,6 +146,20 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
track.TrackTimeZone,
track.UpdateUser,
UpdateTime = DateTime.Now,
track.TrackContent,
track.TrackEnContent,
track.IsVisibility,
track.Remarks,
track.Files,
track.TrackPlaceCity,
track.TrackPlaceCityId,
track.TrackPlaceProvince,
track.TrackPlaceProvinceId,
track.TrackPlaceNation,
track.TrackPlaceNationId,
track.TrackPlacePostcode,
track.DestinationTimeZone,
track.EstimatedDeliveryDate
})
);
@ -174,6 +189,21 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
ctx._source.trackTimeZone = params.trackTimeZone;
ctx._source.updateUser = params.updateUser;
ctx._source.updateTime = params.updateTime;
ctx._source.trackContent = params.trackContent;
ctx._source.trackEnContent = params.trackEnContent;
ctx._source.isVisibility = params.isVisibility;
ctx._source.remarks = params.remarks;
ctx._source.files = params.files;
ctx._source.trackPlaceCity = params.trackPlaceCity;
ctx._source.trackPlaceCityId = params.trackPlaceCityId;
ctx._source.trackPlaceProvince = params.trackPlaceProvince;
ctx._source.trackPlaceProvinceId = params.trackPlaceProvinceId;
ctx._source.trackPlaceNation = params.trackPlaceNation;
ctx._source.trackPlaceNationId = params.trackPlaceNationId;
ctx._source.trackPlacePostcode = params.trackPlacePostcode;
ctx._source.destinationTimeZone = params.destinationTimeZone;
ctx._source.estimatedDeliveryDate = params.estimatedDeliveryDate;
")
.Params(p => p
.Add("trackPlace", track.TrackPlace)
@ -181,6 +211,21 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
.Add("trackTimeZone", track.TrackTimeZone)
.Add("updateUser", track.UpdateUser)
.Add("updateTime", DateTime.Now)
//S06新增字段更新
.Add("trackContent", track.TrackContent)
.Add("trackEnContent", track.TrackEnContent)
.Add("isVisibility", track.IsVisibility)
.Add("remarks", track.Remarks)
.Add("files", track.Files)
.Add("trackPlaceCity", track.TrackPlaceCity)
.Add("trackPlaceCityId", track.TrackPlaceCityId)
.Add("trackPlaceProvince", track.TrackPlaceProvince)
.Add("trackPlaceProvinceId", track.TrackPlaceProvinceId)
.Add("trackPlaceNation", track.TrackPlaceNation)
.Add("trackPlaceNationId", track.TrackPlaceNationId)
.Add("trackPlacePostcode", track.TrackPlacePostcode)
.Add("destinationTimeZone", track.DestinationTimeZone)
.Add("estimatedDeliveryDate", track.EstimatedDeliveryDate)
)
)
);
@ -298,6 +343,26 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
return r.ToIdList();
}
public async Task<List<TrackDetailsIndex>> GetListAsync(int[] orderIds, List<string> trackCodes, TrackSourceEnum source)
{
var r = await Context.SearchAsync<TrackDetailsIndex>(x => x
.Index(GlobalConst.TrackDetailsIndex)
.Query(q =>
q.Terms(t => t.Field(f => f.OrderId).Terms(orderIds))
&& q.Terms(t => t.Field(f => f.TrackCode.Suffix("keyword")).Terms(trackCodes))
&& q.Term(t => t.Source, (int) source)
)
.Size(SafelyLimit)
.Sort(s => s.Field(f => f.ZeroTrackTime, SortOrder.Descending)));
if (!r.IsValid)
{
throw new InvalidOperationException($"轨迹查询失败,orderIds:[{string.Join(',', orderIds)}],原因:{r.DebugInformation}。");
}
return r.ToIdList();
}
public async Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes)
{
// var deleteResponse = await Context.DeleteByQueryAsync<TrackDetailsIndex>(d => d
@ -334,6 +399,7 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
$"轨迹查询失败,orderIds:[{orderIds.JoinAsString(", ")}],trackCodes:[{trackCodes.JoinAsString(", ")}],原因:{search.DebugInformation}。");
}
//按订单id和code分组,只删除组元素数量为1的轨迹
var tracks = search.ToIdList().GroupBy(doc => new
{
doc.OrderId,
@ -351,6 +417,7 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
return tracks.Select(x => x.OrderId).ToList();
}
public async Task DeleteTrackByIdAsync(string id, string indexName)
{
var r = await Context.DeleteAsync<TrackDetailsIndex>(id, u => u
@ -362,4 +429,15 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
throw new InvalidOperationException($"轨迹删除失败,id:{indexName},原因:{r.DebugInformation}。");
}
}
public async Task<List<TrackDetailsIndex>> GetDataByIds(string[] ids)
{
var res = await Context.SearchAsync<TrackDetailsIndex>(m => m
.Index(GlobalConst.TrackDetailsIndex)
.Query(
q => q.Ids(i => i.Values(ids))
));
return res.ToIdList();
}
}