diff --git a/doc/api/resources/invoices.rst b/doc/api/resources/invoices.rst
index 2236403eff..086e8b206a 100644
--- a/doc/api/resources/invoices.rst
+++ b/doc/api/resources/invoices.rst
@@ -28,6 +28,7 @@ payment_provider_text string Text to be prin
payment information
footer_text string Text to be printed in the page footer area
lines list of objects The actual invoice contents
+├ position integer Number of the line within an invoice.
├ description string Text representing the invoice line (e.g. product name)
├ gross_value money (string) Price including taxes
├ tax_value money (string) Tax amount included
@@ -63,6 +64,11 @@ internal_reference string Customer's refe
The attribute ``internal_reference`` has been added.
+.. versionchanged:: 3.4
+
+ The attribute ``lines.number`` has been added.
+
+
Endpoints
---------
@@ -107,6 +113,7 @@ Endpoints
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
"lines": [
{
+ "position": 1,
"description": "Budget Ticket",
"gross_value": "23.00",
"tax_value": "0.00",
@@ -171,6 +178,7 @@ Endpoints
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
"lines": [
{
+ "position": 1,
"description": "Budget Ticket",
"gross_value": "23.00",
"tax_value": "0.00",
diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py
index a5640ef573..2f1afd53e9 100644
--- a/src/pretix/api/serializers/order.py
+++ b/src/pretix/api/serializers/order.py
@@ -905,10 +905,25 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
return order
+class LinePositionField(serializers.IntegerField):
+ """
+ Internally, the position field is stored starting at 0, but for the API, starting at 1 makes it
+ more consistent with other models
+ """
+
+ def to_representation(self, value):
+ return super().to_representation(value) + 1
+
+ def to_internal_value(self, data):
+ return super().to_internal_value(data) - 1
+
+
class InlineInvoiceLineSerializer(I18nAwareModelSerializer):
+ position = LinePositionField(read_only=True)
+
class Meta:
model = InvoiceLine
- fields = ('description', 'gross_value', 'tax_value', 'tax_rate', 'tax_name')
+ fields = ('position', 'description', 'gross_value', 'tax_value', 'tax_rate', 'tax_name')
class InvoiceSerializer(I18nAwareModelSerializer):
diff --git a/src/tests/api/test_orders.py b/src/tests/api/test_orders.py
index 4bcab2ad6c..f9ee4478b4 100644
--- a/src/tests/api/test_orders.py
+++ b/src/tests/api/test_orders.py
@@ -838,6 +838,7 @@ TEST_INVOICE_RES = {
"foreign_currency_rate_date": None,
"lines": [
{
+ "position": 1,
"description": "Budget Ticket
Attendee: Peter",
"gross_value": "23.00",
"tax_value": "0.00",
@@ -845,6 +846,7 @@ TEST_INVOICE_RES = {
"tax_rate": "0.00"
},
{
+ "position": 2,
"description": "Payment fee",
"gross_value": "0.25",
"tax_value": "0.05",
@@ -3674,6 +3676,7 @@ def test_order_create_invoice(token_client, organizer, event, order):
'footer_text': '',
'lines': [
{
+ 'position': 1,
'description': 'Budget Ticket
Attendee: Peter',
'gross_value': '23.00',
'tax_value': '0.00',
@@ -3681,6 +3684,7 @@ def test_order_create_invoice(token_client, organizer, event, order):
'tax_name': ''
},
{
+ 'position': 2,
'description': 'Payment fee',
'gross_value': '0.25',
'tax_value': '0.05',