@ -16,6 +16,7 @@ using Oms.Application.Storage;
using Oms.Domain.OrdersAggregate ;
using Oms.Domain.ChannelsAggregate.Consts ;
using Oms.Domain.ChannelsAggregate.Entities ;
using Oms.Domain.CustomersAggregate.Entities ;
using Oms.Domain.OrdersAggregate.Consts ;
using Oms.Domain.OrdersAggregate.Entities ;
using Oms.Domain.SystemAggregate.Entities ;
@ -296,6 +297,298 @@ public partial class OrderService
return outputs ;
}
/// <summary>
/// 列表页专用映射:不加载申报明细/费用明细,并行 enrichment, 减小 JSON 与 DB 开销。
/// </summary>
private async Task < List < OrderOutput > > MapOrderListOutputsAsync ( IReadOnlyCollection < Order > orders )
{
if ( orders . Count = = 0 )
{
return [ ] ;
}
var orderIds = orders . Select ( x = > x . Id ) . ToArray ( ) ;
var warehouseIds = orders . Where ( x = > x . WarehouseId . HasValue ) . Select ( x = > x . WarehouseId ! . Value ) . Distinct ( ) . ToArray ( ) ;
var productCodes = orders
. Where ( x = > ! string . IsNullOrWhiteSpace ( x . ProductCode ) )
. Select ( x = > x . ProductCode ! . Trim ( ) )
. Distinct ( StringComparer . OrdinalIgnoreCase )
. ToArray ( ) ;
var channelCodes = orders
. Where ( x = > ! string . IsNullOrWhiteSpace ( x . ChannelCode ) )
. Select ( x = > x . ChannelCode ! . Trim ( ) )
. Distinct ( StringComparer . OrdinalIgnoreCase )
. ToArray ( ) ;
var countryCodes = orders
. Where ( x = > ! string . IsNullOrWhiteSpace ( x . ConsigneeCountry ) )
. Select ( x = > x . ConsigneeCountry ! . Trim ( ) )
. Distinct ( StringComparer . OrdinalIgnoreCase )
. ToArray ( ) ;
var customerIds = orders
. Where ( x = > x . CustomerId is > 0 )
. Select ( x = > x . CustomerId ! . Value )
. Distinct ( )
. ToArray ( ) ;
var pickupOrderIds = orders
. Where ( x = > x . PickupOrderId is > 0 )
. Select ( x = > x . PickupOrderId ! . Value )
. Distinct ( )
. ToArray ( ) ;
var sendersTask = OrderRepository . GetSendersByOrderIdsAsync ( orderIds ) ;
var recipientsTask = OrderRepository . GetRecipientsByOrderIdsAsync ( orderIds ) ;
var weightsTask = OrderRepository . GetWeightsByOrderIdsAsync ( orderIds ) ;
var receivableSumTask = OrderRepository . GetReceivableSumByOrderIdsAsync ( orderIds ) ;
var warehousesTask = warehouseIds . Length = = 0
? Task . FromResult ( new List < WarehouseAddress > ( ) )
: WarehouseAddressRepository . GetListAsync ( x = > warehouseIds . Contains ( x . Id ) ) ;
var productsTask = productCodes . Length = = 0
? Task . FromResult ( new List < SalesProduct > ( ) )
: SalesProductRepository . GetListAsync ( x = > productCodes . Contains ( x . ProductCode ) ) ;
var channelsTask = channelCodes . Length = = 0
? Task . FromResult ( new List < ServiceChannel > ( ) )
: ServiceChannelRepository . GetListAsync ( x = > channelCodes . Contains ( x . ChannelCode ) ) ;
var countriesTask = countryCodes . Length = = 0
? Task . FromResult ( new List < Country > ( ) )
: CountryRepository . GetListAsync ( x = > countryCodes . Contains ( x . CountryCode ) ) ;
var auditUserNameTask = UserDisplayNameResolver . ResolveManyAsync (
orders . SelectMany ( x = > new [ ] { x . CreateUserId , x . UpdateUserId } ) ) ;
var customersTask = customerIds . Length = = 0
? Task . FromResult ( new List < Customer > ( ) )
: CustomerRepository . GetListAsync ( x = > customerIds . Contains ( x . Id ) ) ;
var pickupOrdersTask = pickupOrderIds . Length = = 0
? Task . FromResult ( new List < PickupOrder > ( ) )
: PickupOrderRepository . GetListAsync ( x = > pickupOrderIds . Contains ( x . Id ) ) ;
var bindSummaryTask = LoadStockBindListSummariesAsync ( orderIds ) ;
await Task . WhenAll (
sendersTask ,
recipientsTask ,
weightsTask ,
receivableSumTask ,
warehousesTask ,
productsTask ,
channelsTask ,
countriesTask ,
auditUserNameTask ,
customersTask ,
pickupOrdersTask ,
bindSummaryTask ) ;
var senders = await sendersTask ;
var recipients = await recipientsTask ;
var weights = await weightsTask ;
var receivableSumMap = await receivableSumTask ;
var warehouses = await warehousesTask ;
var products = await productsTask ;
var channels = await channelsTask ;
var countries = await countriesTask ;
var auditUserNameMap = await auditUserNameTask ;
var customers = await customersTask ;
var pickupOrders = await pickupOrdersTask ;
var bindSummaryMap = await bindSummaryTask ;
var senderMap = senders . GroupBy ( x = > x . OrderId ) . ToDictionary ( x = > x . Key , x = > x . First ( ) ) ;
var recipientMap = recipients . GroupBy ( x = > x . OrderId ) . ToDictionary ( x = > x . Key , x = > x . First ( ) ) ;
var weightMap = weights . GroupBy ( x = > x . OrderId ) . ToDictionary ( x = > x . Key , x = > x . ToList ( ) ) ;
var warehouseMap = warehouses . ToDictionary ( x = > x . Id ) ;
var productMap = products . ToDictionary ( x = > x . ProductCode , StringComparer . OrdinalIgnoreCase ) ;
var channelMap = channels . ToDictionary ( x = > x . ChannelCode , StringComparer . OrdinalIgnoreCase ) ;
var countryMap = countries . ToDictionary ( x = > x . CountryCode , StringComparer . OrdinalIgnoreCase ) ;
var customerMap = customers . ToDictionary ( x = > x . Id ) ;
var pickupNoMap = pickupOrders . ToDictionary ( x = > x . Id , x = > x . PickupNo ) ;
var carrierWaybillNoMap = pickupOrders
. Where ( x = > ! string . IsNullOrWhiteSpace ( x . CarrierWaybillNo ) )
. ToDictionary ( x = > x . Id , x = > x . CarrierWaybillNo ! ) ;
var addressCountryIds = senders
. Select ( x = > x . Country )
. Concat ( recipients . Select ( x = > x . Country ) )
. Where ( x = > x . HasValue )
. Select ( x = > x ! . Value )
. Distinct ( )
. ToArray ( ) ;
var addressCountries = addressCountryIds . Length = = 0
? [ ]
: await CountryRepository . GetListAsync ( x = > addressCountryIds . Contains ( x . Id ) ) ;
var countryIdCodeMap = addressCountries . ToDictionary (
x = > x . Id ,
x = > x . CountryCode ? ? string . Empty ) ;
var outputs = orders . Select ( order = >
{
senderMap . TryGetValue ( order . Id , out var sender ) ;
recipientMap . TryGetValue ( order . Id , out var recipient ) ;
weightMap . TryGetValue ( order . Id , out var orderWeights ) ;
var chargeableWeight = ResolveDisplayChargeableWeight ( orderWeights ) ;
decimal? receivableAmount = receivableSumMap . TryGetValue ( order . Id , out var sum )
? sum
: null ;
var additionalServices = NormalizeAdditionalServiceCodes (
OmsDocHelper . DeserializeJson < List < string > > ( order . AdditionalServices ) ) ;
var hasInsurance = additionalServices . Any ( x = >
string . Equals ( x , "insurance" , StringComparison . OrdinalIgnoreCase ) ) ;
string? customerName = null ;
string? customerCode = null ;
if ( order . CustomerId is > 0 & & customerMap . TryGetValue ( order . CustomerId . Value , out var customer ) )
{
customerName = customer . CustomerName ;
customerCode = customer . CustomerCode ;
}
SalesProduct ? product = null ;
if ( ! string . IsNullOrWhiteSpace ( order . ProductCode ) )
{
productMap . TryGetValue ( order . ProductCode . Trim ( ) , out product ) ;
}
bindSummaryMap . TryGetValue ( order . Id , out var bindSummary ) ;
return new OrderOutput
{
Id = order . Id ,
ClientNo = order . ClientNo ,
TrackNo = order . TrackNo ,
DownstreamServiceNo = order . DownstreamServiceNo ,
ServiceNo = order . ServiceNo ,
ProductCode = order . ProductCode ,
ProductName = product ? . ProductName ,
MaxTimeliness = product ? . MaxTimeliness ,
ChannelCode = order . ChannelCode ,
DownstreamSupplierCode = order . DownstreamSupplierCode ,
DownstreamSupplierName = order . DownstreamSupplierName ,
DownstreamAppKey = order . DownstreamAppKey ,
DownstreamAppId = order . DownstreamAppId ,
ChannelForecastCode = order . ChannelForecastCode ,
ChannelName = ! string . IsNullOrWhiteSpace ( order . ChannelCode )
& & channelMap . TryGetValue ( order . ChannelCode . Trim ( ) , out var channel )
? channel . ChannelName
: null ,
ConsigneeCountry = order . ConsigneeCountry ,
ConsigneeCountryName = ResolveConsigneeCountryName ( order , countryMap ) ,
CargoAttribute = order . CargoAttribute ,
WarehouseId = order . WarehouseId ,
Warehouse = order . WarehouseId . HasValue & & warehouseMap . TryGetValue ( order . WarehouseId . Value , out var warehouse )
? warehouse . WarehouseName
: null ,
CustomerId = order . CustomerId ,
CustomerName = customerName ,
CustomerCode = customerCode ,
OrderSource = string . IsNullOrWhiteSpace ( order . OrderSource )
? OrderSourceCodes . Manual
: order . OrderSource ,
PickupTime = order . PickupTime ,
CustomerSenderAddressId = order . CustomerSenderAddressId ,
InboundMethod = order . InboundMethod ,
FulfillmentType = string . IsNullOrWhiteSpace ( order . FulfillmentType )
? FulfillmentTypeCodes . Direct
: order . FulfillmentType ,
FulfillmentSource = order . FulfillmentSource ,
StockBindStatus = bindSummary ? . BindStatus ? ? "none" ,
StockBindLineCount = bindSummary ? . LineCount ? ? 0 ,
StockBindQtyTotal = bindSummary ? . QtyTotal ? ? 0 ,
DomesticTrackingNos = bindSummary ? . TrackingNosText ,
FulfillProgress = FulfillmentProgressCodes . Resolve (
FulfillmentTypeCodes . IsWarehouse ( order . FulfillmentType ) ,
bindSummary ? . BindStatus ? ? "none" ,
bindSummary ? . LineCount ? ? 0 ,
bindSummary ? . HasInTransitParcel ? ? false ) ,
PrimaryBinCode = bindSummary ? . PrimaryBinCode ,
PrimarySkuCodes = bindSummary ? . PrimarySkuCodes ,
PickupOrderId = order . PickupOrderId ,
PickupNo = order . PickupOrderId is > 0
& & pickupNoMap . TryGetValue ( order . PickupOrderId . Value , out var pickupNo )
? pickupNo
: null ,
CarrierWaybillNo = order . PickupOrderId is > 0
& & carrierWaybillNoMap . TryGetValue ( order . PickupOrderId . Value , out var carrierWaybillNo )
? carrierWaybillNo
: null ,
RequestId = order . RequestId ,
ExportCustomsMode = order . ExportCustomsMode ,
ExportQualificationId = order . ExportQualificationId ,
PredeclareFailReason = string . IsNullOrWhiteSpace ( order . PredeclareFailReason )
? null
: order . PredeclareFailReason . Trim ( ) ,
AllocationPendingReason = string . IsNullOrWhiteSpace ( order . AllocationPendingReason )
? null
: order . AllocationPendingReason . Trim ( ) ,
AllocationScheme = string . IsNullOrWhiteSpace ( order . AllocationScheme )
? null
: order . AllocationScheme . Trim ( ) ,
// 分页已 IgnoreColumns(AllocationTraceJson);与写入路径一并落库的 TraceTime 作为布尔依据
HasAllocationTrace = order . AllocationTraceTime . HasValue
| | ! string . IsNullOrWhiteSpace ( order . AllocationTraceJson ) ,
DeclaredCurrency = order . DeclaredCurrency ,
DeclaredSum = order . DeclaredSum ,
Quantity = order . Quantity ,
IsCod = order . IsCod > 0 ,
CodCurrency = order . CodCurrency ,
CodSum = order . CodSum ,
OrderStatus = OmsDocHelper . GetOrderStatusName ( order . OrderStatus ) ,
Status = order . OrderStatus ,
HandleStatus = OrderHandleStatusCodes . IsProcessed ( order . HandleStatus )
? OrderHandleStatusCodes . Processed
: OrderHandleStatusCodes . Pending ,
HandleStatusName = OrderHandleStatusCodes . GetDisplayName ( order . HandleStatus ) ,
IssueType = order . IssueType ,
IssueTypeName = IssueTypeCodes . GetDisplayName ( order . IssueType ) ,
IssueTitle = order . IssueTitle ,
IssueContent = order . IssueContent ,
IssueTemplateId = order . IssueTemplateId ,
IssueRemark = order . IssueRemark ,
IssueTime = order . IssueTime ,
ClaimType = order . ClaimType ,
ClaimTypeName = ClaimTypeCodes . GetDisplayName ( order . ClaimType ) ,
ClaimAmount = order . ClaimAmount ,
ClaimCurrency = order . ClaimCurrency ,
ClaimReason = order . ClaimReason ,
ClaimTime = order . ClaimTime ,
PreviousOrderStatus = order . PreviousOrderStatus ,
ReceiveTime = order . ReceiveTime ,
ShipTime = order . ShipTime ,
PayTime = order . PayTime ,
IsPaid = order . IsPaid > 0 ,
SignTime = order . SignTime ,
IsIntercept = order . IsIntercept > 0 ,
IsRemote = order . IsRemote > 0 ,
AdditionalServices = additionalServices ,
HasInsurance = hasInsurance ,
ForecastReceivableAmount = order . ForecastReceivableAmount ,
ForecastPayableAmount = order . ForecastPayableAmount ,
ReceivableSubtotal = order . ReceivableSubtotal ,
LevelDiscountAmount = order . LevelDiscountAmount ,
CouponDiscountAmount = order . CouponDiscountAmount ,
ActualPayAmount = order . PayableAmount ,
CouponInstanceId = order . CouponInstanceId ,
SalesProductRulesVersion = string . IsNullOrWhiteSpace ( order . SalesProductRulesVersion )
? null
: order . SalesProductRulesVersion . Trim ( ) ,
SalesProductPriceVersion = string . IsNullOrWhiteSpace ( order . SalesProductPriceVersion )
? null
: order . SalesProductPriceVersion . Trim ( ) ,
CreateTime = order . CreateTime ,
CreateBy = OmsRbacUserDisplayNameResolver . FormatUserId ( order . CreateUserId , auditUserNameMap ) ,
UpdateTime = OmsDocHelper . NullIfDefault ( order . UpdateTime ) ,
UpdateBy = OmsRbacUserDisplayNameResolver . FormatUserId ( order . UpdateUserId , auditUserNameMap ) ,
Sender = MapSender ( sender , countryIdCodeMap ) ,
Receiver = MapReceiver ( recipient , countryIdCodeMap ) ,
Items = [ ] ,
WeightList = [ ] ,
FeeList = [ ] ,
ChargeableWeight = chargeableWeight ,
ReceivableAmount = receivableAmount ,
} ;
} ) . ToList ( ) ;
if ( OmsSessionHelper . IsCustomerLogin ( CurrentUser ) )
{
RedactChannelFieldsForCustomer ( outputs ) ;
}
return outputs ;
}
private sealed class StockBindListSummary
{
public string BindStatus { get ; init ; } = "none" ;