This commit is contained in:
xiaolipro 2025-11-29 15:44:34 +08:00
parent 3add96f52f
commit 7b3f083b9b
10 changed files with 152 additions and 102 deletions

View File

@ -14,25 +14,25 @@ public class EditTrackPullPriorityInput
/// <summary>
/// 轨迹拉取配置id
/// </summary>
public int? TrackPullConfigId { get; set; }
public int TrackPullConfigId { get; set; }
/// <summary>
/// 客户
/// </summary>
public string? Customer { get; set; }
public string Customer { get; set; }
/// <summary>
/// 订单类型
/// </summary>
public TrackOrderType? OrderType { get; set; }
public TrackOrderType OrderType { get; set; }
/// <summary>
/// 优先级
/// </summary>
public string? Priority { get; set; }
public int Priority { get; set; }
/// <summary>
/// 服务商拉取频率(分钟)
/// </summary>
public int? PullInterval { get; set; }
public int PullInterval { get; set; }
}

View File

@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
using InterfaceForward.Domain.Shared.Helpers;
using Microsoft.AspNetCore.Components.Forms;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.TrackPullAggregate;
using TrackCenter.Repository.Aggregates.OrderAggregate;
@ -71,6 +72,65 @@ public class OrderServiceV2(
};
}
/// <summary>
/// 新增、更新大包(存在就更新)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("OrderV2/UpsertBigBag")]
public async Task<IdBaseDto> UpsertAsync(UpsertBigBagInput input)
{
// 校验订单是否已存在,存在则更新
var order = await orderRepository.GetFirstAsync(x =>
x.AppKey == input.ApiCode && x.OrderType == TrackOrderType.大包 && x.OrderNo == input.BagNo);
// 订单已存在则视为更新
if (order != null)
{
order = await BuiltOrder(input);
await orderRepository.UpdateOrderAsync(order);
var index = new OrderOperationRecordIndex
{
OrderId = order.Id,
OrderNo = input.BagNo,
OptionType = OrderOperationType.修改订单.ToString(),
Content = input.ToJson(),
CreateUserId = CurrentUserId,
CreateUserName = CurrentUser.UserName ?? string.Empty,
};
_ = orderOperationRecordEsRepository.AddAsync(index);
return new IdBaseDto
{
Id = order.Id
};
}
order = await BuiltOrder(input);
var orderId = await orderRepository.CreateOrderAsync(order);
// 写入操作日志
var indexForAdd = new OrderOperationRecordIndex
{
OrderId = orderId,
OrderNo = input.BagNo,
OptionType = nameof(OrderOperationType.创建订单),
Content = input.ToJson(),
CreateUserId = CurrentUserId,
CreateUserName = CurrentUser.UserName ?? string.Empty,
CreateTime = DateTime.Now
};
_ = orderOperationRecordEsRepository.AddAsync(indexForAdd);
return new IdBaseDto
{
Id = orderId
};
}
private async Task<OrderEntity> BuiltOrder(UpsertSmallBagInput input)
{
var order = new OrderEntity
@ -92,86 +152,42 @@ public class OrderServiceV2(
};
var config = await trackPullConfigRepository
.GetListAsync(x => x.AppKey == input.ApiCode
&& x.ServiceProviderCode == input.ApiCode && x.OrderType == TrackOrderType.小包);
.FirstOrDefaultAsync(x => x.AppKey == input.ApiCode
&& x.ServiceProviderCode == input.ApiCode);
order.OrderPullStatus = BuiltOrderPullStatus(config, order);
if (config == null) throw new BusinessException(message: "没有一个拉取配置可以适用,请配置,否则无法拉取轨迹");
order.OrderPullStatus = [CreateOrderPullStatus(config, order)];
return order;
}
private static List<OrderPullStatusEntity> BuiltOrderPullStatus(
List<TrackPullConfigEntity> configs,
OrderEntity order)
private Task<OrderEntity> BuiltOrder(UpsertBigBagInput input)
{
if (configs.IsNullOrEmpty()) return [];
TrackPullConfigEntity? selected = null;
var bestScore = -1;
foreach (var config in configs)
var order = new OrderEntity
{
if (!IsConfigApplicable(config, order))
{
continue;
}
AppKey = input.ApiCode,
ServiceProviderCode = input.ApiCode,
OrderType = TrackOrderType.大包,
OrderNo = input.BagNo,
ThirdPartyOrderNumber = input.OtherNo,
Customer = input.Client,
Channel = input.Channel,
ProductCode = input.Product,
ArrivalCountry = input.Country
};
var score = CalculateMatchScore(config, order);
if (score > bestScore)
{
bestScore = score;
selected = config;
}
}
// tips: 2025-11-29 zzh 大包没有轨迹拉取能力
if (selected == null) throw new BusinessException(message: "没有一个拉取配置可以适用,请配置,否则无法拉取轨迹");
// var config = await trackPullConfigRepository
// .FirstOrDefaultAsync(x => x.AppKey == input.ApiCode
// && x.ServiceProviderCode == input.ApiCode);
//
// if (config == null) throw new BusinessException(message: "没有一个拉取配置可以适用,请配置,否则无法拉取轨迹");
//
// order.OrderPullStatus = [CreateOrderPullStatus(config, order)];
return [CreateOrderPullStatus(selected, order)];
}
private static bool IsConfigApplicable(TrackPullConfigEntity config, OrderEntity order)
{
return IsFieldApplicable(order.Customer, config.Customer) &&
IsFieldApplicable(order.Channel, config.Channel) &&
IsFieldApplicable(order.ProductCode, config.Product);
}
private static bool IsFieldApplicable(string? orderValue, string? configValue)
{
if (string.IsNullOrWhiteSpace(configValue))
{
return true;
}
return string.Equals(configValue, orderValue, StringComparison.OrdinalIgnoreCase);
}
private static int CalculateMatchScore(TrackPullConfigEntity config, OrderEntity order)
{
var score = 0;
if (IsPreciseMatch(order.Customer, config.Customer))
{
score++;
}
if (IsPreciseMatch(order.Channel, config.Channel))
{
score++;
}
if (IsPreciseMatch(order.ProductCode, config.Product))
{
score++;
}
return score;
}
private static bool IsPreciseMatch(string? orderValue, string? configValue)
{
return !string.IsNullOrWhiteSpace(configValue) &&
string.Equals(configValue, orderValue, StringComparison.OrdinalIgnoreCase);
return Task.FromResult(order);
}
private static OrderPullStatusEntity CreateOrderPullStatus(TrackPullConfigEntity config, OrderEntity order)
@ -195,6 +211,11 @@ public class OrderServiceV2(
status.StartTime = DateTime.Now.AddHours(config.SilenceBeforeStart);
}
if (string.IsNullOrWhiteSpace(config.EndTrackCode))
{
status.EndTime = DateTime.Now.AddHours(config.SilenceBeforeStart).AddDays(7);
}
return status;
}
}
@ -273,3 +294,49 @@ public class Consignee
/// </summary>
public string Email { get; set; }
}
public class UpsertBigBagInput
{
/// <summary>
/// 客户名称,或者code,必填
/// </summary>
[Required]
public string Client { get; set; }
/// <summary>
/// 客户单号,必填
/// </summary>
[Required]
public string BagNo { get; set; }
/// <summary>
/// 其他单号
/// </summary>
public string OtherNo { get; set; }
/// <summary>
/// 渠道名称,或者code
/// </summary>
public string Channel { get; set; }
/// <summary>
/// 产品名称,或者code
/// </summary>
public string Product { get; set; }
/// <summary>
/// 产品名称,或者code
/// </summary>
public string Country { get; set; }
/// <summary>
/// 服务商code
/// </summary>
public string ApiCode { get; set; }
}
public class UpsertMsterOrderInput
{
}

