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 | from registrasion import models as rego | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| # Inventory admin | # Inventory admin | ||||||
| 
 | 
 | ||||||
| class ProductInline(admin.TabularInline): | class ProductInline(admin.TabularInline): | ||||||
|  |  | ||||||
|  | @ -1,9 +1,8 @@ | ||||||
| import datetime | import datetime | ||||||
| import itertools |  | ||||||
| 
 | 
 | ||||||
| from django.core.exceptions import ObjectDoesNotExist | from django.core.exceptions import ObjectDoesNotExist | ||||||
| from django.core.exceptions import ValidationError | 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 django.utils import timezone | ||||||
| 
 | 
 | ||||||
| from registrasion import models as rego | from registrasion import models as rego | ||||||
|  | @ -33,7 +32,6 @@ class CartController(object): | ||||||
|             existing.save() |             existing.save() | ||||||
|         return CartController(existing) |         return CartController(existing) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def extend_reservation(self): |     def extend_reservation(self): | ||||||
|         ''' Updates the cart's time last updated value, which is used to |         ''' Updates the cart's time last updated value, which is used to | ||||||
|         determine whether the cart has reserved the items and discounts it |         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.time_last_updated = timezone.now() | ||||||
|         self.cart.reservation_duration = max(reservations) |         self.cart.reservation_duration = max(reservations) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def add_to_cart(self, product, quantity): |     def add_to_cart(self, product, quantity): | ||||||
|         ''' Adds _quantity_ of the given _product_ to the cart. Raises |         ''' Adds _quantity_ of the given _product_ to the cart. Raises | ||||||
|         ValidationError if constraints are violated.''' |         ValidationError if constraints are violated.''' | ||||||
|  | @ -91,7 +88,6 @@ class CartController(object): | ||||||
|         self.cart.revision += 1 |         self.cart.revision += 1 | ||||||
|         self.cart.save() |         self.cart.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def apply_voucher(self, voucher): |     def apply_voucher(self, voucher): | ||||||
|         ''' Applies the given voucher to this cart. ''' |         ''' Applies the given voucher to this cart. ''' | ||||||
| 
 | 
 | ||||||
