Merge branch 'random_fixes'
This commit is contained in:
commit
5debbb2ac8
10 changed files with 109 additions and 65 deletions
|
@ -57,6 +57,7 @@ class InvoiceController(object):
|
|||
return value
|
||||
|
||||
@classmethod
|
||||
@transaction.atomic
|
||||
def _generate(cls, cart):
|
||||
''' Generates an invoice for the given cart. '''
|
||||
invoice = rego.Invoice.objects.create(
|
||||
|
@ -65,10 +66,12 @@ class InvoiceController(object):
|
|||
cart_revision=cart.revision,
|
||||
value=Decimal()
|
||||
)
|
||||
invoice.save()
|
||||
|
||||
# TODO: calculate line items.
|
||||
product_items = rego.ProductItem.objects.filter(cart=cart)
|
||||
|
||||
if len(product_items) == 0:
|
||||
raise ValidationError("Your cart is empty.")
|
||||
|
||||
product_items = product_items.order_by(
|
||||
"product__category__order", "product__order"
|
||||
)
|
||||
|
@ -82,7 +85,6 @@ class InvoiceController(object):
|
|||
quantity=item.quantity,
|
||||
price=product.price,
|
||||
)
|
||||
line_item.save()
|
||||
invoice_value += line_item.quantity * line_item.price
|
||||
|
||||
for item in discount_items:
|
||||
|
@ -92,11 +94,13 @@ class InvoiceController(object):
|
|||
quantity=item.quantity,
|
||||
price=cls.resolve_discount_value(item) * -1,
|
||||
)
|
||||
line_item.save()
|
||||
invoice_value += line_item.quantity * line_item.price
|
||||
|
||||
# TODO: calculate line items from discounts
|
||||
invoice.value = invoice_value
|
||||
|
||||
if invoice.value == 0:
|
||||
invoice.paid = True
|
||||
|
||||
invoice.save()
|
||||
|
||||
return invoice
|
||||
|
|
|
@ -47,7 +47,10 @@ class _QuantityBoxProductsForm(_ProductsForm):
|
|||
@classmethod
|
||||
def set_fields(cls, category, products):
|
||||
for product in products:
|
||||
help_text = "$%d -- %s" % (product.price, product.description)
|
||||
if product.description:
|
||||
help_text = "$%d each -- %s" % (product.price, product.description)
|
||||
else:
|
||||
help_text = "$%d each" % product.price
|
||||
|
||||
field = forms.IntegerField(
|
||||
label=product.name,
|
||||
|
|
|
@ -35,14 +35,18 @@ def items_pending(context):
|
|||
|
||||
|
||||
@register.assignment_tag(takes_context=True)
|
||||
def items_purchased(context):
|
||||
''' Returns all of the items that this user has purchased '''
|
||||
def items_purchased(context, category=None):
|
||||
''' Returns all of the items that this user has purchased, optionally
|
||||
from the given category. '''
|
||||
|
||||
all_items = rego.ProductItem.objects.filter(
|
||||
cart__user=context.request.user,
|
||||
cart__active=False,
|
||||
)
|
||||
|
||||
if category:
|
||||
all_items = all_items.filter(product__category=category)
|
||||
|
||||
products = set(item.product for item in all_items)
|
||||
out = []
|
||||
for product in products:
|
||||
|
|
|
@ -24,3 +24,7 @@ class TestingCartController(CartController):
|
|||
except ObjectDoesNotExist:
|
||||
old_quantity = 0
|
||||
self.set_quantity(product, old_quantity + quantity)
|
||||
|
||||
def next_cart(self):
|
||||
self.cart.active = False
|
||||
self.cart.save()
|
||||
|
|
|
@ -74,12 +74,12 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
|
|||
|
||||
# Burn through some carts -- this made some past EC tests fail
|
||||
current_cart = TestingCartController.for_user(cls.USER_1)
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
current_cart = TestingCartController.for_user(cls.USER_2)
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
@classmethod
|
||||
def make_ceiling(cls, name, limit=None, start_time=None, end_time=None):
|
||||
|
@ -142,8 +142,8 @@ class BasicCartTests(RegistrationCartTestCase):
|
|||
def test_get_cart(self):
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
old_cart = current_cart
|
||||
|
||||
|
@ -214,8 +214,8 @@ class BasicCartTests(RegistrationCartTestCase):
|
|||
with self.assertRaises(ValidationError):
|
||||
current_cart.add_to_cart(self.PROD_1, 10)
|
||||
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
# User should not be able to add 10 of PROD_1 to the current cart now,
|
||||
|
@ -272,8 +272,8 @@ class BasicCartTests(RegistrationCartTestCase):
|
|||
with self.assertRaises(ValidationError):
|
||||
current_cart.add_to_cart(self.PROD_3, 1)
|
||||
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
# The category limit should extend across carts
|
||||
|
@ -298,8 +298,8 @@ class BasicCartTests(RegistrationCartTestCase):
|
|||
current_cart.add_to_cart(self.PROD_4, 1)
|
||||
|
||||
# The limits should extend across carts...
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.set_quantity(self.PROD_3, 4)
|
||||
|
@ -325,8 +325,8 @@ class BasicCartTests(RegistrationCartTestCase):
|
|||
current_cart.add_to_cart(item, quantity)
|
||||
self.assertTrue(item in prods)
|
||||
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ class CeilingsTestCases(RegistrationCartTestCase):
|
|||
second_cart.add_to_cart(self.PROD_1, 1)
|
||||
|
||||
# User 2 pays for their cart
|
||||
second_cart.cart.active = False
|
||||
second_cart.cart.save()
|
||||
|
||||
second_cart.next_cart()
|
||||
|
||||
# User 1 should not be able to add item to their cart
|
||||
# because user 2 has paid for their reserved item, exhausting
|
||||
|
@ -128,8 +128,8 @@ class CeilingsTestCases(RegistrationCartTestCase):
|
|||
first_cart.validate_cart()
|
||||
|
||||
# Paid cart outside the reservation window
|
||||
second_cart.cart.active = False
|
||||
second_cart.cart.save()
|
||||
|
||||
second_cart.next_cart()
|
||||
self.add_timedelta(self.RESERVATION + datetime.timedelta(seconds=1))
|
||||
with self.assertRaises(ValidationError):
|
||||
first_cart.validate_cart()
|
||||
|
@ -140,15 +140,15 @@ class CeilingsTestCases(RegistrationCartTestCase):
|
|||
first_cart = TestingCartController.for_user(self.USER_1)
|
||||
first_cart.add_to_cart(self.PROD_1, 1)
|
||||
|
||||
first_cart.cart.active = False
|
||||
first_cart.cart.save()
|
||||
|
||||
first_cart.next_cart()
|
||||
|
||||
second_cart = TestingCartController.for_user(self.USER_2)
|
||||
with self.assertRaises(ValidationError):
|
||||
second_cart.add_to_cart(self.PROD_1, 1)
|
||||
|
||||
first_cart.cart.released = True
|
||||
first_cart.cart.save()
|
||||
first_cart.next_cart()
|
||||
|
||||
second_cart.add_to_cart(self.PROD_1, 1)
|
||||
|
||||
|
@ -176,8 +176,8 @@ class CeilingsTestCases(RegistrationCartTestCase):
|
|||
cart.add_to_cart(self.PROD_1, 1)
|
||||
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
|
||||
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
# The second cart has no voucher attached, so should apply the
|
||||
# ceiling discount
|
||||
|
|
|
@ -168,8 +168,8 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
# Enable the discount during the first cart.
|
||||
cart = TestingCartController.for_user(self.USER_1)
|
||||
cart.add_to_cart(self.PROD_1, 1)
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
# Use the discount in the second cart
|
||||
cart = TestingCartController.for_user(self.USER_1)
|
||||
|
@ -177,8 +177,8 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
|
||||
# The discount should be applied.
|
||||
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
# The discount should respect the total quantity across all
|
||||
# of the user's carts.
|
||||
|
@ -197,8 +197,8 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
cart.add_to_cart(self.PROD_1, 1)
|
||||
# This would exhaust discount if present
|
||||
cart.add_to_cart(self.PROD_2, 2)
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
self.add_discount_prod_1_includes_prod_2()
|
||||
cart = TestingCartController.for_user(self.USER_1)
|
||||
|
@ -346,9 +346,8 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
|
||||
discounts = discount.available_discounts(self.USER_1, [self.CAT_2], [])
|
||||
self.assertEqual(2, discounts[0].quantity)
|
||||
inv = InvoiceController.for_cart(cart.cart)
|
||||
inv.pay("Dummy reference", inv.invoice.value)
|
||||
self.assertTrue(inv.invoice.paid)
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
def test_discount_quantity_is_correct_after_first_purchase(self):
|
||||
self.test_discount_quantity_is_correct_before_first_purchase()
|
||||
|
@ -358,9 +357,8 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
|
||||
discounts = discount.available_discounts(self.USER_1, [self.CAT_2], [])
|
||||
self.assertEqual(1, discounts[0].quantity)
|
||||
inv = InvoiceController.for_cart(cart.cart)
|
||||
inv.pay("Dummy reference", inv.invoice.value)
|
||||
self.assertTrue(inv.invoice.paid)
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
def test_discount_is_gone_after_quantity_exhausted(self):
|
||||
self.test_discount_quantity_is_correct_after_first_purchase()
|
||||
|
@ -390,12 +388,12 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
self.assertEqual(1, len(discounts))
|
||||
|
||||
cart.cart.active = False # Keep discount enabled
|
||||
cart.cart.save()
|
||||
cart.next_cart()
|
||||
|
||||
cart = TestingCartController.for_user(self.USER_1)
|
||||
cart.add_to_cart(self.PROD_2, 2) # The discount will be exhausted
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
discounts = discount.available_discounts(
|
||||
self.USER_1,
|
||||
|
@ -405,7 +403,7 @@ class DiscountTestCase(RegistrationCartTestCase):
|
|||
self.assertEqual(0, len(discounts))
|
||||
|
||||
cart.cart.released = True
|
||||
cart.cart.save()
|
||||
cart.next_cart()
|
||||
|
||||
discounts = discount.available_discounts(
|
||||
self.USER_1,
|
||||
|
|
|
@ -68,8 +68,8 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
|
|||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.add_to_cart(self.PROD_2, 1)
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
# Create new cart and try to add PROD_1
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
|
@ -103,8 +103,8 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
|
|||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.add_to_cart(self.PROD_3, 1)
|
||||
current_cart.cart.active = False
|
||||
current_cart.cart.save()
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
# Create new cart and try to add PROD_1
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
|
@ -241,15 +241,15 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
|
|||
cart = TestingCartController.for_user(self.USER_1)
|
||||
cart.add_to_cart(self.PROD_3, 1)
|
||||
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
cart_2 = TestingCartController.for_user(self.USER_1)
|
||||
cart_2.add_to_cart(self.PROD_1, 1)
|
||||
cart_2.set_quantity(self.PROD_1, 0)
|
||||
|
||||
cart.cart.released = True
|
||||
cart.cart.save()
|
||||
cart.next_cart()
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
cart_2.set_quantity(self.PROD_1, 1)
|
||||
|
@ -260,15 +260,15 @@ class EnablingConditionTestCases(RegistrationCartTestCase):
|
|||
cart = TestingCartController.for_user(self.USER_1)
|
||||
cart.add_to_cart(self.PROD_2, 1)
|
||||
|
||||
cart.cart.active = False
|
||||
cart.cart.save()
|
||||
|
||||
cart.next_cart()
|
||||
|
||||
cart_2 = TestingCartController.for_user(self.USER_1)
|
||||
cart_2.add_to_cart(self.PROD_1, 1)
|
||||
cart_2.set_quantity(self.PROD_1, 0)
|
||||
|
||||
cart.cart.released = True
|
||||
cart.cart.save()
|
||||
cart.next_cart()
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
cart_2.set_quantity(self.PROD_1, 1)
|
||||
|
|
|
@ -83,18 +83,16 @@ class InvoiceTestCase(RegistrationCartTestCase):
|
|||
code="VOUCHER",
|
||||
limit=1
|
||||
)
|
||||
voucher.save()
|
||||
discount = rego.VoucherDiscount.objects.create(
|
||||
description="VOUCHER RECIPIENT",
|
||||
voucher=voucher,
|
||||
)
|
||||
discount.save()
|
||||
rego.DiscountForProduct.objects.create(
|
||||
discount=discount,
|
||||
product=self.PROD_1,
|
||||
percentage=Decimal(50),
|
||||
quantity=1
|
||||
).save()
|
||||
)
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.apply_voucher(voucher.code)
|
||||
|
@ -111,6 +109,32 @@ class InvoiceTestCase(RegistrationCartTestCase):
|
|||
self.PROD_1.price * Decimal("0.5"),
|
||||
invoice_1.invoice.value)
|
||||
|
||||
def test_zero_value_invoice_is_automatically_paid(self):
|
||||
voucher = rego.Voucher.objects.create(
|
||||
recipient="Voucher recipient",
|
||||
code="VOUCHER",
|
||||
limit=1
|
||||
)
|
||||
discount = rego.VoucherDiscount.objects.create(
|
||||
description="VOUCHER RECIPIENT",
|
||||
voucher=voucher,
|
||||
)
|
||||
rego.DiscountForProduct.objects.create(
|
||||
discount=discount,
|
||||
product=self.PROD_1,
|
||||
percentage=Decimal(100),
|
||||
quantity=1
|
||||
)
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.apply_voucher(voucher.code)
|
||||
|
||||
# Should be able to create an invoice after the product is added
|
||||
current_cart.add_to_cart(self.PROD_1, 1)
|
||||
invoice_1 = InvoiceController.for_cart(current_cart.cart)
|
||||
|
||||
self.assertTrue(invoice_1.invoice.paid)
|
||||
|
||||
def test_invoice_voids_self_if_cart_is_invalid(self):
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
|
||||
|
@ -169,3 +193,8 @@ class InvoiceTestCase(RegistrationCartTestCase):
|
|||
|
||||
with self.assertRaises(ValidationError):
|
||||
invoice_1.void()
|
||||
|
||||
def test_cannot_generate_blank_invoice(self):
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
with self.assertRaises(ValidationError):
|
||||
invoice_1 = InvoiceController.for_cart(current_cart.cart)
|
||||
|
|
|
@ -34,8 +34,8 @@ class VoucherTestCases(RegistrationCartTestCase):
|
|||
# user 2 should be able to apply voucher
|
||||
self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2)
|
||||
cart_2.apply_voucher(voucher.code)
|
||||
cart_2.cart.active = False
|
||||
cart_2.cart.save()
|
||||
|
||||
cart_2.next_cart()
|
||||
|
||||
# After the reservation duration, even though the voucher has applied,
|
||||
# it exceeds the number of vouchers available.
|
||||
|
@ -125,8 +125,8 @@ class VoucherTestCases(RegistrationCartTestCase):
|
|||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.apply_voucher(voucher.code)
|
||||
|
||||
inv = InvoiceController.for_cart(current_cart.cart)
|
||||
inv.pay("Hello!", inv.invoice.value)
|
||||
|
||||
current_cart.next_cart()
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
|
||||
|
@ -139,9 +139,11 @@ class VoucherTestCases(RegistrationCartTestCase):
|
|||
voucher = self.new_voucher(limit=2)
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
current_cart.apply_voucher(voucher.code)
|
||||
current_cart.add_to_cart(self.PROD_1, 1)
|
||||
|
||||
inv = InvoiceController.for_cart(current_cart.cart)
|
||||
inv.pay("Hello!", inv.invoice.value)
|
||||
if not inv.invoice.paid:
|
||||
inv.pay("Hello!", inv.invoice.value)
|
||||
|
||||
current_cart = TestingCartController.for_user(self.USER_1)
|
||||
with self.assertRaises(ValidationError):
|
||||
|
|
Loading…
Reference in a new issue