Example #1
0
    def test_add_to_cart_product_per_user_limit(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        # User should be able to add 1 of PROD_1 to the current cart.
        current_cart.add_to_cart(self.PROD_1, 1)

        # User should be able to add 1 of PROD_1 to the current cart.
        current_cart.add_to_cart(self.PROD_1, 1)

        # User should not be able to add 10 of PROD_1 to the current cart now,
        # because they have a limit of 10.
        with self.assertRaises(ValidationError):
            current_cart.add_to_cart(self.PROD_1, 10)

        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,
        # even though it's a new cart.
        with self.assertRaises(ValidationError):
            current_cart.add_to_cart(self.PROD_1, 10)

        # Second user should not be affected by first user's limits
        second_user_cart = TestingCartController.for_user(self.USER_2)
        second_user_cart.add_to_cart(self.PROD_1, 10)
Example #2
0
    def test_discount_ceiling_only_counts_items_covered_by_ceiling(self):
        self.make_discount_ceiling("Limit ceiling", limit=1, percentage=50)
        voucher = self.new_voucher(code="VOUCHER")

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

        # Buy two of PROD_1, in separate carts:
        cart = TestingCartController.for_user(self.USER_1)
        # the 100% discount from the voucher should apply to the first item
        # and not the ceiling discount.
        cart.apply_voucher("VOUCHER")
        cart.add_to_cart(self.PROD_1, 1)
        self.assertEqual(1, len(cart.cart.discountitem_set.all()))

        cart.next_cart()

        # The second cart has no voucher attached, so should apply the
        # ceiling discount
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)
        self.assertEqual(1, len(cart.cart.discountitem_set.all()))
Example #3
0
    def test_discount_applies_across_carts(self):
        self.add_discount_prod_1_includes_prod_2()

        # Enable the discount during the first cart.
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        cart.next_cart()

        # Use the discount in the second cart
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 1)

        # The discount should be applied.
        self.assertEqual(1, len(cart.cart.discountitem_set.all()))

        cart.next_cart()

        # The discount should respect the total quantity across all
        # of the user's carts.
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 2)

        # Having one item in the second cart leaves one more item where
        # the discount is applicable. The discount should apply, but only for
        # quantity=1
        discount_items = list(cart.cart.discountitem_set.all())
        self.assertEqual(1, discount_items[0].quantity)
Example #4
0
    def test_per_user_category_and_product_limits(self):
        self.set_limits()

        current_cart = TestingCartController.for_user(self.USER_1)

        # Hit both the product and category edges:
        current_cart.set_quantity(self.PROD_3, 4)
        current_cart.set_quantity(self.PROD_4, 6)
        with self.assertRaises(ValidationError):
            # There's unlimited PROD_3, but limited in the category
            current_cart.add_to_cart(self.PROD_3, 1)

        current_cart.set_quantity(self.PROD_3, 0)
        with self.assertRaises(ValidationError):
            # There's only 6 allowed of PROD_4
            current_cart.add_to_cart(self.PROD_4, 1)

        # The limits should extend across carts...

        current_cart.next_cart()

        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.set_quantity(self.PROD_3, 4)

        with self.assertRaises(ValidationError):
            current_cart.set_quantity(self.PROD_3, 5)

        with self.assertRaises(ValidationError):
            current_cart.set_quantity(self.PROD_4, 1)
Example #5
0
    def test_cart_discounts_only_calculated_at_end_of_batches(self):
        def count_discounts(cart):
            return cart.cart.discountitem_set.count()

        cart = TestingCartController.for_user(self.USER_1)
        self.make_discount_ceiling("FLOOZLE")
        count_0 = count_discounts(cart)

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)

            with BatchController.batch(self.USER_1):
                # Memoise the cart
                same_cart_2 = TestingCartController.for_user(self.USER_1)

                same_cart_2.add_to_cart(self.PROD_1, 1)
                count_1 = count_discounts(same_cart_2)

            count_2 = count_discounts(same_cart)

        count_3 = count_discounts(cart)

        self.assertEqual(0, count_0)
        self.assertEqual(0, count_1)
        self.assertEqual(0, count_2)
        self.assertEqual(1, count_3)
