Fixes flake8 errors

This commit is contained in:
Christopher Neugebauer 2016-01-22 17:02:07 +11:00
parent c2400c4695
commit 224878a10c
14 changed files with 125 additions and 152 deletions

View file

@ -6,7 +6,6 @@ import nested_admin
from registrasion import models as rego
# Inventory admin
class ProductInline(admin.TabularInline):

View file

@ -1,9 +1,8 @@
import datetime
import itertools
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError
from django.db.models import Avg, Min, Max, Sum
from django.db.models import Max, Sum
from django.utils import timezone
from registrasion import models as rego
@ -33,7 +32,6 @@ class CartController(object):
existing.save()
return CartController(existing)
def extend_reservation(self):
''' Updates the cart's time last updated value, which is used to
determine whether the cart has reserved the items and discounts it
@ -56,7 +54,6 @@ class CartController(object):
self.cart.time_last_updated = timezone.now()
self.cart.reservation_duration = max(reservations)
def add_to_cart(self, product, quantity):
''' Adds _quantity_ of the given _product_ to the cart. Raises
ValidationError if constraints are violated.'''
@ -91,7 +88,6 @@ class CartController(object):
self.cart.revision += 1
self.cart.save()
def apply_voucher(self, voucher):
''' Applies the given voucher to this cart. '''
@ -110,7 +106,6 @@ class CartController(object):
self.cart.revision += 1
self.cart.save()
def validate_cart(self):
''' Determines whether the status of the current cart is valid;
this is normally called before generating or paying an invoice '''
@ -121,13 +116,15 @@ class CartController(object):
items = rego.ProductItem.objects.filter(cart=self.cart)
for item in items:
# per-user limits are tested at add time, and are unliklely to change
# NOTE: per-user limits are tested at add time
# and are unliklely to change
prod = ProductController(item.product)
# If the cart is not reserved, we need to see if we can re-reserve
quantity = 0 if is_reserved else item.quantity
if not prod.can_add_with_enabling_conditions(self.cart.user, quantity):
if not prod.can_add_with_enabling_conditions(
self.cart.user, quantity):
raise ValidationError("Products are no longer available")
# Validate the discounts
@ -139,7 +136,8 @@ class CartController(object):
if discount in seen_discounts:
continue
seen_discounts.add(discount)
real_discount = rego.DiscountBase.objects.get_subclass(pk=discount.pk)
real_discount = rego.DiscountBase.objects.get_subclass(
pk=discount.pk)
cond = ConditionController.for_condition(real_discount)
quantity = 0 if is_reserved else discount_item.quantity
@ -147,8 +145,6 @@ class CartController(object):
if not cond.is_met(self.cart.user, quantity):
raise ValidationError("Discounts are no longer available")
def recalculate_discounts(self):
''' Calculates all of the discounts available for this product.
NB should be transactional, and it's terribly inefficient.
@ -160,11 +156,10 @@ class CartController(object):
for item in self.cart.productitem_set.all():
self._add_discount(item.product, item.quantity)
def _add_discount(self, product, quantity):
''' Calculates the best available discounts for this product.
NB this will be super-inefficient in aggregate because discounts will be
re-tested for each product. We should work on that.'''
NB this will be super-inefficient in aggregate because discounts will
be re-tested for each product. We should work on that.'''
prod = ProductController(product)
discounts = prod.available_discounts(self.cart.user)

View file

@ -1,4 +1,4 @@
from django.db.models import F, Q
from django.db.models import Q
from django.db.models import Sum
from django.utils import timezone
@ -15,15 +15,15 @@ class ConditionController(object):
@staticmethod
def for_condition(condition):
CONTROLLERS = {
rego.CategoryEnablingCondition : CategoryConditionController,
rego.IncludedProductDiscount : ProductConditionController,
rego.ProductEnablingCondition : ProductConditionController,
rego.TimeOrStockLimitDiscount :
rego.CategoryEnablingCondition: CategoryConditionController,
rego.IncludedProductDiscount: ProductConditionController,
rego.ProductEnablingCondition: ProductConditionController,
rego.TimeOrStockLimitDiscount:
TimeOrStockLimitConditionController,
rego.TimeOrStockLimitEnablingCondition :
rego.TimeOrStockLimitEnablingCondition:
TimeOrStockLimitConditionController,
rego.VoucherDiscount : VoucherConditionController,
rego.VoucherEnablingCondition : VoucherConditionController,
rego.VoucherDiscount: VoucherConditionController,
rego.VoucherEnablingCondition: VoucherConditionController,
}
try:
@ -31,7 +31,6 @@ class ConditionController(object):
except KeyError:
return ConditionController()
def is_met(self, user, quantity):
return True
@ -48,7 +47,8 @@ class CategoryConditionController(ConditionController):
carts = rego.Cart.objects.filter(user=user)
enabling_products = rego.Product.objects.filter(
category=self.condition.enabling_category)
products = rego.ProductItem.objects.filter(cart=carts,
products = rego.ProductItem.objects.filter(
cart=carts,
product=enabling_products)
return len(products) > 0
@ -65,7 +65,8 @@ class ProductConditionController(ConditionController):
condition in one of their carts '''
carts = rego.Cart.objects.filter(user=user)
products = rego.ProductItem.objects.filter(cart=carts,
products = rego.ProductItem.objects.filter(
cart=carts,
product=self.condition.enabling_products.all())
return len(products) > 0
@ -77,7 +78,6 @@ class TimeOrStockLimitConditionController(ConditionController):
def __init__(self, ceiling):
self.ceiling = ceiling
def is_met(self, user, quantity):
''' returns True if adding _quantity_ of _product_ will not vioilate
this ceiling. '''
@ -93,7 +93,6 @@ class TimeOrStockLimitConditionController(ConditionController):
# All limits have been met
return True
def test_date_range(self):
now = timezone.now()
@ -107,7 +106,6 @@ class TimeOrStockLimitConditionController(ConditionController):
return True
def _products(self):
''' Abstracts away the product list, becuase enabling conditions
list products differently to discounts. '''
@ -125,7 +123,6 @@ class TimeOrStockLimitConditionController(ConditionController):
Q(category=categories.all())
)
def test_limits(self, quantity):
if self.ceiling.limit is None:
return True
@ -155,6 +152,7 @@ class VoucherConditionController(ConditionController):
def is_met(self, user, quantity):
''' returns True if the user has the given voucher attached. '''
carts = rego.Cart.objects.filter(user=user,
carts = rego.Cart.objects.filter(
user=user,
vouchers=self.condition.voucher)
return len(carts) > 0

View file

@ -1,11 +1,12 @@
from decimal import Decimal
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Avg, Min, Max, Sum
from django.db.models import Sum
from registrasion import models as rego
from cart import CartController
class InvoiceController(object):
def __init__(self, invoice):
@ -22,12 +23,11 @@ class InvoiceController(object):
cart=cart, cart_revision=cart.revision)
except ObjectDoesNotExist:
cart_controller = CartController(cart)
cart_controller.validate_cart() # Raises ValidationError on fail.
cart_controller.validate_cart() # Raises ValidationError on fail.
invoice = cls._generate(cart)
return InvoiceController(invoice)
@classmethod
def resolve_discount_value(cls, item):
try:
@ -46,7 +46,6 @@ class InvoiceController(object):
value = condition.price
return value
@classmethod
def _generate(cls, cart):
''' Generates an invoice for the given cart. '''
@ -89,7 +88,6 @@ class InvoiceController(object):
return invoice
def is_valid(self):
''' Returns true if the attached invoice is not void and it represents
a valid cart. '''
@ -100,12 +98,10 @@ class InvoiceController(object):
return False
return True
def void(self):
''' Voids the invoice. '''
self.invoice.void = True
def pay(self, reference, amount):
''' Pays the invoice by the given amount. If the payment
equals the total on the invoice, finalise the invoice.
@ -113,7 +109,7 @@ class InvoiceController(object):
'''
if self.invoice.cart is not None:
cart = CartController(self.invoice.cart)
cart.validate_cart() # Raises ValidationError if invalid
cart.validate_cart() # Raises ValidationError if invalid
''' Adds a payment '''
payment = rego.Payment.objects.create(
@ -127,7 +123,7 @@ class InvoiceController(object):
agg = payments.aggregate(Sum("amount"))
total = agg["amount__sum"]
if total==self.invoice.value:
if total == self.invoice.value:
self.invoice.paid = True
cart = self.invoice.cart

View file

@ -2,12 +2,17 @@ import itertools
from collections import namedtuple
from django.db.models import F, Q
from django.db.models import Q
from registrasion import models as rego
from conditions import ConditionController
DiscountEnabler = namedtuple("DiscountEnabler", ("discount", "condition", "value"))
DiscountEnabler = namedtuple(
"DiscountEnabler", (
"discount",
"condition",
"value"))
class ProductController(object):
@ -19,7 +24,9 @@ class ProductController(object):
this Product without exceeding _limit_per_user_.'''
carts = rego.Cart.objects.filter(user=user)
items = rego.ProductItem.objects.filter(product=self.product, cart=carts)
items = rego.ProductItem.objects.filter(
product=self.product,
cart=carts)
count = 0
for item in items:
@ -62,7 +69,6 @@ class ProductController(object):
return True
def get_enabler(self, condition):
if condition.percentage is not None:
value = condition.percentage * self.product.price
@ -91,7 +97,8 @@ class ProductController(object):
discounts = []
for discount in potential_discounts:
real_discount = rego.DiscountBase.objects.get_subclass(pk=discount.discount.pk)
real_discount = rego.DiscountBase.objects.get_subclass(
pk=discount.discount.pk)
cond = ConditionController.for_condition(real_discount)
if cond.is_met(user, 0):
discounts.append(discount)

View file

@ -2,7 +2,6 @@ from __future__ import unicode_literals
import datetime
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
from django.db import models
@ -13,10 +12,6 @@ from django.utils.translation import ugettext_lazy as _
from model_utils.managers import InheritanceManager
from symposion.markdown_parser import parse
from symposion.proposals.models import ProposalBase
# User models
@python_2_unicode_compatible
@ -63,9 +58,11 @@ class Category(models.Model):
]
name = models.CharField(max_length=65, verbose_name=_("Name"))
description = models.CharField(max_length=255, verbose_name=_("Description"))
description = models.CharField(max_length=255,
verbose_name=_("Description"))
order = models.PositiveIntegerField(verbose_name=("Display order"))
render_type = models.IntegerField(choices=CATEGORY_RENDER_TYPES, verbose_name=_("Render type"))
render_type = models.IntegerField(choices=CATEGORY_RENDER_TYPES,
verbose_name=_("Render type"))
@python_2_unicode_compatible
@ -76,10 +73,15 @@ class Product(models.Model):
return self.name
name = models.CharField(max_length=65, verbose_name=_("Name"))
description = models.CharField(max_length=255, verbose_name=_("Description"))
description = models.CharField(max_length=255,
verbose_name=_("Description"))
category = models.ForeignKey(Category, verbose_name=_("Product category"))
price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name=_("Price"))
limit_per_user = models.PositiveIntegerField(blank=True, verbose_name=_("Limit per user"))
price = models.DecimalField(max_digits=8,
decimal_places=2,
verbose_name=_("Price"))
limit_per_user = models.PositiveIntegerField(
blank=True,
verbose_name=_("Limit per user"))
reservation_duration = models.DurationField(
default=datetime.timedelta(hours=1),
verbose_name=_("Reservation duration"))
@ -98,7 +100,9 @@ class Voucher(models.Model):
return "Voucher for %s" % self.recipient
recipient = models.CharField(max_length=64, verbose_name=_("Recipient"))
code = models.CharField(max_length=16, unique=True, verbose_name=_("Voucher code"))
code = models.CharField(max_length=16,
unique=True,
verbose_name=_("Voucher code"))
limit = models.PositiveIntegerField(verbose_name=_("Voucher use limit"))
@ -107,8 +111,8 @@ class Voucher(models.Model):
@python_2_unicode_compatible
class DiscountBase(models.Model):
''' Base class for discounts. Each subclass has controller code that
determines whether or not the given discount is available to be added to the
current cart. '''
determines whether or not the given discount is available to be added to
the current cart. '''
objects = InheritanceManager()
@ -116,7 +120,7 @@ class DiscountBase(models.Model):
return "Discount: " + self.description
description = models.CharField(max_length=255,
verbose_name=_("Description"))
verbose_name=_("Description"))
@python_2_unicode_compatible
@ -156,7 +160,10 @@ class DiscountForCategory(models.Model):
discount = models.ForeignKey(DiscountBase, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
percentage = models.DecimalField(max_digits=4, decimal_places=1, blank=True)
percentage = models.DecimalField(
max_digits=4,
decimal_places=1,
blank=True)
quantity = models.PositiveIntegerField()
@ -176,7 +183,9 @@ class VoucherDiscount(DiscountBase):
''' Discounts that are enabled when a voucher code is in the current
cart. '''
voucher = models.OneToOneField(Voucher, on_delete=models.CASCADE,
voucher = models.OneToOneField(
Voucher,
on_delete=models.CASCADE,
verbose_name=_("Voucher"))
@ -187,14 +196,15 @@ class IncludedProductDiscount(DiscountBase):
class Meta:
verbose_name = _("Product inclusion")
enabling_products = models.ManyToManyField(Product,
enabling_products = models.ManyToManyField(
Product,
verbose_name=_("Including product"))
class RoleDiscount(object):
''' Discounts that are enabled because the active user has a specific
role. This is for e.g. volunteers who can get a discount ticket. '''
## TODO: implement RoleDiscount
# TODO: implement RoleDiscount
pass
@ -253,16 +263,16 @@ class VoucherEnablingCondition(EnablingConditionBase):
enabling sponsor tickets. '''
def __str__(self):
return "Enabled by voucher: %s" % voucher
return "Enabled by voucher: %s" % self.voucher
voucher = models.OneToOneField(Voucher)
#@python_2_unicode_compatible
# @python_2_unicode_compatible
class RoleEnablingCondition(object):
''' The condition is met because the active user has a particular Role.
This is for e.g. enabling Team tickets. '''
## TODO: implement RoleEnablingCondition
# TODO: implement RoleEnablingCondition
pass
@ -289,8 +299,9 @@ class Cart(models.Model):
''' Gets all carts that are 'reserved' '''
return Cart.objects.filter(
(Q(active=True) &
Q(time_last_updated__gt=timezone.now()-F('reservation_duration')
)) |
Q(time_last_updated__gt=(
timezone.now()-F('reservation_duration')
))) |
Q(active=False)
)

View file

@ -1,5 +1,6 @@
from django.utils import timezone
class SetTimeMixin(object):
''' Patches timezone.now() for the duration of a test case. Allows us to
test time-based conditions (ceilings etc) relatively easily. '''

View file

@ -5,7 +5,6 @@ from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from registrasion import models as rego
from registrasion.controllers.cart import CartController
@ -14,6 +13,7 @@ from patch_datetime import SetTimeMixin
UTC = pytz.timezone('UTC')
class RegistrationCartTestCase(SetTimeMixin, TestCase):
def setUp(self):
@ -21,11 +21,15 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
@classmethod
def setUpTestData(cls):
cls.USER_1 = User.objects.create_user(username='testuser',
email='test@example.com', password='top_secret')
cls.USER_1 = User.objects.create_user(
username='testuser',
email='test@example.com',
password='top_secret')
cls.USER_2 = User.objects.create_user(username='testuser2',
email='test2@example.com', password='top_secret')
cls.USER_2 = User.objects.create_user(
username='testuser2',
email='test2@example.com',
password='top_secret')
cls.CAT_1 = rego.Category.objects.create(
name="Category 1",
@ -47,8 +51,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
cls.PROD_1 = rego.Product.objects.create(
name="Product 1",
description= "This is a test product. It costs $10. " \
"A user may have 10 of them.",
description="This is a test product. It costs $10. "
"A user may have 10 of them.",
category=cls.CAT_1,
price=Decimal("10.00"),
reservation_duration=cls.RESERVATION,
@ -59,8 +63,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
cls.PROD_2 = rego.Product.objects.create(
name="Product 2",
description= "This is a test product. It costs $10. " \
"A user may have 10 of them.",
description="This is a test product. It costs $10. "
"A user may have 10 of them.",
category=cls.CAT_1,
price=Decimal("10.00"),
limit_per_user=10,
@ -70,8 +74,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
cls.PROD_3 = rego.Product.objects.create(
name="Product 3",
description= "This is a test product. It costs $10. " \
"A user may have 10 of them.",
description="This is a test product. It costs $10. "
"A user may have 10 of them.",
category=cls.CAT_2,
price=Decimal("10.00"),
limit_per_user=10,
@ -79,7 +83,6 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
)
cls.PROD_2.save()
@classmethod
def make_ceiling(cls, name, limit=None, start_time=None, end_time=None):
limit_ceiling = rego.TimeOrStockLimitEnablingCondition.objects.create(
@ -93,9 +96,9 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
limit_ceiling.products.add(cls.PROD_1, cls.PROD_2)
limit_ceiling.save()
@classmethod
def make_category_ceiling(cls, name, limit=None, start_time=None, end_time=None):
def make_category_ceiling(
cls, name, limit=None, start_time=None, end_time=None):
limit_ceiling = rego.TimeOrStockLimitEnablingCondition.objects.create(
description=name,
mandatory=True,
@ -107,9 +110,9 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
limit_ceiling.categories.add(cls.CAT_1)
limit_ceiling.save()
@classmethod
def make_discount_ceiling(cls, name, limit=None, start_time=None, end_time=None):
def make_discount_ceiling(
cls, name, limit=None, start_time=None, end_time=None):
limit_ceiling = rego.TimeOrStockLimitDiscount.objects.create(
description=name,
start_time=start_time,
@ -141,7 +144,6 @@ class BasicCartTests(RegistrationCartTestCase):
current_cart2 = CartController.for_user(self.USER_1)
self.assertEqual(current_cart.cart, current_cart2.cart)
def test_add_to_cart_collapses_product_items(self):
current_cart = CartController.for_user(self.USER_1)
@ -149,14 +151,14 @@ class BasicCartTests(RegistrationCartTestCase):
current_cart.add_to_cart(self.PROD_1, 1)
current_cart.add_to_cart(self.PROD_1, 1)
## Count of products for a given user should be collapsed.
items = rego.ProductItem.objects.filter(cart=current_cart.cart,
# Count of products for a given user should be collapsed.
items = rego.ProductItem.objects.filter(
cart=current_cart.cart,
product=self.PROD_1)
self.assertEqual(1, len(items))
item = items[0]
self.assertEquals(2, item.quantity)
def test_add_to_cart_per_user_limit(self):
current_cart = CartController.for_user(self.USER_1)

View file

@ -1,19 +1,15 @@
import datetime
import pytz
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from registrasion import models as rego
from registrasion.controllers.cart import CartController
from test_cart import RegistrationCartTestCase
UTC = pytz.timezone('UTC')
class CeilingsTestCases(RegistrationCartTestCase):
def test_add_to_cart_ceiling_limit(self):
@ -44,12 +40,11 @@ class CeilingsTestCases(RegistrationCartTestCase):
# User should be able to add 5 of PROD_2 to the current cart
current_cart.add_to_cart(self.PROD_2, 4)
def test_add_to_cart_ceiling_date_range(self):
self.make_ceiling("date range ceiling",
self.make_ceiling(
"date range ceiling",
start_time=datetime.datetime(2015, 01, 01, tzinfo=UTC),
end_time=datetime.datetime(2015, 02, 01, tzinfo=UTC)
)
end_time=datetime.datetime(2015, 02, 01, tzinfo=UTC))
current_cart = CartController.for_user(self.USER_1)
@ -74,7 +69,6 @@ class CeilingsTestCases(RegistrationCartTestCase):
with self.assertRaises(ValidationError):
current_cart.add_to_cart(self.PROD_1, 1)
def test_add_to_cart_ceiling_limit_reserved_carts(self):
self.make_ceiling("Limit ceiling", limit=1)
@ -106,7 +100,6 @@ class CeilingsTestCases(RegistrationCartTestCase):
with self.assertRaises(ValidationError):
first_cart.add_to_cart(self.PROD_1, 1)
def test_validate_cart_fails_product_ceilings(self):
self.make_ceiling("Limit ceiling", limit=1)
self.__validation_test()

View file

@ -1,11 +1,6 @@
import datetime
import pytz
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from registrasion import models as rego
from registrasion.controllers.cart import CartController
@ -14,6 +9,7 @@ from test_cart import RegistrationCartTestCase
UTC = pytz.timezone('UTC')
class DiscountTestCase(RegistrationCartTestCase):
@classmethod
@ -32,7 +28,6 @@ class DiscountTestCase(RegistrationCartTestCase):
).save()
return discount
@classmethod
def add_discount_prod_1_includes_cat_2(cls, amount=Decimal(100)):
discount = rego.IncludedProductDiscount.objects.create(
@ -49,9 +44,8 @@ class DiscountTestCase(RegistrationCartTestCase):
).save()
return discount
def test_discount_is_applied(self):
discount = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
@ -60,9 +54,8 @@ class DiscountTestCase(RegistrationCartTestCase):
# Discounts should be applied at this point...
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
def test_discount_is_applied_for_category(self):
discount = self.add_discount_prod_1_includes_cat_2()
self.add_discount_prod_1_includes_cat_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
@ -71,9 +64,8 @@ class DiscountTestCase(RegistrationCartTestCase):
# Discounts should be applied at this point...
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
def test_discount_does_not_apply_if_not_met(self):
discount = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_2, 1)
@ -81,9 +73,8 @@ class DiscountTestCase(RegistrationCartTestCase):
# No discount should be applied as the condition is not met
self.assertEqual(0, len(cart.cart.discountitem_set.all()))
def test_discount_applied_out_of_order(self):
discount = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_2, 1)
@ -92,9 +83,8 @@ class DiscountTestCase(RegistrationCartTestCase):
# No discount should be applied as the condition is not met
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
def test_discounts_collapse(self):
discount = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
@ -104,9 +94,8 @@ class DiscountTestCase(RegistrationCartTestCase):
# Discounts should be applied and collapsed at this point...
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
def test_discounts_respect_quantity(self):
discount = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
@ -117,7 +106,6 @@ class DiscountTestCase(RegistrationCartTestCase):
discount_items = list(cart.cart.discountitem_set.all())
self.assertEqual(2, discount_items[0].quantity)
def test_multiple_discounts_apply_in_order(self):
discount_full = self.add_discount_prod_1_includes_prod_2()
discount_half = self.add_discount_prod_1_includes_prod_2(Decimal(50))
@ -137,9 +125,8 @@ class DiscountTestCase(RegistrationCartTestCase):
self.assertEqual(2, discount_items[1].quantity)
self.assertEqual(discount_full.pk, discount_items[1].discount.pk)
def test_discount_applies_across_carts(self):
discount_full = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
# Enable the discount during the first cart.
cart = CartController.for_user(self.USER_1)
@ -167,16 +154,16 @@ class DiscountTestCase(RegistrationCartTestCase):
discount_items = list(cart.cart.discountitem_set.all())
self.assertEqual(1, discount_items[0].quantity)
def test_discount_applies_only_once_enabled(self):
# Enable the discount during the first cart.
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
cart.add_to_cart(self.PROD_2, 2) # This would exhaust discount if present
# This would exhaust discount if present
cart.add_to_cart(self.PROD_2, 2)
cart.cart.active = False
cart.cart.save()
discount_full = self.add_discount_prod_1_includes_prod_2()
self.add_discount_prod_1_includes_prod_2()
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_2, 2)

View file

@ -1,11 +1,6 @@
import datetime
import pytz
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from registrasion import models as rego
from registrasion.controllers.cart import CartController
@ -14,6 +9,7 @@ from test_cart import RegistrationCartTestCase
UTC = pytz.timezone('UTC')
class EnablingConditionTestCases(RegistrationCartTestCase):
@classmethod
@ -29,7 +25,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
enabling_condition.enabling_products.add(cls.PROD_2)
enabling_condition.save()
@classmethod
def add_product_enabling_condition_on_category(cls, mandatory=False):
''' Adds a product enabling condition that operates on a category:
@ -43,7 +38,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
enabling_condition.enabling_products.add(cls.PROD_3)
enabling_condition.save()
def add_category_enabling_condition(cls, mandatory=False):
''' Adds a category enabling condition: adding PROD_1 to a cart is
predicated on adding an item from CAT_2 beforehand.'''
@ -56,7 +50,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
enabling_condition.products.add(cls.PROD_1)
enabling_condition.save()
def test_product_enabling_condition_enables_product(self):
self.add_product_enabling_condition()
@ -68,7 +61,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
current_cart.add_to_cart(self.PROD_2, 1)
current_cart.add_to_cart(self.PROD_1, 1)
def test_product_enabled_by_product_in_previous_cart(self):
self.add_product_enabling_condition()
@ -81,7 +73,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
current_cart = CartController.for_user(self.USER_1)
current_cart.add_to_cart(self.PROD_1, 1)
def test_product_enabling_condition_enables_category(self):
self.add_product_enabling_condition_on_category()
@ -93,7 +84,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
current_cart.add_to_cart(self.PROD_3, 1)
current_cart.add_to_cart(self.PROD_1, 1)
def test_category_enabling_condition_enables_product(self):
self.add_category_enabling_condition()
@ -106,7 +96,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
current_cart.add_to_cart(self.PROD_3, 1)
current_cart.add_to_cart(self.PROD_1, 1)
def test_product_enabled_by_category_in_previous_cart(self):
self.add_category_enabling_condition()
@ -119,7 +108,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
current_cart = CartController.for_user(self.USER_1)
current_cart.add_to_cart(self.PROD_1, 1)
def test_multiple_non_mandatory_conditions(self):
self.add_product_enabling_condition()
self.add_category_enabling_condition()
@ -140,7 +128,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
cart_2.add_to_cart(self.PROD_3, 1)
cart_2.add_to_cart(self.PROD_1, 1)
def test_multiple_mandatory_conditions(self):
self.add_product_enabling_condition(mandatory=True)
self.add_category_enabling_condition(mandatory=True)
@ -149,13 +136,12 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
# Cannot add PROD_1 until both conditions are met
with self.assertRaises(ValidationError):
cart_1.add_to_cart(self.PROD_1, 1)
cart_1.add_to_cart(self.PROD_2, 1) # Meets the product condition
cart_1.add_to_cart(self.PROD_2, 1) # Meets the product condition
with self.assertRaises(ValidationError):
cart_1.add_to_cart(self.PROD_1, 1)
cart_1.add_to_cart(self.PROD_3, 1) # Meets the category condition
cart_1.add_to_cart(self.PROD_3, 1) # Meets the category condition
cart_1.add_to_cart(self.PROD_1, 1)
def test_mandatory_conditions_are_mandatory(self):
self.add_product_enabling_condition(mandatory=False)
self.add_category_enabling_condition(mandatory=True)
@ -164,8 +150,8 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
# Cannot add PROD_1 until both conditions are met
with self.assertRaises(ValidationError):
cart_1.add_to_cart(self.PROD_1, 1)
cart_1.add_to_cart(self.PROD_2, 1) # Meets the product condition
cart_1.add_to_cart(self.PROD_2, 1) # Meets the product condition
with self.assertRaises(ValidationError):
cart_1.add_to_cart(self.PROD_1, 1)
cart_1.add_to_cart(self.PROD_3, 1) # Meets the category condition
cart_1.add_to_cart(self.PROD_3, 1) # Meets the category condition
cart_1.add_to_cart(self.PROD_1, 1)

View file

@ -2,10 +2,7 @@ import datetime
import pytz
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from registrasion import models as rego
from registrasion.controllers.cart import CartController
@ -74,7 +71,6 @@ class InvoiceTestCase(RegistrationCartTestCase):
new_cart = CartController.for_user(self.USER_1)
self.assertNotEqual(current_cart.cart, new_cart.cart)
def test_invoice_includes_discounts(self):
voucher = rego.Voucher.objects.create(
recipient="Voucher recipient",
@ -105,4 +101,6 @@ class InvoiceTestCase(RegistrationCartTestCase):
line_items = rego.LineItem.objects.filter(invoice=invoice_1.invoice)
self.assertEqual(2, len(line_items))
# That invoice should have a value equal to 50% of the cost of PROD_1
self.assertEqual(self.PROD_1.price * Decimal("0.5"), invoice_1.invoice.value)
self.assertEqual(
self.PROD_1.price * Decimal("0.5"),
invoice_1.invoice.value)

View file

@ -2,10 +2,7 @@ import datetime
import pytz
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from registrasion import models as rego
from registrasion.controllers.cart import CartController
@ -41,7 +38,8 @@ class VoucherTestCases(RegistrationCartTestCase):
with self.assertRaises(ValidationError):
cart_2.apply_voucher(voucher)
# After the reservation duration, user 2 should be able to apply voucher
# After the reservation duration
# user 2 should be able to apply voucher
self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2)
cart_2.apply_voucher(voucher)
cart_2.cart.active = False
@ -74,7 +72,6 @@ class VoucherTestCases(RegistrationCartTestCase):
current_cart.apply_voucher(voucher)
current_cart.add_to_cart(self.PROD_1, 1)
def test_voucher_enables_discount(self):
voucher = self.new_voucher()

3
setup.cfg Normal file
View file

@ -0,0 +1,3 @@
[flake8]
exclude = registrasion/migrations/*