mirror of
https://github.com/pretix/pretix.git
synced 2026-09-12 16:04:42 +00:00
handle payment provider (de-)selection and partial payments
This commit is contained in:
@@ -1605,6 +1605,7 @@ def add_payment_to_cart_session(cart_session, provider, min_value: Decimal=None,
|
||||
'max_value': str(max_value) if max_value is not None else None,
|
||||
'info_data': info_data or {},
|
||||
})
|
||||
cart_session['payments_postpone'] = False
|
||||
|
||||
|
||||
def add_payment_to_cart(request, provider, min_value: Decimal=None, max_value: Decimal=None, info_data: dict=None):
|
||||
|
||||
@@ -1440,10 +1440,12 @@ class PaymentStep(CartMixin, TemplateFlowStep):
|
||||
ctx['providers'] = self.provider_forms
|
||||
ctx['show_fees'] = any(p['fee'] for p in self.provider_forms)
|
||||
|
||||
if len(self.provider_forms) == 1:
|
||||
ctx['selected'] = self.provider_forms[0]['provider'].identifier
|
||||
elif 'payment' in self.request.POST:
|
||||
if 'payment' in self.request.POST:
|
||||
ctx['selected'] = self.request.POST['payment']
|
||||
elif self.cart_session.get('payments_postpone') and self._allow_postpone:
|
||||
ctx['selected'] = ''
|
||||
elif len(self.provider_forms) == 1:
|
||||
ctx['selected'] = self.provider_forms[0]['provider'].identifier
|
||||
elif self.single_use_payment:
|
||||
ctx['selected'] = self.single_use_payment['provider']
|
||||
else:
|
||||
|
||||
@@ -135,7 +135,9 @@
|
||||
{% trans "Not sure yet? You can complete your order first and then select a payment method later." %}
|
||||
<br>
|
||||
<span class="text-muted">
|
||||
{% if payment_deadline_minutes %}
|
||||
{% if current_payments %}
|
||||
{% trans "To do so, please first remove the payment methods you already selected above." %}
|
||||
{% elif payment_deadline_minutes %}
|
||||
{% blocktrans trimmed with minutes=payment_deadline_minutes %}
|
||||
Your payment needs to be completed within {{ minutes }} minutes.
|
||||
{% endblocktrans %}
|
||||
@@ -147,7 +149,8 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-12 text-right flip">
|
||||
<button name="postpone" value="on" class="btn btn-primary">
|
||||
<button name="postpone" value="on" class="btn btn-primary"
|
||||
{% if current_payments %}disabled{% endif %}>
|
||||
{% trans "Proceed without selection" %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2405,6 +2405,64 @@ class CheckoutTestCase(BaseCheckoutTestCase, TimemachineTestMixin, TestCase):
|
||||
o = Order.objects.last()
|
||||
assert not o.payments.exists()
|
||||
|
||||
def test_payment_postpone_cleared_on_selection(self):
|
||||
self.event.settings.set('payment_banktransfer__enabled', True)
|
||||
self.event.settings.payment_choice_postpone_allowed_channels = ['web']
|
||||
with scopes_disabled():
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug), {
|
||||
'postpone': 'on',
|
||||
}, follow=False)
|
||||
self.assertRedirects(response, '/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
assert self.client.session['carts'][self.session_key].get('payments_postpone')
|
||||
|
||||
# The only available provider must not be preselected while the choice is postponed
|
||||
response = self.client.get('/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
self.assertEqual(len(doc.select('input[name="payment"]')), 1)
|
||||
self.assertEqual(len(doc.select('input[name="payment"][checked]')), 0)
|
||||
|
||||
# Selecting a payment method takes the order out of the postponed state again
|
||||
response = self.client.post('/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug), {
|
||||
'payment': 'banktransfer',
|
||||
}, follow=False)
|
||||
self.assertRedirects(response, '/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
assert not self.client.session['carts'][self.session_key].get('payments_postpone')
|
||||
|
||||
def test_payment_postpone_disabled_with_partial_payment(self):
|
||||
self.event.settings.set('payment_banktransfer__enabled', True)
|
||||
self.event.settings.payment_choice_postpone_allowed_channels = ['web']
|
||||
gc = self.orga.issued_gift_cards.create(currency="EUR")
|
||||
gc.transactions.create(value=20, acceptor=self.orga)
|
||||
with scopes_disabled():
|
||||
CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
response = self.client.get('/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
self.assertEqual(len(doc.select('button[name="postpone"]')), 1)
|
||||
self.assertEqual(len(doc.select('button[name="postpone"][disabled]')), 0)
|
||||
|
||||
# Apply a gift card that only covers part of the total
|
||||
response = self.client.post('/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug), {
|
||||
'payment': 'giftcard',
|
||||
'payment_giftcard-code': gc.secret,
|
||||
}, follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/checkout/payment/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
|
||||
# Postponing would silently drop the gift card, so it is no longer offered
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
self.assertEqual(len(doc.select('button[name="postpone"][disabled]')), 1)
|
||||
|
||||
def test_premature_confirm(self):
|
||||
response = self.client.get('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/?require_cookie=true' % (self.orga.slug, self.event.slug),
|
||||
|
||||
Reference in New Issue
Block a user