Example #6
0
    def test_cannot_apply_a_refunded_credit_note(self):
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice = TestingInvoiceController.for_cart(self.reget(cart.cart))

        to_pay = invoice.invoice.value
        invoice.pay("Reference", to_pay)
        self.assertTrue(invoice.invoice.is_paid)

        invoice.refund()

        self.assertEquals(1, rego.CreditNote.unclaimed().count())

        credit_note = rego.CreditNote.objects.get(invoice=invoice.invoice)

        cn = TestingCreditNoteController(credit_note)
        cn.refund()

        # Refunding a credit note should mark it as claimed
        self.assertEquals(0, rego.CreditNote.unclaimed().count())

        # Create a new cart with invoice
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice_2 = TestingInvoiceController.for_cart(self.reget(cart.cart))

        # Cannot pay with this credit note.
        with self.assertRaises(ValidationError):
            cn.apply_to_invoice(invoice_2.invoice)
Example #7
0
    def test_apply_credit_note_pays_invoice(self):
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice = TestingInvoiceController.for_cart(self.reget(cart.cart))

        to_pay = invoice.invoice.value
        invoice.pay("Reference", to_pay)
        self.assertTrue(invoice.invoice.is_paid)

        invoice.refund()

        # There should be one credit note generated out of the invoice.
        credit_note = commerce.CreditNote.objects.get(invoice=invoice.invoice)
        cn = TestingCreditNoteController(credit_note)

        # That credit note should be in the unclaimed pile
        self.assertEquals(1, commerce.CreditNote.unclaimed().count())

        # Create a new (identical) cart with invoice
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice2 = TestingInvoiceController.for_cart(self.reget(cart.cart))

        cn.apply_to_invoice(invoice2.invoice)
        self.assertTrue(invoice2.invoice.is_paid)

        # That invoice should not show up as unclaimed any more
        self.assertEquals(0, commerce.CreditNote.unclaimed().count())
Example #8
0
    def test_discounts_are_released_by_refunds(self):
        self.add_discount_prod_1_includes_prod_2(quantity=2)
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount
        discounts = discount.available_discounts(
            self.USER_1,
            [],
            [self.PROD_2],
        )
        self.assertEqual(1, len(discounts))

        cart.cart.active = False  # Keep discount enabled
        cart.next_cart()

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 2)  # The discount will be exhausted

        cart.next_cart()

        discounts = discount.available_discounts(
            self.USER_1,
            [],
            [self.PROD_2],
        )
        self.assertEqual(0, len(discounts))

        cart.cart.released = True
        cart.next_cart()

        discounts = discount.available_discounts(
            self.USER_1,
            [],
            [self.PROD_2],
        )
        self.assertEqual(1, len(discounts))
Example #9
0
    def test_cannot_refund_an_applied_credit_note(self):
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice = TestingInvoiceController.for_cart(self.reget(cart.cart))

        to_pay = invoice.invoice.value
        invoice.pay("Reference", to_pay)
        self.assertTrue(invoice.invoice.is_paid)

        invoice.refund()

        self.assertEquals(1, commerce.CreditNote.unclaimed().count())

        credit_note = commerce.CreditNote.objects.get(invoice=invoice.invoice)

        cn = TestingCreditNoteController(credit_note)

        # Create a new cart with invoice
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice_2 = TestingInvoiceController.for_cart(self.reget(cart.cart))
        cn.apply_to_invoice(invoice_2.invoice)

        self.assertEquals(0, commerce.CreditNote.unclaimed().count())

        # Cannot refund this credit note as it is already applied.
        with self.assertRaises(ValidationError):
            cn.refund()
Example #10
0
    def test_required_category_constraints_prevent_invoicing(self):
        self.CAT_1.required = True
        self.CAT_1.save()

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_3, 1)

        # CAT_1 is required, we don't have CAT_1 yet
        with self.assertRaises(ValidationError):
            invoice = TestingInvoiceController.for_cart(cart.cart)

        # Now that we have CAT_1, we can check out the cart
        cart.add_to_cart(self.PROD_1, 1)
        invoice = TestingInvoiceController.for_cart(cart.cart)

        # Paying for the invoice should work fine
        invoice.pay("Boop", invoice.invoice.value)

        # We have an item in the first cart, so should be able to invoice
        # for the second cart, even without CAT_1 in it.
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_3, 1)

        invoice2 = TestingInvoiceController.for_cart(cart.cart)

        # Void invoice2, and release the first cart
        # now we don't have any CAT_1
        invoice2.void()
        invoice.refund()

        # Now that we don't have CAT_1, we can't checkout this cart
        with self.assertRaises(ValidationError):
            invoice = TestingInvoiceController.for_cart(cart.cart)
