diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 7e9c9611c..81fa9b9e7 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -1419,50 +1419,51 @@ class GiftCardPayment(BasePaymentProvider): def payment_refund_supported(self, payment: OrderPayment) -> bool: return True - def checkout_prepare(self, request: HttpRequest, cart: Dict[str, Any]) -> Union[bool, str, None]: - from pretix.base.services.cart import add_payment_to_cart + def _add_giftcard_to_cart(self, cs, gc): + from pretix.base.services.cart import add_payment_to_cart_session + if gc.currency != self.event.currency: + raise ValidationError(_("This gift card does not support this currency.")) + if gc.testmode and not self.event.testmode: + raise ValidationError(_("This gift card can only be used in test mode.")) + if not gc.testmode and self.event.testmode: + raise ValidationError(_("Only test gift cards can be used in test mode.")) + if gc.expires and gc.expires < time_machine_now(): + raise ValidationError(_("This gift card is no longer valid.")) + if gc.value <= Decimal("0.00"): + raise ValidationError(_("All credit on this gift card has been used.")) + + for p in cs.get('payments', []): + if p['provider'] == self.identifier and p['info_data']['gift_card'] == gc.pk: + raise ValidationError(_("This gift card is already used for your payment.")) + + add_payment_to_cart_session( + cs, + self, + max_value=gc.value, + info_data={ + 'gift_card': gc.pk, + 'gift_card_secret': gc.secret, + } + ) + + def checkout_prepare(self, request: HttpRequest, cart: Dict[str, Any]) -> Union[bool, str, None]: for p in get_cart(request): if p.item.issue_giftcard: messages.error(request, _("You cannot pay with gift cards when buying a gift card.")) return - cs = cart_session(request) try: gc = self.event.organizer.accepted_gift_cards.get( secret=request.POST.get("giftcard").strip() ) - if gc.currency != self.event.currency: - messages.error(request, _("This gift card does not support this currency.")) + cs = cart_session(request) + try: + self._add_giftcard_to_cart(cs, gc) + return True + except ValidationError as e: + messages.error(request, str(e.message)) return - if gc.testmode and not self.event.testmode: - messages.error(request, _("This gift card can only be used in test mode.")) - return - if not gc.testmode and self.event.testmode: - messages.error(request, _("Only test gift cards can be used in test mode.")) - return - if gc.expires and gc.expires < time_machine_now(): - messages.error(request, _("This gift card is no longer valid.")) - return - if gc.value <= Decimal("0.00"): - messages.error(request, _("All credit on this gift card has been used.")) - return - - for p in cs.get('payments', []): - if p['provider'] == self.identifier and p['info_data']['gift_card'] == gc.pk: - messages.error(request, _("This gift card is already used for your payment.")) - return - - add_payment_to_cart( - request, - self, - max_value=gc.value, - info_data={ - 'gift_card': gc.pk, - 'gift_card_secret': gc.secret, - } - ) - return True except GiftCard.DoesNotExist: if self.event.vouchers.filter(code__iexact=request.POST.get("giftcard")).exists(): messages.warning(request, _("You entered a voucher instead of a gift card. Vouchers can only be entered on the first page of the shop below " diff --git a/src/pretix/base/services/cart.py b/src/pretix/base/services/cart.py index 6382c88de..8fe0f142b 100644 --- a/src/pretix/base/services/cart.py +++ b/src/pretix/base/services/cart.py @@ -1426,6 +1426,28 @@ class CartManager: raise CartError(err) +def add_payment_to_cart_session(cart_session, provider, min_value: Decimal=None, max_value: Decimal=None, info_data: dict=None): + """ + :param cart_session: The current cart session. + :param provider: The instance of your payment provider. + :param min_value: The minimum value this payment instrument supports, or ``None`` for unlimited. + :param max_value: The maximum value this payment instrument supports, or ``None`` for unlimited. Highly discouraged + to use for payment providers which charge a payment fee, as this can be very user-unfriendly if + users need a second payment method just for the payment fee of the first method. + :param info_data: A dictionary of information that will be passed through to the ``OrderPayment.info_data`` attribute. + :return: + """ + cart_session.setdefault('payments', []) + cart_session['payments'].append({ + 'id': str(uuid.uuid4()), + 'provider': provider.identifier, + 'multi_use_supported': provider.multi_use_supported, + 'min_value': str(min_value) if min_value is not None else None, + 'max_value': str(max_value) if max_value is not None else None, + 'info_data': info_data or {}, + }) + + def add_payment_to_cart(request, provider, min_value: Decimal=None, max_value: Decimal=None, info_data: dict=None): """ :param request: The current HTTP request context. @@ -1440,16 +1462,7 @@ def add_payment_to_cart(request, provider, min_value: Decimal=None, max_value: D from pretix.presale.views.cart import cart_session cs = cart_session(request) - cs.setdefault('payments', []) - - cs['payments'].append({ - 'id': str(uuid.uuid4()), - 'provider': provider.identifier, - 'multi_use_supported': provider.multi_use_supported, - 'min_value': str(min_value) if min_value is not None else None, - 'max_value': str(max_value) if max_value is not None else None, - 'info_data': info_data or {}, - }) + add_payment_to_cart_session(cs, provider, min_value, max_value, info_data) def get_fees(event, request, total, invoice_address, payments, positions): diff --git a/src/pretix/presale/templates/pretixpresale/event/fragment_cart_box.html b/src/pretix/presale/templates/pretixpresale/event/fragment_cart_box.html index 183c23cb5..d1d94cdc1 100644 --- a/src/pretix/presale/templates/pretixpresale/event/fragment_cart_box.html +++ b/src/pretix/presale/templates/pretixpresale/event/fragment_cart_box.html @@ -10,18 +10,41 @@ {% trans "Your cart" %} - + {% if cart.positions %} + + {% endif %}
- {% include "pretixpresale/event/fragment_cart.html" with cart=cart event=request.event editable=True %} + {% if cart.positions %} + {% include "pretixpresale/event/fragment_cart.html" with cart=cart event=request.event editable=True %} + {% endif %} + {% if cart.current_selected_payments %} +

{% trans "You already selected the following payment methods:" %}

+
+ {% for p in cart.current_selected_payments %} +
+
+
+ {{ p.provider_name }} +
+
+ {% if p.payment_amount %} + {{ p.payment_amount|money:request.event.currency }} + {% endif %} +
+
+
+ {% endfor %} +
+ {% endif %}