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); } }