Example #11
0
    def test_product_enabled_by_category_in_previous_cart(self):
        self.add_category_flag()

        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.add_to_cart(self.PROD_3, 1)

        current_cart.next_cart()

        # Create new cart and try to add PROD_1
        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.add_to_cart(self.PROD_1, 1)
Example #12
0
    def test_cart_revision_does_not_increment_if_not_modified(self):
        cart = TestingCartController.for_user(self.USER_1)
        rev_0 = cart.cart.revision

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)
            # Do nothing on exit
        
        rev_1 = self.reget(cart.cart).revision
        self.assertEqual(rev_0, rev_1)
Example #13
0
    def test_get_cart(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        current_cart.next_cart()

        old_cart = current_cart

        current_cart = TestingCartController.for_user(self.USER_1)
        self.assertNotEqual(old_cart.cart, current_cart.cart)

        current_cart2 = TestingCartController.for_user(self.USER_1)
        self.assertEqual(current_cart.cart, current_cart2.cart)
Example #14
0
    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)

        current_cart.next_cart()

        current_cart = TestingCartController.for_user(self.USER_1)

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

        return current_cart
Example #15
0
    def test_cart_revision_only_increments_at_end_of_batches(self):
        cart = TestingCartController.for_user(self.USER_1)
        rev_0 = cart.cart.revision

        with BatchController.batch(self.USER_1):
            # Memoise the cart
            same_cart = TestingCartController.for_user(self.USER_1)
            same_cart.add_to_cart(self.PROD_1, 1)
            rev_1 = self.reget(same_cart.cart).revision

        rev_2 = self.reget(cart.cart).revision

        self.assertEqual(rev_0, rev_1)
        self.assertNotEqual(rev_0, rev_2)
Example #16
0
    def test_discount_applies_only_once_enabled(self):
        # Enable the discount during the first cart.
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)
        # This would exhaust discount if present
        cart.add_to_cart(self.PROD_2, 2)

        cart.next_cart()

        self.add_discount_prod_1_includes_prod_2()
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 2)

        discount_items = list(cart.cart.discountitem_set.all())
        self.assertEqual(2, discount_items[0].quantity)
Example #17
0
    def test_eit_and_dif_conditions_work_together(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)
        self.add_category_flag(condition=conditions.FlagBase.DISABLE_IF_FALSE)

        cart_1 = TestingCartController.for_user(self.USER_1)
        # Cannot add PROD_1 until both conditions are met
        with self.assertRaises(ValidationError):
            cart_1.add_to_cart(self.PROD_1, 1)

        cart_1.add_to_cart(self.PROD_2, 1)  # Meets the EIT condition

        # Need to meet both conditions before you can add
        with self.assertRaises(ValidationError):
            cart_1.add_to_cart(self.PROD_1, 1)

        cart_1.set_quantity(self.PROD_2, 0)  # Un-meets the EIT condition

        cart_1.add_to_cart(self.PROD_3, 1)  # Meets the DIF condition

        # Need to meet both conditions before you can add
        with self.assertRaises(ValidationError):
            cart_1.add_to_cart(self.PROD_1, 1)

        cart_1.add_to_cart(self.PROD_2, 1)  # Meets the EIT condition

        # Now that both conditions are met, we can add the product
        cart_1.add_to_cart(self.PROD_1, 1)
Example #18
0
    def test_create_invoice(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        # Should be able to create an invoice after the product is added
        current_cart.add_to_cart(self.PROD_1, 1)
        invoice_1 = TestingInvoiceController.for_cart(current_cart.cart)
        # That invoice should have a single line item
        line_items = commerce.LineItem.objects.filter(
            invoice=invoice_1.invoice,
        )
        self.assertEqual(1, len(line_items))
        # That invoice should have a value equal to cost of PROD_1
        self.assertEqual(self.PROD_1.price, invoice_1.invoice.value)

        # Adding item to cart should produce a new invoice
        current_cart.add_to_cart(self.PROD_2, 1)
        invoice_2 = TestingInvoiceController.for_cart(current_cart.cart)
        self.assertNotEqual(invoice_1.invoice, invoice_2.invoice)

        # The old invoice should automatically be voided
        invoice_1_new = commerce.Invoice.objects.get(pk=invoice_1.invoice.id)
        invoice_2_new = commerce.Invoice.objects.get(pk=invoice_2.invoice.id)
        self.assertTrue(invoice_1_new.is_void)
        self.assertFalse(invoice_2_new.is_void)

        # Invoice should have two line items
        line_items = commerce.LineItem.objects.filter(
            invoice=invoice_2.invoice,
        )
        self.assertEqual(2, len(line_items))
        # Invoice should have a value equal to cost of PROD_1 and PROD_2
        self.assertEqual(
            self.PROD_1.price + self.PROD_2.price,
            invoice_2.invoice.value)
Example #19
0
    def test_zero_value_invoice_is_automatically_paid(self):
        voucher = inventory.Voucher.objects.create(
            recipient="Voucher recipient",
            code="VOUCHER",
            limit=1
        )
        discount = conditions.VoucherDiscount.objects.create(
            description="VOUCHER RECIPIENT",
            voucher=voucher,
        )
        conditions.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 = TestingInvoiceController.for_cart(current_cart.cart)

        self.assertTrue(invoice_1.invoice.is_paid)
Example #20
0
    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)
        current_cart.add_to_cart(self.PROD_1, 1)

        inv = TestingInvoiceController.for_cart(current_cart.cart)
        if not inv.invoice.is_paid:
            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()
        current_cart.apply_voucher(voucher.code)
