forked from CGM_Public/pretix_original
Refs #654 -- REST API: Allow invoice creation
This commit is contained in:
@@ -953,7 +953,7 @@ Order state operations
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/mark_expired/
|
||||
|
||||
Marks a unpaid order as expired.
|
||||
Marks an unpaid order as expired.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@@ -1115,6 +1115,47 @@ Order state operations
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: The requested order does not exist.
|
||||
|
||||
Invoice generation
|
||||
------------------
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/create_invoice/
|
||||
|
||||
Creates an invoice for an order which currently does not have an invoice. Returns the
|
||||
invoice object.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/orders/ABC12/create_invoice/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"order": "FOO",
|
||||
"number": "DUMMY-00001",
|
||||
"is_cancellation": false,
|
||||
...
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param code: The ``code`` field of the order to create an invoice for
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The invoice can not be created (invoicing disabled, the order already has an invoice, …)
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: The requested order does not exist.
|
||||
|
||||
|
||||
List of all order positions
|
||||
---------------------------
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.db.models.functions import Coalesce, Concat
|
||||
from django.http import FileResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.timezone import make_aware, now
|
||||
from django.utils.translation import ugettext as _
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from rest_framework import mixins, serializers, status, viewsets
|
||||
from rest_framework.decorators import detail_route
|
||||
@@ -308,6 +309,38 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
def create_invoice(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
has_inv = order.invoices.exists() and not (
|
||||
order.status in (Order.STATUS_PAID, Order.STATUS_PENDING)
|
||||
and order.invoices.filter(is_cancellation=True).count() >= order.invoices.filter(is_cancellation=False).count()
|
||||
)
|
||||
if self.request.event.settings.get('invoice_generate') not in ('admin', 'user', 'paid', 'True') or not invoice_qualified(order):
|
||||
return Response(
|
||||
{'detail': _('You cannot generate an invoice for this order.')},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
elif has_inv:
|
||||
return Response(
|
||||
{'detail': _('An invoice for this order already exists.')},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
inv = generate_invoice(order)
|
||||
order.log_action(
|
||||
'pretix.event.order.invoice.generated',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'invoice': inv.pk
|
||||
}
|
||||
)
|
||||
return Response(
|
||||
InvoiceSerializer(inv).data,
|
||||
status=status.HTTP_201_CREATED
|
||||
)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
def extend(self, request, **kwargs):
|
||||
new_date = request.data.get('expires', None)
|
||||
|
||||
@@ -2626,3 +2626,65 @@ def test_order_update_locale_to_invalid(token_client, organizer, event, order):
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'locale': ['"de" is not a supported locale for this event.']}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_order_create_invoice(token_client, organizer, event, order):
|
||||
event.settings.invoice_generate = 'True'
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orders/{}/create_invoice/'.format(
|
||||
organizer.slug, event.slug, order.code
|
||||
), format='json', data={}
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
assert resp.data == {
|
||||
'order': 'FOO',
|
||||
'number': 'DUMMY-00001',
|
||||
'is_cancellation': False,
|
||||
'invoice_from': '',
|
||||
'invoice_to': 'Sample company\n\n\n \nNew Zealand',
|
||||
'date': '2019-03-23',
|
||||
'refers': None,
|
||||
'locale': 'en',
|
||||
'introductory_text': '',
|
||||
'additional_text': '',
|
||||
'payment_provider_text': '',
|
||||
'footer_text': '',
|
||||
'lines': [
|
||||
{
|
||||
'description': 'Budget Ticket<br />Attendee: Peter',
|
||||
'gross_value': '23.00',
|
||||
'tax_value': '0.00',
|
||||
'tax_rate': '0.00',
|
||||
'tax_name': ''
|
||||
},
|
||||
{
|
||||
'description': 'Payment fee',
|
||||
'gross_value': '0.25',
|
||||
'tax_value': '0.05',
|
||||
'tax_rate': '19.00',
|
||||
'tax_name': ''
|
||||
}
|
||||
],
|
||||
'foreign_currency_display': None,
|
||||
'foreign_currency_rate': None,
|
||||
'foreign_currency_rate_date': None,
|
||||
'internal_reference': ''
|
||||
}
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orders/{}/create_invoice/'.format(
|
||||
organizer.slug, event.slug, order.code
|
||||
), format='json', data={}
|
||||
)
|
||||
assert resp.data == {'detail': 'An invoice for this order already exists.'}
|
||||
assert resp.status_code == 400
|
||||
|
||||
event.settings.invoice_generate = 'False'
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orders/{}/create_invoice/'.format(
|
||||
organizer.slug, event.slug, order.code
|
||||
), format='json', data={}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'detail': 'You cannot generate an invoice for this order.'}
|
||||
|
||||
Reference in New Issue
Block a user