2016-01-22 05:01:30 +00:00
|
|
|
import datetime
|
|
|
|
import pytz
|
|
|
|
|
|
|
|
from decimal import Decimal
|
|
|
|
from django.core.exceptions import ValidationError
|
2016-03-23 02:29:18 +00:00
|
|
|
from django.db import IntegrityError
|
2016-04-25 04:31:25 +00:00
|
|
|
from django.db import transaction
|
2016-01-22 05:01:30 +00:00
|
|
|
|
2016-04-22 05:06:24 +00:00
|
|
|
from registrasion.models import conditions
|
|
|
|
from registrasion.models import inventory
|
2017-04-22 08:39:07 +00:00
|
|
|
from registrasion.tests.controller_helpers import TestingCartController
|
|
|
|
from registrasion.tests.controller_helpers import TestingInvoiceController
|
2016-01-22 05:01:30 +00:00
|
|
|
|
2017-04-22 08:39:07 +00:00
|
|
|
from registrasion.tests.test_cart import RegistrationCartTestCase
|
2016-01-22 05:01:30 +00:00
|
|
|
|
|
|
|
UTC = pytz.timezone('UTC')
|
|
|
|
|
|
|
|
|
|
|
|
class VoucherTestCases(RegistrationCartTestCase):
|
|
|
|
|
|
|
|
def test_apply_voucher(self):
|
|
|
|
voucher = self.new_voucher()
|
|
|
|
|
2017-04-22 08:39:07 +00:00
|
|
|
self.set_time(datetime.datetime(2015, 1, 1, tzinfo=UTC))
|
2016-01-22 05:01:30 +00:00
|
|
|
|
2016-04-03 00:06:35 +00:00
|
|
|
cart_1 = TestingCartController.for_user(self.USER_1)
|
2016-03-23 02:29:18 +00:00
|
|
|
cart_1.apply_voucher(voucher.code)
|
2016-01-22 05:01:30 +00:00
|
|
|
self.assertIn(voucher, cart_1.cart.vouchers.all())
|
|
|
|
|
|
|
|
# Second user should not be able to apply this voucher (it's exhausted)
|
2016-04-03 00:06:35 +00:00
|
|
|
cart_2 = TestingCartController.for_user(self.USER_2)
|
2016-01-22 05:01:30 +00:00
|
|
|
with self.assertRaises(ValidationError):
|
2016-03-23 02:29:18 +00:00
|
|
|
cart_2.apply_voucher(voucher.code)
|
2016-01-22 05:01:30 +00:00
|
|
|
|
2016-01-22 06:02:07 +00:00
|
|
|
# After the reservation duration
|
|
|
|
# user 2 should be able to apply voucher
|
2016-04-22 05:06:24 +00:00
|
|
|
self.add_timedelta(inventory.Voucher.RESERVATION_DURATION * 2)
|
2016-03-23 02:29:18 +00:00
|
|
|
cart_2.apply_voucher(voucher.code)
|
2016-04-06 07:24:25 +00:00
|
|
|
|
|
|
|
cart_2.next_cart()
|
2016-01-22 05:01:30 +00:00
|
|
|
|
2016-04-06 02:48:05 +00:00
|
|
|
# After the reservation duration, even though the voucher has applied,
|
|
|
|
# it exceeds the number of vouchers available.
|
2016-04-22 05:06:24 +00:00
|
|
|
self.add_timedelta(inventory.Voucher.RESERVATION_DURATION * 2)
|
2016-01-22 05:01:30 +00:00
|
|
|
with self.assertRaises(ValidationError):
|
2016-04-06 02:48:05 +00:00
|
|
|
cart_1.validate_cart()
|
2016-01-22 05:01:30 +00:00
|
|
|
|
2016-04-06 03:01:25 +00:00
|
|
|
def test_fix_simple_errors_resolves_unavailable_voucher(self):
|
|
|
|
self.test_apply_voucher()
|
|
|
|
|
|
|
|
# User has an exhausted voucher leftover from test_apply_voucher
|
|
|
|
cart_1 = TestingCartController.for_user(self.USER_1)
|
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
cart_1.validate_cart()
|
|
|
|
|
|
|
|
cart_1.fix_simple_errors()
|
|
|
|
# This should work now.
|
|
|
|
cart_1.validate_cart()
|
|
|
|
|
2016-01-22 05:01:30 +00:00
|
|
|
def test_voucher_enables_item(self):
|
|
|
|
voucher = self.new_voucher()
|
|
|
|
|
2016-04-22 05:06:24 +00:00
|
|
|
flag = conditions.VoucherFlag.objects.create(
|
2016-01-22 05:01:30 +00:00
|
|
|
description="Voucher condition",
|
|
|
|
voucher=voucher,
|
2016-04-22 05:06:24 +00:00
|
|
|
condition=conditions.FlagBase.ENABLE_IF_TRUE,
|
2016-01-22 05:01:30 +00:00
|
|
|
)
|
2016-04-11 07:56:11 +00:00
|
|
|
flag.products.add(self.PROD_1)
|
2016-01-22 05:01:30 +00:00
|
|
|
|
|
|
|
# Adding the product without a voucher will not work
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-01-22 05:01:30 +00:00
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
current_cart.add_to_cart(self.PROD_1, 1)
|
|
|
|
|
|
|
|
# Apply the voucher
|
2016-03-23 02:29:18 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
2016-01-22 05:01:30 +00:00
|
|
|
current_cart.add_to_cart(self.PROD_1, 1)
|
|
|
|
|
|
|
|
def test_voucher_enables_discount(self):
|
|
|
|
voucher = self.new_voucher()
|
|
|
|
|
2016-04-22 05:06:24 +00:00
|
|
|
discount = conditions.VoucherDiscount.objects.create(
|
2016-01-22 05:01:30 +00:00
|
|
|
description="VOUCHER RECIPIENT",
|
|
|
|
voucher=voucher,
|
|
|
|
)
|
2016-04-22 05:06:24 +00:00
|
|
|
conditions.DiscountForProduct.objects.create(
|
2016-01-22 05:01:30 +00:00
|
|
|
discount=discount,
|
|
|
|
product=self.PROD_1,
|
|
|
|
percentage=Decimal(100),
|
|
|
|
quantity=1
|
2016-04-25 04:31:25 +00:00
|
|
|
)
|
2016-01-22 05:01:30 +00:00
|
|
|
|
|
|
|
# Having PROD_1 in place should add a discount
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-03-23 02:29:18 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
2016-01-22 05:01:30 +00:00
|
|
|
current_cart.add_to_cart(self.PROD_1, 1)
|
|
|
|
self.assertEqual(1, len(current_cart.cart.discountitem_set.all()))
|
2016-03-23 02:29:18 +00:00
|
|
|
|
2016-04-25 04:31:25 +00:00
|
|
|
@transaction.atomic
|
2016-03-23 02:29:18 +00:00
|
|
|
def test_voucher_codes_unique(self):
|
2016-03-25 03:51:39 +00:00
|
|
|
self.new_voucher(code="VOUCHER")
|
2016-03-23 02:29:18 +00:00
|
|
|
with self.assertRaises(IntegrityError):
|
2016-03-25 03:51:39 +00:00
|
|
|
self.new_voucher(code="VOUCHER")
|
2016-03-23 02:29:18 +00:00
|
|
|
|
|
|
|
def test_multiple_vouchers_work(self):
|
2016-03-25 03:51:39 +00:00
|
|
|
self.new_voucher(code="VOUCHER1")
|
|
|
|
self.new_voucher(code="VOUCHER2")
|
2016-03-23 02:29:18 +00:00
|
|
|
|
|
|
|
def test_vouchers_case_insensitive(self):
|
|
|
|
voucher = self.new_voucher(code="VOUCHeR")
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-03-23 02:29:18 +00:00
|
|
|
current_cart.apply_voucher(voucher.code.lower())
|
2016-03-26 08:47:01 +00:00
|
|
|
|
|
|
|
def test_voucher_can_only_be_applied_once(self):
|
|
|
|
voucher = self.new_voucher(limit=2)
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-03-26 08:47:01 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
2016-04-06 02:48:05 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
|
|
|
|
|
|
|
# You can apply the code twice, but it will only add to the cart once.
|
|
|
|
self.assertEqual(1, current_cart.cart.vouchers.count())
|
2016-03-26 08:47:01 +00:00
|
|
|
|
|
|
|
def test_voucher_can_only_be_applied_once_across_multiple_carts(self):
|
|
|
|
voucher = self.new_voucher(limit=2)
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-03-26 08:47:01 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
|
|
|
|
2016-04-06 07:24:25 +00:00
|
|
|
current_cart.next_cart()
|
2016-03-26 08:47:01 +00:00
|
|
|
|
2016-04-06 02:22:32 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
|
|
|
|
2016-03-26 08:47:01 +00:00
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
current_cart.apply_voucher(voucher.code)
|
2016-03-27 08:25:24 +00:00
|
|
|
|
|
|
|
return current_cart
|
|
|
|
|
|
|
|
def test_refund_releases_used_vouchers(self):
|
|
|
|
voucher = self.new_voucher(limit=2)
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-03-27 08:25:24 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
2016-04-06 07:19:09 +00:00
|
|
|
current_cart.add_to_cart(self.PROD_1, 1)
|
2016-03-27 08:25:24 +00:00
|
|
|
|
2016-04-07 00:23:38 +00:00
|
|
|
inv = TestingInvoiceController.for_cart(current_cart.cart)
|
2016-04-06 22:28:43 +00:00
|
|
|
if not inv.invoice.is_paid:
|
2016-04-06 07:19:09 +00:00
|
|
|
inv.pay("Hello!", inv.invoice.value)
|
2016-03-27 08:25:24 +00:00
|
|
|
|
2016-04-03 00:06:35 +00:00
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
2016-03-27 08:25:24 +00:00
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
current_cart.apply_voucher(voucher.code)
|
|
|
|
|
2016-04-10 04:41:43 +00:00
|
|
|
inv.refund()
|
2016-03-27 08:25:24 +00:00
|
|
|
current_cart.apply_voucher(voucher.code)
|
2016-04-06 03:01:25 +00:00
|
|
|
|
|
|
|
def test_fix_simple_errors_does_not_remove_limited_voucher(self):
|
|
|
|
voucher = self.new_voucher(code="VOUCHER")
|
|
|
|
current_cart = TestingCartController.for_user(self.USER_1)
|
|
|
|
current_cart.apply_voucher(voucher.code)
|
|
|
|
|
|
|
|
current_cart.fix_simple_errors()
|
|
|
|
self.assertEqual(1, current_cart.cart.vouchers.count())
|