|  | @ -110,7 +106,6 @@ class CartController(object): | ||||||
|         self.cart.revision += 1 |         self.cart.revision += 1 | ||||||
|         self.cart.save() |         self.cart.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def validate_cart(self): |     def validate_cart(self): | ||||||
|         ''' Determines whether the status of the current cart is valid; |         ''' Determines whether the status of the current cart is valid; | ||||||
|         this is normally called before generating or paying an invoice ''' |         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) |         items = rego.ProductItem.objects.filter(cart=self.cart) | ||||||
|         for item in items: |         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) |             prod = ProductController(item.product) | ||||||
| 
 | 
 | ||||||
|             # If the cart is not reserved, we need to see if we can re-reserve |             # If the cart is not reserved, we need to see if we can re-reserve | ||||||
|             quantity = 0 if is_reserved else item.quantity |             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") |                 raise ValidationError("Products are no longer available") | ||||||
| 
 | 
 | ||||||
|         # Validate the discounts |         # Validate the discounts | ||||||
|  | @ -139,7 +136,8 @@ class CartController(object): | ||||||
|             if discount in seen_discounts: |             if discount in seen_discounts: | ||||||
|                 continue |                 continue | ||||||
|             seen_discounts.add(discount) |             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) |             cond = ConditionController.for_condition(real_discount) | ||||||
| 
 | 
 | ||||||
|             quantity = 0 if is_reserved else discount_item.quantity |             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): |             if not cond.is_met(self.cart.user, quantity): | ||||||
|                 raise ValidationError("Discounts are no longer available") |                 raise ValidationError("Discounts are no longer available") | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     def recalculate_discounts(self): |     def recalculate_discounts(self): | ||||||
|         ''' Calculates all of the discounts available for this product. |         ''' Calculates all of the discounts available for this product. | ||||||
|         NB should be transactional, and it's terribly inefficient. |         NB should be transactional, and it's terribly inefficient. | ||||||
|  | @ -160,11 +156,10 @@ class CartController(object): | ||||||
|         for item in self.cart.productitem_set.all(): |         for item in self.cart.productitem_set.all(): | ||||||
|             self._add_discount(item.product, item.quantity) |             self._add_discount(item.product, item.quantity) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def _add_discount(self, product, quantity): |     def _add_discount(self, product, quantity): | ||||||
|         ''' Calculates the best available discounts for this product. |         ''' Calculates the best available discounts for this product. | ||||||
|         NB this will be super-inefficient in aggregate because discounts will be |         NB this will be super-inefficient in aggregate because discounts will | ||||||
|         re-tested for each product. We should work on that.''' |         be re-tested for each product. We should work on that.''' | ||||||
| 
 | 
 | ||||||
|         prod = ProductController(product) |         prod = ProductController(product) | ||||||
|         discounts = prod.available_discounts(self.cart.user) |         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.db.models import Sum | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| 
 | 
 | ||||||
|  | @ -15,15 +15,15 @@ class ConditionController(object): | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def for_condition(condition): |     def for_condition(condition): | ||||||
|         CONTROLLERS = { |         CONTROLLERS = { | ||||||
|             rego.CategoryEnablingCondition : CategoryConditionController, |             rego.CategoryEnablingCondition: CategoryConditionController, | ||||||
|             rego.IncludedProductDiscount : ProductConditionController, |             rego.IncludedProductDiscount: ProductConditionController, | ||||||
|             rego.ProductEnablingCondition : ProductConditionController, |             rego.ProductEnablingCondition: ProductConditionController, | ||||||
|             rego.TimeOrStockLimitDiscount : |             rego.TimeOrStockLimitDiscount: | ||||||
|                 TimeOrStockLimitConditionController, |                 TimeOrStockLimitConditionController, | ||||||
|             rego.TimeOrStockLimitEnablingCondition : |             rego.TimeOrStockLimitEnablingCondition: | ||||||
|                 TimeOrStockLimitConditionController, |                 TimeOrStockLimitConditionController, | ||||||
|             rego.VoucherDiscount : VoucherConditionController, |             rego.VoucherDiscount: VoucherConditionController, | ||||||
|             rego.VoucherEnablingCondition : VoucherConditionController, |             rego.VoucherEnablingCondition: VoucherConditionController, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         try: |         try: | ||||||
|  | @ -31,7 +31,6 @@ class ConditionController(object): | ||||||
|         except KeyError: |         except KeyError: | ||||||
|             return ConditionController() |             return ConditionController() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def is_met(self, user, quantity): |     def is_met(self, user, quantity): | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|  | @ -48,7 +47,8 @@ class CategoryConditionController(ConditionController): | ||||||
|         carts = rego.Cart.objects.filter(user=user) |         carts = rego.Cart.objects.filter(user=user) | ||||||
|         enabling_products = rego.Product.objects.filter( |         enabling_products = rego.Product.objects.filter( | ||||||
|             category=self.condition.enabling_category) |             category=self.condition.enabling_category) | ||||||
|         products = rego.ProductItem.objects.filter(cart=carts, |         products = rego.ProductItem.objects.filter( | ||||||
|  |             cart=carts, | ||||||
|             product=enabling_products) |             product=enabling_products) | ||||||
|         return len(products) > 0 |         return len(products) > 0 | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +65,8 @@ class ProductConditionController(ConditionController): | ||||||
|         condition in one of their carts ''' |         condition in one of their carts ''' | ||||||
| 
 | 
 | ||||||
|         carts = rego.Cart.objects.filter(user=user) |         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()) |             product=self.condition.enabling_products.all()) | ||||||
|         return len(products) > 0 |         return len(products) > 0 | ||||||
| 
 | 
 | ||||||
|  | @ -77,7 +78,6 @@ class TimeOrStockLimitConditionController(ConditionController): | ||||||
|     def __init__(self, ceiling): |     def __init__(self, ceiling): | ||||||
|         self.ceiling = ceiling |         self.ceiling = ceiling | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def is_met(self, user, quantity): |     def is_met(self, user, quantity): | ||||||
|         ''' returns True if adding _quantity_ of _product_ will not vioilate |         ''' returns True if adding _quantity_ of _product_ will not vioilate | ||||||
|         this ceiling. ''' |         this ceiling. ''' | ||||||
|  | @ -93,7 +93,6 @@ class TimeOrStockLimitConditionController(ConditionController): | ||||||
|         # All limits have been met |         # All limits have been met | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_date_range(self): |     def test_date_range(self): | ||||||
|         now = timezone.now() |         now = timezone.now() | ||||||
| 
 | 
 | ||||||
|  | @ -107,7 +106,6 @@ class TimeOrStockLimitConditionController(ConditionController): | ||||||
| 
 | 
 | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def _products(self): |     def _products(self): | ||||||
|         ''' Abstracts away the product list, becuase enabling conditions |         ''' Abstracts away the product list, becuase enabling conditions | ||||||
|         list products differently to discounts. ''' |         list products differently to discounts. ''' | ||||||
|  | @ -125,7 +123,6 @@ class TimeOrStockLimitConditionController(ConditionController): | ||||||
|                 Q(category=categories.all()) |                 Q(category=categories.all()) | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_limits(self, quantity): |     def test_limits(self, quantity): | ||||||
|         if self.ceiling.limit is None: |         if self.ceiling.limit is None: | ||||||
|             return True |             return True | ||||||
|  | @ -155,6 +152,7 @@ class VoucherConditionController(ConditionController): | ||||||
| 
 | 
 | ||||||
|     def is_met(self, user, quantity): |     def is_met(self, user, quantity): | ||||||
|         ''' returns True if the user has the given voucher attached. ''' |         ''' 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) |             vouchers=self.condition.voucher) | ||||||
|         return len(carts) > 0 |         return len(carts) > 0 | ||||||
|  |  | ||||||
|  | @ -1,11 +1,12 @@ | ||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
| from django.core.exceptions import ObjectDoesNotExist | 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 registrasion import models as rego | ||||||
| 
 | 
 | ||||||
| from cart import CartController | from cart import CartController | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class InvoiceController(object): | class InvoiceController(object): | ||||||
| 
 | 
 | ||||||
|     def __init__(self, invoice): |     def __init__(self, invoice): | ||||||
|  | @ -22,12 +23,11 @@ class InvoiceController(object): | ||||||
|                 cart=cart, cart_revision=cart.revision) |                 cart=cart, cart_revision=cart.revision) | ||||||
|         except ObjectDoesNotExist: |         except ObjectDoesNotExist: | ||||||
|             cart_controller = CartController(cart) |             cart_controller = CartController(cart) | ||||||
|             cart_controller.validate_cart() # Raises ValidationError on fail. |             cart_controller.validate_cart()  # Raises ValidationError on fail. | ||||||
|             invoice = cls._generate(cart) |             invoice = cls._generate(cart) | ||||||
| 
 | 
 | ||||||
|         return InvoiceController(invoice) |         return InvoiceController(invoice) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def resolve_discount_value(cls, item): |     def resolve_discount_value(cls, item): | ||||||
|         try: |         try: | ||||||
|  | @ -46,7 +46,6 @@ class InvoiceController(object): | ||||||
|             value = condition.price |             value = condition.price | ||||||
|         return value |         return value | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def _generate(cls, cart): |     def _generate(cls, cart): | ||||||
|         ''' Generates an invoice for the given cart. ''' |         ''' Generates an invoice for the given cart. ''' | ||||||
|  | @ -89,7 +88,6 @@ class InvoiceController(object): | ||||||
| 
 | 
 | ||||||
