Add more refined way to calculating shipping
This commit is contained in:
parent
67070483da
commit
b1af78e7e0
@ -1,4 +1,5 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from measurement.measures import Weight
|
||||||
|
|
||||||
|
|
||||||
class DiscountValueType:
|
class DiscountValueType:
|
||||||
@ -49,12 +50,25 @@ class OrderStatus:
|
|||||||
|
|
||||||
|
|
||||||
class TransactionStatus:
|
class TransactionStatus:
|
||||||
CREATED = 'CREATED' # The order was created with the specified context.
|
# The order was created with the specified context.
|
||||||
SAVED = 'SAVED' # The order was saved and persisted. The order status continues to be in progress until a capture is made with final_capture = true for all purchase units within the order.
|
CREATED = 'CREATED'
|
||||||
APPROVED = 'APPROVED' # The customer approved the payment through the PayPal wallet or another form of guest or unbranded payment. For example, a card, bank account, or so on.
|
# The order was saved and persisted. The order status continues to
|
||||||
VOIDED = 'VOIDED' # All purchase units in the order are voided.
|
# be in progress until a capture is made with final_capture = true
|
||||||
COMPLETED = 'COMPLETED' # The payment was authorized or the authorized payment was captured for the order.
|
# for all purchase units within the order.
|
||||||
PAYER_ACTION_REQUIRED = 'PAYER_ACTION_REQUIRED' # The order requires an action from the payer (e.g. 3DS authentication). Redirect the payer to the 'rel':'payer-action' HATEOAS link returned as part of the response prior to authorizing or capturing the order.
|
SAVED = 'SAVED'
|
||||||
|
# The customer approved the payment through the PayPal wallet or
|
||||||
|
# another form of guest or unbranded payment. For example, a card,
|
||||||
|
# bank account, or so on.
|
||||||
|
APPROVED = 'APPROVED'
|
||||||
|
# All purchase units in the order are voided.
|
||||||
|
VOIDED = 'VOIDED'
|
||||||
|
# The payment was authorized or the authorized payment was captured
|
||||||
|
# for the order.
|
||||||
|
COMPLETED = 'COMPLETED'
|
||||||
|
# The order requires an action from the payer (e.g. 3DS authentication).
|
||||||
|
# Redirect the payer to the 'rel':'payer-action' HATEOAS link returned as
|
||||||
|
# part of the response prior to authorizing or capturing the order.
|
||||||
|
PAYER_ACTION_REQUIRED = 'PAYER_ACTION_REQUIRED'
|
||||||
|
|
||||||
CHOICES = [
|
CHOICES = [
|
||||||
(CREATED, 'Created'),
|
(CREATED, 'Created'),
|
||||||
@ -68,6 +82,7 @@ class TransactionStatus:
|
|||||||
|
|
||||||
class ShippingProvider:
|
class ShippingProvider:
|
||||||
USPS = 'USPS'
|
USPS = 'USPS'
|
||||||
|
USPS_MAX_SHIPPING_WEIGHT = Weight(lb=70)
|
||||||
# UPS = 'UPS'
|
# UPS = 'UPS'
|
||||||
# FEDEX = 'FEDEX'
|
# FEDEX = 'FEDEX'
|
||||||
|
|
||||||
@ -91,20 +106,68 @@ class ShippingService:
|
|||||||
|
|
||||||
|
|
||||||
class ShippingContainer:
|
class ShippingContainer:
|
||||||
LG_FLAT_RATE_BOX = 'LG FLAT RATE BOX'
|
PRIORITY = 'PRIORITY'
|
||||||
|
PRIORITY_COMMERCIAL = 'PRIORITY COMMERCIAL'
|
||||||
|
|
||||||
|
# PRIORITY
|
||||||
|
FLAT_RATE_ENVELOPE = 'FLAT RATE ENVELOPE'
|
||||||
|
LEGAL_FLAT_RATE_ENVELOPE = 'LEGAL FLAT RATE ENVELOPE'
|
||||||
|
PADDED_FLAT_RATE_ENVELOPE = 'PADDED FLAT RATE ENVELOPE'
|
||||||
|
SM_FLAT_RATE_ENVELOPE = 'SM FLAT RATE ENVELOPE'
|
||||||
|
WINDOW_FLAT_RATE_ENVELOPE = 'WINDOW FLAT RATE ENVELOPE'
|
||||||
|
GIFT_CARD_FLAT_RATE_ENVELOPE = 'GIFT CARD FLAT RATE ENVELOPE'
|
||||||
|
SM_FLAT_RATE_BOX = 'SM FLAT RATE BOX'
|
||||||
MD_FLAT_RATE_BOX = 'MD FLAT RATE BOX'
|
MD_FLAT_RATE_BOX = 'MD FLAT RATE BOX'
|
||||||
REGIONAL_RATE_BOX_A = 'REGIONALRATEBOXA'
|
LG_FLAT_RATE_BOX = 'LG FLAT RATE BOX'
|
||||||
REGIONAL_RATE_BOX_B = 'REGIONALRATEBOXB'
|
|
||||||
VARIABLE = 'VARIABLE'
|
VARIABLE = 'VARIABLE'
|
||||||
|
|
||||||
|
# PRIORITY_COMMERCIAL
|
||||||
|
REGIONAL_RATE_BOX_A = 'REGIONALRATEBOXA'
|
||||||
|
REGIONAL_RATE_BOX_B = 'REGIONALRATEBOXB'
|
||||||
|
|
||||||
CHOICES = [
|
CHOICES = [
|
||||||
(LG_FLAT_RATE_BOX, 'Flate Rate Box - Large'),
|
(
|
||||||
(MD_FLAT_RATE_BOX, 'Flate Rate Box - Medium'),
|
PRIORITY, (
|
||||||
(REGIONAL_RATE_BOX_A, 'Regional Rate Box A'),
|
(FLAT_RATE_ENVELOPE, 'Flat Rate Envelope'),
|
||||||
(REGIONAL_RATE_BOX_B, 'Regional Rate Box B'),
|
(LEGAL_FLAT_RATE_ENVELOPE, 'Legal Flat Rate Envelope'),
|
||||||
(VARIABLE, 'Variable')
|
(PADDED_FLAT_RATE_ENVELOPE, 'Padded Flat Rate Envelope'),
|
||||||
|
(SM_FLAT_RATE_ENVELOPE, 'Sm Flat Rate Envelope'),
|
||||||
|
(WINDOW_FLAT_RATE_ENVELOPE, 'Window Flat Rate Envelope'),
|
||||||
|
(GIFT_CARD_FLAT_RATE_ENVELOPE, 'Gift Card Flat Rate Envelope'),
|
||||||
|
(SM_FLAT_RATE_BOX, 'Sm Flat Rate Box'),
|
||||||
|
(MD_FLAT_RATE_BOX, 'Md Flat Rate Box'),
|
||||||
|
(LG_FLAT_RATE_BOX, 'Lg Flat Rate Box'),
|
||||||
|
(VARIABLE, 'Variable'),
|
||||||
|
)
|
||||||
|
), (
|
||||||
|
PRIORITY_COMMERCIAL, (
|
||||||
|
(REGIONAL_RATE_BOX_A, 'Regional Rate Box A'),
|
||||||
|
(REGIONAL_RATE_BOX_B, 'Regional Rate Box B'),
|
||||||
|
)
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
SERVICE_FROM_CONTAINER = {
|
||||||
|
# PRIORITY
|
||||||
|
FLAT_RATE_ENVELOPE: PRIORITY,
|
||||||
|
LEGAL_FLAT_RATE_ENVELOPE: PRIORITY,
|
||||||
|
PADDED_FLAT_RATE_ENVELOPE: PRIORITY,
|
||||||
|
SM_FLAT_RATE_ENVELOPE: PRIORITY,
|
||||||
|
WINDOW_FLAT_RATE_ENVELOPE: PRIORITY,
|
||||||
|
GIFT_CARD_FLAT_RATE_ENVELOPE: PRIORITY,
|
||||||
|
SM_FLAT_RATE_BOX: PRIORITY,
|
||||||
|
MD_FLAT_RATE_BOX: PRIORITY,
|
||||||
|
LG_FLAT_RATE_BOX: PRIORITY,
|
||||||
|
VARIABLE: PRIORITY,
|
||||||
|
|
||||||
|
# PRIORITY_COMMERCIAL
|
||||||
|
REGIONAL_RATE_BOX_A: PRIORITY_COMMERCIAL,
|
||||||
|
REGIONAL_RATE_BOX_B: PRIORITY_COMMERCIAL,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_shipping_service_from_container(container):
|
||||||
|
return ShippingContainer.SERVICE_FROM_CONTAINER[container]
|
||||||
|
|
||||||
|
|
||||||
class CoffeeGrind:
|
class CoffeeGrind:
|
||||||
WHOLE = 'whole-beans'
|
WHOLE = 'whole-beans'
|
||||||
@ -130,9 +193,10 @@ class CoffeeGrind:
|
|||||||
|
|
||||||
|
|
||||||
def build_usps_rate_request(weight, container, zip_destination):
|
def build_usps_rate_request(weight, container, zip_destination):
|
||||||
|
service = ShippingContainer.get_shipping_service_from_container(container)
|
||||||
return \
|
return \
|
||||||
{
|
{
|
||||||
'service': ShippingService.PRIORITY_COMMERCIAL,
|
'service': service,
|
||||||
'zip_origination': settings.DEFAULT_ZIP_ORIGINATION,
|
'zip_origination': settings.DEFAULT_ZIP_ORIGINATION,
|
||||||
'zip_destination': zip_destination,
|
'zip_destination': zip_destination,
|
||||||
'pounds': weight,
|
'pounds': weight,
|
||||||
|
|||||||
13
src/core/exceptions.py
Normal file
13
src/core/exceptions.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
class Error(Exception):
|
||||||
|
"""Base class for other exceptions"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class USPSPostageError(Error):
|
||||||
|
"""Raised when the input value is too small"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ShippingAddressError(Error):
|
||||||
|
"""Raised when the input value is too large"""
|
||||||
|
pass
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 4.0.2 on 2022-11-25 21:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0011_alter_productvariant_image'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sitesettings',
|
||||||
|
name='max_cart_quantity',
|
||||||
|
field=models.PositiveIntegerField(default=20),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='shippingrate',
|
||||||
|
name='container',
|
||||||
|
field=models.CharField(choices=[('PRIORITY', (('FLAT RATE ENVELOPE', 'Flat Rate Envelope'), ('LEGAL FLAT RATE ENVELOPE', 'Legal Flat Rate Envelope'), ('PADDED FLAT RATE ENVELOPE', 'Padded Flat Rate Envelope'), ('SM FLAT RATE ENVELOPE', 'Sm Flat Rate Envelope'), ('WINDOW FLAT RATE ENVELOPE', 'Window Flat Rate Envelope'), ('GIFT CARD FLAT RATE ENVELOPE', 'Gift Card Flat Rate Envelope'), ('SM FLAT RATE BOX', 'Sm Flat Rate Box'), ('MD FLAT RATE BOX', 'Md Flat Rate Box'), ('LG FLAT RATE BOX', 'Lg Flat Rate Box'), ('VARIABLE', 'Variable'))), ('PRIORITY COMMERCIAL', (('REGIONALRATEBOXA', 'Regional Rate Box A'), ('REGIONALRATEBOXB', 'Regional Rate Box B')))], default='VARIABLE', max_length=255),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -516,6 +516,9 @@ class SiteSettings(SingletonBase):
|
|||||||
null=True,
|
null=True,
|
||||||
help_text='Minimum dollar amount in the cart subtotal to qualify for free shipping'
|
help_text='Minimum dollar amount in the cart subtotal to qualify for free shipping'
|
||||||
)
|
)
|
||||||
|
max_cart_quantity = models.PositiveIntegerField(
|
||||||
|
default=20
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'Site Settings'
|
return 'Site Settings'
|
||||||
|
|||||||
@ -8,18 +8,21 @@ from django.shortcuts import redirect, reverse
|
|||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db.models import OuterRef, Q, Subquery
|
from django.db.models import OuterRef, Q, Subquery
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from core.models import (
|
from core.models import (
|
||||||
ProductCategory, Product, ProductVariant, OrderLine, Coupon, ShippingRate,
|
ProductCategory, Product, ProductVariant, OrderLine, Coupon, ShippingRate,
|
||||||
SiteSettings
|
SiteSettings
|
||||||
)
|
)
|
||||||
from core.usps import USPSApi
|
from core.usps import USPSApi
|
||||||
|
from core.exceptions import USPSPostageError, ShippingAddressError
|
||||||
from core import (
|
from core import (
|
||||||
DiscountValueType,
|
DiscountValueType,
|
||||||
VoucherType,
|
VoucherType,
|
||||||
TransactionStatus,
|
TransactionStatus,
|
||||||
OrderStatus,
|
OrderStatus,
|
||||||
ShippingService,
|
ShippingService,
|
||||||
|
ShippingProvider,
|
||||||
ShippingContainer,
|
ShippingContainer,
|
||||||
CoffeeGrind,
|
CoffeeGrind,
|
||||||
build_usps_rate_request
|
build_usps_rate_request
|
||||||
@ -45,6 +48,14 @@ class CartItem:
|
|||||||
'quantity': self.quantity
|
'quantity': self.quantity
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_price(self):
|
||||||
|
return self.variant.price * self.quantity
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_weight(self):
|
||||||
|
return Weight(lb=self.variant.weight.lb * self.quantity)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
yield ('name', str(self.variant))
|
yield ('name', str(self.variant))
|
||||||
yield ('description', self.variant.product.subtitle)
|
yield ('description', self.variant.product.subtitle)
|
||||||
@ -55,7 +66,7 @@ class CartItem:
|
|||||||
yield ('quantity', f'{item["quantity"]}')
|
yield ('quantity', f'{item["quantity"]}')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.variant)
|
return f'{self.variant} [{self.quantity} × ${self.price}]'
|
||||||
|
|
||||||
|
|
||||||
class Cart:
|
class Cart:
|
||||||
@ -64,7 +75,7 @@ class Cart:
|
|||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
self.request = request
|
self.request = request
|
||||||
self.session = request.session
|
self.session = request.session
|
||||||
# self.site_settings = SiteSettings.load()
|
self.site_settings = SiteSettings.load()
|
||||||
self.coupon_code = self.session.get('coupon_code')
|
self.coupon_code = self.session.get('coupon_code')
|
||||||
cart = self.session.get(settings.CART_SESSION_ID)
|
cart = self.session.get(settings.CART_SESSION_ID)
|
||||||
if not cart:
|
if not cart:
|
||||||
@ -78,11 +89,9 @@ class Cart:
|
|||||||
self.add_or_update_item(item)
|
self.add_or_update_item(item)
|
||||||
|
|
||||||
# TODO: abstract this to a function that will check the max amount of item in the cart
|
# TODO: abstract this to a function that will check the max amount of item in the cart
|
||||||
if len(self) <= 20:
|
if self.check_max_cart_quantity(request) and self.check_max_shipping_weight(request):
|
||||||
self.check_item_stock_quantities(request)
|
self.check_item_stock_quantities(request)
|
||||||
self.save()
|
self.save()
|
||||||
else:
|
|
||||||
messages.warning(request, "Cart is full: 20 items or less.")
|
|
||||||
|
|
||||||
def add_or_update_item(self, new_item):
|
def add_or_update_item(self, new_item):
|
||||||
new_item_pk = int(new_item['variant'])
|
new_item_pk = int(new_item['variant'])
|
||||||
@ -115,6 +124,18 @@ class Cart:
|
|||||||
item['quantity'] = item['variant'].product.checkout_limit
|
item['quantity'] = item['variant'].product.checkout_limit
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
def check_max_cart_quantity(self, request):
|
||||||
|
if len(self) > self.site_settings.max_cart_quantity:
|
||||||
|
messages.warning(request, 'Cart is full: 20 items or less.')
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def check_max_shipping_weight(self, request):
|
||||||
|
if self.get_total_weight() > ShippingProvider.USPS_MAX_SHIPPING_WEIGHT.lb:
|
||||||
|
messages.warning(request, 'Weight exceeds shipping limit')
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def remove(self, pk):
|
def remove(self, pk):
|
||||||
self.cart.pop(pk)
|
self.cart.pop(pk)
|
||||||
self.save()
|
self.save()
|
||||||
@ -155,7 +176,7 @@ class Cart:
|
|||||||
|
|
||||||
def get_weight_for_all_items(self):
|
def get_weight_for_all_items(self):
|
||||||
for item in self:
|
for item in self:
|
||||||
yield round(Decimal(item['variant'].weight.value) * item['quantity'], 3)
|
yield round(item['variant'].weight.value * item['quantity'], 3)
|
||||||
|
|
||||||
def get_total_weight(self):
|
def get_total_weight(self):
|
||||||
if len(self) > 0:
|
if len(self) > 0:
|
||||||
@ -201,21 +222,31 @@ class Cart:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
validation = usps.get_rate(usps_rate_request)
|
validation = usps.get_rate(usps_rate_request)
|
||||||
except ConnectionError:
|
except ConnectionError as e:
|
||||||
raise ValidationError(
|
raise e(
|
||||||
'Could not connect to USPS, try again.'
|
'Could not connect to USPS, try again.'
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(validation.result)
|
logger.info(validation.result)
|
||||||
package = dict(validation.result['RateV4Response']['Package'])
|
try:
|
||||||
if 'Error' not in package:
|
postage = dict(
|
||||||
rate = package['Postage']['CommercialRate']
|
validation.result['RateV4Response']['Package']['Postage']
|
||||||
else:
|
)
|
||||||
logger.error('USPS Rate error')
|
except KeyError:
|
||||||
rate = '0.00'
|
raise USPSPostageError(
|
||||||
return Decimal(rate)
|
'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
|
||||||
else:
|
else:
|
||||||
return Decimal('0.00')
|
raise ShippingAddressError(
|
||||||
|
'Could not retrieve shipping address.'
|
||||||
|
)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
del self.session[settings.CART_SESSION_ID]
|
del self.session[settings.CART_SESSION_ID]
|
||||||
|
|||||||
@ -12,11 +12,91 @@ from accounts.models import User, Address
|
|||||||
from core.models import Product, ProductVariant, Order
|
from core.models import Product, ProductVariant, Order
|
||||||
from core import CoffeeGrind
|
from core import CoffeeGrind
|
||||||
from storefront.views import OrderCreateView
|
from storefront.views import OrderCreateView
|
||||||
from storefront.cart import Cart
|
from storefront.cart import CartItem, Cart
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CartItemTest(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.customer = User.objects.create_user(
|
||||||
|
username='petertempler',
|
||||||
|
email='peter@testing.com',
|
||||||
|
password='peterspassword321'
|
||||||
|
)
|
||||||
|
cls.product = Product.objects.create(
|
||||||
|
name="Dante's Tornado",
|
||||||
|
subtitle='Medium Roast',
|
||||||
|
description='Coffee',
|
||||||
|
checkout_limit=10,
|
||||||
|
visible_in_listings=True
|
||||||
|
)
|
||||||
|
cls.variant_1 = ProductVariant.objects.create(
|
||||||
|
product=cls.product,
|
||||||
|
name='12 oz',
|
||||||
|
sku='234987',
|
||||||
|
price=Decimal('12.00'),
|
||||||
|
weight=Weight(oz=12),
|
||||||
|
)
|
||||||
|
cls.variant_2 = ProductVariant.objects.create(
|
||||||
|
product=cls.product,
|
||||||
|
name='16 oz',
|
||||||
|
sku='987621',
|
||||||
|
price=Decimal('16.00'),
|
||||||
|
weight=Weight(oz=16),
|
||||||
|
)
|
||||||
|
cls.variant_3 = ProductVariant.objects.create(
|
||||||
|
product=cls.product,
|
||||||
|
name='16 oz',
|
||||||
|
sku='65432',
|
||||||
|
price=Decimal('75.00'),
|
||||||
|
weight=Weight(lb=5),
|
||||||
|
)
|
||||||
|
cls.order = Order.objects.create(
|
||||||
|
customer=cls.customer,
|
||||||
|
total_amount=Decimal('13.40')
|
||||||
|
)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.client = Client()
|
||||||
|
self.factory = RequestFactory()
|
||||||
|
|
||||||
|
self.client.force_login(self.customer)
|
||||||
|
self.client.session['shipping_address'] = {
|
||||||
|
'first_name': 'Nathan',
|
||||||
|
'last_name': 'Chapman',
|
||||||
|
'email': 'contact@nathanjchapman.com',
|
||||||
|
'street_address_1': '1504 N 230 E',
|
||||||
|
'street_address_2': '',
|
||||||
|
'city': 'North Logan',
|
||||||
|
'state': 'UT',
|
||||||
|
'postal_code': '84341'
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_calculates_total_weight(self):
|
||||||
|
cart_item = CartItem({
|
||||||
|
'options': {'Grind': 'Whole Beans'},
|
||||||
|
'quantity': 14,
|
||||||
|
'variant': self.variant_1
|
||||||
|
})
|
||||||
|
self.assertEqual(
|
||||||
|
cart_item.total_price,
|
||||||
|
Decimal('168.00')
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_calculates_total_price(self):
|
||||||
|
cart_item = CartItem({
|
||||||
|
'options': {'Grind': 'Whole Beans'},
|
||||||
|
'quantity': 14,
|
||||||
|
'variant': self.variant_1
|
||||||
|
})
|
||||||
|
self.assertEqual(
|
||||||
|
cart_item.total_weight,
|
||||||
|
Weight(lb=10.5)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CartTest(TestCase):
|
class CartTest(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
|
|||||||
@ -354,12 +354,7 @@ class OrderCreateView(CreateView):
|
|||||||
shipping_container = self.request.session.get(
|
shipping_container = self.request.session.get(
|
||||||
'shipping_container'
|
'shipping_container'
|
||||||
).container
|
).container
|
||||||
try:
|
shipping_cost = cart.get_shipping_cost(shipping_container)
|
||||||
shipping_cost = cart.get_shipping_cost(shipping_container)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('Could not get shipping information')
|
|
||||||
raise
|
|
||||||
shipping_cost = Decimal('0.00')
|
|
||||||
|
|
||||||
initial = {
|
initial = {
|
||||||
'total_amount': cart.get_total_price(),
|
'total_amount': cart.get_total_price(),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user