Add BasePaymentProvider.payment_control_render_short and use it on refund page

This commit is contained in:
Raphael Michel
2021-01-27 10:34:59 +01:00
parent f93c780e6a
commit 33b34f31d1
7 changed files with 100 additions and 44 deletions

View File

@@ -106,6 +106,8 @@ The provider class
.. automethod:: payment_control_render .. automethod:: payment_control_render
.. automethod:: payment_control_render_short
.. automethod:: payment_refund_supported .. automethod:: payment_refund_supported
.. automethod:: payment_partial_refund_supported .. automethod:: payment_partial_refund_supported

View File

@@ -712,6 +712,18 @@ class BasePaymentProvider:
""" """
return '' return ''
def payment_control_render_short(self, payment: OrderPayment) -> str:
"""
Will be called if the *event administrator* performs an action on the payment. Should
return a very short version of the payment method. Usually, this should return e.g.
a transaction ID or account identifier, but no information on status, dates, etc.
The default implementation falls back to payment_presa_elrender.
:param order: The order object
"""
return self.payment_presale_render(payment)
def refund_control_render(self, request: HttpRequest, refund: OrderRefund) -> str: def refund_control_render(self, request: HttpRequest, refund: OrderRefund) -> str:
""" """
Will be called if the *event administrator* views the details of a refund. Will be called if the *event administrator* views the details of a refund.

View File