View File

@ -88,8 +88,7 @@ public class TrackPullService(
{
Expression<Func<TrackPullConfigEntity, bool>> isAnyExp = x =>
x.AppKey == input.AppKey &&
x.ServiceProviderCode == input.ServiceProviderCode &&
x.OrderType == input.OrderType;
x.ServiceProviderCode == input.ServiceProviderCode;
if (input.Options == OptionTypeNoNull.修改) isAnyExp = isAnyExp.And(x => x.Id != input.Id);
if (await trackPullConfigRepository.IsAnyAsync(isAnyExp))
@ -317,6 +316,8 @@ public class TrackPullService(
if (await trackPullConfigRepository.IsPriorityAnyAsync(isPriorityAnyExp))
throw new BusinessException("配置已存在");
if (input.PullInterval < 60) input.PullInterval = 60;
}
switch (input.Options)
@ -345,8 +346,7 @@ public class TrackPullService(
case OptionTypeNoNull.删除:
{
var oldTrackPullPriorityEntity =
await trackPullConfigRepository.GetPriorityByIdAsync(input.Id!.Value) ??
_ = await trackPullConfigRepository.GetPriorityByIdAsync(input.Id!.Value) ??
throw new BusinessException(message: "找不到数据");
await trackPullConfigRepository.SoftDeletePriorityAsync(x => x.Id == input.Id);

View File

@ -221,6 +221,7 @@ public class OrderEntity : FullAuditedAggregateRoot<int, int>
[SugarColumn(IsIgnore = true)] public List<OrderFlightEntity> OrderFlights { get; set; } = [];
// tips:2025-11-29:sp挪到订单主表了,1v1拉取
[SugarColumn(IsIgnore = true)] public List<OrderPullStatusEntity> OrderPullStatus { get; set; } = [];
public void ResetTrackInfo()

View File

@ -8,12 +8,6 @@ namespace TrackCenter.Domain.Aggregates.TrackPullAggregate;
[SugarTable("t_track_pull_config")]
public class TrackPullConfigEntity : FullAuditedAggregateRoot<int, int>
{
/// <summary>
/// 自增主键
/// </summary>
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
/// <summary>
/// 应用
/// </summary>
@ -24,7 +18,7 @@ public class TrackPullConfigEntity : FullAuditedAggregateRoot<int, int>
/// 服务商代码
/// </summary>
[SugarColumn(ColumnName = "ServiceProviderCode")]
public string? ServiceProviderCode { get; set; }
public string ServiceProviderCode { get; set; }
/// <summary>
/// 解析方式,1取接口通返参映射后的,2取服务商原返参
@ -92,12 +86,6 @@ public class TrackPullConfigEntity : FullAuditedAggregateRoot<int, int>
[SugarColumn(ColumnName = "TrackTimeZoneName")]
public string? TrackTimeZoneName { get; set; }
/// <summary>
/// 订单类型
/// </summary>
[SugarColumn(ColumnName = "OrderType")]
public TrackOrderType OrderType { get; set; }
/// <summary>
/// 开始轨迹code
/// </summary>

View File

@ -30,7 +30,7 @@ public class TrackPullPriorityEntity: FullAuditedEntity<int, int>
/// 优先级
/// </summary>
[SugarColumn(ColumnName = "优先级")]
public string Priority { get; set; }
public int Priority { get; set; }
/// <summary>
/// 服务商拉取频率(分钟)

View File

@ -81,11 +81,6 @@ public class GetTrackPullConfigDetailOutputVO
/// </summary>
public string TrackDetailsPath { get; set; }
/// <summary>
/// 订单类型
/// </summary>
public TrackOrderType OrderType { get; set; }
/// <summary>
/// 开始轨迹code
/// </summary>

View File

@ -24,7 +24,7 @@ public class GetTrackPullPriorityDetailOutputVO
/// <summary>
/// 优先级
/// </summary>
public string Priority { get; set; }
public int Priority { get; set; }
/// <summary>
/// 服务商拉取频率(分钟)

View File

@ -19,13 +19,13 @@ public class GetTrackPullPriorityPageOutputVO
/// <summary>
/// 优先级
/// </summary>
public string Priority { get; set; }
public int Priority { get; set; }
/// <summary>
/// 服务商拉取频率(分钟)
/// </summary>
public int PullInterval { get; set; }
public DateTime CreateTime { get; set; }
public string? CreateUser { get; set; }

View File

@ -102,7 +102,6 @@ public class TrackPullConfigRepository : BasicRepository<TrackPullConfigEntity>,
TrackStatusName = trackPull.TrackStatusName,
OrderPath = trackPull.OrderPath,
TrackDetailsPath = trackPull.TrackDetailsPath,
OrderType = trackPull.OrderType,
StartTrackCode = trackPull.StartTrackCode,
EndTrackCode = trackPull.EndTrackCode,
SilenceBeforeStart = trackPull.SilenceBeforeStart,