Files @ c9a62db774c5
Branch filter:

Location: symposion_app/registrasion/tests/test_voucher.py

Christopher Neugebauer
Resolves #17 - cannot generate invoice if there are no product items
import datetime
import pytz

from decimal import Decimal
from django.core.exceptions import ValidationError
from django.db import IntegrityError

from registrasion import models as rego
from cart_controller_helper import TestingCartController
from registrasion.controllers.invoice import InvoiceController

from test_cart import RegistrationCartTestCase

UTC = pytz.timezone('UTC')


class VoucherTestCases(RegistrationCartTestCase):

    def test_apply_voucher(self):
        voucher = self.new_voucher()

        self.set_time(datetime.datetime(2015, 01, 01, tzinfo=UTC))

        cart_1 = TestingCartController.for_user(self.USER_1)
        cart_1.apply_voucher(voucher.code)
        self.assertIn(voucher, cart_1.cart.vouchers.all())

        # Second user should not be able to apply this voucher (it's exhausted)
        cart_2 = TestingCartController.for_user(self.USER_2)
        with self.assertRaises(ValidationError):
            cart_2.apply_voucher(voucher.code)

        # After the reservation duration
        # user 2 should be able to apply voucher
        self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2)
        cart_2.apply_voucher(voucher.code)
        cart_2.cart.active = False
        cart_2.cart.save()

        # After the reservation duration, even though the voucher has applied,
        # it exceeds the number of vouchers available.
        self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2)
        with self.assertRaises(ValidationError):
            cart_1.validate_cart()

    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()

    def test_voucher_enables_item(self):
        voucher = self.new_voucher()

        enabling_condition = rego.VoucherEnablingCondition.objects.create(
            description="Voucher condition",
            voucher=voucher,
            mandatory=False,
        )
        enabling_condition.save()
        enabling_condition.products.add(self.PROD_1)
        enabling_condition.save()

        # Adding the product without a voucher will not work
        current_cart = TestingCartController.for_user(self.USER_1)
        with self.assertRaises(ValidationError):
            current_cart.add_to_cart(self.PROD_1, 1)

        # Apply the voucher
        current_cart.apply_voucher(voucher.code)
        current_cart.add_to_cart(self.PROD_1, 1)

    def test_voucher_enables_discount(self):
        voucher = self.new_voucher()

        discount = rego.VoucherDiscount.objects.create(
            description="VOUCHER RECIPIENT",
            voucher=voucher,
        )
        discount.save()
        rego.DiscountForProduct.objects.create(
            discount=discount,
            product=self.PROD_1,
            percentage=Decimal(100),
            quantity=1
        ).save()

        # Having PROD_1 in place should add a discount
        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.apply_voucher(voucher.code)
        current_cart.add_to_cart(self.PROD_1, 1)
        self.assertEqual(1, len(current_cart.cart.discountitem_set.all()))

    def test_voucher_codes_unique(self):
        self.new_voucher(code="VOUCHER")
        with self.assertRaises(IntegrityError):
            self.new_voucher(code="VOUCHER")

    def test_multiple_vouchers_work(self):
        self.new_voucher(code="VOUCHER1")
        self.new_voucher(code="VOUCHER2")

    def test_vouchers_case_insensitive(self):
        voucher = self.new_voucher(code="VOUCHeR")
        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.apply_voucher(voucher.code.lower())

    def test_voucher_can_only_be_applied_once(self):
        voucher = self.new_voucher(limit=2)
        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.apply_voucher(voucher.code)
        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())

    def test_voucher_can_only_be_applied_once_across_multiple_carts(self):
        voucher = self.new_voucher(limit=2)
        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 = TestingCartController.for_user(self.USER_1)

        with self.assertRaises(ValidationError):
            current_cart.apply_voucher(voucher.code)

        return current_cart

    def test_refund_releases_used_vouchers(self):
        voucher = self.new_voucher(limit=2)
        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 = TestingCartController.for_user(self.USER_1)
        with self.assertRaises(ValidationError):
            current_cart.apply_voucher(voucher.code)

        inv.refund("Hello!", inv.invoice.value)
        current_cart.apply_voucher(voucher.code)

    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())