diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 6f57c0078d..c0364369d5 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,11 +1,14 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 525 +INVENTREE_API_VERSION = 526 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v526 -> 2026-07-24 : https://github.com/inventree/InvenTree/pull/12463 + - Fix for data export on SalesOrderAllocation API endpoint + v525 -> 2026-07-20 : https://github.com/inventree/InvenTree/pull/12409 - Type clarifications for some fields; no functional changes diff --git a/src/backend/InvenTree/order/api.py b/src/backend/InvenTree/order/api.py index 634a31198a..f8874c1cea 100644 --- a/src/backend/InvenTree/order/api.py +++ b/src/backend/InvenTree/order/api.py @@ -1362,6 +1362,7 @@ class SalesOrderAllocationList( SalesOrderAllocationMixin, BulkDeleteMixin, BulkUpdateMixin, + DataExportViewMixin, OutputOptionsMixin, ListAPI, ): diff --git a/src/backend/InvenTree/order/serializers.py b/src/backend/InvenTree/order/serializers.py index e5d7f0ac0a..f434cf87c0 100644 --- a/src/backend/InvenTree/order/serializers.py +++ b/src/backend/InvenTree/order/serializers.py @@ -26,6 +26,7 @@ from company.serializers import ( ContactSerializer, SupplierPartSerializer, ) +from data_exporter.mixins import DataExportSerializerMixin from generic.states.fields import InvenTreeCustomStatusSerializerMixin from importer.registry import register_importer from InvenTree.helpers import extract_serial_numbers, hash_barcode, normalize, str2bool @@ -1543,7 +1544,7 @@ class SalesOrderShipmentSerializer( class SalesOrderAllocationSerializer( - FilterableSerializerMixin, InvenTreeModelSerializer + DataExportSerializerMixin, FilterableSerializerMixin, InvenTreeModelSerializer ): """Serializer for the SalesOrderAllocation model. diff --git a/src/backend/InvenTree/order/test_api.py b/src/backend/InvenTree/order/test_api.py index 0b7d3ee641..1203684ae1 100644 --- a/src/backend/InvenTree/order/test_api.py +++ b/src/backend/InvenTree/order/test_api.py @@ -2841,6 +2841,36 @@ class SalesOrderAllocateTest(OrderTest): response = self.post(self.url, data, expected_code=201) +class SalesOrderAllocationDownloadTest(OrderTest): + """Unit tests for downloading SalesOrderAllocation data via the API endpoint.""" + + def test_download_csv(self): + """Test that SalesOrderAllocation data can be downloaded as a .csv file. + + Regression test for a bug where the SalesOrderAllocation list endpoint + did not support data export. + """ + url = reverse('api-so-allocation-list') + + required_cols = ['ID', 'Item', 'Quantity', 'Shipment', 'Line', 'Part', 'Order'] + + with self.export_data(url, export_format='csv', expected_code=200) as file: + data = self.process_csv( + file, + required_cols=required_cols, + required_rows=SalesOrderAllocation.objects.count(), + ) + + for row in data: + allocation = SalesOrderAllocation.objects.get(pk=row['ID']) + + self.assertEqual(row['Item'], str(allocation.item.pk)) + self.assertEqual(float(row['Quantity']), float(allocation.quantity)) + self.assertEqual(row['Line'], str(allocation.line.pk)) + self.assertEqual(row['Part'], str(allocation.item.part.pk)) + self.assertEqual(row['Order'], str(allocation.line.order.pk)) + + class SalesOrderAllocateSerialsTest(OrderTest): """Unit tests for allocating stock items against a SalesOrder, by serial number."""