Skip to content

Commit

Permalink
Merge pull request #338 from EasyPost/smartrate_service
Browse files Browse the repository at this point in the history
feat: adds new recommend_ship_date and estimate_delivery_date functions
  • Loading branch information
Justintime50 authored Jul 10, 2024
2 parents 3970032 + 05fb39e commit 8ea650a
Show file tree
Hide file tree
Showing 12 changed files with 1,747 additions and 137 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next Release

- Adds new `shipment.recommend_ship_date`, `smartrate.recommend_ship_date`, and `smartrate.estimate_delivery_date` functions
- Routes `UpsAccount`, `UpsMailInnovationsAccount`, and `UpsSurepostAccount` create/update requests to the new `/ups_oauth_registrations` endpoint
- Starting `2024-08-05`, UPS accounts will require a new payload to register or update. See [UPS OAuth 2.0 Update](https://support.easypost.com/hc/en-us/articles/26635027512717-UPS-OAuth-2-0-Update?utm_medium=email&_hsenc=p2ANqtz-96MmFtWICOzy9sKRbbcZSiMovZSrY3MSX1_bgY9N3f9yLVfWQdLhjAGq-SmNcOnDIS6GYhZ0OApjDBrGkKyLLMx1z6_TFOVp6-wllhEFQINrkuRuc&_hsmi=313130292&utm_content=313130292&utm_source=hs_email) for more details

Expand Down
2 changes: 2 additions & 0 deletions easypost/easypost_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
ReportService,
ScanFormService,
ShipmentService,
SmartRateService,
TrackerService,
UserService,
WebhookService,
Expand Down Expand Up @@ -75,6 +76,7 @@ def __init__(
self.report = ReportService(self)
self.scan_form = ScanFormService(self)
self.shipment = ShipmentService(self)
self.smartrate = SmartRateService(self)
self.tracker = TrackerService(self)
self.user = UserService(self)
self.webhook = WebhookService(self)
Expand Down
1 change: 1 addition & 0 deletions easypost/services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from easypost.services.report_service import ReportService
from easypost.services.scan_form_service import ScanFormService
from easypost.services.shipment_service import ShipmentService
from easypost.services.smartrate_service import SmartRateService
from easypost.services.tracker_service import TrackerService
from easypost.services.user_service import UserService
from easypost.services.webhook_service import WebhookService
10 changes: 10 additions & 0 deletions easypost/services/shipment_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,13 @@ def retrieve_estimated_delivery_date(self, id: str, planned_ship_date: str) -> L
response = Requestor(self._client).request(method=RequestMethod.GET, url=url, params=wrapped_params)

return convert_to_easypost_object(response=response.get("rates", []))

def recommend_ship_date(self, id: str, **params) -> List[Dict[str, Any]]:
"""Retrieve a recommended ship date for an existing Shipment via the Precision Shipping API,
based on a specific desired delivery date.
"""
url = f"{self._instance_url(self._model_class, id)}/smartrate/precision_shipping"

response = Requestor(self._client).request(method=RequestMethod.GET, url=url, params=params)

return convert_to_easypost_object(response=response.get("rates", []))
38 changes: 38 additions & 0 deletions easypost/services/smartrate_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import (
Any,
Dict,
List,
)

from easypost.easypost_object import convert_to_easypost_object
from easypost.requestor import (
RequestMethod,
Requestor,
)
from easypost.services.base_service import BaseService


class SmartRateService(BaseService):
def __init__(self, client):
self._client = client
self._model_class = "Smartrate"

def estimate_delivery_date(self, **params) -> List[Dict[str, Any]]:
"""Retrieve the estimated delivery date of each carrier-service level combination via the
Smart Deliver By API, based on a specific ship date and origin-destination postal code pair.
"""
url = "/smartrate/deliver_by"

response = Requestor(self._client).request(method=RequestMethod.POST, url=url, params=params)

return convert_to_easypost_object(response=response)

def recommend_ship_date(self, **params) -> List[Dict[str, Any]]:
"""Retrieve a recommended ship date for each carrier-service level combination via the
Smart Deliver On API, based on a specific delivery date and origin-destination postal code pair.
"""
url = "/smartrate/deliver_on"

response = Requestor(self._client).request(method=RequestMethod.POST, url=url, params=params)

return convert_to_easypost_object(response=response)
792 changes: 656 additions & 136 deletions tests/cassettes/test_retrieve_estimated_delivery_date.yaml

Large diffs are not rendered by default.

801 changes: 801 additions & 0 deletions tests/cassettes/test_shipment_recommend_ship_date.yaml

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions tests/cassettes/test_smartrate_estimate_delivery_date.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions tests/cassettes/test_smartrate_recommend_ship_date.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,9 @@ def rma_form_options():

@pytest.fixture
def planned_ship_date():
return "2023-12-28"
return "2024-07-11"


@pytest.fixture
def desired_delivery_date():
return "2024-07-16"
10 changes: 10 additions & 0 deletions tests/test_shipment.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,13 @@ def test_retrieve_estimated_delivery_date(basic_shipment, planned_ship_date, tes
rates = test_client.shipment.retrieve_estimated_delivery_date(shipment.id, planned_ship_date=planned_ship_date)

assert all(entry.get("easypost_time_in_transit_data") for entry in rates)


@pytest.mark.vcr()
def test_shipment_recommend_ship_date(basic_shipment, desired_delivery_date, test_client):
"""Test that we retrieve SmartRates when providing a shipment and desired delivery date."""
shipment = test_client.shipment.create(**basic_shipment)

rates = test_client.shipment.recommend_ship_date(shipment.id, desired_delivery_date=desired_delivery_date)

assert all(entry.get("easypost_time_in_transit_data") for entry in rates)
45 changes: 45 additions & 0 deletions tests/test_smartrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest


@pytest.mark.vcr()
def test_smartrate_estimate_delivery_date(
basic_shipment,
ca_address_1,
ca_address_2,
planned_ship_date,
usps,
test_client,
):
"""Test that we retrieve SmartRates when provided a from/to zip and planned ship date."""
params = {
"from_zip": ca_address_1["zip"],
"to_zip": ca_address_2["zip"],
"planned_ship_date": planned_ship_date,
"carriers": [usps],
}

rates = test_client.smartrate.estimate_delivery_date(**params)

assert all(entry.get("easypost_time_in_transit_data") for entry in rates["results"])


@pytest.mark.vcr()
def test_smartrate_recommend_ship_date(
basic_shipment,
ca_address_1,
ca_address_2,
desired_delivery_date,
usps,
test_client,
):
"""Test that we retrieve SmartRates when provided a from/to zip and desired delivery date."""
params = {
"from_zip": ca_address_1["zip"],
"to_zip": ca_address_2["zip"],
"desired_delivery_date": desired_delivery_date,
"carriers": [usps],
}

rates = test_client.smartrate.recommend_ship_date(**params)

assert all(entry.get("easypost_time_in_transit_data") for entry in rates["results"])

0 comments on commit 8ea650a

Please sign in to comment.