|         return invoice |         return invoice | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def is_valid(self): |     def is_valid(self): | ||||||
|         ''' Returns true if the attached invoice is not void and it represents |         ''' Returns true if the attached invoice is not void and it represents | ||||||
|         a valid cart. ''' |         a valid cart. ''' | ||||||
|  | @ -100,12 +98,10 @@ class InvoiceController(object): | ||||||
|                 return False |                 return False | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def void(self): |     def void(self): | ||||||
|         ''' Voids the invoice. ''' |         ''' Voids the invoice. ''' | ||||||
|         self.invoice.void = True |         self.invoice.void = True | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def pay(self, reference, amount): |     def pay(self, reference, amount): | ||||||
|         ''' Pays the invoice by the given amount. If the payment |         ''' Pays the invoice by the given amount. If the payment | ||||||
|         equals the total on the invoice, finalise the invoice. |         equals the total on the invoice, finalise the invoice. | ||||||
|  | @ -113,7 +109,7 @@ class InvoiceController(object): | ||||||
|         ''' |         ''' | ||||||
|         if self.invoice.cart is not None: |         if self.invoice.cart is not None: | ||||||
|             cart = CartController(self.invoice.cart) |             cart = CartController(self.invoice.cart) | ||||||
|             cart.validate_cart() # Raises ValidationError if invalid |             cart.validate_cart()  # Raises ValidationError if invalid | ||||||
| 
 | 
 | ||||||
