Add basic shipping functionality
This commit is contained in:
parent
a41d75e713
commit
c330acc5f6
38
src/core/usps.py
Normal file
38
src/core/usps.py
Normal 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)
|
||||
@ -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', ''),
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user