From cf4b2544f28334c0740545051fbc9b7c748522b8 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Fri, 14 Dec 2018 10:42:08 +0100 Subject: [PATCH] Never create implicit payments for orders that require approval --- src/pretix/base/services/orders.py | 2 +- src/pretix/presale/checkoutflow.py | 5 +++++ src/tests/presale/test_checkout.py | 33 +++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index e30746f5d3..a3bbfb074b 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -532,7 +532,7 @@ def _create_order(event: Event, email: str, positions: List[CartPosition], now_d fee.tax_rule = None # TODO: deprecate fee.save() - if payment_provider: + if payment_provider and not order.require_approval: order.payments.create( state=OrderPayment.PAYMENT_STATE_CREATED, provider=payment_provider.identifier, diff --git a/src/pretix/presale/checkoutflow.py b/src/pretix/presale/checkoutflow.py index 77635d8651..fd835a0665 100644 --- a/src/pretix/presale/checkoutflow.py +++ b/src/pretix/presale/checkoutflow.py @@ -535,6 +535,8 @@ class PaymentStep(QuestionsViewMixin, CartMixin, TemplateFlowStep): for cartpos in get_cart(self.request): if cartpos.item.require_approval: + if 'payment' in self.cart_session: + del self.cart_session['payment'] return False for p in self.request.event.get_payment_providers().values(): @@ -542,6 +544,9 @@ class PaymentStep(QuestionsViewMixin, CartMixin, TemplateFlowStep): if self._is_allowed(p, request): self.cart_session['payment'] = p.identifier return False + elif self.cart_session.get('payment') == p.identifier: + # is_allowed might have changed, e.g. after add-on selection + del self.cart_session['payment'] return True diff --git a/src/tests/presale/test_checkout.py b/src/tests/presale/test_checkout.py index d7e646bca8..8e482bb849 100644 --- a/src/tests/presale/test_checkout.py +++ b/src/tests/presale/test_checkout.py @@ -15,7 +15,8 @@ from django_countries.fields import Country from pretix.base.decimal import round_decimal from pretix.base.models import ( CartPosition, Event, Invoice, InvoiceAddress, Item, ItemCategory, Order, - OrderPosition, Organizer, Question, QuestionAnswer, Quota, Voucher, + OrderPayment, OrderPosition, Organizer, Question, QuestionAnswer, Quota, + Voucher, ) from pretix.base.models.items import ItemAddOn, ItemVariation, SubEventItem from pretix.testutils.sessions import get_cart_session_key @@ -961,6 +962,36 @@ class CheckoutTestCase(TestCase): self.assertTrue(Order.objects.first().require_approval) self.assertEqual(OrderPosition.objects.count(), 1) + def test_require_approval_in_addon_to_free(self): + ItemAddOn.objects.create(base_item=self.ticket, addon_category=self.workshopcat, min_count=1, + price_included=True) + cp1 = CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.ticket, + price=0, expires=now() - timedelta(minutes=10) + ) + self.ticket.default_price = 0 + self.ticket.save() + self.client.get('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), follow=True) + + self.workshop1.require_approval = True + self.workshop1.save() + CartPosition.objects.create( + event=self.event, cart_id=self.session_key, item=self.workshop1, + price=0, expires=now() - timedelta(minutes=10), + addon_to=cp1 + ) + self.client.get('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), follow=True) + + response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True) + doc = BeautifulSoup(response.rendered_content, "lxml") + self.assertEqual(len(doc.select(".thank-you")), 1) + self.assertFalse(CartPosition.objects.filter(id=cp1.id).exists()) + self.assertEqual(Order.objects.count(), 1) + self.assertEqual(Order.objects.first().status, Order.STATUS_PENDING) + self.assertTrue(Order.objects.first().require_approval) + self.assertEqual(OrderPayment.objects.count(), 0) + self.assertEqual(OrderPosition.objects.count(), 2) + def test_free_price(self): self.ticket.free_price = True self.ticket.save()