|         ''' Adds a payment ''' |         ''' Adds a payment ''' | ||||||
|         payment = rego.Payment.objects.create( |         payment = rego.Payment.objects.create( | ||||||
|  | @ -127,7 +123,7 @@ class InvoiceController(object): | ||||||
|         agg = payments.aggregate(Sum("amount")) |         agg = payments.aggregate(Sum("amount")) | ||||||
|         total = agg["amount__sum"] |         total = agg["amount__sum"] | ||||||
| 
 | 
 | ||||||
|         if total==self.invoice.value: |         if total == self.invoice.value: | ||||||
|             self.invoice.paid = True |             self.invoice.paid = True | ||||||
| 
 | 
 | ||||||
|             cart = self.invoice.cart |             cart = self.invoice.cart | ||||||
|  |  | ||||||
|  | @ -2,12 +2,17 @@ import itertools | ||||||
| 
 | 
 | ||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| 
 | 
 | ||||||
| from django.db.models import F, Q | from django.db.models import Q | ||||||
| from registrasion import models as rego | from registrasion import models as rego | ||||||
| 
 | 
 | ||||||
| from conditions import ConditionController | from conditions import ConditionController | ||||||
| 
 | 
 | ||||||
| DiscountEnabler = namedtuple("DiscountEnabler", ("discount", "condition", "value")) | DiscountEnabler = namedtuple( | ||||||
|  |     "DiscountEnabler", ( | ||||||
|  |         "discount", | ||||||
|  |         "condition", | ||||||
|  |         "value")) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class ProductController(object): | class ProductController(object): | ||||||
| 
 | 
 | ||||||
|  | @ -19,7 +24,9 @@ class ProductController(object): | ||||||
|         this Product without exceeding _limit_per_user_.''' |         this Product without exceeding _limit_per_user_.''' | ||||||
| 
 | 
 | ||||||
|         carts = rego.Cart.objects.filter(user=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 |         count = 0 | ||||||
|         for item in items: |         for item in items: | ||||||
|  | @ -62,7 +69,6 @@ class ProductController(object): | ||||||
| 
 | 
 | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def get_enabler(self, condition): |     def get_enabler(self, condition): | ||||||
|         if condition.percentage is not None: |         if condition.percentage is not None: | ||||||
|             value = condition.percentage * self.product.price |             value = condition.percentage * self.product.price | ||||||
|  | @ -91,7 +97,8 @@ class ProductController(object): | ||||||
| 
 | 
 | ||||||
|         discounts = [] |         discounts = [] | ||||||
|         for discount in potential_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) |             cond = ConditionController.for_condition(real_discount) | ||||||
|             if cond.is_met(user, 0): |             if cond.is_met(user, 0): | ||||||
|                 discounts.append(discount) |                 discounts.append(discount) | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ from __future__ import unicode_literals | ||||||
| 
 | 
 | ||||||
| import datetime | import datetime | ||||||
| 
 | 
 | ||||||
| from django.core.exceptions import ObjectDoesNotExist |  | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.contrib.auth.models import User | from django.contrib.auth.models import User | ||||||
| from django.db import models | from django.db import models | ||||||
|  | @ -13,10 +12,6 @@ from django.utils.translation import ugettext_lazy as _ | ||||||
| from model_utils.managers import InheritanceManager | from model_utils.managers import InheritanceManager | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from symposion.markdown_parser import parse |  | ||||||
| from symposion.proposals.models import ProposalBase |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # User models | # User models | ||||||
| 
 | 
 | ||||||
| @python_2_unicode_compatible | @python_2_unicode_compatible | ||||||
|  | @ -63,9 +58,11 @@ class Category(models.Model): | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     name = models.CharField(max_length=65, verbose_name=_("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")) | ||||||
|     order = models.PositiveIntegerField(verbose_name=("Display order")) |     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 | @python_2_unicode_compatible | ||||||
|  | @ -76,10 +73,15 @@ class Product(models.Model): | ||||||
|         return self.name |         return self.name | ||||||
| 
 | 
 | ||||||
|     name = models.CharField(max_length=65, verbose_name=_("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")) |     category = models.ForeignKey(Category, verbose_name=_("Product category")) | ||||||
|     price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name=_("Price")) |     price = models.DecimalField(max_digits=8, | ||||||
|     limit_per_user = models.PositiveIntegerField(blank=True, verbose_name=_("Limit per user")) |                                 decimal_places=2, | ||||||
|  |                                 verbose_name=_("Price")) | ||||||
|  |     limit_per_user = models.PositiveIntegerField( | ||||||
|  |         blank=True, | ||||||
|  |         verbose_name=_("Limit per user")) | ||||||
|     reservation_duration = models.DurationField( |     reservation_duration = models.DurationField( | ||||||
|         default=datetime.timedelta(hours=1), |         default=datetime.timedelta(hours=1), | ||||||
|         verbose_name=_("Reservation duration")) |         verbose_name=_("Reservation duration")) | ||||||
|  | @ -98,7 +100,9 @@ class Voucher(models.Model): | ||||||
|         return "Voucher for %s" % self.recipient |         return "Voucher for %s" % self.recipient | ||||||
| 
 | 
 | ||||||
|     recipient = models.CharField(max_length=64, verbose_name=_("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")) |     limit = models.PositiveIntegerField(verbose_name=_("Voucher use limit")) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -107,8 +111,8 @@ class Voucher(models.Model): | ||||||
| @python_2_unicode_compatible | @python_2_unicode_compatible | ||||||
| class DiscountBase(models.Model): | class DiscountBase(models.Model): | ||||||
|     ''' Base class for discounts. Each subclass has controller code that |     ''' Base class for discounts. Each subclass has controller code that | ||||||
|     determines whether or not the given discount is available to be added to the |     determines whether or not the given discount is available to be added to | ||||||
|     current cart. ''' |     the current cart. ''' | ||||||
| 
 | 
 | ||||||
|     objects = InheritanceManager() |     objects = InheritanceManager() | ||||||
| 
 | 
 | ||||||
|  | @ -116,7 +120,7 @@ class DiscountBase(models.Model): | ||||||
|         return "Discount: " + self.description |         return "Discount: " + self.description | ||||||
| 
 | 
 | ||||||
|     description = models.CharField(max_length=255, |     description = models.CharField(max_length=255, | ||||||
|         verbose_name=_("Description")) |                                    verbose_name=_("Description")) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @python_2_unicode_compatible | @python_2_unicode_compatible | ||||||
|  | @ -156,7 +160,10 @@ class DiscountForCategory(models.Model): | ||||||
| 
 | 
 | ||||||
|     discount = models.ForeignKey(DiscountBase, on_delete=models.CASCADE) |     discount = models.ForeignKey(DiscountBase, on_delete=models.CASCADE) | ||||||
|     category = models.ForeignKey(Category, 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() |     quantity = models.PositiveIntegerField() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -176,7 +183,9 @@ class VoucherDiscount(DiscountBase): | ||||||
|     ''' Discounts that are enabled when a voucher code is in the current |     ''' Discounts that are enabled when a voucher code is in the current | ||||||
|     cart. ''' |     cart. ''' | ||||||
| 
 | 
 | ||||||
|     voucher = models.OneToOneField(Voucher, on_delete=models.CASCADE, |     voucher = models.OneToOneField( | ||||||
|  |         Voucher, | ||||||
|  |         on_delete=models.CASCADE, | ||||||
|         verbose_name=_("Voucher")) |         verbose_name=_("Voucher")) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -187,14 +196,15 @@ class IncludedProductDiscount(DiscountBase): | ||||||
|     class Meta: |     class Meta: | ||||||
|         verbose_name = _("Product inclusion") |         verbose_name = _("Product inclusion") | ||||||
| 
 | 
 | ||||||
|     enabling_products = models.ManyToManyField(Product, |     enabling_products = models.ManyToManyField( | ||||||
|  |         Product, | ||||||
|         verbose_name=_("Including product")) |         verbose_name=_("Including product")) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RoleDiscount(object): | class RoleDiscount(object): | ||||||
|     ''' Discounts that are enabled because the active user has a specific |     ''' Discounts that are enabled because the active user has a specific | ||||||
|     role. This is for e.g. volunteers who can get a discount ticket. ''' |     role. This is for e.g. volunteers who can get a discount ticket. ''' | ||||||
|     ## TODO: implement RoleDiscount |     # TODO: implement RoleDiscount | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -253,16 +263,16 @@ class VoucherEnablingCondition(EnablingConditionBase): | ||||||
|     enabling sponsor tickets. ''' |     enabling sponsor tickets. ''' | ||||||
| 
 | 
 | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         return "Enabled by voucher: %s" % voucher |         return "Enabled by voucher: %s" % self.voucher | ||||||
| 
 | 
 | ||||||
|     voucher = models.OneToOneField(Voucher) |     voucher = models.OneToOneField(Voucher) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #@python_2_unicode_compatible | # @python_2_unicode_compatible | ||||||
| class RoleEnablingCondition(object): | class RoleEnablingCondition(object): | ||||||
|     ''' The condition is met because the active user has a particular Role. |     ''' The condition is met because the active user has a particular Role. | ||||||
|     This is for e.g. enabling Team tickets. ''' |     This is for e.g. enabling Team tickets. ''' | ||||||
|     ## TODO: implement RoleEnablingCondition |     # TODO: implement RoleEnablingCondition | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -289,8 +299,9 @@ class Cart(models.Model): | ||||||
|         ''' Gets all carts that are 'reserved' ''' |         ''' Gets all carts that are 'reserved' ''' | ||||||
|         return Cart.objects.filter( |         return Cart.objects.filter( | ||||||
|             (Q(active=True) & |             (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) |             Q(active=False) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class SetTimeMixin(object): | class SetTimeMixin(object): | ||||||
|     ''' Patches timezone.now() for the duration of a test case. Allows us to |     ''' Patches timezone.now() for the duration of a test case. Allows us to | ||||||
|     test time-based conditions (ceilings etc) relatively easily. ''' |     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.contrib.auth.models import User | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.test import TestCase | from django.test import TestCase | ||||||
| from django.utils import timezone |  | ||||||
| 
 | 
 | ||||||
| from registrasion import models as rego | from registrasion import models as rego | ||||||
| from registrasion.controllers.cart import CartController | from registrasion.controllers.cart import CartController | ||||||
|  | @ -14,6 +13,7 @@ from patch_datetime import SetTimeMixin | ||||||
| 
 | 
 | ||||||
| UTC = pytz.timezone('UTC') | UTC = pytz.timezone('UTC') | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class RegistrationCartTestCase(SetTimeMixin, TestCase): | class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
| 
 | 
 | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|  | @ -21,11 +21,15 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def setUpTestData(cls): |     def setUpTestData(cls): | ||||||
|         cls.USER_1 = User.objects.create_user(username='testuser', |         cls.USER_1 = User.objects.create_user( | ||||||
|             email='test@example.com', password='top_secret') |             username='testuser', | ||||||
|  |             email='test@example.com', | ||||||
|  |             password='top_secret') | ||||||
| 
 | 
 | ||||||
|         cls.USER_2 = User.objects.create_user(username='testuser2', |         cls.USER_2 = User.objects.create_user( | ||||||
|             email='test2@example.com', password='top_secret') |             username='testuser2', | ||||||
|  |             email='test2@example.com', | ||||||
|  |             password='top_secret') | ||||||
| 
 | 
 | ||||||
|         cls.CAT_1 = rego.Category.objects.create( |         cls.CAT_1 = rego.Category.objects.create( | ||||||
|             name="Category 1", |             name="Category 1", | ||||||
|  | @ -47,8 +51,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
| 
 | 
 | ||||||
|         cls.PROD_1 = rego.Product.objects.create( |         cls.PROD_1 = rego.Product.objects.create( | ||||||
|             name="Product 1", |             name="Product 1", | ||||||
|             description= "This is a test product. It costs $10. " \ |             description="This is a test product. It costs $10. " | ||||||
|                 "A user may have 10 of them.", |                         "A user may have 10 of them.", | ||||||
|             category=cls.CAT_1, |             category=cls.CAT_1, | ||||||
|             price=Decimal("10.00"), |             price=Decimal("10.00"), | ||||||
|             reservation_duration=cls.RESERVATION, |             reservation_duration=cls.RESERVATION, | ||||||
|  | @ -59,8 +63,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
| 
 | 
 | ||||||
|         cls.PROD_2 = rego.Product.objects.create( |         cls.PROD_2 = rego.Product.objects.create( | ||||||
|             name="Product 2", |             name="Product 2", | ||||||
|             description= "This is a test product. It costs $10. " \ |             description="This is a test product. It costs $10. " | ||||||
|                 "A user may have 10 of them.", |                         "A user may have 10 of them.", | ||||||
|             category=cls.CAT_1, |             category=cls.CAT_1, | ||||||
|             price=Decimal("10.00"), |             price=Decimal("10.00"), | ||||||
|             limit_per_user=10, |             limit_per_user=10, | ||||||
|  | @ -70,8 +74,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
| 
 | 
 | ||||||
|         cls.PROD_3 = rego.Product.objects.create( |         cls.PROD_3 = rego.Product.objects.create( | ||||||
|             name="Product 3", |             name="Product 3", | ||||||
|             description= "This is a test product. It costs $10. " \ |             description="This is a test product. It costs $10. " | ||||||
|                 "A user may have 10 of them.", |                         "A user may have 10 of them.", | ||||||
|             category=cls.CAT_2, |             category=cls.CAT_2, | ||||||
|             price=Decimal("10.00"), |             price=Decimal("10.00"), | ||||||
|             limit_per_user=10, |             limit_per_user=10, | ||||||
|  | @ -79,7 +83,6 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
|         ) |         ) | ||||||
|         cls.PROD_2.save() |         cls.PROD_2.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def make_ceiling(cls, name, limit=None, start_time=None, end_time=None): |     def make_ceiling(cls, name, limit=None, start_time=None, end_time=None): | ||||||
|         limit_ceiling = rego.TimeOrStockLimitEnablingCondition.objects.create( |         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.products.add(cls.PROD_1, cls.PROD_2) | ||||||
|         limit_ceiling.save() |         limit_ceiling.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @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( |         limit_ceiling = rego.TimeOrStockLimitEnablingCondition.objects.create( | ||||||
|             description=name, |             description=name, | ||||||
|             mandatory=True, |             mandatory=True, | ||||||
|  | @ -107,9 +110,9 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): | ||||||
|         limit_ceiling.categories.add(cls.CAT_1) |         limit_ceiling.categories.add(cls.CAT_1) | ||||||
|         limit_ceiling.save() |         limit_ceiling.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @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( |         limit_ceiling = rego.TimeOrStockLimitDiscount.objects.create( | ||||||
|             description=name, |             description=name, | ||||||
|             start_time=start_time, |             start_time=start_time, | ||||||
|  | @ -141,7 +144,6 @@ class BasicCartTests(RegistrationCartTestCase): | ||||||
|         current_cart2 = CartController.for_user(self.USER_1) |         current_cart2 = CartController.for_user(self.USER_1) | ||||||
|         self.assertEqual(current_cart.cart, current_cart2.cart) |         self.assertEqual(current_cart.cart, current_cart2.cart) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_add_to_cart_collapses_product_items(self): |     def test_add_to_cart_collapses_product_items(self): | ||||||
|         current_cart = CartController.for_user(self.USER_1) |         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) | ||||||
|         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. |         # Count of products for a given user should be collapsed. | ||||||
|         items = rego.ProductItem.objects.filter(cart=current_cart.cart, |         items = rego.ProductItem.objects.filter( | ||||||
|  |             cart=current_cart.cart, | ||||||
|             product=self.PROD_1) |             product=self.PROD_1) | ||||||
|         self.assertEqual(1, len(items)) |         self.assertEqual(1, len(items)) | ||||||
|         item = items[0] |         item = items[0] | ||||||
|         self.assertEquals(2, item.quantity) |         self.assertEquals(2, item.quantity) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_add_to_cart_per_user_limit(self): |     def test_add_to_cart_per_user_limit(self): | ||||||
|         current_cart = CartController.for_user(self.USER_1) |         current_cart = CartController.for_user(self.USER_1) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,19 +1,15 @@ | ||||||
| import datetime | import datetime | ||||||
| import pytz | import pytz | ||||||
| 
 | 
 | ||||||
| from decimal import Decimal |  | ||||||
| from django.contrib.auth.models import User |  | ||||||
| from django.core.exceptions import ValidationError | 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 registrasion.controllers.cart import CartController | ||||||
| 
 | 
 | ||||||
| from test_cart import RegistrationCartTestCase | from test_cart import RegistrationCartTestCase | ||||||
| 
 | 
 | ||||||
| UTC = pytz.timezone('UTC') | UTC = pytz.timezone('UTC') | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class CeilingsTestCases(RegistrationCartTestCase): | class CeilingsTestCases(RegistrationCartTestCase): | ||||||
| 
 | 
 | ||||||
|     def test_add_to_cart_ceiling_limit(self): |     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 |         # User should be able to add 5 of PROD_2 to the current cart | ||||||
|         current_cart.add_to_cart(self.PROD_2, 4) |         current_cart.add_to_cart(self.PROD_2, 4) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_add_to_cart_ceiling_date_range(self): |     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), |             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) |         current_cart = CartController.for_user(self.USER_1) | ||||||
| 
 | 
 | ||||||
|  | @ -74,7 +69,6 @@ class CeilingsTestCases(RegistrationCartTestCase): | ||||||
|         with self.assertRaises(ValidationError): |         with self.assertRaises(ValidationError): | ||||||
|             current_cart.add_to_cart(self.PROD_1, 1) |             current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_add_to_cart_ceiling_limit_reserved_carts(self): |     def test_add_to_cart_ceiling_limit_reserved_carts(self): | ||||||
|         self.make_ceiling("Limit ceiling", limit=1) |         self.make_ceiling("Limit ceiling", limit=1) | ||||||
| 
 | 
 | ||||||
|  | @ -106,7 +100,6 @@ class CeilingsTestCases(RegistrationCartTestCase): | ||||||
|         with self.assertRaises(ValidationError): |         with self.assertRaises(ValidationError): | ||||||
|             first_cart.add_to_cart(self.PROD_1, 1) |             first_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_validate_cart_fails_product_ceilings(self): |     def test_validate_cart_fails_product_ceilings(self): | ||||||
|         self.make_ceiling("Limit ceiling", limit=1) |         self.make_ceiling("Limit ceiling", limit=1) | ||||||
|         self.__validation_test() |         self.__validation_test() | ||||||
|  |  | ||||||
|  | @ -1,11 +1,6 @@ | ||||||
| import datetime |  | ||||||
| import pytz | import pytz | ||||||
| 
 | 
 | ||||||
| from decimal import Decimal | 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 import models as rego | ||||||
| from registrasion.controllers.cart import CartController | from registrasion.controllers.cart import CartController | ||||||
|  | @ -14,6 +9,7 @@ from test_cart import RegistrationCartTestCase | ||||||
| 
 | 
 | ||||||
| UTC = pytz.timezone('UTC') | UTC = pytz.timezone('UTC') | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class DiscountTestCase(RegistrationCartTestCase): | class DiscountTestCase(RegistrationCartTestCase): | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|  | @ -32,7 +28,6 @@ class DiscountTestCase(RegistrationCartTestCase): | ||||||
|         ).save() |         ).save() | ||||||
|         return discount |         return discount | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def add_discount_prod_1_includes_cat_2(cls, amount=Decimal(100)): |     def add_discount_prod_1_includes_cat_2(cls, amount=Decimal(100)): | ||||||
|         discount = rego.IncludedProductDiscount.objects.create( |         discount = rego.IncludedProductDiscount.objects.create( | ||||||
|  | @ -49,9 +44,8 @@ class DiscountTestCase(RegistrationCartTestCase): | ||||||
|         ).save() |         ).save() | ||||||
|         return discount |         return discount | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discount_is_applied(self): |     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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_1, 1) |         cart.add_to_cart(self.PROD_1, 1) | ||||||
|  | @ -60,9 +54,8 @@ class DiscountTestCase(RegistrationCartTestCase): | ||||||
|         # Discounts should be applied at this point... |         # Discounts should be applied at this point... | ||||||
|         self.assertEqual(1, len(cart.cart.discountitem_set.all())) |         self.assertEqual(1, len(cart.cart.discountitem_set.all())) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discount_is_applied_for_category(self): |     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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_1, 1) |         cart.add_to_cart(self.PROD_1, 1) | ||||||
|  | @ -71,9 +64,8 @@ class DiscountTestCase(RegistrationCartTestCase): | ||||||
|         # Discounts should be applied at this point... |         # Discounts should be applied at this point... | ||||||
|         self.assertEqual(1, len(cart.cart.discountitem_set.all())) |         self.assertEqual(1, len(cart.cart.discountitem_set.all())) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discount_does_not_apply_if_not_met(self): |     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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_2, 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 |         # No discount should be applied as the condition is not met | ||||||
|         self.assertEqual(0, len(cart.cart.discountitem_set.all())) |         self.assertEqual(0, len(cart.cart.discountitem_set.all())) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discount_applied_out_of_order(self): |     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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_2, 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 |         # No discount should be applied as the condition is not met | ||||||
|         self.assertEqual(1, len(cart.cart.discountitem_set.all())) |         self.assertEqual(1, len(cart.cart.discountitem_set.all())) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discounts_collapse(self): |     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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_1, 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... |         # Discounts should be applied and collapsed at this point... | ||||||
|         self.assertEqual(1, len(cart.cart.discountitem_set.all())) |         self.assertEqual(1, len(cart.cart.discountitem_set.all())) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discounts_respect_quantity(self): |     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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_1, 1) |         cart.add_to_cart(self.PROD_1, 1) | ||||||
|  | @ -117,7 +106,6 @@ class DiscountTestCase(RegistrationCartTestCase): | ||||||
|         discount_items = list(cart.cart.discountitem_set.all()) |         discount_items = list(cart.cart.discountitem_set.all()) | ||||||
|         self.assertEqual(2, discount_items[0].quantity) |         self.assertEqual(2, discount_items[0].quantity) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_multiple_discounts_apply_in_order(self): |     def test_multiple_discounts_apply_in_order(self): | ||||||
|         discount_full = self.add_discount_prod_1_includes_prod_2() |         discount_full = self.add_discount_prod_1_includes_prod_2() | ||||||
|         discount_half = self.add_discount_prod_1_includes_prod_2(Decimal(50)) |         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(2, discount_items[1].quantity) | ||||||
|         self.assertEqual(discount_full.pk, discount_items[1].discount.pk) |         self.assertEqual(discount_full.pk, discount_items[1].discount.pk) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discount_applies_across_carts(self): |     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. |         # Enable the discount during the first cart. | ||||||
|         cart = CartController.for_user(self.USER_1) |         cart = CartController.for_user(self.USER_1) | ||||||
|  | @ -167,16 +154,16 @@ class DiscountTestCase(RegistrationCartTestCase): | ||||||
|         discount_items = list(cart.cart.discountitem_set.all()) |         discount_items = list(cart.cart.discountitem_set.all()) | ||||||
|         self.assertEqual(1, discount_items[0].quantity) |         self.assertEqual(1, discount_items[0].quantity) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_discount_applies_only_once_enabled(self): |     def test_discount_applies_only_once_enabled(self): | ||||||
|         # Enable the discount during the first cart. |         # Enable the discount during the first cart. | ||||||
|         cart = CartController.for_user(self.USER_1) |         cart = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_1, 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.active = False | ||||||
|         cart.cart.save() |         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 = CartController.for_user(self.USER_1) | ||||||
|         cart.add_to_cart(self.PROD_2, 2) |         cart.add_to_cart(self.PROD_2, 2) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,11 +1,6 @@ | ||||||
| import datetime |  | ||||||
| import pytz | import pytz | ||||||
| 
 | 
 | ||||||
| from decimal import Decimal |  | ||||||
| from django.contrib.auth.models import User |  | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.test import TestCase |  | ||||||
| from django.utils import timezone |  | ||||||
| 
 | 
 | ||||||
| from registrasion import models as rego | from registrasion import models as rego | ||||||
| from registrasion.controllers.cart import CartController | from registrasion.controllers.cart import CartController | ||||||
|  | @ -14,6 +9,7 @@ from test_cart import RegistrationCartTestCase | ||||||
| 
 | 
 | ||||||
| UTC = pytz.timezone('UTC') | UTC = pytz.timezone('UTC') | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class EnablingConditionTestCases(RegistrationCartTestCase): | class EnablingConditionTestCases(RegistrationCartTestCase): | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|  | @ -29,7 +25,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase): | ||||||
|         enabling_condition.enabling_products.add(cls.PROD_2) |         enabling_condition.enabling_products.add(cls.PROD_2) | ||||||
|         enabling_condition.save() |         enabling_condition.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def add_product_enabling_condition_on_category(cls, mandatory=False): |     def add_product_enabling_condition_on_category(cls, mandatory=False): | ||||||
|         ''' Adds a product enabling condition that operates on a category: |         ''' 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.enabling_products.add(cls.PROD_3) | ||||||
|         enabling_condition.save() |         enabling_condition.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def add_category_enabling_condition(cls, mandatory=False): |     def add_category_enabling_condition(cls, mandatory=False): | ||||||
|         ''' Adds a category enabling condition: adding PROD_1 to a cart is |         ''' Adds a category enabling condition: adding PROD_1 to a cart is | ||||||
|         predicated on adding an item from CAT_2 beforehand.''' |         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.products.add(cls.PROD_1) | ||||||
|         enabling_condition.save() |         enabling_condition.save() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_product_enabling_condition_enables_product(self): |     def test_product_enabling_condition_enables_product(self): | ||||||
|         self.add_product_enabling_condition() |         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_2, 1) | ||||||
|         current_cart.add_to_cart(self.PROD_1, 1) |         current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_product_enabled_by_product_in_previous_cart(self): |     def test_product_enabled_by_product_in_previous_cart(self): | ||||||
|         self.add_product_enabling_condition() |         self.add_product_enabling_condition() | ||||||
| 
 | 
 | ||||||
|  | @ -81,7 +73,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase): | ||||||
|         current_cart = CartController.for_user(self.USER_1) |         current_cart = CartController.for_user(self.USER_1) | ||||||
|         current_cart.add_to_cart(self.PROD_1, 1) |         current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_product_enabling_condition_enables_category(self): |     def test_product_enabling_condition_enables_category(self): | ||||||
|         self.add_product_enabling_condition_on_category() |         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_3, 1) | ||||||
|         current_cart.add_to_cart(self.PROD_1, 1) |         current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_category_enabling_condition_enables_product(self): |     def test_category_enabling_condition_enables_product(self): | ||||||
|         self.add_category_enabling_condition() |         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_3, 1) | ||||||
|         current_cart.add_to_cart(self.PROD_1, 1) |         current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_product_enabled_by_category_in_previous_cart(self): |     def test_product_enabled_by_category_in_previous_cart(self): | ||||||
|         self.add_category_enabling_condition() |         self.add_category_enabling_condition() | ||||||
| 
 | 
 | ||||||
|  | @ -119,7 +108,6 @@ class EnablingConditionTestCases(RegistrationCartTestCase): | ||||||
|         current_cart = CartController.for_user(self.USER_1) |         current_cart = CartController.for_user(self.USER_1) | ||||||
|         current_cart.add_to_cart(self.PROD_1, 1) |         current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_multiple_non_mandatory_conditions(self): |     def test_multiple_non_mandatory_conditions(self): | ||||||
|         self.add_product_enabling_condition() |         self.add_product_enabling_condition() | ||||||
|         self.add_category_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_3, 1) | ||||||
|         cart_2.add_to_cart(self.PROD_1, 1) |         cart_2.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_multiple_mandatory_conditions(self): |     def test_multiple_mandatory_conditions(self): | ||||||
|         self.add_product_enabling_condition(mandatory=True) |         self.add_product_enabling_condition(mandatory=True) | ||||||
|         self.add_category_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 |         # Cannot add PROD_1 until both conditions are met | ||||||
|         with self.assertRaises(ValidationError): |         with self.assertRaises(ValidationError): | ||||||
|             cart_1.add_to_cart(self.PROD_1, 1) |             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): |         with self.assertRaises(ValidationError): | ||||||
|             cart_1.add_to_cart(self.PROD_1, 1) |             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) |         cart_1.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_mandatory_conditions_are_mandatory(self): |     def test_mandatory_conditions_are_mandatory(self): | ||||||
|         self.add_product_enabling_condition(mandatory=False) |         self.add_product_enabling_condition(mandatory=False) | ||||||
|         self.add_category_enabling_condition(mandatory=True) |         self.add_category_enabling_condition(mandatory=True) | ||||||
|  | @ -164,8 +150,8 @@ class EnablingConditionTestCases(RegistrationCartTestCase): | ||||||
|         # Cannot add PROD_1 until both conditions are met |         # Cannot add PROD_1 until both conditions are met | ||||||
|         with self.assertRaises(ValidationError): |         with self.assertRaises(ValidationError): | ||||||
|             cart_1.add_to_cart(self.PROD_1, 1) |             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): |         with self.assertRaises(ValidationError): | ||||||
|             cart_1.add_to_cart(self.PROD_1, 1) |             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) |         cart_1.add_to_cart(self.PROD_1, 1) | ||||||
|  |  | ||||||
|  | @ -2,10 +2,7 @@ import datetime | ||||||
| import pytz | import pytz | ||||||
| 
 | 
 | ||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