@@ -17,16 +17,23 @@
</h1> </h1>
<form method="post" href=""> <form method="post" href="">
{% csrf_token %} {% csrf_token %}
<fieldset class="form-inline form-order-change"> <fieldset class="form-inline form-refund-choose">
<legend>{% trans "How should the refund be sent?" %}</legend> <legend>{% trans "How should the refund be sent?" %}</legend>
<p>
{% blocktrans trimmed %}
Any payments that you selected for automatical refunds will be immediately communicate the refund
request to the respective payment provider. Manual refunds will be created as pending refunds, you
can then later mark them as done once you actually transferred the money back to the customer.
{% endblocktrans %}
</p>
<h4>{% trans "Refund to original payment method" %}</h4>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-condensed"> <table class="table table-condensed">
<thead> <thead>
<tr> <tr>
<th>#</th> <th>{% trans "Payment" %}</th>
<th>{% trans "Payment confirmation date" %}</th> <th>{% trans "Payment details" %}</th>
<th>{% trans "Payment method" %}</th>
<th>{% trans "Amount not refunded" %}</th> <th>{% trans "Amount not refunded" %}</th>
<th>{% trans "Refund" %}</th> <th>{% trans "Refund" %}</th>
</tr> </tr>
@@ -34,11 +41,8 @@
<tbody> <tbody>
{% for p in payments %} {% for p in payments %}
<tr> <tr>
<td>{{ p.full_id }}</td> <td>{{ p.full_id }}<br/>{{ p.payment_date|date:"SHORT_DATETIME_FORMAT" }}<br/>{{ p.payment_provider.verbose_name }}</td>
<td>{{ p.payment_date|date:"SHORT_DATETIME_FORMAT" }}</td> <td class="payment-details">{{ p.html_info|safe }}</td>
<td>
{{ p.payment_provider.verbose_name }}
</td>
<td>{{ p.available_amount|money:request.event.currency }}</td> <td>{{ p.available_amount|money:request.event.currency }}</td>
<td> <td>
{% if p.partial_refund_possible %} {% if p.partial_refund_possible %}
@@ -46,9 +50,9 @@
<div class="input-group"> <div class="input-group">
<input type="text" name="refund-{{ p.pk }}" <input type="text" name="refund-{{ p.pk }}"
{% if p.propose_refund %} {% if p.propose_refund %}
value="{{ p.propose_refund|floatformat:2 }}" value="{{ p.propose_refund|floatformat:2 }}"
{% else %} {% else %}
placeholder="{{ p.propose_refund|floatformat:2 }}" placeholder="{{ p.propose_refund|floatformat:2 }}"
{% endif %} {% endif %}
title="" class="form-control"> title="" class="form-control">
<span class="input-group-addon"> <span class="input-group-addon">
@@ -68,59 +72,67 @@
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody>
</table>
</div>
<h4>{% trans "Refund to a different payment method" %}</h4>
<div class="table-responsive">
<table class="table table-condensed">
<thead>
<tr>
<th>{% trans "Payment method" %}</th>
<th>{% trans "Refund" %}</th>
</tr>
</thead>
<tbody>
{% for prov, form in new_refunds %} {% for prov, form in new_refunds %}
<tr> <tr>
<td></td>
<td></td>
<td> <td>
{{ prov.verbose_name }} <strong>
{{ prov.verbose_name }}
</strong>
</td> </td>
<td></td>
<td> <td>
{% trans "Automatically refund" context "amount_label" %} {% trans "Automatically refund" context "amount_label" %}
<div class="input-group"> <div class="input-group">
<input type="text" name="newrefund-{{ prov }}" <input type="text" name="newrefund-{{ prov }}"
placeholder="{{ 0|floatformat:2 }}" placeholder="{{ 0|floatformat:2 }}"
title="" class="form-control"> title="" class="form-control">
<span class="input-group-addon"> <span class="input-group-addon">
{{ request.event.currency }} {{ request.event.currency }}
</span> </span>
</div><br> </div>
<br>
{{ form|safe }} {{ form|safe }}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
<tr> <tr>
<td></td>
<td></td>
<td><strong>{% trans "Transfer to other order" %}</strong></td> <td><strong>{% trans "Transfer to other order" %}</strong></td>
<td></td>
<td> <td>
{% trans "Transfer" context "amount_label" %} {% trans "Transfer" context "amount_label" %}
<div class="input-group"> <div class="input-group">
<input type="text" name="refund-offsetting" <input type="text" name="refund-offsetting"
title="" class="form-control" placeholder="{{ 0|floatformat:2 }}"> title="" class="form-control" placeholder="{{ 0|floatformat:2 }}">
<span class="input-group-addon"> <span class="input-group-addon">
{{ request.event.currency }} {{ request.event.currency }}
</span> </span>
</div> </div>
{% trans "to" context "order_label" %} {% trans "to" context "order_label" %}
<input type="text" name="order-offsetting" <input type="text" name="order-offsetting"
value="" title="" class="form-control"> value="" title="" class="form-control">
</td> </td>
</tr> </tr>
<tr> <tr>
<td></td>
<td></td>
<td> <td>
<strong>{% trans "Create a new gift card" %}</strong> <strong>{% trans "Create a new gift card" %}</strong>
</td> </td>
<td></td>
<td> <td>
<div class="input-group"> <div class="input-group">
<input type="text" name="refund-new-giftcard" <input type="text" name="refund-new-giftcard"
title="" class="form-control" title="" class="form-control"
{% if giftcard_proposal %} {% if giftcard_proposal %}
value="{{ giftcard_proposal|floatformat:2 }}" value="{{ giftcard_proposal|floatformat:2 }}"
{% else %} {% else %}
@@ -138,29 +150,26 @@
</tr> </tr>
<tr> <tr>
<td></td>
<td></td>
<td><strong>{% trans "Manual refund" %}</strong></td> <td><strong>{% trans "Manual refund" %}</strong></td>
<td></td>
<td> <td>
{% trans "Manually refund" context "amount_label" %} {% trans "Manually refund" context "amount_label" %}
<div class="input-group"> <div class="input-group">
<input type="text" name="refund-manual" <input type="text" name="refund-manual"
{% if remainder %} {% if remainder %}
value="{{ remainder|floatformat:2 }}" value="{{ remainder|floatformat:2 }}"
{% else %} {% else %}
placeholder="{{ remainder|floatformat:2 }}" placeholder="{{ remainder|floatformat:2 }}"
{% endif %} {% endif %}
title="" class="form-control"> title="" class="form-control">
<span class="input-group-addon"> <span class="input-group-addon">
{{ request.event.currency }} {{ request.event.currency }}
</span> </span>
</div> </div><br>
<label class="radio"> <label class="radio no-bold">
<input type="radio" name="manual_state" value="created" checked> <input type="radio" name="manual_state" value="created" checked>
{% trans "Keep transfer as to do" %} {% trans "Keep transfer as to do" %}
</label> </label>
<label class="radio"> <label class="radio no-bold">
<input type="radio" name="manual_state" value="done"> <input type="radio" name="manual_state" value="done">
{% trans "Mark refund as done" %} {% trans "Mark refund as done" %}
</label> </label>
@@ -171,13 +180,6 @@
</table> </table>
</div> </div>
</fieldset> </fieldset>
<p>
{% blocktrans trimmed %}
Any payments that you selected for automatical refunds will be immediately communicate the refund
request to the respective payment provider. Manual refunds will be created as pending refunds, you
can then later mark them as done once you actually transferred the money back to the customer.
{% endblocktrans %}
</p>
<p>&nbsp;</p> <p>&nbsp;</p>
<input type="hidden" name="start-action" value="{{ start_form.cleaned_data.action }}"> <input type="hidden" name="start-action" value="{{ start_form.cleaned_data.action }}">
@@ -187,7 +189,7 @@
<div class="form-group"> <div class="form-group">
<label class="control-label" for="id_comment">{% trans "Refund reason" %}</label> <label class="control-label" for="id_comment">{% trans "Refund reason" %}</label>
<input type="text" name="comment" class="form-control" title="{% trans "May be shown to the end user or used e.g. as part of a payment reference." %}" id="id_comment" <input type="text" name="comment" class="form-control" title="{% trans "May be shown to the end user or used e.g. as part of a payment reference." %}" id="id_comment"
value="{{ comment|default:"" }}"> value="{{ comment|default:"" }}">
<div class="help-block">{% trans "May be shown to the end user or used e.g. as part of a payment reference." %}</div> <div class="help-block">{% trans "May be shown to the end user or used e.g. as part of a payment reference." %}</div>
</div> </div>

