diff --git a/src/core/usps.py b/src/core/usps.py new file mode 100644 index 0000000..64e6f34 --- /dev/null +++ b/src/core/usps.py @@ -0,0 +1,38 @@ +import json +import requests +import xmltodict + +from lxml import etree +from usps import USPSApi + +class USPSApiWithRate(USPSApi): + urls = { + 'tracking': 'TrackV2{test}&XML={xml}', + 'label': 'eVS{test}&XML={xml}', + 'validate': 'Verify&XML={xml}', + 'rate': 'RateV4&XML={xml}', + } + + def get_rate(self, *args, **kwargs): + return Rate(self, *args, **kwargs) + + +class Rate: + + def __init__(self, usps, box, **kwargs): + xml = etree.Element('RateV4Request', {'USERID': usps.api_user_id}) + etree.SubElement(xml, 'Revision').text = '2' + package = etree.SubElement(xml, 'Package', {'ID': '0'}) + etree.SubElement(package, 'Service').text = box['service'] + etree.SubElement(package, 'ZipOrigination').text = box['zip_origination'] + etree.SubElement(package, 'ZipDestination').text = box['zip_destination'] + etree.SubElement(package, 'Pounds').text = box['pounds'] + etree.SubElement(package, 'Ounces').text = box['ounces'] + etree.SubElement(package, 'Container').text = box['container'] + etree.SubElement(package, 'Width').text = box['width'] + etree.SubElement(package, 'Length').text = box['length'] + etree.SubElement(package, 'Height').text = box['height'] + etree.SubElement(package, 'Girth').text = box['girth'] + etree.SubElement(package, 'Machinable').text = box['machinable'] + + self.result = usps.send_request('rate', xml) diff --git a/src/ptcoffee/config.py b/src/ptcoffee/config.py index d6a6e0a..0ca241c 100644 --- a/src/ptcoffee/config.py +++ b/src/ptcoffee/config.py @@ -20,6 +20,7 @@ CACHE_CONFIG = { PAYPAL_CLIENT_ID = os.environ.get('PAYPAL_CLIENT_ID', '') PAYPAL_SECRET_ID = os.environ.get('PAYPAL_SECRET_ID', '') +USPS_USER_ID = os.environ.get('USPS_USER_ID', '639NATHA3105') ANYMAIL_CONFIG = { 'MAILGUN_API_KEY': os.environ.get('MAILGUN_API_KEY', ''), diff --git a/src/static/styles/main.css b/src/static/styles/main.css index e8fea5d..d217e48 100644 --- a/src/static/styles/main.css +++ b/src/static/styles/main.css @@ -1,8 +1,8 @@ :root { --fg-color: #34201a; --fg-alt-color: #663a2d; - --bg-color: #f5f5f5; - --bg-alt-color: #c8a783; + --bg-color: #fffbf8; + --bg-alt-color: #b07952; --gray-color: #9d9d9d; --yellow-color: #f8a911; --yellow-alt-color: #ffce6f; diff --git a/src/storefront/cart.py b/src/storefront/cart.py index 92e2ebd..2a73eb9 100644 --- a/src/storefront/cart.py +++ b/src/storefront/cart.py @@ -4,6 +4,7 @@ from django.conf import settings from core.models import Product, OrderLine, Coupon from .payments import CreateOrder +from core.usps import USPSApiWithRate from core import ( DiscountValueType, VoucherType, @@ -63,6 +64,39 @@ class Cart: def __len__(self): return sum(item['quantity'] for item in self.cart.values()) + def get_total_weight(self): + return sum([item['product'].weight.value * item['quantity'] for item in self.cart.values()]) + + def get_shipping_box(self): + logger.debug(len(self)) + + if len(self) > 6 and len(self) <= 10: + return "LG FLAT RATE BOX" + elif len(self) > 2 and len(self) <= 6: + return "REGIONALRATEBOXB" + elif len(self) <= 2: + return "REGIONALRATEBOXA" + else: + return "VARIABLE" + + def get_shipping_cost(self): + box = { + 'service': 'PRIORITY COMMERCIAL', + 'zip_origination': '98368', + 'zip_destination': f'{self.session.get("shipping_address")["postal_code"]}', + 'pounds': '0', + 'ounces': f'{self.get_total_weight()}', + 'container': f'{self.get_shipping_box()}', + 'width': '', + 'length': '', + 'height': '', + 'girth': '', + 'machinable': 'TRUE' + } + usps = USPSApiWithRate(settings.USPS_USER_ID, test=True) + validation = usps.get_rate(box) + return Decimal(validation.result['RateV4Response']['Package']['Postage']['CommercialRate']) + def get_total_price(self): return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values()) @@ -81,7 +115,7 @@ class Cart: 'total_price': f'{self.get_total_price_after_discount()}', 'item_total': f'{self.get_total_price()}', 'discount': f'{self.get_discount()}', - 'shipping_price': '0', + 'shipping_price': f'{self.get_shipping_cost()}', 'tax_total': '0', 'shipping_method': 'US POSTAL SERVICE', 'shipping_address': self.build_shipping_address(self.session.get('shipping_address')), @@ -130,5 +164,8 @@ class Cart: return round((self.coupon.discount_value / Decimal('100')) * self.get_total_price(), 2) return Decimal('0') - def get_total_price_after_discount(self): + def get_subtotal_price_after_discount(self): return round(self.get_total_price() - self.get_discount(), 2) + + def get_total_price_after_discount(self): + return round(self.get_total_price() - self.get_discount() + self.get_shipping_cost(), 2) diff --git a/src/storefront/templates/storefront/cart_detail.html b/src/storefront/templates/storefront/cart_detail.html index 9312e1d..41353c8 100644 --- a/src/storefront/templates/storefront/cart_detail.html +++ b/src/storefront/templates/storefront/cart_detail.html @@ -51,7 +51,7 @@ - + {% if cart.coupon %} @@ -61,7 +61,7 @@ {% endif %} - +
Subtotal${{cart.get_total_price|floatformat:"2"}}${{ cart.get_total_price|floatformat:"2" }}
Total${{cart.get_total_price_after_discount|floatformat:"2"}}${{cart.get_subtotal_price_after_discount|floatformat:"2"}}
diff --git a/src/storefront/templates/storefront/order_form.html b/src/storefront/templates/storefront/order_form.html index cc93262..6880b4d 100644 --- a/src/storefront/templates/storefront/order_form.html +++ b/src/storefront/templates/storefront/order_form.html @@ -62,6 +62,10 @@ {{cart.coupon.discount_value}} {{cart.coupon.get_discount_value_type_display}} {% endif %} + + Shipping + ${{ cart.get_shipping_cost }} + Total ${{cart.get_total_price_after_discount|floatformat:"2"}}