Commit d1b61272 authored by Luko van der Maas's avatar Luko van der Maas

Merge branch 'add-thalia-pay-to-payment-model' into 'master'

Add Thalia Pay payment methods to admin and user frontend

Closes #934, #933, and #930

See merge request !1380
parents ea638677 67fda57a
This diff was suppressed by a .gitattributes entry.
......@@ -7,16 +7,16 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-08-14 08:06+0200\n"
"PO-Revision-Date: 2019-08-07 19:57+0200\n"
"Last-Translator: Thom Wiggers <thom@thomwiggers.nl>\n"
"POT-Creation-Date: 2019-10-30 20:58+0100\n"
"PO-Revision-Date: 2019-10-30 21:01+0100\n"
"Last-Translator: Job Doesburg <job.doesburg@gmail.com>\n"
"Language-Team: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2.3\n"
"X-Generator: Poedit 2.2.4\n"
#: admin.py
msgid "lecture year"
......@@ -249,6 +249,15 @@ msgstr ""
msgid "registration end"
msgstr "einde aanmelden"
#: models.py
msgid ""
"If you set a registration period registration will be required. If you don't "
"set one, registration won't be required."
msgstr ""
"Als je een aanmeldperiode instelt is aanmelden vereist, als je dat niet doet "
"is aanmelden niet vereist. Geef de voorkeur aan tijden waar mensen geen "
"college hebben, bijvoorbeeld 12:30 in plaats van 13:37."
#: models.py templates/events/admin/details.html
msgid "cancel deadline"
msgstr "afmelddeadline"
......@@ -437,6 +446,14 @@ msgstr "Je mag je niet aanmelden."
msgid "You are not registered for this event."
msgstr "Je bent niet aangemeld voor dit evenement."
#: services.py
msgid "You have already paid for this event."
msgstr "Je hebt al betaald voor dit evenement"
#: services.py
msgid "You do not have Thalia Pay enabled."
msgstr "Je maakt geen gebruik van Thalia Pay."
#: services.py
msgid "Unable to find the right registration."
msgstr "De juiste registratie is niet gevonden."
......@@ -445,6 +462,10 @@ msgstr "De juiste registratie is niet gevonden."
msgid "You are not allowed to update this registration."
msgstr "Je mag deze aanmelding niet bijwerken."
#: services.py
msgid "This user does not have Thalia Pay enabled"
msgstr "Deze persoon kan geen Thalia Pay gebruiken"
#: templates/events/admin/details.html templates/events/admin/email_export.html
msgid "Thalia site admin"
msgstr "Thalia site admin"
......@@ -563,16 +584,8 @@ msgid "Send message"
msgstr "Stuur pushnotificatie"
#: templates/events/admin/registrations_table.html
msgid "not paid"
msgstr "niet betaald"
#: templates/events/admin/registrations_table.html
msgid "paid cash"
msgstr "contant betaald"
#: templates/events/admin/registrations_table.html
msgid "paid card"
msgstr "pin betaald"
msgid "payment"
msgstr "betaling"
#: templates/events/admin/registrations_table.html
msgid "late"
......@@ -582,6 +595,26 @@ msgstr "te laat"
msgid "add"
msgstr "toevoegen"
#: templates/events/admin/registrations_table.html
msgid "None"
msgstr "Geen"
#: templates/events/admin/registrations_table.html
msgid "Card"
msgstr "Pin"
#: templates/events/admin/registrations_table.html
msgid "Cash"
msgstr "Contant"
#: templates/events/admin/registrations_table.html
msgid "Thalia Pay"
msgstr "Thalia Pay"
#: templates/events/admin/registrations_table.html
msgid "Wire"
msgstr "Overschrijving"
#: templates/events/admin/registrations_table.html
msgid "registered"
msgstr "aangemeld"
......@@ -682,6 +715,10 @@ msgstr "Je was niet aanwezig"
msgid "payment status"
msgstr "betalingsstatus"
#: templates/events/event.html
msgid "You pay with Thalia Pay"
msgstr "Je betaalt met Thalia Pay"
#: templates/events/event.html
msgid "You have paid"
msgstr "Je hebt betaald"
......@@ -690,6 +727,10 @@ msgstr "Je hebt betaald"
msgid "You have not paid yet"
msgstr "Je hebt nog niet betaald"
#: templates/events/event.html
msgid "Pay with Thalia Pay"
msgstr "Betaal met Thalia Pay"
#: templates/events/event.html
msgid "Update registration"
msgstr "Aanmelding bijwerken"
......@@ -862,6 +903,10 @@ msgstr "Opslaan"
msgid "Registration successful."
msgstr "Je aanmelding was succesvol."
#: views.py
msgid "You have paid with Thalia Pay."
msgstr "Je hebt betaald met Thalia Pay."
#: views.py
msgid "Registration successfully cancelled."
msgstr "Je afmelding was succesvol."
......@@ -138,6 +138,11 @@ def cancel_registration(member, event):
if (event_permissions(member, event)["cancel_registration"] and
registration):
if registration.payment is not None:
p = registration.payment
registration.payment = None
registration.save()
p.delete()
if registration.queue_position == 0:
emails.notify_first_waiting(event)
......@@ -155,6 +160,49 @@ def cancel_registration(member, event):
raise RegistrationError(_("You are not registered for this event."))
def pay_with_tpay(member, event):
"""
Add a Thalia Pay payment to an event registration
:param member: the user
:param event: the event
"""
registration = None
try:
registration = Registration.objects.get(
event=event,
member=member
)
except Registration.DoesNotExist:
raise RegistrationError(_("You are not registered for this event."))
if member.tpay_enabled:
if registration.payment is None:
note = f'Event registration {registration.event.title_en}. '
if registration.name:
note += f'Paid by {registration.name}. '
note += (f'{registration.event.start}. '
f'Registration date: {registration.date}.')
registration.payment = Payment.objects.create(
amount=registration.event.price,
paid_by=member,
notes=note,
processed_by=member,
type=Payment.TPAY
)
registration.save()
elif registration.payment.type == Payment.NONE:
registration.payment.type = Payment.TPAY
registration.save()
else:
raise RegistrationError(_("You have already paid for this "
"event."))
else:
raise RegistrationError(
_("You do not have Thalia Pay enabled."))
def update_registration(member=None, event=None,
registration=None, field_values=None):
"""
......@@ -265,24 +313,35 @@ def update_registration_by_organiser(registration, member, data):
p.delete()
elif (data['payment']['type'] != Payment.NONE
and registration.payment is not None):
registration.payment.type = data['payment']['type']
registration.payment.save()
if (data['payment']['type'] != Payment.TPAY or
(data['payment']['type'] == Payment.TPAY
and member.tpay_enabled)):
registration.payment.type = data['payment']['type']
registration.payment.save()
else:
raise RegistrationError(
_("This user does not have Thalia Pay enabled"))
elif (data['payment']['type'] != Payment.NONE
and registration.payment is None):
note = f'Event registration {registration.event.title_en}. '
if registration.name:
note += f'Paid by {registration.name}. '
note += (f'{registration.event.start}. '
f'Registration date: {registration.date}.')
registration.payment = Payment.objects.create(
amount=registration.event.price,
paid_by=registration.member,
notes=note,
processed_by=member,
type=data['payment']['type']
)
if (data['payment']['type'] != Payment.TPAY or
(data['payment']['type'] == Payment.TPAY
and member.tpay_enabled)):
note = f'Event registration {registration.event.title_en}. '
if registration.name:
note += f'Paid by {registration.name}. '
note += (f'{registration.event.start}. '
f'Registration date: {registration.date}.')
registration.payment = Payment.objects.create(
amount=registration.event.price,
paid_by=registration.member,
notes=note,
processed_by=member,
type=data['payment']['type']
)
else:
raise RegistrationError(
_("This user does not have Thalia Pay enabled"))
if 'present' in data:
registration.present = data['present']
......
......@@ -49,6 +49,9 @@
{% if registration.payment and registration.payment.type == payment.CARD %}selected{% endif %}>{% trans 'Card' %}</option>
<option value="{{ payment.CASH }}"
{% if registration.payment and registration.payment.type == payment.CASH %}selected{% endif %}>{% trans 'Cash' %}</option>
<option value="{{ payment.TPAY }}"
{% if not registration.member.tpay_enabled %} disabled {% endif %}
{% if registration.payment and registration.payment.type == payment.TPAY %}selected{% endif %}>{% trans 'Thalia Pay' %}</option>
<option value="{{ payment.WIRE }}"
{% if registration.payment and registration.payment.type == payment.WIRE %}selected{% endif %}>{% trans 'Wire' %}</option>
</select>
......
......@@ -112,9 +112,20 @@
<th>{% trans "payment status"|capfirst %}</th>
<td>
{% if registration.is_paid %}
{% trans "You have paid" %}
{% if registration.payment.type == payment_method_tpay %}
{% trans "You pay with Thalia Pay" %}
{% else %}
{% trans "You have paid" %}
{% endif %}
{% else %}
{% trans "You have not paid yet" %}
{% if registration.member.tpay_enabled %}
<form action="{% url 'events:pay' event.id %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-primary"
value="{% trans "Pay with Thalia Pay" %}"/>
</form>
{% endif %}
{% endif %}
</td>
</tr>
......
......@@ -3,7 +3,7 @@ from django.urls import path, include
from events.feeds import EventFeed
from events.views import EventIndex, EventDetail, EventRegisterView, \
RegistrationView, EventCancelView, AlumniEventsView
RegistrationView, EventCancelView, AlumniEventsView, EventPayView
app_name = "events"
......@@ -14,6 +14,8 @@ urlpatterns = [
name='register'),
path('<int:pk>/registration/cancel/', EventCancelView.as_view(),
name='cancel'),
path('<int:pk>/registration/pay/', EventPayView.as_view(),
name='pay'),
path('<int:pk>/registration/', RegistrationView.as_view(),
name='registration'),
path('', EventIndex.as_view(), name='index'),
......
......@@ -11,6 +11,7 @@ from django.views.generic import DetailView, TemplateView, FormView
from events import services
from events.exceptions import RegistrationError
from payments.models import Payment
from .forms import FieldsForm
from .models import Event, Registration
......@@ -45,6 +46,7 @@ class EventDetail(DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
context['payment_method_tpay'] = Payment.TPAY
event = context['event']
if event.max_participants:
......@@ -110,6 +112,29 @@ class EventRegisterView(View):
return redirect(event)
@method_decorator(login_required, name='dispatch')
class EventPayView(View):
"""
Defines a view that allows the user to add a Thalia Pay payment to
their event registration using a POST request. The user should be
authenticated.
"""
def get(self, request, *args, **kwargs):
return redirect('events:event', pk=kwargs['pk'])
def post(self, request, *args, **kwargs):
event = get_object_or_404(Event, pk=kwargs['pk'])
try:
services.pay_with_tpay(request.member, event)
messages.success(request,
_("You have paid with Thalia Pay."))
except RegistrationError as e:
messages.error(request, e)
return redirect(event)
@method_decorator(login_required, name='dispatch')
class EventCancelView(View):
"""
......
......@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-08 10:57+0200\n"
"POT-Creation-Date: 2019-10-30 21:03+0100\n"
"PO-Revision-Date: 2019-09-08 10:57+0200\n"
"Last-Translator: Thom Wiggers <thom@thomwiggers.nl>\n"
"Language-Team: \n"
......@@ -244,7 +244,8 @@ msgstr "Telefoonnummer noodcontact"
msgid "The phone number for the emergency contact"
msgstr "Het telefoonummer van de noodcontact"
#: models.py templates/members/user/profile.html
#: models.py templates/members/user/edit_profile.html
#: templates/members/user/profile.html
msgid "Birthday"
msgstr "Verjaardag"
......
......@@ -19,6 +19,8 @@ from django.utils import timezone
from django.utils.crypto import get_random_string
from django.utils.translation import pgettext_lazy, gettext_lazy as _
from payments.models import BankAccount
from thaliawebsite.settings import THALIA_PAY_ENABLED_PAYMENT_METHOD
from activemembers.models import MemberGroup, MemberGroupMembership
from utils import countries
......@@ -191,6 +193,16 @@ class Member(User):
def get_absolute_url(self):
return reverse('members:profile', args=[str(self.pk)])
@property
def tpay_enabled(self):
"""Does this user have a bank account with Direct Debit enabled"""
bank_accounts = BankAccount.objects.filter(owner=self)
if THALIA_PAY_ENABLED_PAYMENT_METHOD and bank_accounts.exists():
if bank_accounts.last().valid:
return True
else:
return False
def _profile_image_path(_instance, _filename):
"""
......
......@@ -52,7 +52,7 @@ class PaymentAdmin(admin.ModelAdmin):
ordering = ('-created_at', 'processing_date')
autocomplete_fields = ('paid_by', 'processed_by')
actions = ['process_cash_selected', 'process_card_selected',
'process_wire_selected', 'export_csv']
'process_tpay_selected', 'process_wire_selected', 'export_csv']
@staticmethod
def _member_link(member: Member) -> str:
......@@ -101,6 +101,7 @@ class PaymentAdmin(admin.ModelAdmin):
if not request.user.has_perm('payments.process_payments'):
del(actions['process_cash_selected'])
del(actions['process_card_selected'])
del(actions['process_tpay_selected'])
del(actions['process_wire_selected'])
return actions
......@@ -126,6 +127,17 @@ class PaymentAdmin(admin.ModelAdmin):
process_card_selected.short_description = _(
'Process selected payments (card)')
def process_tpay_selected(self, request: HttpRequest,
queryset: QuerySet) -> None:
"""Process the selected payment as Thalia Pay"""
if request.user.has_perm('payments.process_payments'):
updated_payments = services.process_payment(
queryset, request.member, Payment.TPAY
)
self._process_feedback(request, updated_payments)
process_tpay_selected.short_description = _(
'Process selected payments (Thalia Pay, only if enabled)')
def process_wire_selected(self, request: HttpRequest,
queryset: QuerySet) -> None:
"""Process the selected payment as wire"""
......
This diff was suppressed by a .gitattributes entry.
......@@ -7,16 +7,16 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-08 10:58+0200\n"
"PO-Revision-Date: 2019-09-08 10:58+0200\n"
"Last-Translator: Thom Wiggers <thom@thomwiggers.nl>\n"
"POT-Creation-Date: 2019-10-30 20:56+0100\n"
"PO-Revision-Date: 2019-10-30 20:58+0100\n"
"Last-Translator: Job Doesburg <job.doesburg@gmail.com>\n"
"Language-Team: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2.3\n"
"X-Generator: Poedit 2.2.4\n"
#: admin.py
msgid "paid by"
......@@ -34,6 +34,11 @@ msgstr "Verwerk geselecteerde betalingen (contant)"
msgid "Process selected payments (card)"
msgstr "Verwerk geselecteerde betalingen (pin)"
#: admin.py
msgid "Process selected payments (Thalia Pay, only if enabled)"
msgstr ""
"Verwerk geselecteerde betalingen (Thalia Pay, alleen indien beschikbaar)"
#: admin.py
msgid "Process selected payments (wire)"
msgstr "Verwerk geselecteerde betalingen (overboeking)"
......@@ -178,6 +183,10 @@ msgstr "Contante betaling"
msgid "Card payment"
msgstr "Pin betaling"
#: models.py
msgid "Thalia Pay payment"
msgstr "Thalia Pay betaling"
#: models.py
msgid "Wire payment"
msgstr "Overboeking"
......@@ -253,6 +262,11 @@ msgstr "Verwerk (contant)"
msgid "Process (card payment)"
msgstr "Verwerk (pin)"
#: templates/admin/payments/change_form.html
#: templates/payments/widgets/payment.html
msgid "Process (Thalia Pay payment)"
msgstr "Verwerk (Thalia Pay)"
#: templates/admin/payments/change_form.html
#: templates/payments/widgets/payment.html
msgid "Process (wire payment)"
......
# Generated by Django 2.2.1 on 2019-10-30 19:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('payments', '0004_bankaccount'),
]
operations = [
migrations.AlterField(
model_name='payment',
name='type',
field=models.CharField(choices=[('no_payment', 'No payment'), ('cash_payment', 'Cash payment'), ('card_payment', 'Card payment'), ('tpay_payment', 'Thalia Pay payment'), ('wire_payment', 'Wire payment')], default='no_payment', max_length=20, verbose_name='type'),
),
]
......@@ -23,12 +23,14 @@ class Payment(models.Model):
NONE = 'no_payment'
CASH = 'cash_payment'
CARD = 'card_payment'
TPAY = 'tpay_payment'
WIRE = 'wire_payment'
PAYMENT_TYPE = (
(NONE, _('No payment')),
(CASH, _('Cash payment')),
(CARD, _('Card payment')),
(TPAY, _('Thalia Pay payment')),
(WIRE, _('Wire payment')),
)
......
......@@ -28,11 +28,12 @@ def process_payment(queryset: QuerySet, processed_by: Member,
# is not appropriate, moreover save() automatically sets
# the processing date
for payment in queryset:
payment.type = pay_type
payment.processed_by = processed_by
payment.save()
data.append(payment)
if (pay_type != Payment.TPAY or
(pay_type == Payment.TPAY and payment.paid_by.tpay_enabled)):
payment.type = pay_type
payment.processed_by = processed_by
payment.save()
data.append(payment)
return data
......
......@@ -16,6 +16,11 @@
<div class="submit-row payments-row">
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}" data-type="cash_payment" class="button process">{% trans "Process (cash payment)" %}</a>
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}" data-type="card_payment" class="button process">{% trans "Process (card payment)" %}</a>
{% if payment.paid_by.tpay_enabled %}
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}" data-type="tpay_payment" class="button process">{% trans "Process (Thalia Pay payment)" %}</a>
{% else %}
<a class="button" disabled>{% trans "Process (Thalia Pay payment)" %}</a>
{% endif %}
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}" data-type="wire_payment" class="button process">{% trans "Process (wire payment)" %}</a>
</div>
{% endif %}
......
......@@ -14,6 +14,13 @@
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}"
data-next="true" data-type="card_payment"
class="button process">{% trans "Process (card payment)" %}</a>
{% if widget.value %}
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}"
data-next="true" data-type="tpay_payment"
class="button process">{% trans "Process (Thalia Pay payment)" %}</a>
{% else %}
<div class="button" disabled>{% trans "Process (Thalia Pay payment)" %}</div>
{% endif %}
<a data-href="{% url 'admin:payments_payment_process' pk=payment.pk %}"
data-next="true" data-type="wire_payment"
class="button process">{% trans "Process (wire payment)" %}</a>
......
......@@ -229,6 +229,49 @@ class PaymentAdminTest(TestCase):
}, messages.SUCCESS
)
@mock.patch('django.contrib.admin.ModelAdmin.message_user')
@mock.patch('payments.services.process_payment')
def test_process_tpay(self, process_payment, message_user) -> None:
"""
Tests that a Thalia Pay payment is processed correctly
"""
object_id = 'c85ea333-3508-46f1-8cbb-254f8c138020'
payment = Payment.objects.create(pk=object_id,
amount=7.5)
queryset = Payment.objects.filter(pk=object_id)
process_payment.return_value = [payment]
change_url = reverse('admin:payments_payment_changelist')
request_noperms = self.client.post(
change_url,
{'action': 'process_tpay_selected',
'index': 1,
'_selected_action': [object_id]}).wsgi_request
self._give_user_permissions()
request_hasperms = self.client.post(
change_url,
{'action': 'process_tpay_selected',
'index': 1,
'_selected_action': [object_id]}).wsgi_request
process_payment.reset_mock()
message_user.reset_mock()
self.admin.process_tpay_selected(request_noperms, queryset)
process_payment.assert_not_called()
self.admin.process_tpay_selected(request_hasperms, queryset)
process_payment.assert_called_once_with(queryset,
self.user, Payment.TPAY)
message_user.assert_called_once_with(
request_hasperms,
_('Successfully processed %(count)d %(items)s.')
% {
"count": 1,
"items": model_ngettext(Payment(), 1)
}, messages.SUCCESS
)
@mock.patch('django.contrib.admin.ModelAdmin.message_user')
@mock.patch('payments.services.process_payment')
def test_process_wire(self, process_payment, message_user) -> None:
......@@ -291,6 +334,7 @@ class PaymentAdminTest(TestCase):
'process_cash_selected',
'process_card_selected',
'process_wire_selected',
'process_tpay_selected',
'export_csv'])
def test_get_urls(self) -> None:
......
This diff was suppressed by a .gitattributes entry.
......@@ -7,16 +7,16 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-06-07 16:41+0200\n"
"PO-Revision-Date: 2019-06-07 16:41+0200\n"
"Last-Translator: Thom Wiggers <thom@thomwiggers.nl>\n"
"POT-Creation-Date: 2019-10-30 21:02+0100\n"
"PO-Revision-Date: 2019-10-30 21:03+0100\n"
"Last-Translator: Job Doesburg <job.doesburg@gmail.com>\n"
"Language-Team: \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2.3\n"
"X-Generator: Poedit 2.2.4\n"
#: admin.py
msgid "reminder"
......@@ -148,6 +148,10 @@ msgstr "Pin"
msgid "Cash"
msgstr "Contant"
#: templates/pizzas/admin/orders.html
msgid "Thalia Pay"
msgstr "Thalia Pay"
#: templates/pizzas/admin/orders.html templates/pizzas/admin/summary.html
msgid "Nobody ordered yet"
msgstr "Nog geen bestellingen"
......@@ -244,6 +248,10 @@ msgstr "Je kunt niet meer annuleren."
msgid "Are you sure you want to cancel your order?"
msgstr "Weet je zeker dat je de bestelling wilt annuleren?"
#: templates/pizzas/index.html
msgid "Pay with Thalia Pay"
msgstr "Betaal met Thalia Pay"
#: templates/pizzas/index.html
msgid "Changing your order"
msgstr "Bestelling bewerken"
......@@ -272,3 +280,7 @@ msgstr "Je bestelling is geannuleerd."
#: views.py
msgid "Your order could not be found."
msgstr "Je bestelling kont niet worden gevonden."
#: views.py
msgid "Your order has been paid with Thalia Pay."
msgstr "Je bestelling wordt betaald met Thalia Pay."
......@@ -253,8 +253,9 @@ class Order(models.Model):
@property
def can_be_changed(self):
try:
return (self.payment and not self.payment.processed
and not self.pizza_event.has_ended)
return (self.payment and not (self.payment.processed and not
self.payment.type == Payment.TPAY) and not
self.pizza_event.has_ended)
except ObjectDoesNotExist:
return False
......
......@@ -113,6 +113,9 @@
{% if order.payment.type == payment.CARD %}selected{% endif %}>{% trans 'Card' %}</option>
<option value="{{ payment.CASH }}"
{% if order.payment.type == payment.CASH %}selected{% endif %}>{% trans 'Cash' %}</option>
<option value="{{ payment.TPAY }}"
{% if order.payment.type == payment.TPAY %}selected{% endif %}
{% if not order.payment.paid_by.tpay_enabled %} disabled {% endif %}>{% trans 'Thalia Pay' %}</option>
</select>
</td>
<td>
......
......@@ -133,6 +133,20 @@
onclick="return confirm('{% trans "Are you sure you want to cancel your order?" %}')"/>
</form>
{% endif %}
{% if order.member.tpay_enabled and not order.payment.processed %}
<form
class="d-inline-block"
method="post"
action="{% url 'pizzas:pay-order' %}">
{% csrf_token %}
<input type="hidden"
name="order"
value="{{ order.pk }}"/>
<input type="submit"
value="{% trans "Pay with Thalia Pay" %}"
class="btn btn-primary"/>
</form>
{% endif %}
</td>
</tr>
</tbody>
......
......@@ -6,7 +6,8 @@ app_name = "pizzas"
urlpatterns = [
path('pizzas/', include([