Example #21
0
    def test_paying_invoice_makes_new_cart(self):
        current_cart = TestingCartController.for_user(self.USER_1)
        current_cart.add_to_cart(self.PROD_1, 1)

        invoice = TestingInvoiceController.for_cart(current_cart.cart)
        invoice.pay("A payment!", invoice.invoice.value)

        # This payment is for the correct amount invoice should be paid.
        self.assertTrue(invoice.invoice.is_paid)

        # Cart should not be active
        self.assertFalse(invoice.invoice.cart.active)

        # Asking for a cart should generate a new one
        new_cart = TestingCartController.for_user(self.USER_1)
        self.assertNotEqual(current_cart.cart, new_cart.cart)
Example #22
0
    def test_set_quantity(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        def get_item():
            return rego.ProductItem.objects.get(
                cart=current_cart.cart,
                product=self.PROD_1)

        current_cart.set_quantity(self.PROD_1, 1)
        self.assertEqual(1, get_item().quantity)

        # Setting the quantity to zero should remove the entry from the cart.
        current_cart.set_quantity(self.PROD_1, 0)
        with self.assertRaises(ObjectDoesNotExist):
            get_item()

        current_cart.set_quantity(self.PROD_1, 9)
        self.assertEqual(9, get_item().quantity)

        with self.assertRaises(ValidationError):
            current_cart.set_quantity(self.PROD_1, 11)

        self.assertEqual(9, get_item().quantity)

        with self.assertRaises(ValidationError):
            current_cart.set_quantity(self.PROD_1, -1)

        self.assertEqual(9, get_item().quantity)

        current_cart.set_quantity(self.PROD_1, 2)
        self.assertEqual(2, get_item().quantity)
Example #23
0
    def test_items_released_from_ceiling_by_refund(self):
        self.make_ceiling("Limit ceiling", limit=1)

        first_cart = TestingCartController.for_user(self.USER_1)
        first_cart.add_to_cart(self.PROD_1, 1)

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

        second_cart.add_to_cart(self.PROD_1, 1)
Example #24
0
    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())
Example #25
0
 def test_per_user_category_limit_ignored_if_blank(self):
     self.set_limits()
     current_cart = TestingCartController.for_user(self.USER_1)
     # There is no product limit on PROD_2, and there is no cat limit
     current_cart.add_to_cart(self.PROD_2, 1)
     # There is no cat limit on PROD_1, but there is a prod limit
     current_cart.add_to_cart(self.PROD_1, 1)
Example #26
0
    def test_invoice_includes_discounts(self):
        voucher = inventory.Voucher.objects.create(
            recipient="Voucher recipient",
            code="VOUCHER",
            limit=1
        )
        discount = conditions.VoucherDiscount.objects.create(
            description="VOUCHER RECIPIENT",
            voucher=voucher,
        )
        conditions.DiscountForProduct.objects.create(
            discount=discount,
            product=self.PROD_1,
            percentage=Decimal(50),
            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 = TestingInvoiceController.for_cart(current_cart.cart)

        # That invoice should have two line items
        line_items = commerce.LineItem.objects.filter(
            invoice=invoice_1.invoice,
        )
        self.assertEqual(2, len(line_items))
        # 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)
Example #27
0
    def test_items_released_from_ceiling_by_refund(self):
        self.make_ceiling("Limit ceiling", limit=1)

        first_cart = TestingCartController.for_user(self.USER_1)
        first_cart.add_to_cart(self.PROD_1, 1)

        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.status = commerce.Cart.STATUS_RELEASED
        first_cart.cart.save()

        second_cart.add_to_cart(self.PROD_1, 1)
Example #28
0
    def test_discount_does_not_apply_if_not_met(self):
        self.add_discount_prod_1_includes_prod_2()

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 1)

        # No discount should be applied as the condition is not met
        self.assertEqual(0, len(cart.cart.discountitem_set.all()))