| from django.contrib.auth.models import User |  | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.test import TestCase |  | ||||||
| from django.utils import timezone |  | ||||||
| 
 | 
 | ||||||
| from registrasion import models as rego | from registrasion import models as rego | ||||||
| from registrasion.controllers.cart import CartController | from registrasion.controllers.cart import CartController | ||||||
|  | @ -74,7 +71,6 @@ class InvoiceTestCase(RegistrationCartTestCase): | ||||||
|         new_cart = CartController.for_user(self.USER_1) |         new_cart = CartController.for_user(self.USER_1) | ||||||
|         self.assertNotEqual(current_cart.cart, new_cart.cart) |         self.assertNotEqual(current_cart.cart, new_cart.cart) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_invoice_includes_discounts(self): |     def test_invoice_includes_discounts(self): | ||||||
|         voucher = rego.Voucher.objects.create( |         voucher = rego.Voucher.objects.create( | ||||||
|             recipient="Voucher recipient", |             recipient="Voucher recipient", | ||||||
|  | @ -105,4 +101,6 @@ class InvoiceTestCase(RegistrationCartTestCase): | ||||||
|         line_items = rego.LineItem.objects.filter(invoice=invoice_1.invoice) |         line_items = rego.LineItem.objects.filter(invoice=invoice_1.invoice) | ||||||
|         self.assertEqual(2, len(line_items)) |         self.assertEqual(2, len(line_items)) | ||||||
|         # That invoice should have a value equal to 50% of the cost of PROD_1 |         # 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 | import pytz | ||||||
| 
 | 
 | ||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
| from django.contrib.auth.models import User |  | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.test import TestCase |  | ||||||
| from django.utils import timezone |  | ||||||
| 
 | 
 | ||||||
| from registrasion import models as rego | from registrasion import models as rego | ||||||
| from registrasion.controllers.cart import CartController | from registrasion.controllers.cart import CartController | ||||||
|  | @ -41,7 +38,8 @@ class VoucherTestCases(RegistrationCartTestCase): | ||||||
|         with self.assertRaises(ValidationError): |         with self.assertRaises(ValidationError): | ||||||
|             cart_2.apply_voucher(voucher) |             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) |         self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2) | ||||||
|         cart_2.apply_voucher(voucher) |         cart_2.apply_voucher(voucher) | ||||||
|         cart_2.cart.active = False |         cart_2.cart.active = False | ||||||
|  | @ -74,7 +72,6 @@ class VoucherTestCases(RegistrationCartTestCase): | ||||||
|         current_cart.apply_voucher(voucher) |         current_cart.apply_voucher(voucher) | ||||||
|         current_cart.add_to_cart(self.PROD_1, 1) |         current_cart.add_to_cart(self.PROD_1, 1) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def test_voucher_enables_discount(self): |     def test_voucher_enables_discount(self): | ||||||
|         voucher = self.new_voucher() |         voucher = self.new_voucher() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								setup.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								setup.cfg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | [flake8] | ||||||
|  | exclude = registrasion/migrations/* | ||||||
|  | 
 | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Christopher Neugebauer
						Christopher Neugebauer