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_CLIENT_ID = os.environ.get('PAYPAL_CLIENT_ID', '')
|
||||||
PAYPAL_SECRET_ID = os.environ.get('PAYPAL_SECRET_ID', '')
|
PAYPAL_SECRET_ID = os.environ.get('PAYPAL_SECRET_ID', '')
|
||||||
|
USPS_USER_ID = os.environ.get('USPS_USER_ID', '639NATHA3105')
|
||||||
|
|
||||||
ANYMAIL_CONFIG = {
|
ANYMAIL_CONFIG = {
|
||||||
'MAILGUN_API_KEY': os.environ.get('MAILGUN_API_KEY', ''),
|
'MAILGUN_API_KEY': os.environ.get('MAILGUN_API_KEY', ''),
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
:root {
|
:root {
|
||||||
--fg-color: #34201a;
|
--fg-color: #34201a;
|
||||||
--fg-alt-color: #663a2d;
|
--fg-alt-color: #663a2d;
|
||||||
--bg-color: #f5f5f5;
|
--bg-color: #fffbf8;
|
||||||
--bg-alt-color: #c8a783;
|
--bg-alt-color: #b07952;
|
||||||
--gray-color: #9d9d9d;
|
--gray-color: #9d9d9d;
|
||||||
--yellow-color: #f8a911;
|
--yellow-color: #f8a911;
|
||||||
--yellow-alt-color: #ffce6f;
|
--yellow-alt-color: #ffce6f;
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from django.conf import settings
|
|||||||
from core.models import Product, OrderLine, Coupon
|
from core.models import Product, OrderLine, Coupon
|
||||||
from .payments import CreateOrder
|
from .payments import CreateOrder
|
||||||
|
|
||||||
|
from core.usps import USPSApiWithRate
|
||||||
from core import (
|
from core import (
|
||||||
DiscountValueType,
|
DiscountValueType,
|
||||||
VoucherType,
|
VoucherType,
|
||||||
@ -63,6 +64,39 @@ class Cart:
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
return sum(item['quantity'] for item in self.cart.values())
|
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):
|
def get_total_price(self):
|
||||||
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())
|
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()}',
|
'total_price': f'{self.get_total_price_after_discount()}',
|
||||||
'item_total': f'{self.get_total_price()}',
|
'item_total': f'{self.get_total_price()}',
|
||||||
'discount': f'{self.get_discount()}',
|
'discount': f'{self.get_discount()}',
|
||||||
'shipping_price': '0',
|
'shipping_price': f'{self.get_shipping_cost()}',
|
||||||
'tax_total': '0',
|
'tax_total': '0',
|
||||||
'shipping_method': 'US POSTAL SERVICE',
|
'shipping_method': 'US POSTAL SERVICE',
|
||||||
'shipping_address': self.build_shipping_address(self.session.get('shipping_address')),
|
'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 round((self.coupon.discount_value / Decimal('100')) * self.get_total_price(), 2)
|
||||||
return Decimal('0')
|
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)
|
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">
|
<table class="cart__totals">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Subtotal</td>
|
<td>Subtotal</td>
|
||||||
<td>${{cart.get_total_price|floatformat:"2"}}</td>
|
<td>${{ cart.get_total_price|floatformat:"2" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if cart.coupon %}
|
{% if cart.coupon %}
|
||||||
<tr>
|
<tr>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total</th>
|
<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>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -62,6 +62,10 @@
|
|||||||
<td>{{cart.coupon.discount_value}} {{cart.coupon.get_discount_value_type_display}}</td>
|
<td>{{cart.coupon.discount_value}} {{cart.coupon.get_discount_value_type_display}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<td>Shipping</td>
|
||||||
|
<td>${{ cart.get_shipping_cost }}</small></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total</th>
|
<th>Total</th>
|
||||||
<td><strong>${{cart.get_total_price_after_discount|floatformat:"2"}}</strong></td>
|
<td><strong>${{cart.get_total_price_after_discount|floatformat:"2"}}</strong></td>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user