diff --git a/src/pretix/control/forms/orders.py b/src/pretix/control/forms/orders.py index 2aeea894d8..fbaac26c43 100644 --- a/src/pretix/control/forms/orders.py +++ b/src/pretix/control/forms/orders.py @@ -151,10 +151,6 @@ class ForceQuotaConfirmationForm(forms.Form): del self.fields['force'] -class ConfirmPaymentForm(ForceQuotaConfirmationForm): - pass - - class ReactivateOrderForm(ForceQuotaConfirmationForm): pass @@ -220,10 +216,11 @@ class DenyForm(forms.Form): ) -class MarkPaidForm(ConfirmPaymentForm): +class MarkPaidForm(ForceQuotaConfirmationForm): send_email = forms.BooleanField( required=False, label=_('Notify customer by email'), + help_text=_('A mail will only be sent if the order is fully paid after this.'), initial=True ) amount = forms.DecimalField( @@ -240,9 +237,10 @@ class MarkPaidForm(ConfirmPaymentForm): ) def __init__(self, *args, **kwargs): + payment = kwargs.pop('payment', None) super().__init__(*args, **kwargs) change_decimal_field(self.fields['amount'], self.instance.event.currency) - self.fields['amount'].initial = max(Decimal('0.00'), self.instance.pending_sum) + self.fields['amount'].initial = max(Decimal('0.00'), payment.amount if payment else self.instance.pending_sum) class ExporterForm(forms.Form): diff --git a/src/pretix/control/templates/pretixcontrol/order/pay_complete.html b/src/pretix/control/templates/pretixcontrol/order/pay_complete.html index 591621ed9f..21d132d3f8 100644 --- a/src/pretix/control/templates/pretixcontrol/order/pay_complete.html +++ b/src/pretix/control/templates/pretixcontrol/order/pay_complete.html @@ -21,7 +21,13 @@ Do you really want to mark this payment as complete? {% endblocktrans %}

- {% bootstrap_form form layout='horizontal' horizontal_label_class='sr-only' horizontal_field_class='col-md-12' %} + {% bootstrap_form_errors form %} + {% bootstrap_field form.amount layout='horizontal' %} + {% bootstrap_field form.payment_date layout='horizontal' %} + {% bootstrap_field form.send_email layout='horizontal' %} + {% if form.force %} + {% bootstrap_field form.force layout='horizontal' horizontal_label_class='sr-only' horizontal_field_class='col-md-12' %} + {% endif %}
diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index ef1e6fad94..ef495bfee6 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -119,9 +119,9 @@ from pretix.control.forms.filter import ( RefundFilterForm, ) from pretix.control.forms.orders import ( - CancelForm, CommentForm, ConfirmPaymentForm, DenyForm, EventCancelForm, - ExporterForm, ExtendForm, MarkPaidForm, OrderContactForm, - OrderFeeChangeForm, OrderLocaleForm, OrderMailForm, OrderPositionAddForm, + CancelForm, CommentForm, DenyForm, EventCancelForm, ExporterForm, + ExtendForm, MarkPaidForm, OrderContactForm, OrderFeeChangeForm, + OrderLocaleForm, OrderMailForm, OrderPositionAddForm, OrderPositionAddFormset, OrderPositionChangeForm, OrderPositionMailForm, OrderRefundForm, OtherOperationsForm, ReactivateOrderForm, ) @@ -1014,9 +1014,10 @@ class OrderPaymentConfirm(OrderView): @cached_property def mark_paid_form(self): - return ConfirmPaymentForm( + return MarkPaidForm( instance=self.order, data=self.request.POST if self.request.method == "POST" else None, + payment=self.payment, ) def post(self, *args, **kwargs): @@ -1027,8 +1028,19 @@ class OrderPaymentConfirm(OrderView): 'order': self.order, }) try: + payment_date = None + if self.mark_paid_form.cleaned_data['payment_date'] != now().date(): + payment_date = make_aware(datetime.combine( + self.mark_paid_form.cleaned_data['payment_date'], + time(hour=0, minute=0, second=0) + ), self.order.event.timezone) + + self.payment.amount = self.mark_paid_form.cleaned_data['amount'] + self.payment.save(update_fields=['amount']) self.payment.confirm(user=self.request.user, + send_mail=self.mark_paid_form.cleaned_data['send_email'], count_waitinglist=False, + payment_date=payment_date, force=self.mark_paid_form.cleaned_data.get('force', False)) except Quota.QuotaExceededException as e: messages.error(self.request, str(e)) diff --git a/src/tests/control/test_orders.py b/src/tests/control/test_orders.py index 1bae296511..d427b22e72 100644 --- a/src/tests/control/test_orders.py +++ b/src/tests/control/test_orders.py @@ -1823,7 +1823,10 @@ def test_confirm_payment(client, env): with scopes_disabled(): p = env[2].payments.last() client.login(email='dummy@dummy.dummy', password='dummy') - response = client.post('/control/event/dummy/dummy/orders/FOO/payments/{}/confirm'.format(p.pk), {}, follow=True) + response = client.post('/control/event/dummy/dummy/orders/FOO/payments/{}/confirm'.format(p.pk), { + 'amount': str(p.amount), + 'payment_date': str(now().date().isoformat()), + }, follow=True) assert 'alert-success' in response.content.decode() p.refresh_from_db() assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED @@ -1838,7 +1841,10 @@ def test_confirm_payment_invalid_state(client, env): p.state = OrderPayment.PAYMENT_STATE_FAILED p.save() client.login(email='dummy@dummy.dummy', password='dummy') - response = client.post('/control/event/dummy/dummy/orders/FOO/payments/{}/confirm'.format(p.pk), {}, follow=True) + response = client.post('/control/event/dummy/dummy/orders/FOO/payments/{}/confirm'.format(p.pk), { + 'amount': str(p.amount), + 'payment_date': str(now().date().isoformat()), + }, follow=True) assert 'alert-danger' in response.content.decode() p.refresh_from_db() assert p.state == OrderPayment.PAYMENT_STATE_FAILED @@ -1853,7 +1859,10 @@ def test_confirm_payment_partal_amount(client, env): p.amount -= Decimal(5.00) p.save() client.login(email='dummy@dummy.dummy', password='dummy') - response = client.post('/control/event/dummy/dummy/orders/FOO/payments/{}/confirm'.format(p.pk), {}, follow=True) + response = client.post('/control/event/dummy/dummy/orders/FOO/payments/{}/confirm'.format(p.pk), { + 'amount': str(p.amount), + 'payment_date': str(now().date().isoformat()), + }, follow=True) assert 'alert-success' in response.content.decode() p.refresh_from_db() assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED