From cfc1d6e00b6a67e648de35256d105ade9fd947ce Mon Sep 17 00:00:00 2001 From: Alexey Busygin Date: Wed, 4 Sep 2024 11:40:36 +0200 Subject: [PATCH] #75 Fixed missing CustomerClassification --- .../UPS/UpsRatingRequestBuilderTests.cs | 59 +++++++++ .../Models/UPS/UpsRatingRequestBuilder.cs | 123 ++++++++++++++++++ .../ShippingProviders/UPSProvider.cs | 105 +-------------- 3 files changed, 184 insertions(+), 103 deletions(-) create mode 100644 ShippingRates.Tests/Models/UPS/UpsRatingRequestBuilderTests.cs create mode 100644 ShippingRates/Models/UPS/UpsRatingRequestBuilder.cs diff --git a/ShippingRates.Tests/Models/UPS/UpsRatingRequestBuilderTests.cs b/ShippingRates.Tests/Models/UPS/UpsRatingRequestBuilderTests.cs new file mode 100644 index 0000000..6d3b42f --- /dev/null +++ b/ShippingRates.Tests/Models/UPS/UpsRatingRequestBuilderTests.cs @@ -0,0 +1,59 @@ +using NUnit.Framework; +using ShippingRates.Models.UPS; +using ShippingRates.ShippingProviders; +using System.Collections.Generic; + +namespace ShippingRates.Tests.Models.UPS +{ + [TestFixture()] + internal class UpsRatingRequestBuilderTests + { + [Test()] + public void UpsRatingRequestBuilder_CustomerClassification() + { + // US shipment + var from = new Address("Annapolis", "MD", "21401", "US"); + var to = new Address("", "", "30404", "US"); + + var package1 = new Package(1, 1, 1, 3, 0); + var package2 = new Package(1, 2, 3, 4, 5); + + var shipment = new Shipment(from, to, new List() { package1, package2 }); + + // International shipment + var fromNL = new Address("Amsterdam", "", "1043 AG", "NL"); + var shipmentNL = new Shipment(fromNL, to, new List() { package1, package2 }); + + // Daily rates + var dailyRatesConfig = new UPSProviderConfiguration() + { + UseDailyRates = true + }; + var dailyRatesBuilder = new UpsRatingRequestBuilder(dailyRatesConfig); + var dailyRatesRequest = dailyRatesBuilder.Build(shipment); + Assert.That(dailyRatesRequest?.RateRequest?.CustomerClassification, Is.Not.Null); + Assert.That(dailyRatesRequest?.RateRequest?.CustomerClassification.Code, Is.EqualTo("01")); + + // Retail rates + var retailRatesConfig = new UPSProviderConfiguration() + { + UseRetailRates = true + }; + var retailRatesBuilder = new UpsRatingRequestBuilder(retailRatesConfig); + var retailRatesRequest = retailRatesBuilder.Build(shipment); + Assert.That(retailRatesRequest?.RateRequest?.CustomerClassification, Is.Not.Null); + Assert.That(retailRatesRequest?.RateRequest?.CustomerClassification.Code, Is.EqualTo("04")); + + // Regular rates + var regularRatesConfig = new UPSProviderConfiguration(); + var regularRatesBuilder = new UpsRatingRequestBuilder(regularRatesConfig); + var regularRatesRequest = regularRatesBuilder.Build(shipment); + Assert.That(regularRatesRequest?.RateRequest?.CustomerClassification, Is.Not.Null); + Assert.That(regularRatesRequest?.RateRequest?.CustomerClassification.Code, Is.EqualTo("00")); + + // International shipment + var internationalRequest = dailyRatesBuilder.Build(shipmentNL); + Assert.That(internationalRequest?.RateRequest?.CustomerClassification, Is.Null); + } + } +} diff --git a/ShippingRates/Models/UPS/UpsRatingRequestBuilder.cs b/ShippingRates/Models/UPS/UpsRatingRequestBuilder.cs new file mode 100644 index 0000000..0d09412 --- /dev/null +++ b/ShippingRates/Models/UPS/UpsRatingRequestBuilder.cs @@ -0,0 +1,123 @@ +using ShippingRates.ShippingProviders; +using System; +using System.Linq; + +namespace ShippingRates.Models.UPS +{ + internal class UpsRatingRequestBuilder + { + private readonly UPSProviderConfiguration _configuration; + + public UpsRatingRequestBuilder(UPSProviderConfiguration configuration) + { + _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); + } + + public UpsRatingRequest Build(Shipment shipment) + { + var shipFromUS = shipment.OriginAddress.CountryCode == "US"; + var unitsSystem = shipFromUS ? UnitsSystem.USCustomary : UnitsSystem.Metric; + + var request = new UpsRatingRequest() + { + RateRequest = new RateRequest() + { + PickupType = new PickupType() + { + Code = "03" + }, + Shipment = new UpsShipment() + { + PaymentDetails = new PaymentDetails() + { + ShipmentCharge = new ShipmentCharge() + { + BillShipper = new BillShipper() + { + AccountNumber = _configuration.AccountNumber + }, + Type = "01" + } + }, + Shipper = new Shipper() + { + ShipperNumber = _configuration.AccountNumber, + Address = new UpsAddress(shipment.OriginAddress) + }, + ShipFrom = new ShipAddress(new UpsAddress(shipment.OriginAddress)), + ShipTo = new ShipAddress(new UpsAddress(shipment.DestinationAddress)), + NumOfPieces = shipment.Packages.Count, + Package = shipment.Packages.Select(p => new UpsPackage(p, unitsSystem)).ToArray() + } + } + }; + if (!string.IsNullOrEmpty(_configuration.ServiceDescription)) + { + request.RateRequest.Shipment.Service = new Service() + { + Code = GetServiceCode(_configuration.ServiceDescription) + }; + } + if (shipment.DestinationAddress.IsResidential) + { + request.RateRequest.Shipment.ShipTo.Address.ResidentialAddressIndicator = "Y"; + } + if (shipment.HasDocumentsOnly) + { + request.RateRequest.Shipment.DocumentsOnlyIndicator = "Document"; + } + if (shipment.Options.SaturdayDelivery) + { + request.RateRequest.Shipment.ShipmentServiceOptions = new ShipmentServiceOptions() + { + SaturdayDeliveryIndicator = "Y" + }; + } + if (_configuration.UseNegotiatedRates) + { + request.RateRequest.Shipment.ShipmentRatingOptions = new ShipmentRatingOptions() + { + NegotiatedRatesIndicator = "Y" + }; + } + if (shipFromUS) // Valid if ship from US + { + var code = _configuration.UseRetailRates + ? "04" + : (_configuration.UseDailyRates ? "01" : "00"); + + request.RateRequest.CustomerClassification = new CustomerClassification() + { + Code = code, + }; + } + if (shipment.Options.ShippingDate != null) + { + request.RateRequest.Shipment.DeliveryTimeInformation = new DeliveryTimeInformation() + { + PackageBillType = shipment.HasDocumentsOnly ? "02" : "03", + Pickup = new Pickup() + { + Date = shipment.Options.ShippingDate.Value.ToString("yyyyMMdd"), + Time = "1000" + } + }; + } + + return request; + } + + static string GetServiceCode(string serviceDescription) + { + if (serviceDescription.Length == 2) + return serviceDescription; + + var serviceCode = UPSProvider.GetServiceCodes().FirstOrDefault(c => c.Value == serviceDescription).Key; + + if (string.IsNullOrEmpty(serviceCode)) + throw new ArgumentException($"Invalid UPS service description {serviceCode}"); + + return serviceCode; + } + } +} diff --git a/ShippingRates/ShippingProviders/UPSProvider.cs b/ShippingRates/ShippingProviders/UPSProvider.cs index 635ae43..1f73b06 100644 --- a/ShippingRates/ShippingProviders/UPSProvider.cs +++ b/ShippingRates/ShippingProviders/UPSProvider.cs @@ -64,7 +64,8 @@ public override async Task GetRates() if (!string.IsNullOrEmpty(token)) { - var request = GetRequest(); + var requestBuilder = new UpsRatingRequestBuilder(_configuration); + var request = requestBuilder.Build(Shipment); var ratingsResponse = await UpsRatingService.GetRatingAsync(httpClient, token, _configuration.UseProduction, request, AddError); ParseResponse(ratingsResponse); } @@ -80,95 +81,6 @@ public override async Task GetRates() } } - private UpsRatingRequest GetRequest() - { - var shipFromUS = Shipment.OriginAddress.CountryCode == "US"; - var unitsSystem = shipFromUS ? UnitsSystem.USCustomary : UnitsSystem.Metric; - - var request = new UpsRatingRequest() - { - RateRequest = new RateRequest() - { - PickupType = new PickupType() - { - Code = "03" - }, - Shipment = new UpsShipment() - { - PaymentDetails = new PaymentDetails() - { - ShipmentCharge = new ShipmentCharge() - { - BillShipper = new BillShipper() - { - AccountNumber = _configuration.AccountNumber - }, - Type = "01" - } - }, - Shipper = new Shipper() - { - ShipperNumber = _configuration.AccountNumber, - Address = new UpsAddress(Shipment.OriginAddress) - }, - ShipFrom = new ShipAddress(new UpsAddress(Shipment.OriginAddress)), - ShipTo = new ShipAddress(new UpsAddress(Shipment.DestinationAddress)), - NumOfPieces = Shipment.Packages.Count, - Package = Shipment.Packages.Select(p => new UpsPackage(p, unitsSystem)).ToArray() - } - } - }; - if (!string.IsNullOrEmpty(_configuration.ServiceDescription)) - { - request.RateRequest.Shipment.Service = new Service() - { - Code = GetServiceCode(_configuration.ServiceDescription) - }; - } - if (Shipment.DestinationAddress.IsResidential) - { - request.RateRequest.Shipment.ShipTo.Address.ResidentialAddressIndicator = "Y"; - } - if (Shipment.HasDocumentsOnly) - { - request.RateRequest.Shipment.DocumentsOnlyIndicator = "Document"; - } - if (Shipment.Options.SaturdayDelivery) - { - request.RateRequest.Shipment.ShipmentServiceOptions = new ShipmentServiceOptions() - { - SaturdayDeliveryIndicator = "Y" - }; - } - if (_configuration.UseNegotiatedRates) - { - request.RateRequest.Shipment.ShipmentRatingOptions = new ShipmentRatingOptions() - { - NegotiatedRatesIndicator = "Y" - }; - } - if (shipFromUS) // Valid if ship from US - { - var code = _configuration.UseRetailRates - ? "04" - : (_configuration.UseDailyRates ? "01" : "00"); - } - if (Shipment.Options.ShippingDate != null) - { - request.RateRequest.Shipment.DeliveryTimeInformation = new DeliveryTimeInformation() - { - PackageBillType = Shipment.HasDocumentsOnly ? "02" : "03", - Pickup = new Pickup() - { - Date = Shipment.Options.ShippingDate.Value.ToString("yyyyMMdd"), - Time = "1000" - } - }; - } - - return request; - } - private void ParseResponse(UpsRatingResponse response) { if (response?.RateResponse?.RatedShipment == null) @@ -221,19 +133,6 @@ private void ParseResponse(UpsRatingResponse response) } } - static string GetServiceCode(string serviceDescription) - { - if (serviceDescription.Length == 2) - return serviceDescription; - - var serviceCode = _serviceCodes.FirstOrDefault(c => c.Value == serviceDescription).Key; - - if (string.IsNullOrEmpty(serviceCode)) - throw new ArgumentException($"Invalid UPS service description {serviceCode}"); - - return serviceCode; - } - public static IDictionary GetServiceCodes() => _serviceCodes; } }