Skip to content

Commit

Permalink
Add OSCAR_MAX_BASKET_QUANTITY_THRESHOLD
Browse files Browse the repository at this point in the history
  • Loading branch information
patrys committed Dec 15, 2011
1 parent a32db8c commit 8a38a5a
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 64 deletions.
48 changes: 33 additions & 15 deletions oscar/apps/basket/forms.py
@@ -1,4 +1,5 @@
from django import forms
from django.conf import settings
from django.db.models import get_model
from django.utils.translation import gettext_lazy as _

Expand All @@ -9,30 +10,30 @@

class BasketLineForm(forms.ModelForm):
save_for_later = forms.BooleanField(initial=False, required=False)

class Meta:
model = basketline_model
exclude = ('basket', 'product', 'line_reference', )


class SavedLineForm(forms.ModelForm):
move_to_basket = forms.BooleanField(initial=False, required=False)

class Meta:
model = basketline_model
exclude = ('basket', 'product', 'line_reference', 'quantity', )


class BasketVoucherForm(forms.Form):
code = forms.CharField(max_length=128)

def __init__(self, *args, **kwargs):
return super(BasketVoucherForm, self).__init__(*args,**kwargs)


class ProductSelectionForm(forms.Form):
product_id = forms.IntegerField(min_value=1)

def clean_product_id(self):
id = self.cleaned_data['product_id']

Expand All @@ -45,23 +46,40 @@ def clean_product_id(self):
class AddToBasketForm(forms.Form):
product_id = forms.IntegerField(widget=forms.HiddenInput(), min_value=1)
quantity = forms.IntegerField(initial=1, min_value=1)
def __init__(self, instance, *args, **kwargs):

def __init__(self, basket, instance, *args, **kwargs):
super(AddToBasketForm, self).__init__(*args, **kwargs)
self.basket = basket
self.instance = instance
if instance:
if instance.is_group:
self._create_group_product_fields(instance)
else:
self._create_product_fields(instance)

def clean_product_id(self):
id = self.cleaned_data['product_id']
product = Product.objects.get(id=id)
if not product.has_stockrecord or not product.stockrecord.is_available_to_buy:
raise forms.ValidationError(_("This product is not available for purchase"))
return id

def clean_quantity(self):
qty = self.cleaned_data['quantity']
basket_threshold = settings.OSCAR_MAX_BASKET_QUANTITY_THRESHOLD
if basket_threshold:
total_basket_quantity = self.basket.num_items
max_allowed = basket_threshold - total_basket_quantity
if qty > max_allowed:
raise forms.ValidationError(
_("Due to technical limitations we are not able to ship"
" more than %(threshold)d items in one order. Your basket"
" currently has %(basket)d items.") % {
'threshold': basket_threshold,
'basket': total_basket_quantity,
})
return qty

def _create_group_product_fields(self, item):
"""
Adds the fields for a "group"-type product (eg, a parent product with a
Expand All @@ -70,23 +88,23 @@ def _create_group_product_fields(self, item):
choices = []
for variant in item.variants.all():
if variant.has_stockrecord:
summary = u"%s (%s) - %.2f" % (variant.get_title(), variant.attribute_summary(),
summary = u"%s (%s) - %.2f" % (variant.get_title(), variant.attribute_summary(),
variant.stockrecord.price_incl_tax)
choices.append((variant.id, summary))
self.fields['product_id'] = forms.ChoiceField(choices=tuple(choices))

def _create_product_fields(self, item):
u"""Add the product option fields."""
for option in item.options:
self._add_option_field(item, option)

def _add_option_field(self, item, option):
u"""
Creates the appropriate form field for the product option.
This is designed to be overridden so that specific widgets can be used for
This is designed to be overridden so that specific widgets can be used for
certain types of options.
"""
self.fields[option.code] = forms.CharField()
self.fields[option.code] = forms.CharField()


57 changes: 39 additions & 18 deletions oscar/apps/basket/tests.py
@@ -1,10 +1,10 @@
from decimal import Decimal as D

from django.utils import unittest
from django.test.client import Client
from django.conf import settings
from django.core.urlresolvers import reverse
from django.test import TestCase

from oscar.apps.basket.models import Basket, Line
from oscar.apps.basket.models import Basket, Line
from oscar.test.helpers import create_product, TwillTestCase


Expand All @@ -17,42 +17,39 @@ def test_for_smoke(self):
self.assertPageTitleMatches('Oscar')


class BasketModelTest(unittest.TestCase):
class BasketModelTest(TestCase):

def setUp(self):
self.basket = Basket.objects.create()
self.dummy_product = create_product()

def test_empty_baskets_have_zero_lines(self):
self.assertTrue(Basket().num_lines == 0)

def test_new_baskets_are_empty(self):
self.assertTrue(Basket().is_empty)

def test_basket_have_with_one_line(self):
Line.objects.create(basket=self.basket, product=self.dummy_product)
self.assertTrue(self.basket.num_lines == 1)

def test_add_product_creates_line(self):
self.basket.add_product(self.dummy_product)
self.assertTrue(self.basket.num_lines == 1)

def test_adding_multiproduct_line_returns_correct_number_of_items(self):
self.basket.add_product(self.dummy_product, 10)
self.assertEqual(self.basket.num_items, 10)


class BasketViewsTest(unittest.TestCase):

def setUp(self):
self.client = Client()



class BasketViewsTest(TestCase):

def test_empty_basket_view(self):
url = reverse('basket:summary')
response = self.client.get(url)
self.assertEquals(200, response.status_code)
self.assertEquals(0, response.context['basket'].num_lines)

def test_anonymous_add_to_basket_creates_cookie(self):
dummy_product = create_product(price=D('10.00'))
url = reverse('basket:add')
Expand All @@ -61,3 +58,27 @@ def test_anonymous_add_to_basket_creates_cookie(self):
'quantity': 1}
response = self.client.post(url, post_params)
self.assertTrue('oscar_open_basket' in response.cookies)

class BasketThresholdTest(TestCase):

def setUp(self):
self._old_threshold = settings.OSCAR_MAX_BASKET_QUANTITY_THRESHOLD
settings.OSCAR_MAX_BASKET_QUANTITY_THRESHOLD = 3

def tearDown(self):
settings.OSCAR_MAX_BASKET_QUANTITY_THRESHOLD = self._old_threshold

def test_adding_more_than_threshold_raises(self):
dummy_product = create_product(price=D('10.00'))
url = reverse('basket:add')
post_params = {'product_id': dummy_product.id,
'action': 'add',
'quantity': 2}
response = self.client.post(url, post_params)
self.assertTrue('oscar_open_basket' in response.cookies)
post_params = {'product_id': dummy_product.id,
'action': 'add',
'quantity': 2}
response = self.client.post(url, post_params)
self.assertTrue('Your basket currently has 2 items.' in
response.cookies['messages'].value)

0 comments on commit 8a38a5a

Please sign in to comment.