Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Consolidate SmartRate functions, add new functions #566

Merged
merged 17 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Next Release

- Add new `SmartRate` service for interacting with the SmartRate API
- New `RecommendShipDateForShipment` function to recommend ship date for a shipment based on a desired delivery date.
- New `EstimateDeliveryDateForRoute` function to estimate delivery date based on a list of carriers, to/from ZIP codes and a planned ship date (no existing shipment required).
- New `RecommendShipDateForRoute` function to to recommend ship date based on a list of carriers, to/from ZIP codes and a planned ship date (no existing shipment required).
- New model classes as needed for JSON response to new API functions
- Enforce one-or-other for `Shipment` and `Batch` parameters in `Pickup.Create` parameter set
- Add internal parameter dependency utility

Expand Down
8 changes: 8 additions & 0 deletions EasyPost.Integration/Basics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
var endShipper = new EndShipper();
var endShipperCollection = new EndShipperCollection();
var error = new Error();
var estimateDeliveryDateForZipPairResult = new EstimateDeliveryDateForZipPairResult();
var @event = new Event();
var eventCollection = new EventCollection();
var fee = new Fee();
Expand All @@ -55,6 +56,8 @@
var predefinedPackage = new PredefinedPackage();
var rate = new Rate();
var rateWithEstimatedDeliveryDate = new RateWithEstimatedDeliveryDate();
var recommendShipDateForZipPairResult = new RecommendShipDateForZipPairResult();
var recommendShipDateForShipmentResult = new RecommendShipDateForShipmentResult();
var referralCustomer = new ReferralCustomer();
var refund = new Refund();
var report = new Report();
Expand All @@ -70,6 +73,9 @@
var supportedFeature = new SupportedFeature();
var taxIdentifier = new TaxIdentifier();
var timeInTransit = new TimeInTransit();
var timeInTransitDetails = new TimeInTransitDetails();

Check warning on line 76 in EasyPost.Integration/Basics.cs

View workflow job for this annotation

GitHub Actions / Integration_Tests

'TimeInTransitDetails' is obsolete: 'This class will be removed in a future version and replaced with TimeInTransitDetailsForDeliveryDateEstimate.'
var timeInTransitDetailsForDeliveryDateEstimate = new TimeInTransitDetailsForDeliveryDateEstimate();
var timeInTransitDetailsByDeliveryDate = new TimeInTransitDetailsForShipDateRecommendation();
var tracker = new Tracker();
var trackerCollection = new TrackerCollection();
var trackingDetail = new TrackingDetail();
Expand Down Expand Up @@ -139,6 +145,8 @@
var shipmentInsureParameters = new EasyPost.Parameters.Shipment.Insure();
var shipmentRegenerateRatesParameters = new EasyPost.Parameters.Shipment.RegenerateRates();
var shipmentRetrieveEstimatedDeliveryDateParameters = new EasyPost.Parameters.Shipment.RetrieveEstimatedDeliveryDate();
var smartRateEstimateDeliveryDateForZipPairParameters = new EasyPost.Parameters.SmartRate.EstimateDeliveryDateForZipPair();
var smartRateRecommendShipDateForZipPairParameters = new EasyPost.Parameters.SmartRate.RecommendShipDateForZipPair();
var taxIdentifierCreateParameters = new EasyPost.Parameters.TaxIdentifier.Create();
var trackerCreateParameters = new EasyPost.Parameters.Tracker.Create();
var trackerAllParameters = new EasyPost.Parameters.Tracker.All();
Expand Down
2 changes: 1 addition & 1 deletion EasyPost.Integration/TestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ internal Client SetUpTest(string cassetteName, Func<string, HttpClient, Client>
// set up cassette
Cassette cassette = new(_testCassettesFolder, cassetteName, new CassetteOrder.Alphabetical());

// add cassette to vcr
// add cassette to vcr
_vcr.Insert(cassette);

string filePath = Path.Combine(_testCassettesFolder, cassetteName + ".json");
Expand Down
2 changes: 2 additions & 0 deletions EasyPost.Tests/EasyPost.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,7 @@

<ItemGroup>
<Folder Include="cassettes" />
<Folder Include="cassettes\netstandard\smartrate_service_with_parameters\" />
<Folder Include="cassettes\net\smartrate_service_with_parameters\" />
</ItemGroup>
</Project>
4 changes: 3 additions & 1 deletion EasyPost.Tests/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ internal static Dictionary<string, object> BasicPickup

internal static string PickupService => GetFixtureStructure().ServiceNames.Usps.PickupService;

internal static string PlannedShipDate => "2024-04-08";
internal static string PlannedShipDate => "2024-07-17";

internal static string DesiredDeliveryDate => "2024-07-17";

internal static Dictionary<string, object> ReferralCustomer => GetFixtureStructure().Users.Referral;

Expand Down
27 changes: 27 additions & 0 deletions EasyPost.Tests/ServicesTests/ShipmentServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,10 +531,37 @@ public async Task TestRetrieveEstimatedDeliveryDates()

foreach (var rate in ratesWithEstimatedDeliveryDates)
{
// Deprecated property
Assert.NotNull(rate.EasyPostTimeInTransitData);
Assert.NotNull(rate.EasyPostTimeInTransitData.EasyPostEstimatedDeliveryDate);
Assert.NotNull(rate.EasyPostTimeInTransitData.DaysInTransit);
Assert.NotNull(rate.EasyPostTimeInTransitData.PlannedShipDate);

// Replacement property, same data
Assert.NotNull(rate.TimeInTransitDetails);
Assert.NotNull(rate.TimeInTransitDetails.EasyPostEstimatedDeliveryDate);
Assert.NotNull(rate.TimeInTransitDetails.DaysInTransit);
Assert.NotNull(rate.TimeInTransitDetails.PlannedShipDate);
}
}

