Fix #571 -- Partial payments and refunds

This commit is contained in:
Raphael Michel
2018-06-26 12:09:36 +02:00
parent 8e7af49206
commit 18a378976b
115 changed files with 6026 additions and 1598 deletions

View File

@@ -89,6 +89,12 @@
{% trans "Overview" %}
</a>
</li>
<li>
<a href="{% url 'control:event.orders.refunds' organizer=request.event.organizer.slug event=request.event.slug %}"
{% if url_name == "event.orders.refunds" %}class="active"{% endif %}>
{% trans "Refunds" %}
</a>
</li>
<li>
<a href="{% url 'control:event.orders.export' organizer=request.event.organizer.slug event=request.event.slug %}"
{% if url_name == "event.orders.export" %}class="active"{% endif %}>

View File

@@ -15,6 +15,25 @@
{% endif %}
</small>
</h1>
{% if has_overpaid_orders %}
<div class="alert alert-warning">
{% blocktrans trimmed %}
This event contains <strong>overpaid orders</strong>, for example due to duplicate payment attempts.
You should review the cases and consider refunding the overpaid amount to the user.
{% endblocktrans %}
<a href="{% url "control:event.orders" event=request.event.slug organizer=request.event.organizer.slug %}?status=overpaid"
class="btn btn-primary">{% trans "Show overpaid orders" %}</a>
</div>
{% endif %}
{% if has_pending_refunds %}
<div class="alert alert-warning">
{% blocktrans trimmed %}
This event contains <strong>pending refunds</strong> that you should take care of.
{% endblocktrans %}
<a href="{% url "control:event.orders.refunds" event=request.event.slug organizer=request.event.organizer.slug %}"
class="btn btn-primary">{% trans "Show pending refunds" %}</a>
</div>
{% endif %}
{% if actions|length > 0 %}
<div class="panel panel-danger">
<div class="panel-heading">

View File