Example #29
0
    def test_product_discount_does_not_appear_with_category(self):
        self.add_discount_prod_1_includes_prod_2(quantity=1)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount

        discounts = discount.available_discounts(self.USER_1, [self.CAT_1], [])
        self.assertEqual(0, len(discounts))
Example #30
0
    def test_product_flag_fails_if_cart_refunded(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 1)

        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.status = commerce.Cart.STATUS_RELEASED
        cart.cart.save()

        with self.assertRaises(ValidationError):
            cart_2.set_quantity(self.PROD_1, 1)
Example #31
0
    def test_category_flag_enables_product(self):
        self.add_category_flag()

        # Cannot buy PROD_1 without buying PROD_2
        current_cart = TestingCartController.for_user(self.USER_1)
        with self.assertRaises(ValidationError):
            current_cart.add_to_cart(self.PROD_1, 1)

        # PROD_3 is in CAT_2
        current_cart.add_to_cart(self.PROD_3, 1)
        current_cart.add_to_cart(self.PROD_1, 1)
Example #32
0
    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()
Example #33
0
    def test_apply_credit_note_generates_new_credit_note_if_overpaying(self):
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 2)

        invoice = TestingInvoiceController.for_cart(self.reget(cart.cart))

        to_pay = invoice.invoice.value
        invoice.pay("Reference", to_pay)
        self.assertTrue(invoice.invoice.is_paid)

        invoice.refund()

        # There should be one credit note generated out of the invoice.
        credit_note = commerce.CreditNote.objects.get(invoice=invoice.invoice)
        cn = TestingCreditNoteController(credit_note)

        self.assertEquals(1, commerce.CreditNote.unclaimed().count())

        # Create a new cart (of half value of inv 1) and get invoice
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice2 = TestingInvoiceController.for_cart(self.reget(cart.cart))

        cn.apply_to_invoice(invoice2.invoice)
        self.assertTrue(invoice2.invoice.is_paid)

        # We generated a new credit note, and spent the old one,
        # unclaimed should still be 1.
        self.assertEquals(1, commerce.CreditNote.unclaimed().count())

        credit_note2 = commerce.CreditNote.objects.get(
            invoice=invoice2.invoice,
        )

        # The new credit note should be the residual of the cost of cart 1
        # minus the cost of cart 2.
        self.assertEquals(
            invoice.invoice.value - invoice2.invoice.value,
            credit_note2.value,
        )
Example #34
0
    def test_cannot_apply_credit_note_on_invalid_invoices(self):
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice = TestingInvoiceController.for_cart(self.reget(cart.cart))

        to_pay = invoice.invoice.value
        invoice.pay("Reference", to_pay)
        self.assertTrue(invoice.invoice.is_paid)

        invoice.refund()

        # There should be one credit note generated out of the invoice.
        credit_note = commerce.CreditNote.objects.get(invoice=invoice.invoice)
        cn = TestingCreditNoteController(credit_note)

        # Create a new cart with invoice, pay it
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice_2 = TestingInvoiceController.for_cart(self.reget(cart.cart))
        invoice_2.pay("LOL", invoice_2.invoice.value)

        # Cannot pay paid invoice
        with self.assertRaises(ValidationError):
            cn.apply_to_invoice(invoice_2.invoice)

        invoice_2.refund()
        # Cannot pay refunded invoice
        with self.assertRaises(ValidationError):
            cn.apply_to_invoice(invoice_2.invoice)

        # Create a new cart with invoice
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice_2 = TestingInvoiceController.for_cart(self.reget(cart.cart))
        invoice_2.void()
        # Cannot pay void invoice
        with self.assertRaises(ValidationError):
            cn.apply_to_invoice(invoice_2.invoice)
Example #35
0
    def test_fix_simple_errors_resolves_unavailable_products(self):
        self.test_validate_cart_when_flags_become_unmet()
        cart = TestingCartController.for_user(self.USER_1)

        # Should just remove all of the unavailable products
        cart.fix_simple_errors()
        # Should now succeed
        cart.validate_cart()

        # Should keep PROD_2 in the cart
        items = commerce.ProductItem.objects.filter(cart=cart.cart)
        self.assertFalse([i for i in items if i.product == self.PROD_1])
