using Oms.Application.Dtos.Orders;
using Oms.Domain.ChannelsAggregate.Repositories;
using Oms.Domain.OrdersAggregate.Consts;
using Oms.Domain.OrdersAggregate.Entities;
using Oms.Domain.SystemAggregate.Entities;
namespace Oms.Application.Shared;
///
/// 从揽收单表组装 itfx createOrderOne 标准请求体(不读关联物流单)。
///
public static class PickupOrderDownstreamCreateOneBodyBuilder
{
public static async Task<(ItfxCreateOrderOneBody Body, string? ForecastProductCode)> BuildAsync(
PickupOrder pickup,
WarehouseAddress warehouse,
ISalesProductRepository salesProductRepository,
IServiceChannelRepository serviceChannelRepository,
CancellationToken cancellationToken = default)
{
var productCode = await ResolveForecastProductCodeAsync(
pickup.CarrierService,
salesProductRepository,
serviceChannelRepository,
cancellationToken);
var isReverse = string.Equals(
PickupDirectionCodes.NormalizeOrDefault(pickup.Direction),
PickupDirectionCodes.Reverse,
StringComparison.OrdinalIgnoreCase);
var customerSide = MapCustomerSide(pickup);
var warehouseSide = MapWarehouseSide(warehouse);
var weight = pickup.TotalActualWeight ?? pickup.ChargeableWeight;
var qty = pickup.ParcelCount > 0 ? pickup.ParcelCount : 1;
var cargoName = string.IsNullOrWhiteSpace(pickup.Remark)
? "上门揽收包裹"
: pickup.Remark.Trim();
return (new ItfxCreateOrderOneBody
{
ClientNo = pickup.PickupNo,
ServiceNo = pickup.PickupNo,
TrackNo = pickup.CarrierWaybillNo,
ProductCode = productCode,
CargoAttribute = CargoAttributeCodes.General,
WarehouseId = pickup.WarehouseId,
CustomerId = pickup.CustomerId,
Length = 1,
Width = 1,
Height = 1,
ActualWeight = weight,
ChargeableWeight = pickup.ChargeableWeight ?? weight,
IsCod = false,
DeclaredCurrency = pickup.Currency,
DeclaredSum = FormatDecimal(pickup.ReceivableAmount ?? pickup.FreightAmount ?? 1),
Quantity = qty.ToString(),
Sender = isReverse ? warehouseSide.Sender : customerSide.Sender,
Receiver = isReverse ? customerSide.Receiver : warehouseSide.Receiver,
Items =
[
new OrderParcelItemInput
{
CnName = cargoName,
EnName = cargoName,
UnitPrice = 1,
UnitWeight = weight,
Quantity = qty,
Amount = 1,
Weight = weight
}
]
}, productCode);
}
///
/// createOrderOne.productCode:承运服务(销售产品)对应渠道的 ForecastCode,缺省回退 CarrierService。
///
public static async Task ResolveForecastProductCodeAsync(
string? carrierService,
ISalesProductRepository salesProductRepository,
IServiceChannelRepository serviceChannelRepository,
CancellationToken cancellationToken = default)
{
var salesProductCode = carrierService?.Trim();
if (string.IsNullOrWhiteSpace(salesProductCode))
{
return null;
}
var product = await salesProductRepository.GetByProductCodeAsync(salesProductCode, cancellationToken);
if (product == null)
{
return salesProductCode;
}
var providers = await salesProductRepository.GetAllocationProvidersAsync(product.Id, cancellationToken);
var channelId = providers
.Where(x => x.ServiceChannelId is > 0)
.OrderBy(x => x.SerialNumber)
.Select(x => x.ServiceChannelId!.Value)
.FirstOrDefault();
if (channelId <= 0)
{
return salesProductCode;
}
var channel = await serviceChannelRepository.FirstOrDefaultAsync(x => x.Id == channelId, cancellationToken);
var forecastCode = channel?.ForecastCode?.Trim();
return string.IsNullOrWhiteSpace(forecastCode) ? salesProductCode : forecastCode;
}
private static string? FormatDecimal(decimal? value) =>
value.HasValue ? value.Value.ToString(System.Globalization.CultureInfo.InvariantCulture) : null;
private static (OrderParcelSenderInput Sender, OrderParcelReceiverInput Receiver) MapCustomerSide(PickupOrder pickup)
{
var sender = new OrderParcelSenderInput
{
SenderName = pickup.SenderName,
Company = pickup.SenderCompany,
Phone = pickup.SenderPhone,
TelePhone = pickup.SenderTelePhone,
Email = pickup.SenderEmail,
CountryCode = string.IsNullOrWhiteSpace(pickup.SenderCountryCode)
? "CN"
: pickup.SenderCountryCode.Trim().ToUpperInvariant(),
Province = pickup.SenderProvince,
City = pickup.SenderCity,
ZipCode = pickup.SenderZipCode,
StreetAddress1 = pickup.SenderStreetAddress1,
StreetAddress2 = pickup.SenderStreetAddress2,
StreetAddress3 = pickup.SenderStreetAddress3,
HouseNumber = pickup.SenderHouseNumber
};
var receiver = new OrderParcelReceiverInput
{
RecipientsName = pickup.SenderName,
CompanyName = pickup.SenderCompany,
Phone = pickup.SenderPhone,
TelePhone = pickup.SenderTelePhone,
Email = pickup.SenderEmail,
CountryCode = string.IsNullOrWhiteSpace(pickup.SenderCountryCode)
? "CN"
: pickup.SenderCountryCode.Trim().ToUpperInvariant(),
Province = pickup.SenderProvince,
City = pickup.SenderCity,
ZipCode = string.IsNullOrWhiteSpace(pickup.SenderZipCode) ? "000000" : pickup.SenderZipCode,
StreetAddress1 = pickup.SenderStreetAddress1,
StreetAddress2 = pickup.SenderStreetAddress2,
StreetAddress3 = pickup.SenderStreetAddress3,
StreetNumber = pickup.SenderHouseNumber
};
return (sender, receiver);
}
private static (OrderParcelSenderInput Sender, OrderParcelReceiverInput Receiver) MapWarehouseSide(
WarehouseAddress warehouse)
{
var contact = string.IsNullOrWhiteSpace(warehouse.Recipient)
? warehouse.WarehouseName
: warehouse.Recipient!.Trim();
var street = string.IsNullOrWhiteSpace(warehouse.ShippingAddress)
? warehouse.WarehouseName
: warehouse.ShippingAddress!.Trim();
var sender = new OrderParcelSenderInput
{
SenderName = contact,
Phone = warehouse.ContactPhone,
CountryCode = "CN",
StreetAddress1 = street,
ZipCode = "000000"
};
var receiver = new OrderParcelReceiverInput
{
RecipientsName = contact,
Phone = warehouse.ContactPhone,
CountryCode = "CN",
ZipCode = "000000",
StreetAddress1 = street
};
return (sender, receiver);
}
}