@@ -25,7 +25,8 @@
<div class="btn-toolbar" role="toolbar">
<div class="btn-group" role="group">
{% if order.status == 'n' or order.status == 'e' %}
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=p" class="btn btn-default">
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=p"
class="btn {% if overpaid >= 0 %}btn-primary{% else %}btn-default{% endif %}">
{% trans "Mark as paid" %}
</a>
<a href="{% url "control:event.order.extend" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default">
@@ -36,10 +37,13 @@
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=c" class="btn btn-default">
{% trans "Cancel order" %}
</a>
{% elif order.status == 'p' %}
{% endif %}
{% if order.status == 'p' %}
<button name="status" value="n" class="btn btn-default">{% trans "Mark as not paid" %}</button>
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=r" class="btn btn-default">
{% trans "Refund order" %}
{% endif %}
{% if overpaid|add:order.total != 0 %}
<a href="{% url "control:event.order.refunds.start" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default">
{% trans "Create a refund" %}
</a>
{% endif %}
@@ -66,6 +70,26 @@
</form>
{% endif %}
{% if overpaid > 0 %}
<form action="{% url "control:event.order.refunds.start" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}"
method="post">
{% csrf_token %}
<input type="hidden" name="start-action" value="do_nothing">
<input type="hidden" name="start-mode" value="partial">
<input type="hidden" name="start-partial_amount" value="{{ overpaid }}">
<div class="alert alert-warning">
{% blocktrans trimmed with amount=overpaid|money:request.event.currency %}
This order is currently overpaid by {{ amount }}.
{% endblocktrans %}
<button class="btn btn-primary" type="submit">
{% blocktrans trimmed with amount=overpaid|money:request.event.currency %}
Initiate a refund of {{ amount }}
{% endblocktrans %}
</button>
</div>
</form>
{% endif %}
<div class="row">
<div class="col-xs-12 col-lg-10">
<div class="panel panel-primary items">
@@ -87,10 +111,7 @@
<span class="fa fa-edit"></span>
</a>
</dd>
{% if order.status == "p" %}
<dt>{% trans "Payment date" %}</dt>
<dd>{{ order.payment_date }}</dd>
{% elif order.status == "n" %}
{% if order.status == "n" %}
<dt>{% trans "Expiry date" %}</dt>
<dd>{{ order.expires }}</dd>
{% endif %}
@@ -207,7 +228,8 @@
</a>
{% endif %}
{% if line.subevent %}
<br /><span class="fa fa-calendar"></span> {{ line.subevent.name }} &middot; {{ line.subevent.get_date_range_display }}
<br/>
<span class="fa fa-calendar"></span> {{ line.subevent.name }} &middot; {{ line.subevent.get_date_range_display }}
{% endif %}
{% if line.has_questions %}
<dl>
@@ -239,7 +261,7 @@
{{ q.answer.file_name }}
</a>
<span class="label label-danger" data-toggle="tooltip"
title="{% trans "This file has been uploaded by a user and could contain viruses or other malicious content." %}">
title="{% trans "This file has been uploaded by a user and could contain viruses or other malicious content." %}">
{% trans "UNSAFE" %}
</span>
{% else %}
@@ -262,7 +284,7 @@
{% if event.settings.display_net_prices %}
<strong>{{ line.net_price|money:event.currency }}</strong>
{% if line.tax_rate %}
<br />
<br/>
<small>
{% blocktrans trimmed with rate=line.tax_rate taxname=line.tax_rule.name|default:s_taxes %}
<strong>plus</strong> {{ rate }}% {{ taxname }}
@@ -272,7 +294,7 @@
{% else %}
<strong>{{ line.price|money:event.currency }}</strong>
{% if line.tax_rate and line.price %}
<br />
<br/>
<small>
{% blocktrans trimmed with rate=line.tax_rate taxname=line.tax_rule.name|default:s_taxes %}
incl. {{ rate }}% {{ taxname }}
@@ -350,28 +372,154 @@
</div>
</div>
{% eventsignal event "pretix.control.signals.order_info" order=order request=request %}
<div class="row">
<div class="row payments">
<div class="{% if request.event.settings.invoice_address_asked or order.invoice_address %}col-md-6{% else %}col-md-12{% endif %}">
<div class="panel panel-default items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Payment information" %}
{% trans "Payments" %}
</h3>
</div>
<div class="panel-body">
{% if order.payment_manual %}
<div class="alert alert-info">
{% trans "The payment state of this order was manually modified." %}
</div>
{% endif %}
{{ payment }}
{% if order.status == 'n' %}
<p>{% blocktrans trimmed with date=order.expires %}
The payment has to be completed before {{ date }}.
{% endblocktrans %}</p>
{% endif %}
<div class="table-responsive">
<table class="table table-condensed">
<thead>
<tr>
<th>#</th>
<th>{% trans "Start date" %}</th>
<th>{% trans "Confirmation date" %}</th>
<th>{% trans "Payment method" %}</th>
<th>{% trans "Status" %}</th>
<th class="text-right">{% trans "Amount" %}</th>
</tr>
</thead>
<tbody>
{% for p in payments %}
<tr>
<td>{{ p.full_id }}</td>
<td>
{% if p.migrated %}
<span class="label label-default" data-toggle="tooltip"
title="{% trans "This payment was created with an older version of pretix, therefore accurate data might not be available." %}">
{% trans "MIGRATED" %}
</span>
{% else %}
{{ p.created|date:"SHORT_DATETIME_FORMAT" }}
{% endif %}
</td>
<td>{{ p.payment_date|date:"SHORT_DATETIME_FORMAT" }}</td>
<td>
{{ p.payment_provider.verbose_name }}
{% if p.state == "pending" or p.state == "created" %}
<a href="{% url "control:event.order.payments.cancel" event=request.event.slug organizer=request.event.organizer.slug code=order.code payment=p.pk %}"
class="btn btn-danger btn-xs" data-toggle="tooltip"
title="{% trans "Cancel payment" %}">
<span class="fa fa-times"></span>
</a>
<a href="{% url "control:event.order.payments.confirm" event=request.event.slug organizer=request.event.organizer.slug code=order.code payment=p.pk %}"
class="btn btn-primary btn-xs" data-toggle="tooltip"
title="{% trans "Confirm as paid" %}">
<span class="fa fa-check"></span>
</a>
{% endif %}
</td>
<td>
<span class="label label-{% if p.state == "created" or p.state == "pending" %}warning{% elif p.state == "confirmed" %}success{% else %}danger{% endif %}">
{{ p.get_state_display }}
</span>
</td>
<td class="text-right">{{ p.amount|money:request.event.currency }}</td>
</tr>
{% if p.html_info %}
<tr>
<td colspan="1"></td>
<td colspan="5">{{ p.html_info|safe }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% if refunds %}
<div class="panel panel-default items">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Refunds" %}
</h3>
</div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-condensed">
<thead>
<tr>
<th>#</th>
<th>{% trans "Start date" %}</th>
<th>{% trans "Completion date" %}</th>
<th>{% trans "Source" %}</th>
<th>{% trans "Payment method" %}</th>
<th>{% trans "Payment" %}</th>
<th>{% trans "Status" %}</th>
<th class="text-right">{% trans "Amount" %}</th>
<th class="text-right"></th>
</tr>
</thead>
<tbody>
{% for r in refunds %}
<tr>
<td>{{ r.full_id }}</td>
<td>{{ r.created|date:"SHORT_DATETIME_FORMAT" }}</td>
<td>{{ r.execution_date|date:"SHORT_DATETIME_FORMAT" }}</td>
<td>{{ r.get_source_display }}</td>
<td>
{{ r.payment_provider.verbose_name }}
</td>
<td>
{% if r.payment %}
{{ r.payment.full_id }}
{% endif %}
</td>
<td>
<span class="label label-{% if r.state == "external" or r.state == "transit" or r.state == "created" %}warning{% elif r.state == "done" %}success{% else %}danger{% endif %}">
{{ r.get_state_display }}
</span>
</td>
<td class="text-right">{{ r.amount|money:request.event.currency }}</td>
<td class="text-right">
{% if r.state == "transit" or r.state == "created" %}
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=order.code refund=r.pk %}"
class="btn btn-danger btn-xs" data-toggle="tooltip"
title="{% trans "Cancel transfer" %}">
<span class="fa fa-times"></span>
</a>
<a href="{% url "control:event.order.refunds.done" event=request.event.slug organizer=request.event.organizer.slug code=order.code refund=r.pk %}"
class="btn btn-primary btn-xs" data-toggle="tooltip"
title="{% trans "Confirm as done" %}">
<span class="fa fa-check"></span>
</a>
{% elif r.state == "external" %}
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
class="btn btn-default btn-xs" data-toggle="tooltip">
<span class="fa fa-times"></span>
{% trans "Ignore" %}
</a>
<a href="{% url "control:event.order.refunds.process" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
class="btn btn-primary btn-xs"
data-toggle="tooltip">
<span class="fa fa-check"></span>
{% trans "Process refund" %}
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
</div>
{% if request.event.settings.invoice_address_asked or order.invoice_address %}
<div class="col-md-6">