Example #36
0
    def __available_products_test(self, item, quantity):
        self.set_limits()

        def get_prods():
            return ProductController.available_products(
                self.USER_1,
                products=[self.PROD_2, self.PROD_3, self.PROD_4],
            )

        current_cart = TestingCartController.for_user(self.USER_1)
        prods = get_prods()
        self.assertTrue(item in prods)
        current_cart.add_to_cart(item, quantity)
        self.assertTrue(item in prods)

        current_cart.next_cart()

        current_cart = TestingCartController.for_user(self.USER_1)

        prods = get_prods()
        self.assertTrue(item not in prods)
Example #37
0
    def test_category_discount_appears_once_if_met_twice(self):
        self.add_discount_prod_1_includes_cat_2(quantity=1)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount

        discounts = discount.available_discounts(
            self.USER_1,
            [self.CAT_2],
            [self.PROD_3],
        )
        self.assertEqual(1, len(discounts))
Example #38
0
    def test_cannot_void_partially_paid_invoice(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        # Should be able to create an invoice after the product is added
        current_cart.add_to_cart(self.PROD_1, 1)
        invoice = TestingInvoiceController.for_cart(current_cart.cart)

        invoice.pay("Reference", invoice.invoice.value - 1)
        self.assertTrue(invoice.invoice.is_unpaid)

        with self.assertRaises(ValidationError):
            invoice.void()
Example #39
0
    def test_voiding_invoice_creates_new_invoice(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        # Should be able to create an invoice after the product is added
        current_cart.add_to_cart(self.PROD_1, 1)
        invoice_1 = TestingInvoiceController.for_cart(current_cart.cart)

        self.assertFalse(invoice_1.invoice.is_void)
        invoice_1.void()

        invoice_2 = TestingInvoiceController.for_cart(current_cart.cart)
        self.assertNotEqual(invoice_1.invoice, invoice_2.invoice)
Example #40
0
    def test_product_discount_does_not_appear_with_category(self):
        self.add_discount_prod_1_includes_prod_2(quantity=1)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount

        discounts = DiscountController.available_discounts(
            self.USER_1,
            [self.CAT_1],
            [],
        )
        self.assertEqual(0, len(discounts))
Example #41
0
    def test_product_discount_appears_with_product(self):
        self.add_discount_prod_1_includes_prod_2(quantity=1)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount

        discounts = discount.available_discounts(
            self.USER_1,
            [],
            [self.PROD_2],
        )
        self.assertEqual(1, len(discounts))
Example #42
0
    def test_category_discount_appears_once_with_two_valid_product(self):
        self.add_discount_prod_1_includes_cat_2(quantity=1)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount

        discounts = discount.available_discounts(
            self.USER_1,
            [],
            [self.PROD_3, self.PROD_4]
        )
        self.assertEqual(1, len(discounts))
Example #43
0
    def test_category_discount_applies_once_per_category(self):
        self.add_discount_prod_1_includes_cat_2(quantity=1)
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        # Add two items from category 2
        cart.add_to_cart(self.PROD_3, 1)
        cart.add_to_cart(self.PROD_4, 1)

        discount_items = list(cart.cart.discountitem_set.all())
        # There is one discount, and it should apply to one item.
        self.assertEqual(1, len(discount_items))
        self.assertEqual(1, discount_items[0].quantity)
Example #44
0
    def test_add_to_cart_collapses_product_items(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        # Add a product twice
        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.
        items = commerce.ProductItem.objects.filter(cart=current_cart.cart,
                                                    product=self.PROD_1)
        self.assertEqual(1, len(items))
        item = items[0]
        self.assertEquals(2, item.quantity)
Example #45
0
    def test_category_discount_applies_to_highest_value(self):
        self.add_discount_prod_1_includes_cat_2(quantity=1)
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        # Add two items from category 2, add the less expensive one first
        cart.add_to_cart(self.PROD_4, 1)
        cart.add_to_cart(self.PROD_3, 1)

        discount_items = list(cart.cart.discountitem_set.all())
        # There is one discount, and it should apply to the more expensive.
        self.assertEqual(1, len(discount_items))
        self.assertEqual(self.PROD_3, discount_items[0].product)
Example #46
0
    def test_available_products_on_products_works_when_condition_is_met(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        cart_1 = TestingCartController.for_user(self.USER_1)
        cart_1.add_to_cart(self.PROD_2, 1)

        prods = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1, self.PROD_2],
        )

        self.assertTrue(self.PROD_1 in prods)
        self.assertTrue(self.PROD_2 in prods)
Example #47
0
    def test_multiple_dif_conditions(self):
        self.add_product_flag(condition=conditions.FlagBase.DISABLE_IF_FALSE)
        self.add_category_flag(condition=conditions.FlagBase.DISABLE_IF_FALSE)

        cart_1 = TestingCartController.for_user(self.USER_1)
        # Cannot add PROD_1 until both conditions are met
        with self.assertRaises(ValidationError):
            cart_1.add_to_cart(self.PROD_1, 1)
        cart_1.add_to_cart(self.PROD_2, 1)  # Meets the product condition
        with self.assertRaises(ValidationError):
            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_1, 1)
Example #48
0
    def test_discount_quantity_is_per_user(self):
        self.add_discount_prod_1_includes_cat_2(quantity=1)

        # Both users should be able to apply the same discount
        # in the same way
        for user in (self.USER_1, self.USER_2):
            cart = TestingCartController.for_user(user)
            cart.add_to_cart(self.PROD_1, 1)  # Enable the discount
            cart.add_to_cart(self.PROD_3, 1)

            discount_items = list(cart.cart.discountitem_set.all())
            # The discount is applied.
            self.assertEqual(1, len(discount_items))
Example #49
0
    def test_per_user_category_limit_only(self):
        self.set_limits()

        current_cart = TestingCartController.for_user(self.USER_1)

        # Cannot add to cart if category limit is filled by one product.
        current_cart.set_quantity(self.PROD_3, 10)
        with self.assertRaises(ValidationError):
            current_cart.set_quantity(self.PROD_4, 1)

        # Can add to cart if category limit is not filled by one product
        current_cart.set_quantity(self.PROD_3, 5)
        current_cart.set_quantity(self.PROD_4, 5)
        # Cannot add to cart if category limit is filled by two products
        with self.assertRaises(ValidationError):
            current_cart.add_to_cart(self.PROD_3, 1)

        current_cart.next_cart()

        current_cart = TestingCartController.for_user(self.USER_1)
        # The category limit should extend across carts
        with self.assertRaises(ValidationError):
            current_cart.add_to_cart(self.PROD_3, 10)
Example #50
0
    def test_discount_quantity_is_correct_after_first_purchase(self):
        self.test_discount_quantity_is_correct_before_first_purchase()

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_3, 1)  # Exhaust the quantity

        discounts = DiscountController.available_discounts(
            self.USER_1,
            [self.CAT_2],
            [],
        )
        self.assertEqual(1, discounts[0].quantity)

        cart.next_cart()
