diff --git a/doc/api/resources/orders.rst b/doc/api/resources/orders.rst index 107e8811b9..4aaf3e18b5 100644 --- a/doc/api/resources/orders.rst +++ b/doc/api/resources/orders.rst @@ -769,6 +769,8 @@ Creating orders * does not support file upload questions + * does not support redeeming gift cards + You can supply the following fields of the resource: * ``code`` (optional) diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 6f17b19faa..6895195187 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -1044,7 +1044,9 @@ class GiftCardPayment(BasePaymentProvider): messages.error(request, _("This gift card can not be redeemed since its code is not unique. Please contact the organizer of this event.")) def execute_payment(self, request: HttpRequest, payment: OrderPayment) -> str: - for p in payment.order.positions.all(): + # This method will only be called when retrying payments, e.g. after a payment_prepare call. It is not called + # during the order creation phase because this payment provider is a special case. + for p in payment.order.positions.all(): # noqa - just a safeguard if p.item.issue_giftcard: raise PaymentException(_("You cannot pay with gift cards when buying a gift card.")) @@ -1053,13 +1055,11 @@ class GiftCardPayment(BasePaymentProvider): raise PaymentException("Invalid state, should never occur.") with transaction.atomic(): gc = GiftCard.objects.select_for_update().get(pk=gcpk) - if gc.currency != self.event.currency: + if gc.currency != self.event.currency: # noqa - just a safeguard raise PaymentException(_("This gift card does not support this currency.")) - if not gc.accepted_by(self.event.organizer): + if not gc.accepted_by(self.event.organizer): # noqa - just a safeguard raise PaymentException(_("This gift card is not accepted by this event organizer.")) - if gc.testmode != payment.order.testmode: - raise PaymentException(_("Only the gift card or only the order are created in test mode.")) - if payment.amount > gc.value: + if payment.amount > gc.value: # noqa - just a safeguard raise PaymentException(_("This gift card was used in the meantime. Please try again")) trans = gc.transactions.create( value=-1 * payment.amount, diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 49169b0124..76471e1464 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -569,14 +569,12 @@ def _get_fees(positions: List[CartPosition], payment_provider: BasePaymentProvid fees += resp total += sum(f.value for f in fees) - summed = 0 gift_card_values = {} for gc in gift_cards: fval = Decimal(gc.value) # TODO: don't require an extra query - fval = min(fval, total - summed) + fval = min(fval, total) if fval > 0: total -= fval - summed += fval gift_card_values[gc] = fval if payment_provider: @@ -967,6 +965,7 @@ class OrderChangeManager: 'seat_subevent_mismatch': _('You selected seat "{seat}" for a date that does not match the selected ticket date. Please choose a seat again.'), 'seat_required': _('The selected product requires you to select a seat.'), 'seat_forbidden': _('The selected product does not allow to select a seat.'), + 'gift_card_change': _('You cannot change the price of a position that has been used to issue a gift card.'), } ItemOperation = namedtuple('ItemOperation', ('position', 'item', 'variation')) SubeventOperation = namedtuple('SubeventOperation', ('position', 'subevent')) @@ -1034,6 +1033,9 @@ class OrderChangeManager: def change_price(self, position: OrderPosition, price: Decimal): price = position.item.tax(price, base_price_is='gross') + if position.issued_gift_cards.exists(): + raise OrderError(self.error_messages['gift_card_change']) + self._totaldiff += price.gross - position.price if self.order.event.settings.invoice_include_free or price.gross != Decimal('0.00') or position.price != Decimal('0.00'): @@ -1710,13 +1712,14 @@ def signal_listener_issue_giftcards(sender: Event, order: Order, **kwargs): issued = Decimal('0.00') for gc in p.issued_gift_cards.all(): issued += gc.transactions.first().value - gc = sender.organizer.issued_gift_cards.create( - currency=sender.currency, issued_in=p, testmode=order.testmode - ) - gc.transactions.create(value=p.price - issued, order=order) - any_giftcards = True - p.secret = gc.secret - p.save(update_fields=['secret']) + if p.price - issued > 0: + gc = sender.organizer.issued_gift_cards.create( + currency=sender.currency, issued_in=p, testmode=order.testmode + ) + gc.transactions.create(value=p.price - issued, order=order) + any_giftcards = True + p.secret = gc.secret + p.save(update_fields=['secret']) if any_giftcards: tickets.invalidate_cache.apply_async(kwargs={'event': sender.pk, 'order': order.pk}) diff --git a/src/pretix/control/templates/pretixcontrol/organizers/giftcards.html b/src/pretix/control/templates/pretixcontrol/organizers/giftcards.html index 3789ed9516..7445310505 100644 --- a/src/pretix/control/templates/pretixcontrol/organizers/giftcards.html +++ b/src/pretix/control/templates/pretixcontrol/organizers/giftcards.html @@ -52,8 +52,7 @@ - {{ g.secret }} - + {{ g.secret }} {% if g.testmode %} {% trans "TEST MODE" %} {% endif %} diff --git a/src/pretix/presale/templates/pretixpresale/event/checkout_payment.html b/src/pretix/presale/templates/pretixpresale/event/checkout_payment.html index 21d10ee536..43b26a5940 100644 --- a/src/pretix/presale/templates/pretixpresale/event/checkout_payment.html +++ b/src/pretix/presale/templates/pretixpresale/event/checkout_payment.html @@ -11,7 +11,6 @@
{% csrf_token %}
- {# TODO: make this proper #} {% for p in providers %}