View File

@@ -1,27 +1,18 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% block title %}
{% trans "Refund order" %}
{% trans "Cancel payment" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Refund order" %}
<a class="btn btn-link btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans trimmed with order=order.code %}
Back to order {{ order }}
{% endblocktrans %}
</a>
{% trans "Cancel payment" %}
</h1>
<p>{% blocktrans trimmed %}
Do you really want to cancel this payment? You cannot revert this action.
{% endblocktrans %}</p>
<form method="post" href="">
<p>{% blocktrans trimmed %}
Do you really want to refund this order? You cannot revert this action.
{% endblocktrans %}</p>
{{ payment|safe }}
{% csrf_token %}
<input type="hidden" name="status" value="r" />
<div class="row checkout-button-row">
<div class="col-md-4">
<a class="btn btn-block btn-default btn-lg"
@@ -31,7 +22,7 @@
</div>
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-block btn-danger btn-lg" type="submit">
{% trans "Yes, refund order" %}
{% trans "Yes, cancel payment" %}
</button>
</div>
<div class="clearfix"></div>

View File

@@ -0,0 +1,36 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}
{% trans "Mark payment as complete" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Mark payment as complete" %}
<a class="btn btn-link btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans trimmed with order=order.code %}
Back to order {{ order }}
{% endblocktrans %}
</a>
</h1>
<form method="post" class="form-horizontal" href="">
{% csrf_token %}
<p>{% blocktrans trimmed %}
Do you really want to mark this payment as complete?
{% endblocktrans %}</p>
<input type="hidden" name="status" value="p" />
{% bootstrap_form form layout='horizontal' horizontal_label_class='sr-only' horizontal_field_class='col-md-12' %}
<div class="form-group submit-group">
<a class="btn btn-default btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% trans "Cancel" %}
</a>
<button class="btn btn-primary btn-save btn-lg" type="submit">
{% trans "Mark as paid" %}
</button>
<div class="clearfix"></div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,38 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% block title %}
{% trans "Cancel refund" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Cancel refund" %}
</h1>
<p>{% blocktrans trimmed %}
Do you really want to cancel this refund? You cannot revert this action.
{% endblocktrans %}</p>
<div class="alert alert-info">
{% blocktrans trimmed %}
If the money is already on the way back, this will not stop the money, it will just mark this transfer as
aborted in pretix. This will also not reactivate the order, it will just allow you to choose a new refund
method.
{% endblocktrans %}
</div>
<form method="post" href="">
{% csrf_token %}
<div class="row checkout-button-row">
<div class="col-md-4">
<a class="btn btn-block btn-default btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% trans "No, take me back" %}
</a>
</div>
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-block btn-danger btn-lg" type="submit">
{% trans "Yes, cancel refund" %}
</button>
</div>
<div class="clearfix"></div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,145 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load money %}
{% block title %}
{% trans "Refund order" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Refund order" %}
<a class="btn btn-link btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans trimmed with order=order.code %}
Back to order {{ order }}
{% endblocktrans %}
</a>
</h1>
<form method="post" href="">
{% csrf_token %}
<fieldset class="form-inline form-order-change">
<legend>{% trans "How should the refund be sent?" %}</legend>
<div class="table-responsive">
<table class="table table-condensed">
<thead>
<tr>
<th>#</th>
<th>{% trans "Payment confirmation date" %}</th>
<th>{% trans "Payment method" %}</th>
<th>{% trans "Amount not refunded" %}</th>
<th>{% trans "Refund" %}</th>
</tr>
</thead>
<tbody>
{% for p in payments %}
<tr>
<td>{{ p.full_id }}</td>
<td>{{ p.payment_date|date:"SHORT_DATETIME_FORMAT" }}</td>
<td>
{{ p.payment_provider.verbose_name }}
</td>
<td>{{ p.available_amount|money:request.event.currency }}</td>
<td>
{% if p.partial_refund_possible %}
{% trans "Automatically refund" context "amount_label" %}
<div class="input-group">
<input type="text" name="refund-{{ p.pk }}"
value="{{ p.propose_refund|floatformat:2 }}"
title="" class="form-control">
<span class="input-group-addon">
{{ request.event.currency }}
</span>
</div>
{% elif p.full_refund_possible %}
<label class="checkbox">
<input type="checkbox" name="refund-{{ p.pk }}"
value="{{ p.amount|floatformat:2 }}"
{% if p.propose_refund == p.amount %}checked{% endif %}>
{% trans "Automatically refund full amount" %}
</label>
{% else %}
<em>{% trans "This payment method does not support automatic refunds." %}</em>
{% endif %}
</td>
</tr>
{% endfor %}
<tr>
<td></td>
<td></td>
<td><strong>{% trans "Transfer to other order" %}</strong></td>
<td></td>
<td>
{% trans "Transfer" context "amount_label" %}
<div class="input-group">
<input type="text" name="refund-offsetting"
title="" class="form-control" value="{{ 0|floatformat:2 }}">
<span class="input-group-addon">
{{ request.event.currency }}
</span>
</div>
{% trans "to" context "order_label" %}
<input type="text" name="order-offsetting"
value="" title="" class="form-control">
</td>
</tr>
<tr>
<td></td>
<td></td>
<td><strong>{% trans "Manual refund" %}</strong></td>
<td></td>
<td>
{% trans "Manually refund" context "amount_label" %}
<div class="input-group">
<input type="text" name="refund-manual"
value="{{ remainder|floatformat:2 }}"
title="" class="form-control">
<span class="input-group-addon">
{{ request.event.currency }}
</span>
</div>
<label class="radio">
<input type="radio" name="manual_state" value="created" checked>
{% trans "Keep transfer as to do" %}
</label>
<label class="radio">
<input type="radio" name="manual_state" value="done">
{% trans "Mark refund as done" %}
</label>
</td>
</tr>
</tbody>
</table>
</div>
</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>
<input type="hidden" name="start-action" value="{{ start_form.cleaned_data.action }}">
<input type="hidden" name="start-mode" value="{{ start_form.cleaned_data.mode }}">
<input type="hidden" name="start-partial_amount" value="{{ partial_amount }}">
<div class="row checkout-button-row">
<div class="col-md-4">
<a class="btn btn-block btn-default btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% trans "Cancel" %}
</a>
</div>
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-block btn-danger btn-lg" type="submit" name="perform" value="true">
{% trans "Perform refund" %}
</button>
</div>
<div class="clearfix"></div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,34 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}
{% trans "Mark refund as done" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Mark refund as done" %}
<a class="btn btn-link btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans trimmed with order=order.code %}
Back to order {{ order }}
{% endblocktrans %}
</a>
</h1>
<form method="post" class="form-horizontal" href="">
{% csrf_token %}
<p>{% blocktrans trimmed %}
Do you really want to mark this refund as complete?
{% endblocktrans %}</p>
<div class="form-group submit-group">
<a class="btn btn-default btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% trans "Cancel" %}
</a>
<button class="btn btn-primary btn-save btn-lg" type="submit">
{% trans "Mark as done" %}
</button>
<div class="clearfix"></div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,55 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load money %}
{% block title %}
{% trans "Mark refund as done" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Mark refund as done" %}
<a class="btn btn-link btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans trimmed with order=order.code %}
Back to order {{ order }}
{% endblocktrans %}
</a>
</h1>
<form method="post" class="" action="">
{% csrf_token %}
<p>
{% blocktrans trimmed with amount=refund.amount|money:request.event.currency method=refund.payment_provider.verbose_name pending=pending_sum|money:request.event.currency total=order.total|money:request.event.currency %}
We recevied notice that <strong>{{ amount }}</strong> have been refunded via
<strong>{{ method }}</strong>. If this refund is processed, the order will be underpaid by
<strong>{{ pending }}</strong>. The order total is <strong>{{ total }}</strong>.
{% endblocktrans %}
</p>
<p>
{% blocktrans trimmed with amount=refund.amount|money:request.event.currency method=refund.payment_provider.verbose_name %}
What should happen to the ticket order?
{% endblocktrans %}
</p>
<div class="form-inline">
<label class="radio">
<input type="radio" name="action" value="n" {% if not propose_cancel %}checked{% endif %}>
{% trans "Mark the order as unpaid and allow the customer to pay again with another payment method." %}
</label>
<br>
<label class="radio">
<input type="radio" name="action" value="r" {% if propose_cancel %}checked{% endif %}>
{% trans "Cancel the order irrevocably." %}
</label>
</div>
<div class="form-group submit-group">
<a class="btn btn-default btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% trans "Cancel" %}
</a>
<button class="btn btn-primary btn-save btn-lg" type="submit">
{% trans "Process refund" %}
</button>
<div class="clearfix"></div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,60 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}
{% trans "Refund order" %}
{% endblock %}
{% block content %}
<h1>
{% trans "Refund order" %}
<a class="btn btn-link btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans trimmed with order=order.code %}
Back to order {{ order }}
{% endblocktrans %}
</a>
</h1>
<form method="post" href="">
{% bootstrap_form_errors form %}
<fieldset class="form-inline form-order-change">
<legend>{% trans "How much do you want to refund?" %}</legend>
<div class="radio">
<label>
<input name="{{ form.prefix }}-mode" type="radio" value="full"
{% if not form.mode.value or form.mode.value == "full" %}checked="checked"{% endif %}>
{% trans "Refund full paid amount" %}
</label>
</div>
<div class="radio">
<label>
<input name="{{ form.prefix }}-mode" type="radio" value="partial"
{% if form.mode.value == "partial" %}checked="checked"{% endif %}>
{% trans "Refund only" %}
{% bootstrap_field form.partial_amount addon_after=request.event.currency layout='inline' %}
</label>
</div>
</fieldset>
<p>&nbsp;</p>
<fieldset class="form-inline form-order-change">
<legend>{% trans "What should happen to the order?" %}</legend>
{% bootstrap_field form.action layout='horizontal' horizontal_label_class='sr-only' horizontal_field_class='' %}
</fieldset>
<p>&nbsp;</p>
{% csrf_token %}
<div class="row checkout-button-row">
<div class="col-md-4">
<a class="btn btn-block btn-default btn-lg"
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% trans "Cancel" %}
</a>
</div>
<div class="col-md-4 col-md-offset-4">
<button class="btn btn-block btn-primary btn-lg" type="submit">
{% trans "Continue" %}
</button>
</div>
<div class="clearfix"></div>
</div>
</form>
{% endblock %}

