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) 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' }