admin/src/Oms.Application/Shared/PickupOrderDownstreamCreateOneBodyBuilder.cs
zzh 26f9d8be7f
All checks were successful
Build and Deploy / deploy (push) Successful in 1m43s
feat: 揽收单预报下游改从 t_pickup_order 组装 createOrderOne
新增 /order/pickup-order/downstream-forward,productCode/supplierCode/地址重量商品均取揽收单,不再依赖关联物流单。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 19:17:09 +08:00

191 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 从揽收单表组装 itfx createOrderOne 标准请求体(不读关联物流单)。
/// </summary>
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);
}
/// <summary>
/// createOrderOne.productCode:承运服务(销售产品)对应渠道的 ForecastCode,缺省回退 CarrierService。
/// </summary>
public static async Task<string?> 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);
}
}