Implement basic shipping with XPS Ship API

This commit is contained in:
Nathan Chapman 2023-11-17 22:31:21 -07:00
parent 520142fd62
commit f65169ebbc
3 changed files with 95 additions and 67 deletions

View File

@ -5,8 +5,7 @@ from django.db.models import Q
from measurement.measures import Weight
from core.usps import USPSApi
from core.exceptions import USPSPostageError, ShippingAddressError
from core.xps import get_quote
from core.models import (
ShippingRate,
SiteSettings,
@ -43,42 +42,27 @@ def get_shipping_container_from_choices(choices):
return SiteSettings.load().default_shipping_rate.container
return choices[0].container
# - A 48 36
# - B 80 48 60 72 64 80 96
# - Small mailing box: 12 24 16 32
# - Shoe box: 48 64
# - Large flat rate box: 96 128
def get_shipping_cost(total_weight, postal_code):
if not total_weight > Weight(lb=0):
return Decimal('0.00')
container = get_shipping_container_from_choices(
get_shipping_container_choices_from_weight(total_weight)
)
container = "box_a"
if total_weight <= Weight(lb=3):
container = "box_a"
elif total_weight <= Weight(lb=6):
container = "box_b"
else:
container = "large_flat_rate_box"
usps_rate_request = build_usps_rate_request(
str(total_weight.lb), container, str(postal_code)
)
usps = USPSApi(SiteSettings.load().usps_user_id)
try:
validation = usps.get_rate(usps_rate_request)
except ConnectionError as e:
raise e(
'Could not connect to USPS, try again.'
)
logger.info(validation.result)
try:
postage = dict(
validation.result['RateV4Response']['Package']['Postage']
)
except KeyError:
raise USPSPostageError(
'Could not retrieve postage.'
)
if usps_rate_request['service'] == ShippingContainer.PRIORITY:
shipping_cost = Decimal(postage['Rate'])
elif usps_rate_request['service'] == ShippingContainer.PRIORITY_COMMERCIAL:
shipping_cost = Decimal(postage['CommercialRate'])
shipping_cost = get_quote(postal_code, total_weight, container)
return shipping_cost

View File

@ -10,12 +10,78 @@ customer_id = "12375190"
headers = {'Authorization': 'RSIS ' + api_key, 'Content-Type': 'application/json'}
base_url = "https://xpsshipper.com/restapi/v1/customers/" + customer_id
def get_container(weight, name):
containers = {
"box_a": {
"type_code": "usps_custom_package",
"dim_unit": "in",
"pieces": {
"weight": weight,
"length": "10.125",
"width": "7.125",
"height": "5",
"insuranceAmount": None,
"declaredValue": None
}
},
"box_b": {
"type_code": "usps_custom_package",
"dim_unit": "in",
"pieces": {
"weight": weight,
"length": "13",
"width": "11",
"height": "6",
"insuranceAmount": None,
"declaredValue": None
}
},
"large_flat_rate_box": {
"type_code": "usps_large_flat_rate_box",
"dim_unit": None,
"pieces": {
"weight": weight,
"length": None,
"width": None,
"height": None,
"insuranceAmount": None,
"declaredValue": None
}
}
}
return containers[name]
def get_quote(weight):
def get_quote(destination_zip, weight, container):
data = get_data(destination_zip, weight, container)
resp = request("/quote", data)
return resp["totalAmount"]
def request(url, data):
r = requests.post(base_url + url, headers=headers, data=json.dumps(data))
return r.json()
def get_data(destination_zip, weight, container):
container = get_container(weight, container)
data = {
"carrierCode": "usps",
"serviceCode": "usps_priority",
"packageTypeCode": container["type_code"],
"signatureOptionCode": "NO_SIGNATURE_REQUIRED",
"sender": {
"country": "US",
"zip": "98368"
},
"receiver": {
"country": "US",
"zip": destination_zip
},
"residential": True,
"weightUnit": "lb",
"dimUnit": container["dim_unit"],
"currency": "USD",
"customsCurrency": "USD",
"pieces": [ container["pieces"] ]
}
return data

View File

@ -14,8 +14,8 @@ from core.models import (
ProductCategory, Product, ProductVariant, OrderLine, Coupon, ShippingRate,
SiteSettings
)
from core.usps import USPSApi
from core.exceptions import USPSPostageError, ShippingAddressError
from core.xps import get_data, get_quote
from core import (
DiscountValueType,
VoucherType,
@ -259,42 +259,20 @@ class Cart:
return Decimal('0.00')
if len(self) > 0 and self.session.get('shipping_address'):
usps_rate_request = build_usps_rate_request(
str(self.total_weight.lb),
container,
str(self.session.get('shipping_address')['postal_code'])
)
postal_code = str(self.session.get('shipping_address')['postal_code'])
usps = USPSApi(self.site_settings.usps_user_id)
container = "box_a"
try:
validation = usps.get_rate(usps_rate_request)
except ConnectionError as e:
raise e(
'Could not connect to USPS, try again.'
)
if self.total_weight <= Weight(lb=3):
container = "box_a"
elif self.total_weight <= Weight(lb=6):
container = "box_b"
else:
container = "large_flat_rate_box"
logger.info(validation.result)
try:
postage = dict(
validation.result['RateV4Response']['Package']['Postage']
)
except KeyError:
logger.warning(validation.result)
raise USPSPostageError(
'Could not retrieve postage.'
)
shipping_price = get_quote(postal_code, str(self.total_weight.lb), container)
if usps_rate_request['service'] == ShippingContainer.PRIORITY:
shipping_price = Decimal(postage['Rate'])
elif usps_rate_request['service'] == ShippingContainer.PRIORITY_COMMERCIAL:
shipping_price = Decimal(postage['CommercialRate'])
return shipping_price
else:
raise ShippingAddressError(
'Could not retrieve shipping address.'
)
return Decimal(shipping_price)
def create_order(self):
params = self.build_order_params()