Add basic shipping functionality

This commit is contained in:
Nathan Chapman 2022-04-23 15:17:11 -06:00
parent a41d75e713
commit c330acc5f6
6 changed files with 86 additions and 6 deletions

38
src/core/usps.py Normal file
View File

@ -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)

View File

@ -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', ''),

View File

@ -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;

View File

@ -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)

View File

@ -51,7 +51,7 @@
<table class="cart__totals">
<tr>
<td>Subtotal</td>
<td>${{cart.get_total_price|floatformat:"2"}}</td>
<td>${{ cart.get_total_price|floatformat:"2" }}</td>
</tr>
{% if cart.coupon %}
<tr>
@ -61,7 +61,7 @@
{% endif %}
<tr>
<th>Total</th>
<td><strong>${{cart.get_total_price_after_discount|floatformat:"2"}}</strong></td>
<td><strong>${{cart.get_subtotal_price_after_discount|floatformat:"2"}}</strong></td>
</tr>
</table>
</div>

View File

@ -62,6 +62,10 @@
<td>{{cart.coupon.discount_value}} {{cart.coupon.get_discount_value_type_display}}</td>
</tr>
{% endif %}
<tr>
<td>Shipping</td>
<td>${{ cart.get_shipping_cost }}</small></td>
</tr>
<tr>
<th>Total</th>
<td><strong>${{cart.get_total_price_after_discount|floatformat:"2"}}</strong></td>