Merge branch 'S06' into test
This commit is contained in:
commit
e918839b85
@ -14,7 +14,7 @@ public partial class TrackService
|
|||||||
private readonly ITrackTemplateRepository _trackTemplateRepository;
|
private readonly ITrackTemplateRepository _trackTemplateRepository;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询轨迹
|
/// 查询轨迹(时区补正)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@ -90,12 +90,17 @@ public partial class TrackService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
var sortedList = await TracksOrdered(res, input);
|
var sortedList = await TracksOrdered(res, input, input.SortMethod, input.TrackTemplateCode);
|
||||||
|
|
||||||
return new UnifyResultDto<List<GetTrackOutput>>(true, sortedList, "操作成功");
|
return new UnifyResultDto<List<GetTrackOutput>>(true, sortedList, "操作成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询轨迹(原样返回)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[HttpPost("Track/QueryV2")]
|
[HttpPost("Track/QueryV2")]
|
||||||
public async Task<UnifyResultDto<List<GetTrackOutput>>> QueryV2Async(GetTrackInputV2 input)
|
public async Task<UnifyResultDto<List<GetTrackOutput>>> QueryV2Async(GetTrackInputV2 input)
|
||||||
{
|
{
|
||||||
@ -163,15 +168,15 @@ public partial class TrackService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
var sortedList = await TracksOrdered(res, input);
|
var sortedList = await TracksOrdered(res, input, input.SortMethod);
|
||||||
|
|
||||||
return new UnifyResultDto<List<GetTrackOutput>>(true, sortedList, "操作成功");
|
return new UnifyResultDto<List<GetTrackOutput>>(true, sortedList, "操作成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<List<GetTrackOutput>> TracksOrdered(List<GetTrackOutput> list, GetTrackInput input)
|
private async Task<List<GetTrackOutput>> TracksOrdered(List<GetTrackOutput> list, OrderNosInfo orderNosInfo, SortMethod? sortMethod, string? trackTemplateCode = null)
|
||||||
{
|
{
|
||||||
switch (input.SortMethod)
|
switch (sortMethod)
|
||||||
{
|
{
|
||||||
case SortMethod.ByTrackTime:
|
case SortMethod.ByTrackTime:
|
||||||
case SortMethod.ByTemplateAndTrackTime:
|
case SortMethod.ByTemplateAndTrackTime:
|
||||||
@ -184,11 +189,11 @@ public partial class TrackService
|
|||||||
list.ForEach(item => item.TrackDetails.Sort((a, b) => b.Time.CompareTo(a.Time)));
|
list.ForEach(item => item.TrackDetails.Sort((a, b) => b.Time.CompareTo(a.Time)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(input.SortMethod), input.SortMethod, "不支持的排序方式");
|
throw new ArgumentOutOfRangeException(nameof(sortMethod), sortMethod, "不支持的排序方式");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.SortMethod != SortMethod.ByTemplateAndTrackTime
|
if (sortMethod != SortMethod.ByTemplateAndTrackTime
|
||||||
&& input.SortMethod != SortMethod.ByTemplateAndTrackTimeDesc)
|
&& sortMethod != SortMethod.ByTemplateAndTrackTimeDesc)
|
||||||
{
|
{
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -196,134 +201,178 @@ public partial class TrackService
|
|||||||
//查出订单模板
|
//查出订单模板
|
||||||
var templates = await _trackTemplateRepository.GetTrackTemplateListAsync(new GetTrackTemplateListInputVo
|
var templates = await _trackTemplateRepository.GetTrackTemplateListAsync(new GetTrackTemplateListInputVo
|
||||||
{
|
{
|
||||||
SubSystemId = input.SubSystemId,
|
SubSystemId = orderNosInfo.SubSystemId,
|
||||||
TemplateCode = input.TrackTemplateCode
|
TemplateCode = trackTemplateCode
|
||||||
});
|
});
|
||||||
|
|
||||||
if (templates.Count == 0)
|
if (templates.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("轨迹模板不存在");
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//查出订单和模板的关系,构建订单号和模板code的关系
|
||||||
|
var orderNoTemplateDict = (await _orderRepository
|
||||||
|
.GetOrderTemplateAsync(orderNosInfo.SubSystemId, orderNosInfo.OrderType, orderNosInfo.OrderNos))
|
||||||
|
.ToDictionary(x => x.OrderNo, x => x.TemplateCodes?.Split(",").ToHashSet());
|
||||||
|
|
||||||
|
//查询出订单和模板的关联关系,保证该订单使用自己的模板排序
|
||||||
foreach (var getTrackOutput in list)
|
foreach (var getTrackOutput in list)
|
||||||
{
|
{
|
||||||
getTrackOutput.TrackDetails = SortByTemplate(getTrackOutput.TrackDetails, templates, input.SortMethod.Value);
|
//查看该订单具有的模板
|
||||||
|
var curOrderNoTemplateCodes = orderNoTemplateDict[getTrackOutput.OrderNo];
|
||||||
|
if (curOrderNoTemplateCodes == null || curOrderNoTemplateCodes.Count == 0) continue;
|
||||||
|
|
||||||
|
//选出这个订单号所具有的模板
|
||||||
|
var tipTemplates = templates.Where(x => curOrderNoTemplateCodes.Contains(x.TemplateCode)).ToList();
|
||||||
|
if (tipTemplates.Count == 0) continue;
|
||||||
|
|
||||||
|
getTrackOutput.TrackDetails = SortByTemplatesAsync(getTrackOutput.TrackDetails, tipTemplates, sortMethod == SortMethod.ByTemplateAndTrackTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<List<GetTrackOutput>> TracksOrdered(List<GetTrackOutput> list, GetTrackInputV2 input)
|
/// <summary>
|
||||||
|
/// 轨迹发生时间(统一utc)排序,相同时间按模板排序,考虑多个模板的情况
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static List<TrackDetail> SortByTemplatesAsync(List<TrackDetail> seq, List<TrackTemplateOutputVo> templates, bool isAsc = true)
|
||||||
{
|
{
|
||||||
switch (input.SortMethod)
|
//转化为统一时间
|
||||||
|
var trackWraps = seq.Select(x => new TrackWrap(x));
|
||||||
|
var sortedTracks = (isAsc
|
||||||
|
? trackWraps.OrderBy(x => x.Time)
|
||||||
|
: trackWraps.OrderByDescending(x => x.Time)).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
//用于统计时间相同的轨迹
|
||||||
|
var timeEqTrackDict = new Dictionary<DateTime, List<TrackIdxWarp>>();
|
||||||
|
for (var i = 0; i < sortedTracks.Count; i++)
|
||||||
{
|
{
|
||||||
case SortMethod.ByTrackTime:
|
var trackWrap = sortedTracks[i];
|
||||||
case SortMethod.ByTemplateAndTrackTime:
|
if (timeEqTrackDict.TryGetValue(trackWrap.Time, out var list))
|
||||||
// tips:quick-sort 直接修改原list
|
list.Add(new TrackIdxWarp(trackWrap.Track, i));
|
||||||
list.ForEach(item => item.TrackDetails.Sort((a, b) => a.Time.CompareTo(b.Time)));
|
else
|
||||||
break;
|
timeEqTrackDict.Add(trackWrap.Time, new List<TrackIdxWarp>
|
||||||
case null:
|
|
||||||
case SortMethod.ByTrackTimeDesc:
|
|
||||||
case SortMethod.ByTemplateAndTrackTimeDesc:
|
|
||||||
list.ForEach(item => item.TrackDetails.Sort((a, b) => b.Time.CompareTo(a.Time)));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(input.SortMethod), input.SortMethod, "不支持的排序方式");
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
//按模板排序
|
|
||||||
private static List<TrackDetail> SortByTemplate(List<TrackDetail> tracks, List<TrackTemplateOutputVo> templates, SortMethod sortMethod)
|
|
||||||
{
|
|
||||||
if (templates.Count == 0 ||
|
|
||||||
tracks.Count == 0)
|
|
||||||
{
|
|
||||||
return new List<TrackDetail>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var isAsc = sortMethod == SortMethod.ByTemplateAndTrackTime;
|
|
||||||
|
|
||||||
var allTemplateCodes = new HashSet<string>();
|
|
||||||
|
|
||||||
foreach (var template in templates)
|
|
||||||
{
|
|
||||||
tracks = Sort(tracks, template, isAsc, allTemplateCodes);
|
|
||||||
}
|
|
||||||
// tracks = templates.Aggregate(tracks,
|
|
||||||
// (current, template) => Sort(current, template, isAsc, allTemplateCodes));
|
|
||||||
|
|
||||||
return tracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<TrackDetail> Sort(List<TrackDetail> seq, TrackTemplateOutputVo template, bool isAsc = true, HashSet<string>? allTemplateCodes = null)
|
|
||||||
{
|
|
||||||
if (template.TemplateContents.Count == 0)
|
|
||||||
{
|
|
||||||
return seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建一个字典,用于存储排序序列中元素的索引
|
|
||||||
var sortDict = new Dictionary<TrackDetail, int>();
|
|
||||||
template.TemplateContents.Sort((x, y) => x.Sort.CompareTo(y.Sort));
|
|
||||||
var sortSeq = template.TemplateContents
|
|
||||||
.Select(x => seq.FirstOrDefault(y => y.Code == x.Code))
|
|
||||||
.Where(x => x != null)
|
|
||||||
.ToList();
|
|
||||||
for (var i = 0; i < sortSeq.Count; i++)
|
|
||||||
{
|
|
||||||
sortDict[sortSeq[i]!] = isAsc ? i : sortSeq.Count - i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将模板code添加到上下文集合中
|
|
||||||
if (allTemplateCodes != null)
|
|
||||||
{
|
|
||||||
allTemplateCodes.UnionWith(template.TemplateContents.Select(x => x.Code));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据排序序列和字典中的索引对序列进行排序
|
|
||||||
// 使用稳定排序算法,如OrderBy,它保持相等元素的相对顺序
|
|
||||||
var sorted = seq.OrderBy(item => sortDict.GetValueOrDefault(item, int.MaxValue)).ToList();
|
|
||||||
|
|
||||||
// 存在
|
|
||||||
if (allTemplateCodes != null)
|
|
||||||
{
|
|
||||||
//查询到没有命中到模板的轨迹
|
|
||||||
var noTipTemplateTracks = sorted.Where(x => !allTemplateCodes.Contains(x.Code)).ToList();
|
|
||||||
|
|
||||||
//查询未命中轨迹的索引字典
|
|
||||||
var trackIdxDict = new Dictionary<TrackDetail, int>();
|
|
||||||
var trackSortDict = new SortedDictionary<int, TrackDetail>();
|
|
||||||
foreach (var track in noTipTemplateTracks)
|
|
||||||
{
|
|
||||||
trackIdxDict[track] = sorted.IndexOf(track);
|
|
||||||
trackSortDict[trackIdxDict[track]] = track;
|
|
||||||
}
|
|
||||||
|
|
||||||
//没有命中的轨迹排序
|
|
||||||
var noTipTemplateTrackSorted = (isAsc
|
|
||||||
? noTipTemplateTracks.OrderBy(x => x.Time)
|
|
||||||
: noTipTemplateTracks.OrderByDescending(x => x.Time))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
for (var i = 0; i < trackSortDict.Count; i++)
|
|
||||||
{
|
|
||||||
//在序列中的实际位置
|
|
||||||
var (idx, st) = trackSortDict.ElementAt(0);
|
|
||||||
//在这个位置它应该是哪个轨迹
|
|
||||||
var track = noTipTemplateTrackSorted[0];
|
|
||||||
//交换位置
|
|
||||||
if (track != st)
|
|
||||||
{
|
{
|
||||||
var idx2 = trackIdxDict[track];
|
new TrackIdxWarp(trackWrap.Track, i)
|
||||||
sorted[idx2] = st;
|
});
|
||||||
sorted[idx] = track;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//选出需要按模板重排序的轨迹
|
||||||
|
var timeEqTracks = timeEqTrackDict
|
||||||
|
.Where(kv => kv.Value.Count > 1)
|
||||||
|
.ToDictionary(kv => kv.Key, kv => kv.Value);
|
||||||
|
|
||||||
|
//初始化为最后一个模板排序
|
||||||
|
var preSortDict = templates[templates.Count - 1]
|
||||||
|
.TemplateContents
|
||||||
|
.OrderBy(x => x.Sort)
|
||||||
|
.ToDictionary(x => x.Code, x => x.Sort);
|
||||||
|
|
||||||
|
for (var i = templates.Count - 2; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var curCodeSortDict = templates[i]
|
||||||
|
.TemplateContents
|
||||||
|
.ToDictionary(x => x.Code, y => y.Sort);
|
||||||
|
|
||||||
|
//没在之前模板出现的code
|
||||||
|
var noTipPreCodeSortDict = curCodeSortDict
|
||||||
|
.Where(x => !preSortDict.ContainsKey(x.Key))
|
||||||
|
.ToDictionary(x => x.Key, y => y.Value);
|
||||||
|
|
||||||
|
//插入未命中的模板code
|
||||||
|
foreach (var (noTipCode, curNoTipCodeSort) in noTipPreCodeSortDict)
|
||||||
|
{
|
||||||
|
//初始化插入位置
|
||||||
|
var insertPos = -1;
|
||||||
|
foreach (var (preCode, _) in preSortDict)
|
||||||
|
{
|
||||||
|
if (curCodeSortDict.TryGetValue(preCode, out var preCodeSort))
|
||||||
|
{
|
||||||
|
//未命中的相对于之前模板的偏后,设置插入位置在
|
||||||
|
if (preCodeSort < curNoTipCodeSort)
|
||||||
|
{
|
||||||
|
insertPos = preSortDict[preCode] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//结束了还没选好位置,未命中的code相对于之前的模板code在当前模板最前面
|
||||||
|
if (insertPos == -1)
|
||||||
|
{
|
||||||
|
foreach (var (c, s) in preSortDict)
|
||||||
|
preSortDict[c] = s + 1;
|
||||||
|
preSortDict[noTipCode] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var (c, s) in preSortDict.Where(x => x.Value >= insertPos))
|
||||||
|
preSortDict[c] = s + 1;
|
||||||
|
preSortDict[noTipCode] = insertPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sorted;
|
|
||||||
|
foreach (var trackIdxWarps in timeEqTracks.Values)
|
||||||
|
{
|
||||||
|
var curIndex = trackIdxWarps.Min(x => x.Index);
|
||||||
|
//按模板从小到大排序
|
||||||
|
var sortByTemplate = (isAsc
|
||||||
|
? trackIdxWarps
|
||||||
|
.OrderBy(x => preSortDict.GetValueOrDefault(x.Track.Code, int.MaxValue))
|
||||||
|
: trackIdxWarps
|
||||||
|
.OrderByDescending(x => preSortDict.GetValueOrDefault(x.Track.Code, int.MaxValue))
|
||||||
|
).ToList();
|
||||||
|
for (var j = 0; j < sortByTemplate.Count; j++)
|
||||||
|
{
|
||||||
|
var track = sortByTemplate[j];
|
||||||
|
//当前索引不对应
|
||||||
|
if (track.Index != curIndex + j)
|
||||||
|
{
|
||||||
|
var temp1 = sortedTracks[track.Index].Track;
|
||||||
|
var temp2 = sortedTracks[curIndex + j].Track;
|
||||||
|
sortedTracks[track.Index].Track = temp2;
|
||||||
|
sortedTracks[curIndex + j].Track = temp1;
|
||||||
|
trackIdxWarps.First(x => x.Index == curIndex + j).Index = track.Index;
|
||||||
|
track.Index = curIndex + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedTracks.Select(x => x.Track).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class TrackIdxWarp
|
||||||
|
{
|
||||||
|
public TrackDetail Track { get; set; }
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public TrackIdxWarp(TrackDetail track, int index)
|
||||||
|
{
|
||||||
|
Track = track;
|
||||||
|
Index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class TrackWrap
|
||||||
|
{
|
||||||
|
public TrackDetail Track { get; set; }
|
||||||
|
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
|
||||||
|
public TrackWrap(TrackDetail track)
|
||||||
|
{
|
||||||
|
Track = track;
|
||||||
|
var timeZone = track.TimeZone ?? GlobalConst.NoneTrackTimeZone;
|
||||||
|
Time = Math.Abs(timeZone - GlobalConst.NoneTrackTimeZone) < 1
|
||||||
|
? track.Time
|
||||||
|
: track.Time.Subtract(TimeSpan.FromHours(timeZone));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
IHttpClientProxy<IUserBaseInfoService> requestCurrentUserService, ITrackTemplateRepository trackTemplateRepository)
|
IHttpClientProxy<IUserBaseInfoService> requestCurrentUserService, ITrackTemplateRepository trackTemplateRepository)
|
||||||
{
|
{
|
||||||
_orderRepository = orderRepository;
|
_orderRepository = orderRepository;
|
||||||
|
this._orderRepository = orderRepository;
|
||||||
_capPublisher = capPublisher;
|
_capPublisher = capPublisher;
|
||||||
_trackContentRepository = trackContentRepository;
|
_trackContentRepository = trackContentRepository;
|
||||||
_requestCurrentUserService = requestCurrentUserService;
|
_requestCurrentUserService = requestCurrentUserService;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public interface IOrderRepository : IBasicRepository<OrderEntity>
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input);
|
Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通过三方平台和三方单号查询订单
|
/// 通过三方平台和三方单号查询订单
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceProvidrCode">三方平台</param>
|
/// <param name="serviceProvidrCode">三方平台</param>
|
||||||
@ -62,6 +62,27 @@ public interface IOrderRepository : IBasicRepository<OrderEntity>
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<(string code, int id)>> GetSubSystemListByCodesAsync(List<string> codes);
|
Task<List<(string code, int id)>> GetSubSystemListByCodesAsync(List<string> codes);
|
||||||
|
|
||||||
|
#region 订单模板
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据订单id,获取订单所属的模板
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="orderId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<OrderTemplateVO>> GetOrderTemplateAsync(int[] orderId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据子系统+订单号+类型,获取订单所属的模板
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subSystemId"></param>
|
||||||
|
/// <param name="orderType"></param>
|
||||||
|
/// <param name="orderNos"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<OrderTemplateVO>> GetOrderTemplateAsync(int subSystemId,int orderType,List<string> orderNos);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region 订单关联
|
#region 订单关联
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -45,6 +45,8 @@ public interface ITrackTemplateRepository : IBasicRepository<TrackTemplateEntity
|
|||||||
Expression<Func<TrackTemplateContentEntity, bool>> whereExpression);
|
Expression<Func<TrackTemplateContentEntity, bool>> whereExpression);
|
||||||
|
|
||||||
Task<List<TrackTemplateOutputVo>> GetTrackTemplateListAsync(GetTrackTemplateListInputVo input);
|
Task<List<TrackTemplateOutputVo>> GetTrackTemplateListAsync(GetTrackTemplateListInputVo input);
|
||||||
|
|
||||||
Task<UnifyPageResultDto<TemplateContentDtoVo>> GetPageTrackTemplateListAsync(GetPageTrackTemplateListInputVo input);
|
Task<UnifyPageResultDto<TemplateContentDtoVo>> GetPageTrackTemplateListAsync(GetPageTrackTemplateListInputVo input);
|
||||||
|
|
||||||
Task<List<string>> GetContentByTemplateCodes(string[] codes, int systemId);
|
Task<List<string>> GetContentByTemplateCodes(string[] codes, int systemId);
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/SJZY.Track.Domain/Dtos/Order/OrderTemplateVO.cs
Normal file
13
src/SJZY.Track.Domain/Dtos/Order/OrderTemplateVO.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace SJZY.Track.Domain.Dtos.Order;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订单关联的模板模型
|
||||||
|
/// </summary>
|
||||||
|
public class OrderTemplateVO
|
||||||
|
{
|
||||||
|
public int OrderId { get; set; }
|
||||||
|
|
||||||
|
public string OrderNo { get; set; }
|
||||||
|
|
||||||
|
public string? TemplateCodes { get; set; }
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using SJZY.Expand.ABP.Core.Logger;
|
using SJZY.Expand.ABP.Core.Logger;
|
||||||
using SJZY.Track.Domain;
|
using SJZY.Track.Domain;
|
||||||
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
@ -10,56 +11,64 @@ namespace SJZY.Track.Repository.Repositories;
|
|||||||
|
|
||||||
public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, ITransientDependency
|
public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, ITransientDependency
|
||||||
{
|
{
|
||||||
public async Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input)
|
//MemoryCache本身线程安全简单使用,短暂数据不一致可以容忍,每过固定时间强制清除缓存
|
||||||
|
private static readonly MemoryCache _memoryCache = new(new MemoryCacheOptions());
|
||||||
|
private static readonly Dictionary<int, string> _empty = new();
|
||||||
|
private static readonly Dictionary<string, Dictionary<int, string>> _empty2 = new();
|
||||||
|
private const int ThirdPartyOrderNumberCacheTimeSpan = 3 * 60;
|
||||||
|
private const int MainDataEnumCacheTimeSpan = 5 * 60;
|
||||||
|
|
||||||
|
private async Task<Dictionary<int, string>> GetThirdPartyOrderNumberForCacheAsync(int[] orderIds)
|
||||||
{
|
{
|
||||||
//查询完去重
|
const string key = "ThirdPartyOrderNumber";
|
||||||
var pageList = await Context.Queryable<OrderEntity>()
|
if (orderIds.Length == 0) return _empty;
|
||||||
|
|
||||||
|
var dict = _memoryCache.Get<Dictionary<int, string>>(key);
|
||||||
|
|
||||||
|
orderIds = orderIds.Distinct().ToArray();
|
||||||
|
if (dict != null && dict.Count != 0 && !orderIds.Except(dict.Keys).Any()) return dict;
|
||||||
|
|
||||||
|
var orders = await Context.Queryable<OrderEntity>()
|
||||||
.Includes(a => a.OrderPlatformNumbers)
|
.Includes(a => a.OrderPlatformNumbers)
|
||||||
.LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false)
|
.LeftJoin<OrderPlatformNumberEntity>((a, b) => a.Id == b.OrderId && b.IsDeleted == false)
|
||||||
.LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false)
|
.Where((a, b) => orderIds.Contains(a.Id))
|
||||||
.LeftJoin<OrderPlatformNumberEntity>((a, b, c, d) => a.Id == d.OrderId && d.IsDeleted == false)
|
.Select(a => new OrderEntity()
|
||||||
.WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId)
|
|
||||||
.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),
|
|
||||||
(a, b, c) => a.CreateTime >= input.CreateTimeStart)
|
|
||||||
.WhereIF((!input.CreateTimeStart.HasValue) && input.CreateTimeEnd.HasValue,
|
|
||||||
(a, b, c) => a.CreateTime <= input.CreateTimeEnd)
|
|
||||||
.WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId)
|
|
||||||
.WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType)
|
|
||||||
.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,
|
Id = a.Id,
|
||||||
OrderNumber = a.OrderNo,
|
OrderPlatformNumbers = a.OrderPlatformNumbers
|
||||||
OrderType = a.OrderType,
|
|
||||||
QuestionType = a.QuestionType,
|
|
||||||
CustomerShortName = b.Abbreviation,
|
|
||||||
CustomerCode = b.Code,
|
|
||||||
CustomerId = a.CustomId,
|
|
||||||
NewestTrackContent = a.LatestTrackContent,
|
|
||||||
NewestTrackEnContent = a.LatestTrackEnContent,
|
|
||||||
NewestTrackPlace = a.LatestTrackPlace,
|
|
||||||
NewestTrackTime = a.LatestTrackTime,
|
|
||||||
IsFinish = a.IsCompleted,
|
|
||||||
CreateTime = a.CreateTime,
|
|
||||||
SubSystem = c.CnName,
|
|
||||||
SubSystemId = c.Id,
|
|
||||||
DestinationTimeZone = a.DestinationTimeZone,
|
|
||||||
EstimatedDeliveryDate = a.EstimatedDeliveryDate,
|
|
||||||
ThirdPartyOrderNumber = BuildThirdPartyOrderNumber(a.OrderPlatformNumbers)
|
|
||||||
})
|
})
|
||||||
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (orders.Count == 0)
|
||||||
|
return _empty;
|
||||||
|
|
||||||
|
orders = orders.DistinctBy(x => x.Id).ToList();
|
||||||
|
|
||||||
|
dict = orders.ToDictionary(x => x.Id, x => BuildThirdPartyOrderNumber(x.OrderPlatformNumbers));
|
||||||
|
|
||||||
|
_memoryCache.Set(key, dict, new MemoryCacheEntryOptions
|
||||||
|
{
|
||||||
|
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(ThirdPartyOrderNumberCacheTimeSpan),
|
||||||
|
Size = dict.Count
|
||||||
|
});
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Dictionary<string, Dictionary<int, string>>> GetMainDataEnumForCacheAsync(List<int> orderTypes, List<int> questTypes)
|
||||||
|
{
|
||||||
|
const string key = "EnumForMainData";
|
||||||
|
if (orderTypes.Count == 0 && questTypes.Count == 0) return _empty2;
|
||||||
|
|
||||||
|
var dict = _memoryCache.Get<Dictionary<string, Dictionary<int, string>>>(key);
|
||||||
|
if (dict != null && dict.Count != 0
|
||||||
|
&& !orderTypes.Except(dict[GlobalConst.MainDataKey_OrderType].Keys).Any()
|
||||||
|
&& !questTypes.Except(dict[GlobalConst.MainDataKey_TrackQuestionType].Keys).Any())
|
||||||
|
{
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
//查询订单类型描述
|
|
||||||
var orderTypes = pageList.List.Select(x => x.OrderType).Distinct().ToList();
|
|
||||||
var questTypes = pageList.List.Select(x => x.QuestionType).Distinct().ToList();
|
|
||||||
//从主数据中心查询类型描述
|
//从主数据中心查询类型描述
|
||||||
var typeDispDict = (await Context.Queryable<VEnumValueInfoEntity>()
|
dict = (await Context.Queryable<VEnumValueInfoEntity>()
|
||||||
.Where(x =>
|
.Where(x =>
|
||||||
(x.Property == GlobalConst.MainDataKey_OrderType && orderTypes.Contains(x.Enumkey))
|
(x.Property == GlobalConst.MainDataKey_OrderType && orderTypes.Contains(x.Enumkey))
|
||||||
|| (x.Property == GlobalConst.MainDataKey_TrackQuestionType && questTypes.Contains(x.Enumkey))
|
|| (x.Property == GlobalConst.MainDataKey_TrackQuestionType && questTypes.Contains(x.Enumkey))
|
||||||
@ -78,20 +87,161 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
|
|||||||
y => y.ToDictionary(x => x.Enumkey, x => x.Disp)
|
y => y.ToDictionary(x => x.Enumkey, x => x.Disp)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (dict.Count == 0)
|
||||||
|
return _empty2;
|
||||||
|
|
||||||
|
_memoryCache.Set(key, dict, new MemoryCacheEntryOptions
|
||||||
|
{
|
||||||
|
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(MainDataEnumCacheTimeSpan),
|
||||||
|
Size = dict.Count
|
||||||
|
});
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<UnifyPageResultDto<TrackOrderVO>> GetTrackOrderPagedList(GetPageTrackOrderInputVO input)
|
||||||
|
{
|
||||||
|
//查询完去重
|
||||||
|
UnifyPageResultDto<TrackOrderVO> pageList;
|
||||||
|
//没传递单号时
|
||||||
|
if (input.OrderNos.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
pageList = await Context.Queryable<OrderEntity>()
|
||||||
|
.LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false)
|
||||||
|
.LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false)
|
||||||
|
.WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId)
|
||||||
|
.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),
|
||||||
|
(a, b, c) => a.CreateTime >= input.CreateTimeStart)
|
||||||
|
.WhereIF((!input.CreateTimeStart.HasValue) && input.CreateTimeEnd.HasValue,
|
||||||
|
(a, b, c) => a.CreateTime <= input.CreateTimeEnd)
|
||||||
|
.WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId)
|
||||||
|
.WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType)
|
||||||
|
.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)
|
||||||
|
.Select((a, b, c) => new TrackOrderVO
|
||||||
|
{
|
||||||
|
Id = a.Id,
|
||||||
|
OrderNumber = a.OrderNo,
|
||||||
|
OrderType = a.OrderType,
|
||||||
|
QuestionType = a.QuestionType,
|
||||||
|
CustomerShortName = b.Abbreviation,
|
||||||
|
CustomerCode = b.Code,
|
||||||
|
CustomerId = a.CustomId,
|
||||||
|
NewestTrackContent = a.LatestTrackContent,
|
||||||
|
NewestTrackEnContent = a.LatestTrackEnContent,
|
||||||
|
NewestTrackPlace = a.LatestTrackPlace,
|
||||||
|
NewestTrackTime = a.LatestTrackTime,
|
||||||
|
IsFinish = a.IsCompleted,
|
||||||
|
CreateTime = a.CreateTime,
|
||||||
|
SubSystem = c.CnName,
|
||||||
|
SubSystemId = c.Id,
|
||||||
|
DestinationTimeZone = a.DestinationTimeZone,
|
||||||
|
EstimatedDeliveryDate = a.EstimatedDeliveryDate
|
||||||
|
})
|
||||||
|
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||||||
|
}
|
||||||
|
//传递单号时
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var orderNos = input.OrderNos!.Distinct().ToList();
|
||||||
|
|
||||||
|
//匹配主单
|
||||||
|
var orderIds = await Context.Queryable<OrderEntity>()
|
||||||
|
.Where(x => orderNos.Contains(x.OrderNo))
|
||||||
|
.Select(x => x.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
//匹配外部单
|
||||||
|
var orderIdsForThirdParty = await Context.Queryable<OrderPlatformNumberEntity>()
|
||||||
|
.Where(x => !string.IsNullOrWhiteSpace(x.OrderNumber) && orderNos.Contains(x.OrderNumber))
|
||||||
|
.Select(x => x.OrderId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var orderHashset = orderIds.ToHashSet();
|
||||||
|
orderHashset.UnionWith(orderIdsForThirdParty);
|
||||||
|
orderIds = orderHashset.ToList();
|
||||||
|
|
||||||
|
//没有任何单
|
||||||
|
if (orderIds.Count == 0)
|
||||||
|
{
|
||||||
|
return new UnifyPageResultDto<TrackOrderVO>
|
||||||
|
{
|
||||||
|
List = new List<TrackOrderVO>(),
|
||||||
|
Pagination = new PageInfoOutput()
|
||||||
|
{
|
||||||
|
PageIndex = input.PageIndex,
|
||||||
|
PageSize = input.PageSize,
|
||||||
|
Total = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pageList = await Context.Queryable<OrderEntity>()
|
||||||
|
.Where(x => orderIds.Contains(x.Id))
|
||||||
|
.LeftJoin<VExternalSubjectEntity>((a, b) => a.CustomId == b.Id && b.IsDeleted == false)
|
||||||
|
.LeftJoin<VSystemEntity>((a, b, c) => a.SubSystemId == c.Id && c.IsDeleted == false)
|
||||||
|
.WhereIF(input.SubSystemId > 0, (a, b, c) => a.SubSystemId == input.SubSystemId)
|
||||||
|
.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),
|
||||||
|
(a, b, c) => a.CreateTime >= input.CreateTimeStart)
|
||||||
|
.WhereIF((!input.CreateTimeStart.HasValue) && input.CreateTimeEnd.HasValue,
|
||||||
|
(a, b, c) => a.CreateTime <= input.CreateTimeEnd)
|
||||||
|
.WhereIF(input.CustomerId > 0, (a, b, c) => a.CustomId == input.CustomerId)
|
||||||
|
.WhereIF(input.TrackOrderType > 0, (a, b, c) => a.OrderType == input.TrackOrderType)
|
||||||
|
.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)
|
||||||
|
.Select((a, b, c) => new TrackOrderVO
|
||||||
|
{
|
||||||
|
Id = a.Id,
|
||||||
|
OrderNumber = a.OrderNo,
|
||||||
|
OrderType = a.OrderType,
|
||||||
|
QuestionType = a.QuestionType,
|
||||||
|
CustomerShortName = b.Abbreviation,
|
||||||
|
CustomerCode = b.Code,
|
||||||
|
CustomerId = a.CustomId,
|
||||||
|
NewestTrackContent = a.LatestTrackContent,
|
||||||
|
NewestTrackEnContent = a.LatestTrackEnContent,
|
||||||
|
NewestTrackPlace = a.LatestTrackPlace,
|
||||||
|
NewestTrackTime = a.LatestTrackTime,
|
||||||
|
IsFinish = a.IsCompleted,
|
||||||
|
CreateTime = a.CreateTime,
|
||||||
|
SubSystem = c.CnName,
|
||||||
|
SubSystemId = c.Id,
|
||||||
|
DestinationTimeZone = a.DestinationTimeZone,
|
||||||
|
EstimatedDeliveryDate = a.EstimatedDeliveryDate,
|
||||||
|
})
|
||||||
|
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//补三方单号,从缓存中加速查
|
||||||
|
var orderIdArr = pageList.List.Select(x => x.Id).ToArray();
|
||||||
|
var thirdPartyOrderNumbers = await GetThirdPartyOrderNumberForCacheAsync(orderIdArr);
|
||||||
|
pageList.List.ForEach(x => x.ThirdPartyOrderNumber = thirdPartyOrderNumbers[x.Id]);
|
||||||
|
|
||||||
|
//查询订单类型描述,从缓存中加速查
|
||||||
|
var orderTypes = pageList.List.Select(x => x.OrderType).Distinct().ToList();
|
||||||
|
var questTypes = pageList.List.Select(x => x.QuestionType).Distinct().ToList();
|
||||||
|
var typeDisplayDict = await GetMainDataEnumForCacheAsync(orderTypes, questTypes);
|
||||||
|
|
||||||
//填充数描述信息
|
//填充数描述信息
|
||||||
pageList.List.ForEach(x =>
|
pageList.List.ForEach(x =>
|
||||||
{
|
{
|
||||||
x.OrderTypeName = typeDispDict.TryGetValue(GlobalConst.MainDataKey_OrderType, out var orderTypeDisplayDict)
|
x.OrderTypeName = typeDisplayDict.TryGetValue(GlobalConst.MainDataKey_OrderType, out var orderTypeDisplayDict)
|
||||||
? orderTypeDisplayDict.TryGetValue(x.OrderType, out var orderTypeDisplay)
|
? orderTypeDisplayDict.TryGetValue(x.OrderType, out var orderTypeDisplay)
|
||||||
? orderTypeDisplay
|
? orderTypeDisplay
|
||||||
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] Enumkey:[{x.OrderType}]"
|
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] "
|
||||||
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}]";
|
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] EnumKey:[{x.OrderType}]";
|
||||||
|
|
||||||
x.QuestionTypeName = typeDispDict.TryGetValue(GlobalConst.MainDataKey_TrackQuestionType, out var questDisplayDict)
|
x.QuestionTypeName = typeDisplayDict.TryGetValue(GlobalConst.MainDataKey_TrackQuestionType, out var questDisplayDict)
|
||||||
? questDisplayDict.TryGetValue(x.QuestionType, out var questDisplay)
|
? questDisplayDict.TryGetValue(x.QuestionType, out var questDisplay)
|
||||||
? questDisplay
|
? questDisplay
|
||||||
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}] Enumkey:[{x.OrderType}]"
|
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_OrderType}]"
|
||||||
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_TrackQuestionType}]";
|
: $"未在主数据中心找到Property:[{GlobalConst.MainDataKey_TrackQuestionType}] EnumKey:[{x.OrderType}]";
|
||||||
});
|
});
|
||||||
|
|
||||||
return pageList;
|
return pageList;
|
||||||
@ -246,6 +396,32 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
|
|||||||
return res.Select(x => (x.Key, x.Id)).ToList();
|
return res.Select(x => (x.Key, x.Id)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<List<OrderTemplateVO>> GetOrderTemplateAsync(int[] orderId)
|
||||||
|
{
|
||||||
|
return Context.Queryable<OrderEntity>()
|
||||||
|
.Where(x => orderId.Contains(x.Id))
|
||||||
|
.Select(a => new OrderTemplateVO
|
||||||
|
{
|
||||||
|
OrderId = a.Id,
|
||||||
|
OrderNo = a.OrderNo,
|
||||||
|
TemplateCodes = a.TemplateCodes
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<List<OrderTemplateVO>> GetOrderTemplateAsync(int subSystemId, int orderType, List<string> orderNos)
|
||||||
|
{
|
||||||
|
return Context.Queryable<OrderEntity>()
|
||||||
|
.Where(x => orderNos.Contains(x.OrderNo) && x.SubSystemId == subSystemId && x.OrderType == orderType)
|
||||||
|
.Select(a => new OrderTemplateVO
|
||||||
|
{
|
||||||
|
OrderId = a.Id,
|
||||||
|
OrderNo = a.OrderNo,
|
||||||
|
TemplateCodes = a.TemplateCodes
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public Task<VSystemEntity> GetSystemInfoById(int id)
|
public Task<VSystemEntity> GetSystemInfoById(int id)
|
||||||
{
|
{
|
||||||
return Context.Queryable<VSystemEntity>().FirstAsync(m => m.IsDeleted == false && m.Id == id);
|
return Context.Queryable<VSystemEntity>().FirstAsync(m => m.IsDeleted == false && m.Id == id);
|
||||||
@ -275,10 +451,12 @@ public class OrderRepository : BasicRepository<OrderEntity>, IOrderRepository, I
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static string BuildThirdPartyOrderNumber(List<OrderPlatformNumberEntity> orderPlatformNumberEntities)
|
private static string BuildThirdPartyOrderNumber(List<OrderPlatformNumberEntity> orderPlatformNumberEntities)
|
||||||
{
|
{
|
||||||
|
if (orderPlatformNumberEntities.Count == 0) return GlobalConst.EmptyString;
|
||||||
const string separator = "、";
|
const string separator = "、";
|
||||||
var thirdPartyOrderNumbers = orderPlatformNumberEntities
|
var thirdPartyOrderNumbers = orderPlatformNumberEntities
|
||||||
.Where(x => !string.IsNullOrWhiteSpace(x.OrderNumber))
|
.Where(x => !string.IsNullOrWhiteSpace(x.OrderNumber))
|
||||||
.Select(x => $"{x.OrderNumber}({x.Platform})").ToList();
|
.Select(x => $"{x.OrderNumber}({x.Platform})")
|
||||||
|
.ToList();
|
||||||
return string.Join(separator, thirdPartyOrderNumbers);
|
return string.Join(separator, thirdPartyOrderNumbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user