diff --git a/doc/api/resources/orders.rst b/doc/api/resources/orders.rst index 9c3b5031d1..92b6623f1b 100644 --- a/doc/api/resources/orders.rst +++ b/doc/api/resources/orders.rst @@ -1030,6 +1030,10 @@ Creating orders Order state operations ---------------------- +.. versionchanged:: 3.12 + + The ``mark_paid`` operation now takes a ``send_email`` parameter. + .. http:post:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/mark_paid/ Marks a pending or expired order as successfully paid. @@ -1041,6 +1045,11 @@ Order state operations POST /api/v1/organizers/bigevents/events/sampleconf/orders/ABC12/mark_paid/ HTTP/1.1 Host: pretix.eu Accept: application/json, text/javascript + Content-Type: application/json + + { + "send_email": true + } **Example response**: @@ -1723,6 +1732,10 @@ Order payment endpoints Payments can now be created through the API. +.. versionchanged:: 3.12 + + The ``confirm`` operation now takes a ``send_email`` parameter. + .. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/payments/ Returns a list of all payments for an order. @@ -1823,7 +1836,10 @@ Order payment endpoints Accept: application/json, text/javascript Content-Type: application/json - {"force": false} + { + "send_email": true, + "force": false + } **Example response**: diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index 2ea788d177..f2b2f93ed6 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -228,6 +228,7 @@ class OrderViewSet(viewsets.ModelViewSet): @action(detail=True, methods=['POST']) def mark_paid(self, request, **kwargs): order = self.get_object() + send_mail = request.data.get('send_email', True) if order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED): @@ -269,6 +270,7 @@ class OrderViewSet(viewsets.ModelViewSet): try: p.confirm(auth=self.request.auth, user=self.request.user if request.user.is_authenticated else None, + send_mail=send_mail, count_waitinglist=False) except Quota.QuotaExceededException as e: return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST) @@ -976,6 +978,7 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): def confirm(self, request, **kwargs): payment = self.get_object() force = request.data.get('force', False) + send_mail = request.data.get('send_email', True) if payment.state not in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED): return Response({'detail': 'Invalid state of payment'}, status=status.HTTP_400_BAD_REQUEST) @@ -984,6 +987,7 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): payment.confirm(user=self.request.user if self.request.user.is_authenticated else None, auth=self.request.auth, count_waitinglist=False, + send_mail=send_mail, force=force) except Quota.QuotaExceededException as e: return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST) diff --git a/src/tests/api/test_orders.py b/src/tests/api/test_orders.py index 8cdf3ebdea..32e8f00276 100644 --- a/src/tests/api/test_orders.py +++ b/src/tests/api/test_orders.py @@ -469,6 +469,7 @@ def test_payment_confirm(token_client, organizer, event, order): p = order.payments.get(local_id=2) assert resp.status_code == 200 assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED + assert len(djmail.outbox) == 1 resp = token_client.post('/api/v1/organizers/{}/events/{}/orders/{}/payments/2/confirm/'.format( organizer.slug, event.slug, order.code @@ -476,6 +477,18 @@ def test_payment_confirm(token_client, organizer, event, order): assert resp.status_code == 400 +@pytest.mark.django_db +def test_payment_confirm_no_email(token_client, organizer, event, order): + resp = token_client.post('/api/v1/organizers/{}/events/{}/orders/{}/payments/2/confirm/'.format( + organizer.slug, event.slug, order.code + ), format='json', data={'force': True, 'send_email': False}) + with scopes_disabled(): + p = order.payments.get(local_id=2) + assert resp.status_code == 200 + assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED + assert len(djmail.outbox) == 0 + + @pytest.mark.django_db def test_payment_cancel(token_client, organizer, event, order): resp = token_client.post('/api/v1/organizers/{}/events/{}/orders/{}/payments/2/cancel/'.format( @@ -1058,6 +1071,7 @@ def test_order_mark_paid_pending(token_client, organizer, event, order): ) ) assert resp.status_code == 200 + assert len(djmail.outbox) == 1 assert resp.data['status'] == Order.STATUS_PAID @@ -1082,10 +1096,15 @@ def test_order_mark_paid_expired_quota_free(token_client, organizer, event, orde resp = token_client.post( '/api/v1/organizers/{}/events/{}/orders/{}/mark_paid/'.format( organizer.slug, event.slug, order.code - ) + ), + format='json', + data={ + 'send_email': False + } ) assert resp.status_code == 200 order.refresh_from_db() + assert len(djmail.outbox) == 0 assert order.status == Order.STATUS_PAID