Example #51
0
    def test_fix_simple_errors_does_not_remove_limited_items(self):
        cart = TestingCartController.for_user(self.USER_1)

        cart.add_to_cart(self.PROD_2, 1)
        cart.add_to_cart(self.PROD_1, 10)

        # Should just remove all of the unavailable products
        cart.fix_simple_errors()
        # Should now succeed
        cart.validate_cart()

        # Should keep PROD_2 in the cart
        # and also PROD_1, which is now exhausted for user.
        items = commerce.ProductItem.objects.filter(cart=cart.cart)
        self.assertTrue([i for i in items if i.product == self.PROD_1])
Example #52
0
    def test_validate_cart_when_flags_become_unmet(self):
        self.add_product_flag(condition=conditions.FlagBase.ENABLE_IF_TRUE)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_2, 1)
        cart.add_to_cart(self.PROD_1, 1)

        # Should pass
        cart.validate_cart()

        cart.set_quantity(self.PROD_2, 0)

        # Should fail
        with self.assertRaises(ValidationError):
            cart.validate_cart()
Example #53
0
    def test_discount_quantity_is_correct_before_first_purchase(self):
        self.add_discount_prod_1_includes_cat_2(quantity=2)

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)  # Enable the discount
        cart.add_to_cart(self.PROD_3, 1)  # Exhaust the quantity

        discounts = DiscountController.available_discounts(
            self.USER_1,
            [self.CAT_2],
            [],
        )
        self.assertEqual(2, discounts[0].quantity)

        cart.next_cart()