View File

@@ -1001,6 +1001,10 @@ class OrderRefundView(OrderView):
(prov, form) (prov, form)
) )
for p in payments:
if p.payment_provider:
p.html_info = (p.payment_provider.payment_control_render_short(p) or "").strip()
return render(self.request, 'pretixcontrol/order/refund_choose.html', { return render(self.request, 'pretixcontrol/order/refund_choose.html', {
'payments': payments, 'payments': payments,
'new_refunds': new_refunds, 'new_refunds': new_refunds,

View File

@@ -282,6 +282,19 @@ class BankTransfer(BasePaymentProvider):
def payment_partial_refund_supported(self, payment: OrderPayment) -> bool: def payment_partial_refund_supported(self, payment: OrderPayment) -> bool:
return self.payment_refund_supported(payment) return self.payment_refund_supported(payment)
def payment_control_render_short(self, payment: OrderPayment) -> str:
pi = payment.info_data or {}
r = pi.get('payer', '')
if pi.get('iban'):
if r:
r += ' / '
r += pi.get('iban')
if pi.get('bic'):
if r:
r += ' / '
r += pi.get('bic')
return r
def payment_presale_render(self, payment: OrderPayment) -> str: def payment_presale_render(self, payment: OrderPayment) -> str:
pi = payment.info_data or {} pi = payment.info_data or {}
if self.payment_refund_supported(payment): if self.payment_refund_supported(payment):

View File

@@ -477,6 +477,9 @@ class Paypal(BasePaymentProvider):
'payment_info': payment.info_data, 'order': payment.order, 'sale_id': sale_id} 'payment_info': payment.info_data, 'order': payment.order, 'sale_id': sale_id}
return template.render(ctx) return template.render(ctx)
def payment_control_render_short(self, payment: OrderPayment) -> str:
return payment.info_data.get('payer', {}).get('payer_info', {}).get('email', '')
def payment_partial_refund_supported(self, payment: OrderPayment): def payment_partial_refund_supported(self, payment: OrderPayment):
# Paypal refunds are possible for 180 days after purchase: # Paypal refunds are possible for 180 days after purchase:
# https://www.paypal.com/lc/smarthelp/article/how-do-i-issue-a-refund-faq780#:~:text=Refund%20after%20180%20days%20of,PayPal%20balance%20of%20the%20recipient. # https://www.paypal.com/lc/smarthelp/article/how-do-i-issue-a-refund-faq780#:~:text=Refund%20after%20180%20days%20of,PayPal%20balance%20of%20the%20recipient.

View File

@@ -327,6 +327,9 @@ input[type=number].short {
label.label-empty { label.label-empty {
pointer-events: none; pointer-events: none;
} }
label.no-bold {
font-weight: normal;
}
label .optional { label .optional {
color: $text-muted; color: $text-muted;
font-weight: normal; font-weight: normal;
@@ -501,11 +504,28 @@ table td > .checkbox input[type="checkbox"] {
} }
} }
.form-order-change { .form-order-change, .form-refund-choose {
.row { .row {
padding: 5px 0; padding: 5px 0;
} }
} }
.form-refund-choose {
.payment-details {
max-width: 200px;
overflow: hidden;
dt {
float: none;
text-align: left;
font-weight: normal;
width: auto;
color: $text-muted;
}
dd {
margin-left: 0px;
word-break: break-word;
}
}
}
@media(max-width: $screen-xs-max) { @media(max-width: $screen-xs-max) {
.nameparts-form-group { .nameparts-form-group {