diff --git a/src/SJZY.Track.Api/appsettings.json b/src/SJZY.Track.Api/appsettings.json
index 41fc37c6..ac8a5882 100644
--- a/src/SJZY.Track.Api/appsettings.json
+++ b/src/SJZY.Track.Api/appsettings.json
@@ -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"
diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineInput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineInput.cs
index e69de29b..9294efc0 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineInput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineInput.cs
@@ -0,0 +1,19 @@
+namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
+
+public class GetDetailTimelineInput
+{
+ ///
+ /// 订单编号
+ ///
+ public string OrderNumber { get; set; }
+
+ ///
+ /// 子系统id
+ ///
+ public int SystemId{ get; set; }
+
+ ///
+ /// 是否客户端,false时展示所有轨迹,true时只展示对外的轨迹
+ ///
+ public bool IsCustomeClient { get; set; }
+}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineOutput.cs b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineOutput.cs
index e69de29b..a621240b 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineOutput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/ProvideServices/GetDetailTimelineOutput.cs
@@ -0,0 +1,54 @@
+namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
+
+public class GetDetailTimelineOutput
+{
+ ///
+ /// 轨迹编码
+ ///
+ public string TrackCode { get; set; }
+
+ ///
+ /// 轨迹内容
+ ///
+ public string Content { get; set; }
+
+ ///
+ /// 轨迹英文内容
+ ///
+ public string EnContent { get; set; }
+
+ ///
+ /// 轨迹发生地
+ ///
+ public string TrackPlace { get; set; } = null!;
+
+ ///
+ /// 轨迹发生时间
+ ///
+ public long TrackTime { get; set; }
+
+ ///
+ /// 轨迹时间前缀
+ ///
+ public string TrackTimePrefix { get; set; }
+
+ ///
+ /// 轨迹发生时区
+ ///
+ public string TrackTimeZone { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string Remark { get; set; }
+
+ ///
+ /// 文件 osskey 集合
+ ///
+ public List Files { get; set; }
+
+ ///
+ /// 是否高亮
+ ///
+ public bool IsHighlight { get; set; }
+}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/EditTrackContentInput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/EditTrackContentInput.cs
index 6b7c663f..14b5461e 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/EditTrackContentInput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/EditTrackContentInput.cs
@@ -46,6 +46,26 @@ public class EditTrackContentInput
/// 是否对外
///
public bool IsExternal { get; set; }
+
+ ///
+ /// 是否可重复
+ ///
+ public bool IsRepeatable { get; set; }
+
+ ///
+ /// 是否允许手动修改
+ ///
+ public bool IsAllowManuallyUpdate { get; set; }
+
+ ///
+ /// 是否允许手动创建
+ ///
+ public bool IsAllowManuallyCreate { get; set; }
+
+ ///
+ /// 是否同步轨迹订单上的预计到达时间
+ ///
+ public bool IsChangeOrderEdd { get; set; }
}
public class GetTrackContentDetailDto
diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentInput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentInput.cs
index e69de29b..fb6aa163 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentInput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentInput.cs
@@ -0,0 +1,25 @@
+namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
+
+public class GetAvailableContentInput
+{
+ ///
+ /// 子系统id
+ ///
+ public int SystemId { get; set; }
+
+ ///
+ /// 订单号
+ ///
+ public string? OrderNo { get; set; }
+
+ ///
+ /// 操作类型 1=创建 2=修改
+ ///
+ public TrackOptionType TrackOptionType { get; set; }
+}
+
+public enum TrackOptionType
+{
+ 创建 = 1,
+ 修改 = 2
+}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentOutput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentOutput.cs
index e69de29b..69e77773 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentOutput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetAvailableContentOutput.cs
@@ -0,0 +1,29 @@
+namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
+
+public class GetAvailableContentOutput
+{
+ ///
+ /// Id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// 轨迹内容代码
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// 轨迹内容
+ ///
+ public string Content { get; set; }
+
+ ///
+ /// 轨迹内容英文
+ ///
+ public string EnContent { get; set; }
+
+ ///
+ /// 是否对外
+ ///
+ public bool IsExternal { get; set; }
+}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeInput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeInput.cs
index e69de29b..8f7b1c85 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeInput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeInput.cs
@@ -0,0 +1,14 @@
+namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
+
+public class GetTrackContentByCodeInput
+{
+ ///
+ /// 子系统id
+ ///
+ public int SystemId { get; set; }
+
+ ///
+ /// 轨迹内容code
+ ///
+ public string Code { get; set; }
+}
diff --git a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeOutput.cs b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeOutput.cs
index e69de29b..e584522d 100644
--- a/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeOutput.cs
+++ b/src/SJZY.Track.Application.Contract/Dtos/TrackContents/GetTrackContentByCodeOutput.cs
@@ -0,0 +1,19 @@
+namespace SJZY.Track.Application.Contract.Dtos.TrackContents;
+
+public class GetTrackContentByCodeOutput
+{
+ ///
+ /// 中文内容
+ ///
+ public string Content { get; set; }
+
+ ///
+ /// 英文内容
+ ///
+ public string EnContent { get; set; }
+
+ ///
+ /// 是否对外
+ ///
+ public bool IsExternal { get; set; }
+}
diff --git a/src/SJZY.Track.Application/Services/TrackContents/TrackContentService.cs b/src/SJZY.Track.Application/Services/TrackContents/TrackContentService.cs
index faf3f428..b4bea62f 100644
--- a/src/SJZY.Track.Application/Services/TrackContents/TrackContentService.cs
+++ b/src/SJZY.Track.Application/Services/TrackContents/TrackContentService.cs
@@ -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 _trackFlagBasicQuery;
private readonly IBasicQuery _trackStatusBasicQuery;
+ private readonly IOrderRepository _orderRepository;
+ private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
public TrackContentService(
IStringLocalizer stringLocalizer,
ITrackContentRepository trackContentRepository,
IBasicQuery trackStatusBasicQuery,
- IBasicQuery trackFlagBasicQuery)
+ IBasicQuery trackFlagBasicQuery,
+ IOrderRepository orderRepository,
+ ITrackDetailsEsRepository trackDetailsEsRepository)
{
_stringLocalizer = stringLocalizer;
_trackContentRepository = trackContentRepository;
_trackStatusBasicQuery = trackStatusBasicQuery;
_trackFlagBasicQuery = trackFlagBasicQuery;
+ _orderRepository = orderRepository;
+ _trackDetailsEsRepository = trackDetailsEsRepository;
}
///
@@ -96,8 +105,7 @@ public class TrackContentService : ApplicationService
///
///
[HttpPost("GetList")]
- public async Task> GetPageTrackContent(
- GetPageTrackContentInput input)
+ public async Task> GetPageTrackContent(GetPageTrackContentInput input)
{
var vo = ObjectMapper.Map(input);
var resultDto = await _trackContentRepository.GetPageTrackContent(vo);
@@ -181,6 +189,95 @@ public class TrackContentService : ApplicationService
return true;
}
+ ///
+ /// 根据轨迹内容code获取轨迹内容
+ ///
+ ///
+ ///
+ [HttpPost("GetTrackContentByCode")]
+ public async Task> GetTrackContentByCodeAsync([FromBody] GetTrackContentByCodeInput input)
+ {
+ if (input.SystemId <= 0)
+ return new UnifyResultDto(false, "子系统Id必须大于等于0");
+
+ if (string.IsNullOrEmpty(input.Code))
+ return new UnifyResultDto(false, "轨迹内容code不能为空");
+
+ var content = await _trackContentRepository.GetByCodeAsync(input.SystemId, input.Code);
+ if (content == null)
+ return new UnifyResultDto(false, "在当前子系统中未找到指定code的轨迹内容");
+
+ var res = new UnifyResultDto(true)
+ {
+ Data = new GetTrackContentByCodeOutput
+ {
+ Content = content.Content,
+ EnContent = content.EnContent,
+ IsExternal = content.IsExternal
+ }
+ };
+
+ return res;
+ }
+
+ ///
+ /// 创建轨迹时获取可用的轨迹内容
+ ///
+ ///
+ ///
+ [HttpPost("GetAvailableContent")]
+ public async Task>> GetAvailableContent(GetAvailableContentInput input)
+ {
+ if (input.SystemId <= 0)
+ return new UnifyResultDto>(false, "系统id需大于0!");
+
+ if (string.IsNullOrEmpty(input.OrderNo))
+ return new UnifyResultDto>(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>(true)
+ {
+ Data = new List()
+ };
+
+ foreach (var item in contentList)
+ {
+ if (!item.IsRepeatable && trackDetails?.Any(m => m.TrackCode == item.Code) == true) //跳过已存在轨迹内容
+ 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 AddAsync(EditTrackContentInput input)
diff --git a/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs b/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs
index 7c7950dd..b1fff209 100644
--- a/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs
+++ b/src/SJZY.Track.Application/Services/TrackOrders/TrackOrderService.cs
@@ -4,6 +4,7 @@ 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 +19,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 +28,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 轨迹订单列表
@@ -164,6 +168,73 @@ public class TrackOrderService : ApplicationService
return list;
}
+
+ ///
+ /// 按时间轴获取轨迹内容
+ ///
+ ///
+ ///
+ [HttpPost("GetDetailTimeline")]
+ public async Task>> GetDetailTimeline(GetDetailTimelineInput input)
+ {
+ var res = new UnifyResultDto>(true);
+
+ var order = await _orderRepository.GetFirstAsync(m => m.OrderNo == input.OrderNumber);
+ if (order == null)
+ return new UnifyResultDto>(false, "订单不存在");
+
+ if (input.SystemId <= 0)
+ return new UnifyResultDto>(false, "子系统id不合法");
+
+ var trackStatus = await _trackStatusRepository.GetListAsync(m => m.SubSystemId == input.SystemId);
+
+ var trackDetails = await _trackDetailsEsRepository.GetListAsync(order.Id);
+ res.Data = new List();
+ var isCompleted = false;
+ foreach (var item in trackDetails)
+ {
+ //是否完结
+ isCompleted = trackStatus.Any(m => m.IsCompleted && m.Code == item.TrackStatus);
+
+
+
+ res.Data.Add(new GetDetailTimelineOutput()
+ {
+ IsHighlight = true,
+ Files = new List(),
+ //Remark = item.Remark,
+ //TrackTimeZone = item.TrackTimeZone,
+ TrackTime = ToUnixTimestamp(item.TrackTime),
+ TrackPlace = item.TrackPlace,
+ EnContent = item.TrackEnContent,
+ Content = item.TrackContent,
+ TrackCode = item.TrackCode
+ });
+ }
+
+ //如果轨迹状态没完结则追加最后一个默认节点
+ if (!isCompleted)
+ {
+ res.Data.Add(new GetDetailTimelineOutput()
+ {
+ Content = "签收",
+ IsHighlight = false,
+ TrackTimeZone = $"GMT{(order.DestinationTimeZone >= 0 ? "+" : "-")}{order.DestinationTimeZone}",
+ TrackTime = ToUnixTimestamp(order.EstimatedDeliveryDate),
+ TrackTimePrefix = "预计签收时间:",
+ });
+ }
+
+ return res;
+ }
+
+ public static long ToUnixTimestamp(DateTime time)
+ {
+ //var sTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ var sTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Utc, TimeZoneInfo.Local);
+ return (long) (time - sTime).TotalMilliseconds;
+ }
+
///
/// 根据轨迹id删除单条轨迹
///
diff --git a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs
index 9a24699e..492555ec 100644
--- a/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs
+++ b/src/SJZY.Track.Domain/Aggregates/OrderAggregate/OrderEntity.cs
@@ -172,6 +172,18 @@ public class OrderEntity : IFullAuditedBasicEntitys, IAggregateRoot
[SugarColumn(IsIgnore = true)] public List OrderPullStatus { get; set; }
+ ///
+ /// 目的地时区
+ ///
+ [SugarColumn(ColumnName = "DestinationTimeZone")]
+ public float DestinationTimeZone { get; set; }
+
+ ///
+ /// 预计到达时间
+ ///
+ [SugarColumn(ColumnName = "EstimatedDeliveryDate")]
+ public DateTime EstimatedDeliveryDate { get; set; }
+
public void ResetTrackInfo()
{
IsCompleted = false;
diff --git a/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/ITrackContentRepository.cs b/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/ITrackContentRepository.cs
index 000dbe3b..b321e87b 100644
--- a/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/ITrackContentRepository.cs
+++ b/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/ITrackContentRepository.cs
@@ -26,4 +26,6 @@ public interface ITrackContentRepository : IBasicRepository
Expression> whereExpression);
Task GetTemplateIsExist(int trackContentId);
+ Task GetByCodeAsync(int systemId, string code);
+ Task> GetListBySystemIdAsync(int systemId);
}
diff --git a/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/TrackContentEntity.cs b/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/TrackContentEntity.cs
index ee797ce1..d5b41963 100644
--- a/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/TrackContentEntity.cs
+++ b/src/SJZY.Track.Domain/Aggregates/TrackContentAggregate/TrackContentEntity.cs
@@ -36,6 +36,12 @@ public class TrackContentEntity : IFullAuditedBasicEntitys, IAggregateRoot
[SugarColumn(ColumnName = "SubSystemId")]
public int SubSystemId { get; set; }
+ ///
+ /// 子系统名称
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public string SubSystem { get; set; }
+
///
/// 轨迹标记id,多个逗号分隔
///
@@ -53,4 +59,28 @@ public class TrackContentEntity : IFullAuditedBasicEntitys, IAggregateRoot
///
[SugarColumn(ColumnName = "IsExternal")]
public bool IsExternal { get; set; }
+
+ ///
+ /// 是否可重复
+ ///
+ [SugarColumn(ColumnName = "IsRepeatable")]
+ public bool IsRepeatable { get; set; }
+
+ ///
+ /// 是否允许手动修改
+ ///
+ [SugarColumn(ColumnName = "IsAllowManuallyUpdate")]
+ public bool IsAllowManuallyUpdate { get; set; }
+
+ ///
+ /// 是否允许手动创建
+ ///
+ [SugarColumn(ColumnName = "IsAllowManuallyCreate")]
+ public bool IsAllowManuallyCreate { get; set; }
+
+ ///
+ /// 是否同步轨迹订单上的预计到达时间
+ ///
+ [SugarColumn(ColumnName = "IsChangeOrderEdd")]
+ public bool IsChangeOrderEdd { get; set; }
}
diff --git a/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs b/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs
index c1399c6a..a4fe71cd 100644
--- a/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs
+++ b/src/SJZY.Track.Repository/Repositories/TrackContentRepository.cs
@@ -113,7 +113,6 @@ public class TrackContentRepository : BasicRepository, ITrac
return false;
}
-
public async Task> GetMapPageAsync(
GetTrackContentMapPageInputVO input)
{
@@ -220,4 +219,27 @@ public class TrackContentRepository : BasicRepository, ITrac
return await Context.Updateable().SetColumns(columns).Where(whereExpression)
.ExecuteCommandAsync() > 0;
}
+
+ public Task GetByCodeAsync(int systemId, string code)
+ {
+ return Context.Queryable().FirstAsync(m => m.SubSystemId == systemId && m.Code == code);
+ }
+
+ public Task> GetListBySystemIdAsync(int systemId)
+ {
+ return Context.Queryable()
+ .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();
+ }
}