symposion_app/registrasion/controllers/conditions.py

163 lines
5 KiB
Python
Raw Normal View History

2016-01-22 06:02:07 +00:00
from django.db.models import Q
2016-01-22 05:01:30 +00:00
from django.db.models import Sum
from django.utils import timezone
from registrasion import models as rego
class ConditionController(object):
''' Base class for testing conditions that activate EnablingCondition
or Discount objects. '''
def __init__(self):
pass
@staticmethod
def for_condition(condition):
CONTROLLERS = {
2016-01-22 06:02:07 +00:00
rego.CategoryEnablingCondition: CategoryConditionController,
rego.IncludedProductDiscount: ProductConditionController,
rego.ProductEnablingCondition: ProductConditionController,
rego.TimeOrStockLimitDiscount:
2016-01-22 05:01:30 +00:00
TimeOrStockLimitConditionController,
2016-01-22 06:02:07 +00:00
rego.TimeOrStockLimitEnablingCondition:
2016-01-22 05:01:30 +00:00
TimeOrStockLimitConditionController,
2016-01-22 06:02:07 +00:00
rego.VoucherDiscount: VoucherConditionController,
rego.VoucherEnablingCondition: VoucherConditionController,
2016-01-22 05:01:30 +00:00
}
try:
return CONTROLLERS[type(condition)](condition)
except KeyError:
return ConditionController()
def is_met(self, user, quantity):
return True
class CategoryConditionController(ConditionController):
def __init__(self, condition):
self.condition = condition
def is_met(self, user, quantity):
''' returns True if the user has a product from a category that invokes
this condition in one of their carts '''
carts = rego.Cart.objects.filter(user=user, released=False)
2016-01-22 05:01:30 +00:00
enabling_products = rego.Product.objects.filter(
2016-04-02 00:02:01 +00:00
category=self.condition.enabling_category,
)
2016-01-22 06:02:07 +00:00
products = rego.ProductItem.objects.filter(
cart=carts,
2016-04-02 00:02:01 +00:00
product__in=enabling_products,
)
2016-01-22 05:01:30 +00:00
return len(products) > 0
class ProductConditionController(ConditionController):
''' Condition tests for ProductEnablingCondition and
IncludedProductDiscount. '''
def __init__(self, condition):
self.condition = condition
def is_met(self, user, quantity):
''' returns True if the user has a product that invokes this
condition in one of their carts '''
carts = rego.Cart.objects.filter(user=user, released=False)
2016-01-22 06:02:07 +00:00
products = rego.ProductItem.objects.filter(
cart=carts,
2016-04-02 00:02:01 +00:00
product__in=self.condition.enabling_products.all(),
)
2016-01-22 05:01:30 +00:00
return len(products) > 0
class TimeOrStockLimitConditionController(ConditionController):
''' Condition tests for TimeOrStockLimit EnablingCondition and
Discount.'''
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. '''
# Test date range
if not self.test_date_range():
return False
# Test limits
if not self.test_limits(quantity):
return False
# All limits have been met
return True
def test_date_range(self):
now = timezone.now()
if self.ceiling.start_time is not None:
if now < self.ceiling.start_time:
return False
if self.ceiling.end_time is not None:
if now > self.ceiling.end_time:
return False
return True
def _products(self):
''' Abstracts away the product list, becuase enabling conditions
list products differently to discounts. '''
if isinstance(self.ceiling, rego.TimeOrStockLimitEnablingCondition):
category_products = rego.Product.objects.filter(
2016-04-02 00:02:01 +00:00
category=self.ceiling.categories.all(),
2016-01-22 05:01:30 +00:00
)
return self.ceiling.products.all() | category_products
else:
categories = rego.Category.objects.filter(
2016-04-02 00:02:01 +00:00
discountforcategory__discount=self.ceiling,
2016-01-22 05:01:30 +00:00
)
return rego.Product.objects.filter(
Q(discountforproduct__discount=self.ceiling) |
Q(category=categories.all())
)
def test_limits(self, quantity):
if self.ceiling.limit is None:
return True
reserved_carts = rego.Cart.reserved_carts()
product_items = rego.ProductItem.objects.filter(
2016-04-02 00:02:01 +00:00
product__in=self._products().all(),
2016-01-22 05:01:30 +00:00
)
product_items = product_items.filter(cart=reserved_carts)
agg = product_items.aggregate(Sum("quantity"))
count = agg["quantity__sum"]
if count is None:
count = 0
if count + quantity > self.ceiling.limit:
return False
return True
class VoucherConditionController(ConditionController):
''' Condition test for VoucherEnablingCondition and VoucherDiscount.'''
def __init__(self, condition):
self.condition = condition
def is_met(self, user, quantity):
''' returns True if the user has the given voucher attached. '''
2016-01-22 06:02:07 +00:00
carts = rego.Cart.objects.filter(
user=user,
2016-04-02 00:02:01 +00:00
vouchers=self.condition.voucher,
)
2016-01-22 05:01:30 +00:00
return len(carts) > 0