Fixes flake8 errors
This commit is contained in:
parent
c2400c4695
commit
224878a10c
14 changed files with 125 additions and 152 deletions
|
@ -6,7 +6,6 @@ import nested_admin
|
|||
from registrasion import models as rego
|
||||
|
||||
|
||||
|
||||
# Inventory admin
|
||||
|
||||
class ProductInline(admin.TabularInline):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -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. '''
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
3
setup.cfg
Normal file
|
@ -0,0 +1,3 @@
|
|||
[flake8]
|
||||
exclude = registrasion/migrations/*
|
||||
|
Loading…
Reference in a new issue