Skip to content

Commit 27809d7

Browse files
Copy order params (#11479)
* Copy parameters when duplicating an order * Add unit test for order parameter duplication * Bunmp API version * Fix test reliability * Disable image fetching for SampleSupplierPlugin - Allow turning on manually - Prevent CI issues due to rate limiting * Revery pypdf.. ???
1 parent bcde270 commit 27809d7

8 files changed

Lines changed: 102 additions & 10 deletions

File tree

src/backend/InvenTree/InvenTree/api_version.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
"""InvenTree API version information."""
22

33
# InvenTree API version
4-
INVENTREE_API_VERSION = 460
4+
INVENTREE_API_VERSION = 461
55
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
66

77
INVENTREE_API_TEXT = """
88
9+
v461 -> 2026-03-10 : https://github.com/inventree/InvenTree/pull/11479
10+
- Adds option to copy parameters when duplicating an order via the API
11+
912
v460 -> 2026-02-25 : https://github.com/inventree/InvenTree/pull/11374
1013
- Adds "updated_at" field to PurchaseOrder, SalesOrder and ReturnOrder API endpoints
1114
- Adds "updated_before" and "updated_after" date filters to all three order list endpoints

src/backend/InvenTree/order/serializers.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class DuplicateOrderSerializer(serializers.Serializer):
7575
class Meta:
7676
"""Metaclass options."""
7777

78-
fields = ['order_id', 'copy_lines', 'copy_extra_lines']
78+
fields = ['order_id', 'copy_lines', 'copy_extra_lines', 'copy_parameters']
7979

8080
order_id = serializers.IntegerField(
8181
required=True, label=_('Order ID'), help_text=_('ID of the order to duplicate')
@@ -95,6 +95,13 @@ class Meta:
9595
help_text=_('Copy extra line items from the original order'),
9696
)
9797

98+
copy_parameters = serializers.BooleanField(
99+
required=False,
100+
default=True,
101+
label=_('Copy Parameters'),
102+
help_text=_('Copy order parameters from the original order'),
103+
)
104+
98105

99106
class AbstractOrderSerializer(
100107
DataImportExportSerializerMixin, FilterableSerializerMixin, serializers.Serializer
@@ -242,6 +249,7 @@ def create(self, validated_data):
242249
order_id = duplicate.get('order_id', None)
243250
copy_lines = duplicate.get('copy_lines', True)
244251
copy_extra_lines = duplicate.get('copy_extra_lines', True)
252+
copy_parameters = duplicate.get('copy_parameters', True)
245253

246254
try:
247255
copy_from = instance.__class__.objects.get(pk=order_id)
@@ -260,6 +268,9 @@ def create(self, validated_data):
260268
line.order = instance
261269
line.save()
262270

271+
if copy_parameters:
272+
instance.copy_parameters_from(copy_from)
273+
263274
return instance
264275

265276

src/backend/InvenTree/order/test_api.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,65 @@ def test_so_create(self):
15741574
expected_code=201,
15751575
)
15761576

1577+
def test_so_duplicate(self):
1578+
"""Test SalesOrder duplication via the API."""
1579+
from common.models import Parameter, ParameterTemplate
1580+
1581+
url = reverse('api-so-list')
1582+
1583+
self.assignRole('sales_order.add')
1584+
1585+
so = models.SalesOrder.objects.get(pk=1)
1586+
self.assertEqual(so.status, SalesOrderStatus.PENDING)
1587+
1588+
# Add some parameters to the sales order
1589+
for idx in range(5):
1590+
template = ParameterTemplate.objects.create(name=f'Template {idx}')
1591+
1592+
Parameter.objects.create(
1593+
template=template,
1594+
model_type=so.get_content_type(),
1595+
model_id=so.pk,
1596+
data=f'Value {idx}',
1597+
)
1598+
1599+
self.assertEqual(so.parameters.count(), 5)
1600+
1601+
# Create a duplicate of this sales order
1602+
# We explicitly specify "copy_parameters" as False, so the duplicated sales order should not have any parameters
1603+
response = self.post(
1604+
url,
1605+
{
1606+
'reference': 'SO-12345',
1607+
'customer': so.customer.pk,
1608+
'duplicate': {'order_id': so.pk, 'copy_parameters': False},
1609+
},
1610+
)
1611+
1612+
duplicate_id = response.data['pk']
1613+
duplicate_so = models.SalesOrder.objects.get(pk=duplicate_id)
1614+
1615+
self.assertEqual(duplicate_so.reference, 'SO-12345')
1616+
self.assertEqual(duplicate_so.customer, so.customer)
1617+
self.assertEqual(duplicate_so.parameters.count(), 0)
1618+
1619+
# Duplicate again, with default values for the "duplicate" options (which should result in parameters being copied)
1620+
response = self.post(
1621+
url,
1622+
{
1623+
'reference': 'SO-12346',
1624+
'customer': so.customer.pk,
1625+
'duplicate': {'order_id': so.pk},
1626+
},
1627+
)
1628+
1629+
duplicate_id = response.data['pk']
1630+
duplicate_so = models.SalesOrder.objects.get(pk=duplicate_id)
1631+
1632+
self.assertEqual(duplicate_so.reference, 'SO-12346')
1633+
self.assertEqual(duplicate_so.customer, so.customer)
1634+
self.assertEqual(duplicate_so.parameters.count(), 5)
1635+
15771636
def test_so_cancel(self):
15781637
"""Test API endpoint for cancelling a SalesOrder."""
15791638
so = models.SalesOrder.objects.get(pk=1)

src/backend/InvenTree/plugin/samples/supplier/supplier_sample.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Sample supplier plugin."""
22

3+
from django.conf import settings
4+
35
from company.models import Company, ManufacturerPart, SupplierPart, SupplierPriceBreak
46
from part.models import Part
57
from plugin.mixins import SupplierMixin, supplier
@@ -13,7 +15,16 @@ class SampleSupplierPlugin(SupplierMixin, InvenTreePlugin):
1315
SLUG = 'samplesupplier'
1416
TITLE = 'My sample supplier plugin'
1517

16-
VERSION = '0.0.1'
18+
VERSION = '0.0.2'
19+
20+
SETTINGS = {
21+
'DOWNLOAD_IMAGES': {
22+
'name': 'Download part images',
23+
'description': 'Enable downloading of part images during import (not recommended during testing)',
24+
'validator': bool,
25+
'default': False,
26+
}
27+
}
1728

1829
def __init__(self):
1930
"""Initialize the sample supplier plugin."""
@@ -108,7 +119,12 @@ def import_part(self, data, **kwargs) -> Part:
108119

109120
# If the part was created, set additional fields
110121
if created:
111-
if data['image_url']:
122+
# Prevent downloading images during testing, as this can lead to unreliable tests
123+
if (
124+
data['image_url']
125+
and not settings.TESTING
126+
and self.get_setting('DOWNLOAD_IMAGES')
127+
):
112128
file, fmt = self.download_image(data['image_url'])
113129
filename = f'part_{part.pk}_image.{fmt.lower()}'
114130
part.image.save(filename, file)

src/backend/requirements-3.14.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,9 +1669,9 @@ pynacl==1.6.2 \
16691669
# via
16701670
# -c src/backend/requirements.txt
16711671
# paramiko
1672-
pypdf==6.8.0 \
1673-
--hash=sha256:2a025080a8dd73f48123c89c57174a5ff3806c71763ee4e49572dc90454943c7 \
1674-
--hash=sha256:cb7eaeaa4133ce76f762184069a854e03f4d9a08568f0e0623f7ea810407833b
1672+
pypdf==6.7.5 \
1673+
--hash=sha256:07ba7f1d6e6d9aa2a17f5452e320a84718d4ce863367f7ede2fd72280349ab13 \
1674+
--hash=sha256:40bb2e2e872078655f12b9b89e2f900888bb505e88a82150b64f9f34fa25651d
16751675
# via
16761676
# -c src/backend/requirements.txt
16771677
# -r src/backend/requirements.in

src/frontend/src/forms/PurchaseOrderForms.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ export function usePurchaseOrderFields({
292292
value: duplicateOrderId
293293
},
294294
copy_lines: {},
295-
copy_extra_lines: {}
295+
copy_extra_lines: {},
296+
copy_parameters: {}
296297
}
297298
};
298299
}

src/frontend/src/forms/ReturnOrderForms.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ export function useReturnOrderFields({
9191
value: false,
9292
hidden: true
9393
},
94-
copy_extra_lines: {}
94+
copy_extra_lines: {},
95+
copy_parameters: {}
9596
}
9697
};
9798
}

src/frontend/src/forms/SalesOrderForms.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ export function useSalesOrderFields({
9090
value: duplicateOrderId
9191
},
9292
copy_lines: {},
93-
copy_extra_lines: {}
93+
copy_extra_lines: {},
94+
copy_parameters: {}
9495
}
9596
};
9697
}

0 commit comments

Comments
 (0)