Example #54
0
    def test_flag_ceiling_aggregates_products(self):
        # Create two carts, add 1xprod_1 to each. Ceiling should disappear
        # after second.
        self.make_ceiling("Multi-product limit ceiling", limit=2)

        for i in xrange(2):
            cart = TestingCartController.for_user(self.USER_1)
            cart.add_to_cart(self.PROD_1, 1)
            cart.next_cart()

        products = ProductController.available_products(
            self.USER_1,
            products=[self.PROD_1],
        )

        self.assertEqual(0, len(products))
Example #55
0
    def test_paying_invoice_makes_new_cart(self):
        invoice = self._invoice_containing_prod_1(1)

        invoice.pay("A payment!", invoice.invoice.value)

        # This payment is for the correct amount invoice should be paid.
        self.assertTrue(invoice.invoice.is_paid)

        # Cart should not be active
        self.assertNotEqual(
            commerce.Cart.STATUS_ACTIVE,
            invoice.invoice.cart.status,
        )

        # Asking for a cart should generate a new one
        new_cart = TestingCartController.for_user(self.USER_1)
        self.assertNotEqual(invoice.invoice.cart, new_cart.cart)
Example #56
0
    def test_available_categories(self):
        self.add_product_flag_on_category(
            condition=conditions.FlagBase.ENABLE_IF_TRUE, )

        cart_1 = TestingCartController.for_user(self.USER_1)

        cats = CategoryController.available_categories(self.USER_1, )

        self.assertFalse(self.CAT_1 in cats)
        self.assertTrue(self.CAT_2 in cats)

        cart_1.add_to_cart(self.PROD_3, 1)

        cats = CategoryController.available_categories(self.USER_1, )

        self.assertTrue(self.CAT_1 in cats)
        self.assertTrue(self.CAT_2 in cats)
Example #57
0
    def test_refund_marks_void_and_unpaid_and_cart_released(self):
        current_cart = TestingCartController.for_user(self.USER_1)

        # Should be able to create an invoice after the product is added
        current_cart.add_to_cart(self.PROD_1, 1)
        invoice = TestingInvoiceController.for_cart(current_cart.cart)

        invoice.pay("A Payment!", invoice.invoice.value)
        self.assertFalse(invoice.invoice.is_void)
        self.assertTrue(invoice.invoice.is_paid)
        self.assertFalse(invoice.invoice.is_refunded)
        self.assertFalse(invoice.invoice.cart.released)

        invoice.refund()
        self.assertFalse(invoice.invoice.is_void)
        self.assertFalse(invoice.invoice.is_paid)
        self.assertTrue(invoice.invoice.is_refunded)
        self.assertTrue(invoice.invoice.cart.released)
Example #58
0
    def test_voucher_enables_item(self):
        voucher = self.new_voucher()

        flag = conditions.VoucherFlag.objects.create(
            description="Voucher condition",
            voucher=voucher,
            condition=conditions.FlagBase.ENABLE_IF_TRUE,
        )
        flag.products.add(self.PROD_1)

        # 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)
Example #59
0
    def test_multiple_discounts_apply_in_order(self):
        discount_full = self.add_discount_prod_1_includes_prod_2()
        discount_half = self.add_discount_prod_1_includes_prod_2(Decimal(50))

        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)
        cart.add_to_cart(self.PROD_2, 3)

        # There should be two discounts
        discount_items = list(cart.cart.discountitem_set.all())
        discount_items.sort(key=lambda item: item.quantity)
        self.assertEqual(2, len(discount_items))
        # The half discount should be applied only once
        self.assertEqual(1, discount_items[0].quantity)
        self.assertEqual(discount_half.pk, discount_items[0].discount.pk)
        # The full discount should be applied twice
        self.assertEqual(2, discount_items[1].quantity)
        self.assertEqual(discount_full.pk, discount_items[1].discount.pk)
Example #60
0
    def test_full_paid_invoice_does_not_generate_credit_note(self):
        cart = TestingCartController.for_user(self.USER_1)
        cart.add_to_cart(self.PROD_1, 1)

        invoice = TestingInvoiceController.for_cart(self.reget(cart.cart))

        # Invoice is paid evenly
        invoice.pay("Reference", invoice.invoice.value)

        # The total paid should be equal to the value of the invoice only
        self.assertEqual(invoice.invoice.value, invoice.total_payments())
        self.assertTrue(invoice.invoice.is_paid)

        # There should be no credit notes
        credit_notes = commerce.CreditNote.objects.filter(
            invoice=invoice.invoice,
        )
        self.assertEqual(0, credit_notes.count())