View File

@@ -127,7 +127,19 @@
{% endif %}
</td>
<td>{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
<td class="text-right">{{ o.total|money:request.event.currency }}</td>
<td class="text-right">
{% if o.has_external_refund or o.has_pending_refund %}
<span class="label label-danger">{% trans "REFUND PENDING" %}</span>
{% elif o.has_pending_refund %}
<span class="label label-warning">{% trans "REFUND PENDING" %}</span>
{% endif %}
{% if o.is_overpaid %}
<span class="label label-warning">{% trans "OVERPAID" %}</span>
{% elif o.is_underpaid %}
<span class="label label-danger">{% trans "UNDERPAID" %}</span>
{% endif %}
{{ o.total|money:request.event.currency }}
</td>
<td class="text-right">{{ o.pcnt }}</td>
<td class="text-right">{% include "pretixcontrol/orders/fragment_order_status.html" with order=o %}</td>
</tr>

View File

@@ -0,0 +1,104 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load eventurl %}
{% load urlreplace %}
{% load money %}
{% load bootstrap3 %}
{% block title %}{% trans "Refunds" %}{% endblock %}
{% block content %}
<h1>{% trans "Refunds" %}</h1>
<div class="row filter-form">
<form class="" action="" method="get">
<div class="col-md-5 col-xs-6">
{% bootstrap_field filter_form.status layout='inline' %}
</div>
<div class="col-md-5 col-xs-6">
{% bootstrap_field filter_form.provider layout='inline' %}
</div>
<div class="col-md-2 col-xs-12">
<button class="btn btn-primary btn-block" type="submit">
<span class="fa fa-filter"></span>
<span class="hidden-md">
{% trans "Filter" %}
</span>
</button>
</div>
</form>
</div>
{% if not filter_form.filtered and refunds|length == 0 %}
<div class="empty-collection">
<p>
{% blocktrans trimmed %}
No refunds are currently open.
{% endblocktrans %}
</p>
</div>
{% else %}
<div class="table-responsive">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>#</th>
<th>{% trans "Payment provider" %}</th>
<th>{% trans "Start date" %}</th>
<th>{% trans "Source" %}</th>
<th>{% trans "Status" %}</th>
<th class="text-right">{% trans "Amount" %}</th>
<th class="text-right">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for r in refunds %}
<tr>
<td>
<strong>
<a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code %}">
{{ r.order.code }}</a>-R-{{ r.local_id }}
</strong>
</td>
<td>
{{ r.payment_provider.verbose_name }}
</td>
<td>{{ o.created|date:"SHORT_DATETIME_FORMAT" }}</td>
<td>{{ r.get_source_display }}</td>
<td>
<span class="label label-{% if r.state == "external" or r.state == "transit" or r.state == "created" %}warning{% elif r.state == "done" %}success{% else %}danger{% endif %}">
{{ r.get_state_display }}
</span>
</td>
<td class="text-right">
{{ r.amount|money:request.event.currency }}
</td>
<td class="text-right">
{% if r.state == "transit" or r.state == "created" %}
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
class="btn btn-danger btn-xs" data-toggle="tooltip">
<span class="fa fa-times"></span>
{% trans "Cancel" %}
</a>
<a href="{% url "control:event.order.refunds.done" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
class="btn btn-primary btn-xs" data-toggle="tooltip">
<span class="fa fa-check"></span>
{% trans "Confirm as done" %}
</a>
{% elif r.state == "external" %}
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
class="btn btn-default btn-xs" data-toggle="tooltip">
<span class="fa fa-times"></span>
{% trans "Ignore" %}
</a>
<a href="{% url "control:event.order.refunds.process" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
class="btn btn-primary btn-xs" data-toggle="tooltip">
<span class="fa fa-check"></span>
{% trans "Process refund" %}
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include "pretixcontrol/pagination.html" %}
{% endif %}
{% endblock %}