[Fact]
[CrudOperations.Read]
[Testing.Function]
public async Task TestRecommendShipDateForShipment()
{
UseVCR("recommend_ship_date");

Shipment shipment = await Client.Shipment.Create(Fixtures.BasicShipment);

List<RecommendShipDateForShipmentResult> ratesWithEstimatedDeliveryDates = await Client.Shipment.RecommendShipDate(shipment.Id, Fixtures.DesiredDeliveryDate);

foreach (var rate in ratesWithEstimatedDeliveryDates)
{
Assert.NotNull(rate.TimeInTransitDetails);
Assert.NotNull(rate.TimeInTransitDetails.EasyPostRecommendedShipDate);
Assert.NotNull(rate.TimeInTransitDetails.DaysInTransit);
Assert.NotNull(rate.TimeInTransitDetails.DesiredDeliveryDate);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyPost.Models.API;
using EasyPost.Tests._Utilities;
Expand Down Expand Up @@ -304,7 +305,7 @@ public async Task TestRegenerateRates()

[Fact]
[Testing.Function]
public async Task TestRetrieveEstimatedDeliveryDates()
public async Task TestEstimatedDeliveryDates()
{
UseVCR("estimated_delivery_dates");

Expand Down
145 changes: 145 additions & 0 deletions EasyPost.Tests/ServicesTests/WithParameters/SmartRateServiceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyPost.Exceptions.General;
using EasyPost.Models.API;
using EasyPost.Tests._Utilities;
using EasyPost.Tests._Utilities.Attributes;
using EasyPost.Utilities.Internal.Attributes;
using Xunit;

namespace EasyPost.Tests.ServicesTests.WithParameters
{
public class SmartRateServiceTests : UnitTest
{
public SmartRateServiceTests() : base("smartrate_service_with_parameters")
{
}

#region Tests

#region Test CRUD Operations

[Fact]
[CrudOperations.Read]
[Testing.Function]
public async Task TestEstimateDeliveryDate()
{
UseVCR("estimate_delivery_date");

Dictionary<string, object> address1Data = Fixtures.CaAddress1;
Dictionary<string, object> address2Data = Fixtures.CaAddress2;
Parameters.Address.Create address1Parameters = Fixtures.Parameters.Addresses.Create(address1Data);
Parameters.Address.Create address2Parameters = Fixtures.Parameters.Addresses.Create(address2Data);

Parameters.SmartRate.EstimateDeliveryDateForZipPair estimateDeliveryDateForZipPairParameters = new()
{
FromZip = address1Parameters.Zip,
ToZip = address2Parameters.Zip,
PlannedShipDate = Fixtures.PlannedShipDate,
Carriers = ["USPS", "FedEx", "UPS", "DHL"],
};

EstimateDeliveryDateForZipPairResult results = await Client.SmartRate.EstimateDeliveryDate(estimateDeliveryDateForZipPairParameters);

Assert.Equal(results.FromZip, estimateDeliveryDateForZipPairParameters.FromZip);
Assert.Equal(results.ToZip, estimateDeliveryDateForZipPairParameters.ToZip);
Assert.Equal(results.PlannedShipDate, estimateDeliveryDateForZipPairParameters.PlannedShipDate);
Assert.NotNull(results.Results);
Assert.NotEmpty(results.Results);
foreach (var estimate in results.Results)
{
Assert.NotNull(estimate.Carrier);
Assert.NotNull(estimate.Service);
Assert.NotNull(estimate.TimeInTransitDetails);
Assert.NotNull(estimate.TimeInTransitDetails.DaysInTransit);
Assert.NotNull(estimate.TimeInTransitDetails.DaysInTransit.Percentile75);
}
}

[Fact]
[CrudOperations.Read]
[Testing.Function]
public async Task TestRecommendShipDate()
{
UseVCR("recommend_ship_date");

Dictionary<string, object> address1Data = Fixtures.CaAddress1;
Dictionary<string, object> address2Data = Fixtures.CaAddress2;
Parameters.Address.Create address1Parameters = Fixtures.Parameters.Addresses.Create(address1Data);
Parameters.Address.Create address2Parameters = Fixtures.Parameters.Addresses.Create(address2Data);

Parameters.SmartRate.RecommendShipDateForZipPair recommendShipDateForZipPairParameters = new()
{
FromZip = address1Parameters.Zip,
ToZip = address2Parameters.Zip,
DesiredDeliveryDate = Fixtures.DesiredDeliveryDate,
Carriers = ["USPS", "FedEx", "UPS", "DHL"],
};

RecommendShipDateForZipPairResult results = await Client.SmartRate.RecommendShipDate(recommendShipDateForZipPairParameters);

Assert.Equal(results.FromZip, recommendShipDateForZipPairParameters.FromZip);
Assert.Equal(results.ToZip, recommendShipDateForZipPairParameters.ToZip);
Assert.Equal(results.DesiredDeliveryDate, recommendShipDateForZipPairParameters.DesiredDeliveryDate);
Assert.NotNull(results.Results);
Assert.NotEmpty(results.Results);
foreach (var estimate in results.Results)
{
Assert.NotNull(estimate.Carrier);
Assert.NotNull(estimate.Service);
Assert.NotNull(estimate.EasyPostTimeInTransitData);
Assert.NotNull(estimate.EasyPostTimeInTransitData.DaysInTransit);
Assert.NotNull(estimate.EasyPostTimeInTransitData.DaysInTransit.Percentile75);
}
}

#endregion

[Fact]
[Testing.Function]
public async Task TestLowestSmartRateFiltering()
{
/***
* Mock rates since these can change from the API and we want to test the local filtering logic, not the API call.
* The API call is tested in <see cref="TestGetSmartRates"/>
*/
List<SmartRate> smartRates =
[
new SmartRate
{
Service = "Priority",
Carrier = "USPS",
Rate = 1.00, // this rate is cheaper but doesn't meet the filters
TimeInTransit = new TimeInTransit
{
Percentile90 = 3,
},
},

new SmartRate
{
Service = "First",
Carrier = "USPS",
Rate = 6.07,
TimeInTransit = new TimeInTransit
{
Percentile90 = 2,
},
}

];

// test lowest SmartRate with valid filters
SmartRate lowestSmartRate = Utilities.Rates.GetLowestSmartRate(smartRates, 2, SmartRateAccuracy.Percentile90);
Assert.Equal("First", lowestSmartRate.Service);
Assert.Equal(6.07, lowestSmartRate.Rate);
Assert.Equal("USPS", lowestSmartRate.Carrier);

// test lowest SmartRate with invalid filters (should error due to strict delivery_days)
await Assert.ThrowsAsync<FilteringError>(() => Task.FromResult(Utilities.Rates.GetLowestSmartRate(smartRates, 0, SmartRateAccuracy.Percentile90)));
}

#endregion
}
}
Loading
Loading