Add limit to default location annotation (#7771)

* Add limit to default location annotation

Limits the number of results from the default_location filter to 1

* Add unit test to verify annotation functionality
This commit is contained in:
Lavissa 2024-08-02 01:15:57 +02:00 committed by GitHub
parent e5fabc6788
commit 2cb8f4128e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 79 additions and 6 deletions

View File

@ -296,15 +296,12 @@ def annotate_default_location(reference=''):
rght__gt=OuterRef(f'{reference}rght'),
level__lte=OuterRef(f'{reference}level'),
parent__isnull=False,
)
default_location__isnull=False,
).order_by('-level')
return Coalesce(
F(f'{reference}default_location'),
Subquery(
subquery.order_by('-level')
.filter(default_location__isnull=False)
.values('default_location')
),
Subquery(subquery.values('default_location')[:1]),
Value(None),
output_field=IntegerField(),
)

View File

@ -505,6 +505,82 @@ class PartCategoryAPITest(InvenTreeAPITestCase):
self.assertEqual(item['parent'], parent)
self.assertEqual(item['subcategories'], subcategories)
def test_part_category_default_location(self):
"""Test default location propagation through location trees."""
"""Making a tree structure like this:
main
loc 2
sub1
sub2
loc 3
sub3
loc 4
sub4
sub5
Expected behaviour:
main parent loc: Out of test scope. Parent category data not controlled by the test
sub1 parent loc: loc 2
sub2 parent loc: loc 2
sub3 parent loc: loc 3
sub4 parent loc: loc 4
sub5 parent loc: loc 3
"""
main = PartCategory.objects.create(
name='main',
parent=PartCategory.objects.first(),
default_location=StockLocation.objects.get(id=2),
)
sub1 = PartCategory.objects.create(name='sub1', parent=main)
sub2 = PartCategory.objects.create(
name='sub2', parent=sub1, default_location=StockLocation.objects.get(id=3)
)
sub3 = PartCategory.objects.create(
name='sub3', parent=sub2, default_location=StockLocation.objects.get(id=4)
)
sub4 = PartCategory.objects.create(name='sub4', parent=sub3)
sub5 = PartCategory.objects.create(name='sub5', parent=sub2)
part = Part.objects.create(name='test', category=sub4)
PartCategory.objects.rebuild()
# This query will trigger an internal server error if annotation results are not limited to 1
url = reverse('api-part-list')
response = self.get(url, expected_code=200)
# sub1, expect main to be propagated
url = reverse('api-part-category-detail', kwargs={'pk': sub1.pk})
response = self.get(url, expected_code=200)
self.assertEqual(
response.data['parent_default_location'], main.default_location.pk
)
# sub2, expect main to be propagated
url = reverse('api-part-category-detail', kwargs={'pk': sub2.pk})
response = self.get(url, expected_code=200)
self.assertEqual(
response.data['parent_default_location'], main.default_location.pk
)
# sub3, expect sub2 to be propagated
url = reverse('api-part-category-detail', kwargs={'pk': sub3.pk})
response = self.get(url, expected_code=200)
self.assertEqual(
response.data['parent_default_location'], sub2.default_location.pk
)
# sub4, expect sub3 to be propagated
url = reverse('api-part-category-detail', kwargs={'pk': sub4.pk})
response = self.get(url, expected_code=200)
self.assertEqual(
response.data['parent_default_location'], sub3.default_location.pk
)
# sub5, expect sub2 to be propagated
url = reverse('api-part-category-detail', kwargs={'pk': sub5.pk})
response = self.get(url, expected_code=200)
self.assertEqual(
response.data['parent_default_location'], sub2.default_location.pk
)
class PartOptionsAPITest(InvenTreeAPITestCase):
"""Tests for the various OPTIONS endpoints in the /part/ API.