Skip to content

Commit

Permalink
#75 Fixed missing CustomerClassification
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeybusygin committed Sep 4, 2024
1 parent 3e3c2f7 commit cfc1d6e
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 103 deletions.
59 changes: 59 additions & 0 deletions ShippingRates.Tests/Models/UPS/UpsRatingRequestBuilderTests.cs
Original file line number Diff line number Diff line change
@@ -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<Package>() { package1, package2 });

// International shipment
var fromNL = new Address("Amsterdam", "", "1043 AG", "NL");
var shipmentNL = new Shipment(fromNL, to, new List<Package>() { 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);
}
}
}
123 changes: 123 additions & 0 deletions ShippingRates/Models/UPS/UpsRatingRequestBuilder.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
105 changes: 2 additions & 103 deletions ShippingRates/ShippingProviders/UPSProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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)
Expand Down Expand Up @@ -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<string, string> GetServiceCodes() => _serviceCodes;
}
}

0 comments on commit cfc1d6e

Please sign in to comment.