def test_consumed_with_exclusive_offer(self, filled_basket): offer1 = ConditionalOfferFactory(name='offer1') offer2 = ConditionalOfferFactory(name='offer2') offer3 = ConditionalOfferFactory(name='offer3') offer1.exclusive = True offer2.exclusive = False offer3.exclusive = False for line in filled_basket.all_lines(): assert line.consumer.consumed(offer1) == 0 assert line.consumer.consumed(offer2) == 0 line1, line2 = list(filled_basket.all_lines()) line1.consumer.consume(1, offer1) # offer1 is exclusive so that blocks other offers assert line1.is_available_for_offer_discount(offer2) is False line1.consumer.consume(99, offer1) # ran out of room for offer1 assert line1.is_available_for_offer_discount(offer1) is False # offer2 was never an option assert line1.is_available_for_offer_discount(offer2) is False # exclusivity is per line so line2 is available for offer2 line2.consumer.consume(1, offer2) # nope: exclusive and non-exclusive don't mix assert line2.is_available_for_offer_discount(offer1) is False line2.consumer.consume(99, offer2) # ran out of room for offer2 assert line2.is_available_for_offer_discount(offer1) is False # but still room for offer3! assert line2.is_available_for_offer_discount(offer3) is True
def test_consumed_with_offer(self, filled_basket): offer1 = ConditionalOfferFactory(name='offer1') offer2 = ConditionalOfferFactory(name='offer2') offer1.exclusive = False offer2.exclusive = False for line in filled_basket.all_lines(): assert line.consumer.consumed(offer1) == 0 assert line.consumer.consumed(offer2) == 0 line1 = filled_basket.all_lines()[0] line2 = filled_basket.all_lines()[1] line1.consumer.consume(1, offer1) assert line1.consumer.consumed() == 1 assert line1.consumer.consumed(offer1) == 1 assert line1.consumer.consumed(offer2) == 0 line1.consumer.consume(9, offer1) assert line1.consumer.consumed() == line1.quantity assert line1.consumer.consumed(offer1) == line1.quantity assert line1.consumer.consumed(offer2) == 0 line1.consumer.consume(99, offer1) assert line1.consumer.consumed(offer1) == line1.quantity assert line1.consumer.consumed(offer2) == 0 line1.consumer.consume(1, offer2) line2.consumer.consume(1, offer2) assert line1.consumer.consumed(offer2) == 1 assert line2.consumer.consumed(offer2) == 1
def test_consumed_with_exclusive_offer_1(self, filled_basket): offer1 = ConditionalOfferFactory(name='offer1') offer2 = ConditionalOfferFactory(name='offer2') offer3 = ConditionalOfferFactory(name='offer3') offer1.exclusive = True offer2.exclusive = False offer3.exclusive = False for line in filled_basket.all_lines(): assert line.consumer.consumed(offer1) == 0 assert line.consumer.consumed(offer2) == 0 line1, line2 = list(filled_basket.all_lines()) # exclusive offer consumes one item on line1 line1.consumer.consume(1, offer1) # offer1 consumed only one item, so other 9 are available for offer2 assert line1.is_available_for_offer_discount(offer2) line1.consumer.consume(99, offer1) # ran out of room for offer1 and offer2 assert line1.is_available_for_offer_discount(offer1) is False assert line1.is_available_for_offer_discount(offer2) is False # exclusivity is per line so line2 is available for offer2 line2.consumer.consume(1, offer2) # offer2 consumed only one item, so other 19 are available for offer1 assert line2.is_available_for_offer_discount(offer1) line2.consumer.consume(99, offer2) # ran out of room for offer1 assert line2.is_available_for_offer_discount(offer1) is False # but still room for offer3! assert line2.is_available_for_offer_discount(offer3) is True
def test_consumed_with_exclusive_offer(self, filled_basket): offer1 = ConditionalOfferFactory(name='offer1') offer2 = ConditionalOfferFactory(name='offer2') offer3 = ConditionalOfferFactory(name='offer3') offer1.exclusive = True offer2.exclusive = False offer3.exclusive = False for line in filled_basket.all_lines(): assert line.consumer.consumed(offer1) == 0 assert line.consumer.consumed(offer2) == 0 line1 = filled_basket.all_lines()[0] line2 = filled_basket.all_lines()[1] line1.consumer.consume(1, offer1) assert line1.is_available_for_offer_discount(offer2) is True line1.consumer.consume(99, offer1) assert line1.is_available_for_offer_discount(offer2) is False line2.consumer.consume(1, offer2) assert line2.is_available_for_offer_discount(offer1) is True line2.consumer.consume(99, offer2) assert line2.is_available_for_offer_discount(offer1) is False assert line2.is_available_for_offer_discount(offer3) is True
def setUp(self): super(VoucherViewSetTests, self).setUp() self.user = self.create_user(is_staff=True) self.client.login(username=self.user.username, password=self.password) voucher1 = VoucherFactory() voucher1.offers.add(ConditionalOfferFactory()) self.voucher = VoucherFactory(code=COUPON_CODE) self.voucher.offers.add(ConditionalOfferFactory(name='test2'))
def test_consumed_with_exclusive_offer_2(self, filled_basket): offer1 = ConditionalOfferFactory(name='offer1') offer2 = ConditionalOfferFactory(name='offer2') offer3 = ConditionalOfferFactory(name='offer3') offer1.exclusive = True offer2.exclusive = False offer3.exclusive = False for line in filled_basket.all_lines(): assert line.consumer.consumed(offer1) == 0 assert line.consumer.consumed(offer2) == 0 line1, line2 = list(filled_basket.all_lines()) # exclusive offer consumes one item on line1 line1.consumer.consume(1, offer1) remaining1 = line1.quantity - 1 assert line1.quantity_with_offer_discount(offer1) == 1 assert line1.quantity_with_offer_discount(offer2) == 0 assert line1.quantity_with_offer_discount(offer3) == 0 assert line1.quantity_without_offer_discount(offer1) == remaining1 assert line1.quantity_without_offer_discount(offer2) == remaining1 assert line1.quantity_without_offer_discount(offer3) == remaining1 # exclusive offer consumes all items on line1 line1.consumer.consume(remaining1, offer1) assert line1.quantity_with_offer_discount(offer1) == line1.quantity assert line1.quantity_with_offer_discount(offer2) == 0 assert line1.quantity_with_offer_discount(offer3) == 0 assert line1.quantity_without_offer_discount(offer1) == 0 assert line1.quantity_without_offer_discount(offer2) == 0 assert line1.quantity_without_offer_discount(offer3) == 0 # non-exclusive offer consumes one item on line2 line2.consumer.consume(1, offer2) remaining2 = line2.quantity - 1 assert line2.quantity_with_offer_discount(offer1) == 0 assert line2.quantity_with_offer_discount(offer2) == 1 assert line2.quantity_with_offer_discount(offer3) == 0 assert line2.quantity_without_offer_discount(offer1) == remaining2 assert line2.quantity_without_offer_discount(offer2) == remaining2 assert line2.quantity_without_offer_discount(offer3) == line2.quantity # non-exclusive offer consumes all items on line2 line2.consumer.consume(remaining2, offer2) assert line2.quantity_with_offer_discount(offer1) == 0 assert line2.quantity_with_offer_discount(offer2) == line2.quantity assert line2.quantity_with_offer_discount(offer3) == 0 assert line2.quantity_without_offer_discount(offer1) == 0 assert line2.quantity_without_offer_discount(offer2) == 0 assert line2.quantity_without_offer_discount(offer3) == line2.quantity
def test_consumed_with_combined_offer(self, filled_basket): offer1 = ConditionalOfferFactory(name='offer1') offer2 = ConditionalOfferFactory(name='offer2') offer3 = ConditionalOfferFactory(name='offer3') offer4 = ConditionalOfferFactory(name='offer4') offer1.exclusive = True offer2.exclusive = False offer3.exclusive = False offer4.exclusive = False offer2.combinations.add(offer3) assert offer3 in offer2.combined_offers assert offer2 in offer3.combined_offers for line in filled_basket.all_lines(): assert line.consumer.consumed(offer1) == 0 assert line.consumer.consumed(offer2) == 0 assert line.consumer.consumed(offer3) == 0 line1 = filled_basket.all_lines()[0] # combinable offer consumes one item of line1 line1.consumer.consume(1, offer2) remaining1 = line1.quantity - 1 assert line1.quantity_with_offer_discount(offer1) == 0 assert line1.quantity_with_offer_discount(offer2) == 1 assert line1.quantity_with_offer_discount(offer3) == 0 assert line1.quantity_with_offer_discount(offer4) == 0 assert line1.quantity_without_offer_discount(offer1) == remaining1 assert line1.quantity_without_offer_discount(offer2) == remaining1 assert line1.quantity_without_offer_discount(offer3) == line1.quantity assert line1.quantity_without_offer_discount(offer4) == remaining1 # combinable offer consumes one item of line1 line1.consumer.consume(1, offer3) assert line1.quantity_with_offer_discount(offer1) == 0 assert line1.quantity_with_offer_discount(offer2) == 1 assert line1.quantity_with_offer_discount(offer3) == 1 assert line1.quantity_with_offer_discount(offer4) == 0 assert line1.quantity_without_offer_discount(offer1) == remaining1 assert line1.quantity_without_offer_discount(offer2) == remaining1 assert line1.quantity_without_offer_discount(offer3) == remaining1 assert line1.quantity_without_offer_discount(offer4) == remaining1 # combinable offer consumes all items of line1 line1.consumer.consume(remaining1, offer2) assert line1.quantity_with_offer_discount(offer1) == 0 assert line1.quantity_with_offer_discount(offer2) == line1.quantity assert line1.quantity_with_offer_discount(offer3) == 1 assert line1.quantity_with_offer_discount(offer4) == 0 assert line1.quantity_without_offer_discount(offer1) == 0 assert line1.quantity_without_offer_discount(offer2) == 0 assert line1.quantity_without_offer_discount(offer3) == remaining1 assert line1.quantity_without_offer_discount(offer4) == 0
def test_applies_offer_multiple_times_by_default(self): add_product(self.basket, D('100'), 5) offer = ConditionalOfferFactory( pk=1, condition=self.condition, benefit=self.benefit) self.applicator.apply_offers(self.basket, [offer]) applications = self.basket.offer_applications.applications self.assertEqual(5, applications[1]['freq'])
def test_basketline_formset_ordering(self): # when we use a unordered queryset in the Basketlineformset, the # discounts will be lost because django will query the database # again to enforce ordered results add_product(self.basket, D('100'), 5) offer = ConditionalOfferFactory(pk=1, condition=self.condition, benefit=self.benefit) # now we force an unordered queryset so we can see that our discounts # will disappear due to a new ordering query (see django/forms/model.py) default_line_ordering = Line._meta.ordering Line._meta.ordering = [] self.basket._lines = self.basket.lines.all() self.applicator.apply_offers(self.basket, [offer]) formset = formsets.BasketLineFormSet(strategy=self.basket.strategy, queryset=self.basket.all_lines()) # the discount is in all_lines(): self.assertTrue(self.basket.all_lines()[0].has_discount) # but not in the formset self.assertFalse(formset.forms[0].instance.has_discount) # Restore the ordering on the line Line._meta.ordering = default_line_ordering # clear the cached lines and apply the offer again self.basket._lines = None self.applicator.apply_offers(self.basket, [offer]) formset = formsets.BasketLineFormSet(strategy=self.basket.strategy, queryset=self.basket.all_lines()) self.assertTrue(formset.forms[0].instance.has_discount)
def test_respects_maximum_applications_field(self): add_product(self.basket, D('100'), 5) offer = ConditionalOfferFactory( pk=1, condition=self.condition, benefit=self.benefit, max_basket_applications=1) self.applicator.apply_offers(self.basket, [offer]) applications = self.basket.offer_applications.applications self.assertEqual(1, applications[1]['freq'])
def test_applies_offer_multiple_times_by_default(self): add_product(self.basket, D('100'), 5) offer = ConditionalOfferFactory( pk=1, condition=self.condition, benefit=self.benefit) self.applicator.apply self.applicator.apply_offers(self.basket, [offer]) line = self.basket.all_lines()[0] self.assertTrue(line.quantity_with_offer_discount(offer) == 5)
def test_no_product(self): """ Verify that an exception is raised if there is no product. """ voucher = VoucherFactory() offer = ConditionalOfferFactory() voucher.offers.add(offer) with self.assertRaises(exceptions.ProductNotFoundError): get_voucher_and_products_from_code(code=voucher.code)
def multi_offers(): offer1 = ConditionalOfferFactory( condition__range__includes_all_products=True, benefit__range__includes_all_products=True, name='offer1', exclusive=False, ) offer2 = ConditionalOfferFactory( condition__range__includes_all_products=True, benefit__range__includes_all_products=True, name='offer2', exclusive=False) offer3 = ConditionalOfferFactory( condition__range__includes_all_products=True, benefit__range__includes_all_products=True, name='offer3', exclusive=False) return offer1, offer2, offer3
def single_offer(): return ConditionalOfferFactory( condition__range__includes_all_products=True, condition__value=1, benefit__range__includes_all_products=True, benefit__max_affected_items=1, name='offer1', exclusive=False, )
def test_no_product(self): """ Verify that None is returned if there is no product. """ voucher = VoucherFactory(code='NOPRODUCT') offer = ConditionalOfferFactory() voucher.offers.add(offer) voucher, product = get_voucher(code='NOPRODUCT') self.assertIsNotNone(voucher) self.assertEqual(voucher.code, 'NOPRODUCT') self.assertIsNone(product)
def test_changing_offer_type_for_voucher_offer_without_vouchers(self): offer = ConditionalOfferFactory(offer_type=ConditionalOffer.VOUCHER) data = { 'name': offer.name, 'description': offer.description, 'offer_type': ConditionalOffer.SITE, } form = forms.MetaDataForm(data, instance=offer) self.assertTrue(form.is_valid())
def test_respects_maximum_applications_field(self): add_product(self.basket, D('100'), 5) offer = ConditionalOfferFactory( pk=1, condition=self.condition, benefit=self.benefit, max_basket_applications=1) self.applicator.apply_offers(self.basket, [offer]) line = self.basket.all_lines()[0] self.assertTrue(line.quantity_with_offer_discount(offer) == 5) applications = self.basket.offer_applications.applications self.assertTrue(applications[1]['freq'] == 1)
def test_grouped_voucher_discounts(self): voucher = VoucherFactory() offer1 = ConditionalOfferFactory(name='offer1') offer1.set_voucher(voucher) result1 = models.BasketDiscount(D('2.00')) offer2 = ConditionalOfferFactory(name='offer2') offer2.set_voucher(voucher) result2 = models.BasketDiscount(D('1.00')) self.applications.add(offer1, result1) self.applications.add(offer2, result2) assert len(self.applications) == 2 discounts = self.applications.grouped_voucher_discounts discounts = [x for x in discounts] assert len(discounts) == 1 assert discounts[0]['voucher'] == voucher assert discounts[0]['discount'] == D('3.00')
def vouchers(obj, create, extracted, **kwargs): if not create: return offer = ConditionalOfferFactory(offer_type=ConditionalOffer.VOUCHER) for i in range(0, obj.count): voucher = Voucher.objects.create(name="%s - %d" % (obj.name, i + 1), code=get_unused_code(length=obj.code_length), voucher_set=obj, usage=Voucher.MULTI_USE, start_datetime=obj.start_datetime, end_datetime=obj.end_datetime) voucher.offers.add(offer)
def test_changing_offer_type_for_voucher_offer_with_vouchers(self): offer = ConditionalOfferFactory(offer_type=ConditionalOffer.VOUCHER) VoucherFactory().offers.add(offer) data = { 'name': offer.name, 'description': offer.description, 'offer_type': ConditionalOffer.SITE, } form = forms.MetaDataForm(data, instance=offer) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['offer_type'][0], "This can only be changed if it has no vouchers attached to it")
def prepare_voucher(self, range_=None, start_datetime=None, benefit_value=100, benefit_type='Percentage'): """ Create a voucher and add an offer to it that contains a created product. """ if range_ is None: product = ProductFactory(title='Test product') range_ = RangeFactory(products=[product, ]) else: product = range_.all_products()[0] if start_datetime is None: start_datetime = now() - datetime.timedelta(days=1) voucher = VoucherFactory(code='COUPONTEST', start_datetime=start_datetime, usage=Voucher.SINGLE_USE) benefit = BenefitFactory(type=benefit_type, range=range_, value=benefit_value) offer = ConditionalOfferFactory(benefit=benefit) voucher.offers.add(offer) return voucher, product
def test_generator_queryset_and_annotation(self): offer = ConditionalOfferFactory(pk=2) OrderDiscountFactory(offer_id=offer.pk, offer_name=offer.name, amount=2, order=create_order()) OrderDiscountFactory(offer_id=offer.pk, offer_name=offer.name, amount=3, order=create_order()) # Discount on a deleted offer OrderDiscountFactory(offer_id=1, offer_name="Deleted offer", amount=4, order=create_order()) queryset = OfferReportGenerator().generate() self.assertEqual(queryset.count(), 2) self.assertEqual(queryset[0]["offer_id"], 2) self.assertEqual(queryset[0]["display_offer_name"], offer.name) self.assertEqual(queryset[0]["total_discount"], 5) self.assertEqual(queryset[0]["offer"], offer.pk) self.assertEqual(queryset[1]["offer_id"], 1) self.assertEqual(queryset[1]["display_offer_name"], "Deleted offer") self.assertEqual(queryset[1]["total_discount"], 4) self.assertEqual(queryset[1]["offer"], None)
def test_available_with_offer(self): basket = BasketFactory() product1 = ProductFactory() product2 = ProductFactory() basket.add_product(product1, quantity=1) basket.add_product(product2, quantity=10) benefit = models.Benefit( type=models.Benefit.PERCENTAGE, value=10, max_affected_items=5, ) benefit.save() offer1 = ConditionalOfferFactory(name='offer1', benefit=benefit) lines = basket.all_lines() assert lines[0].consumer.available(offer1) == 1 assert lines[1].consumer.available(offer1) == 5
def test_apply_offer_with_multibuy_benefit_and_count_condition(self): rng = RangeFactory(includes_all_products=True) condition = ConditionFactory(range=rng, type=ConditionFactory._meta.model.COUNT, value=1) benefit = BenefitFactory(range=rng, type=BenefitFactory._meta.model.MULTIBUY, value=1) offer = ConditionalOfferFactory(condition=condition, benefit=benefit) add_product(self.basket, D('100'), 5) applicator = Applicator() applicator.apply_offers(self.basket, [offer]) line = self.basket.all_lines()[0] assert line.quantity_with_offer_discount(offer) == 1 self.basket.refresh_from_db() assert self.basket.total_discount == D('100')
def setUp(self): """ Create test data. """ super(UpdateEffectiveContractDiscountTests, self).setUp() # Set up orders with a enterprise_customer self.enterprise_customer_uuid = '123e4567-e89b-12d3-a456-426655440000' self.unit_price = 100 self.condition = ManualEnrollmentOrderDiscountConditionFactory( enterprise_customer_uuid=self.enterprise_customer_uuid ) self.offer = ConditionalOfferFactory(condition=self.condition, id=9999) self.order = OrderFactory() self.order_discount = OrderDiscountFactory(offer_id=self.offer.id, order=self.order) self.line = OrderLineFactory(order=self.order, unit_price_excl_tax=self.unit_price) self.line.save() self.order_discount = OrderDiscountFactory(offer_id=self.offer.id, order=self.order) self.order.save() self.offer.save() self.condition.save()
def setUp(self): """ Create test data. """ super(MigrateEnterpriseConditionalOffersTests, self).setUp() # Set up vouchers that relate to a range with a enterprise_customer uuid = '123e4567-e89b-12d3-a456-426655440000' range_with_ent_customer = RangeFactory(enterprise_customer=uuid) condition = ConditionFactory(range=range_with_ent_customer) benefit_percent = BenefitFactory( range=range_with_ent_customer, type='Percentage', value=10.00, ) benefit_absolute = BenefitFactory( range=range_with_ent_customer, type='Absolute', value=47, ) for i in range(2): code = '{}EntUserPercentBenefit'.format(i) voucher = VoucherFactory(code=code) offer_name = "Coupon [{}]-{}-{}".format(voucher.pk, benefit_percent.type, benefit_percent.value) conditional_offer = ConditionalOfferFactory( condition=condition, benefit=benefit_percent, name=offer_name, ) voucher.offers.add(conditional_offer) for i in range(2): code = '{}EntUserAbsoluteBenefit'.format(i) voucher = VoucherFactory(code=code) offer_name = "Coupon [{}]-{}-{}".format(voucher.pk, benefit_absolute.type, benefit_absolute.value) conditional_offer = ConditionalOfferFactory( condition=condition, benefit=benefit_absolute, name=offer_name, ) voucher.offers.add(conditional_offer) # Set up vouchers that do not relate to a range with an enterprise_customer range_no_ent_customer = RangeFactory() condition = ConditionFactory(range=range_no_ent_customer) benefit = BenefitFactory( range=range_no_ent_customer, type='Percentage', value=10.00, ) for i in range(3): code = '{}NoEntUserPercentBenefit'.format(i) voucher = VoucherFactory(code=code) offer_name = "Coupon [{}]-{}-{}".format(voucher.pk, benefit.type, benefit.value) conditional_offer = ConditionalOfferFactory( condition=condition, benefit=benefit, name=offer_name, ) voucher.offers.add(conditional_offer) assert Voucher.objects.filter( offers__condition__range__enterprise_customer__isnull=False).count( ) == 4 assert Voucher.objects.filter( offers__condition__range__enterprise_customer__isnull=True).count( ) == 3 self.command = Command()
def setUp(self): ConditionalOffer = get_model('offer', 'ConditionalOffer') self.offer = ConditionalOfferFactory(offer_type=ConditionalOffer.SITE)
def setUp(self): super(OfferDecoratorTests, self).setUp() self.condition = ConditionFactory() self.offer = ConditionalOfferFactory(condition=self.condition, partner=self.partner) self.user = UserFactory()