ptcoffee_django/core/shipping.py
2023-01-21 14:15:36 -07:00

102 lines
2.7 KiB
Python

import logging
from decimal import Decimal
from django.conf import settings
from django.db.models import Q
from measurement.measures import Weight
from core.usps import USPSApi
from core.exceptions import USPSPostageError, ShippingAddressError
from core.models import (
ShippingRate,
SiteSettings,
)
from core import (
ShippingService,
ShippingProvider,
ShippingContainer
)
logger = logging.getLogger(__name__)
def get_shipping_container_choices_from_weight(weight):
is_selectable = Q(
is_selectable=True
)
min_weight_matched = Q(
min_order_weight__lte=weight) | Q(
min_order_weight__isnull=True
)
max_weight_matched = Q(
max_order_weight__gte=weight) | Q(
max_order_weight__isnull=True
)
containers = ShippingRate.objects.filter(
is_selectable & min_weight_matched & max_weight_matched
)
return containers
def get_shipping_container_from_choices(choices):
if len(choices) == 0:
return SiteSettings.load().default_shipping_rate.container
return choices[0].container
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)
)
usps_rate_request = build_usps_rate_request(
str(total_weight.lb), container, str(postal_code)
)
usps = USPSApi(SiteSettings.load().usps_user_id, test=settings.DEBUG)
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'])
return shipping_cost
def build_usps_rate_request(weight, container, zip_destination):
service = ShippingContainer.get_shipping_service_from_container(container)
return \
{
'service': service,
'zip_origination': SiteSettings.load().default_zip_origination,
'zip_destination': zip_destination,
'pounds': weight,
'ounces': '0',
'container': container,
'width': '',
'length': '',
'height': '',
'girth': '',
'machinable': 'TRUE'
}