diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 2b32f794d8..3139ed4bd9 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -484,7 +484,7 @@ class BasePaymentProvider: """ return _('Payment provider: %s' % self.verbose_name) - def order_control_refund_render(self, order: Order) -> str: + def order_control_refund_render(self, order: Order, request: HttpRequest=None) -> str: """ Will be called if the event administrator clicks an order's 'refund' button. This can be used to display information *before* the order is being refunded. @@ -494,6 +494,11 @@ class BasePaymentProvider: automatically. :param order: The order object + :param request: The HTTP request + + .. versionchanged:: 1.6 + + The parameter ``request`` has been added. """ return '
%s
' % _('The money can not be automatically refunded, ' 'please transfer the money back manually.') diff --git a/src/pretix/control/templates/pretixcontrol/order/refund.html b/src/pretix/control/templates/pretixcontrol/order/refund.html index 66e4431cb2..0b1fc6302e 100644 --- a/src/pretix/control/templates/pretixcontrol/order/refund.html +++ b/src/pretix/control/templates/pretixcontrol/order/refund.html @@ -13,13 +13,13 @@ {% endblocktrans %} -

{% blocktrans trimmed %} - Do you really want to refund this order? You cannot revert this action. - {% endblocktrans %}

- - {{ payment|safe }} -
+

{% blocktrans trimmed %} + Do you really want to refund this order? You cannot revert this action. + {% endblocktrans %}

+ + {{ payment|safe }} + {% csrf_token %}
diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 9e29bd0bb6..78ea8f3d18 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -240,9 +240,14 @@ class OrderTransition(OrderView): 'order': self.order, }) elif self.order.status == Order.STATUS_PAID and to == 'r': + try: + cr = self.payment_provider.order_control_refund_render(self.order, self.request) + except TypeError: + cr = self.payment_provider.order_control_refund_render(self.order) + return render(self.request, 'pretixcontrol/order/refund.html', { 'order': self.order, - 'payment': self.payment_provider.order_control_refund_render(self.order), + 'payment': cr, }) else: return HttpResponseNotAllowed(['POST']) diff --git a/src/pretix/plugins/paypal/payment.py b/src/pretix/plugins/paypal/payment.py index 63637d401b..a969433c08 100644 --- a/src/pretix/plugins/paypal/payment.py +++ b/src/pretix/plugins/paypal/payment.py @@ -19,6 +19,18 @@ from pretix.plugins.paypal.models import ReferencedPayPalObject logger = logging.getLogger('pretix.plugins.paypal') +class RefundForm(forms.Form): + auto_refund = forms.ChoiceField( + initial='auto', + label=_('Refund automatically?'), + choices=( + ('auto', _('Automatically refund charge with PayPal')), + ('manual', _('Do not send refund instruction to PayPal, only mark as refunded in pretix')) + ), + widget=forms.RadioSelect, + ) + + class Paypal(BasePaymentProvider): identifier = 'paypal' verbose_name = _('PayPal') @@ -248,10 +260,28 @@ class Paypal(BasePaymentProvider): 'payment_info': payment_info, 'order': order} return template.render(ctx) - def order_control_refund_render(self, order) -> str: - return '
%s
' % _('The money will be automatically refunded.') + def _refund_form(self, request): + return RefundForm(data=request.POST if request.method == "POST" else None) + + def order_control_refund_render(self, order, request) -> str: + template = get_template('pretixplugins/paypal/control_refund.html') + ctx = { + 'request': request, + 'form': self._refund_form(request), + } + return template.render(ctx) def order_control_refund_perform(self, request, order) -> "bool|str": + f = self._refund_form(request) + if not f.is_valid(): + messages.error(request, _('Your input was invalid, please try again.')) + return + elif f.cleaned_data.get('auto_refund') == 'manual': + order = mark_order_refunded(order, user=request.user) + order.payment_manual = True + order.save() + return + self.init_api() if order.payment_info: diff --git a/src/pretix/plugins/paypal/templates/pretixplugins/paypal/control_refund.html b/src/pretix/plugins/paypal/templates/pretixplugins/paypal/control_refund.html new file mode 100644 index 0000000000..731ccae48e --- /dev/null +++ b/src/pretix/plugins/paypal/templates/pretixplugins/paypal/control_refund.html @@ -0,0 +1,2 @@ +{% load bootstrap3 %} +{% bootstrap_form form %} diff --git a/src/pretix/plugins/stripe/payment.py b/src/pretix/plugins/stripe/payment.py index 8918c75f2a..a05966964b 100644 --- a/src/pretix/plugins/stripe/payment.py +++ b/src/pretix/plugins/stripe/payment.py @@ -21,6 +21,18 @@ from pretix.plugins.stripe.models import ReferencedStripeObject logger = logging.getLogger('pretix.plugins.stripe') +class RefundForm(forms.Form): + auto_refund = forms.ChoiceField( + initial='auto', + label=_('Refund automatically?'), + choices=( + ('auto', _('Automatically refund charge with Stripe')), + ('manual', _('Do not send refund instruction to Stripe, only mark as refunded in pretix')) + ), + widget=forms.RadioSelect, + ) + + class StripeSettingsHolder(BasePaymentProvider): identifier = 'stripe_settings' verbose_name = _('Stripe') @@ -247,12 +259,30 @@ class StripeMethod(BasePaymentProvider): } return template.render(ctx) - def order_control_refund_render(self, order) -> str: - return '
%s
' % _('The money will be automatically refunded.') + def _refund_form(self, request): + return RefundForm(data=request.POST if request.method == "POST" else None) + + def order_control_refund_render(self, order, request) -> str: + template = get_template('pretixplugins/stripe/control_refund.html') + ctx = { + 'request': request, + 'form': self._refund_form(request), + } + return template.render(ctx) def order_control_refund_perform(self, request, order) -> "bool|str": self._init_api() + f = self._refund_form(request) + if not f.is_valid(): + messages.error(request, _('Your input was invalid, please try again.')) + return + elif f.cleaned_data.get('auto_refund') == 'manual': + order = mark_order_refunded(order, user=request.user) + order.payment_manual = True + order.save() + return + if order.payment_info: payment_info = json.loads(order.payment_info) else: diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control.html b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control.html index 16476585d8..00a4c9c6aa 100644 --- a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control.html +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control.html @@ -14,7 +14,7 @@ This order has been planned to be paid with {{ method }}, but the payment has not yet been completed. {% endblocktrans %}

{% endif %} - {% if order.status == "p" %} + {% if "source" in payment_info %}
{% trans "Charge ID" %}
{{ payment_info.id }}
diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control_refund.html b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control_refund.html new file mode 100644 index 0000000000..731ccae48e --- /dev/null +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/control_refund.html @@ -0,0 +1,2 @@ +{% load bootstrap3 %} +{% bootstrap_form form %}