Implement same functionality for StockLocationTree API endpoint

This commit is contained in:
Oliver Walters 2026-06-19 03:22:32 +00:00
parent a771ab984b
commit 7fb7a04460
4 changed files with 39 additions and 21 deletions

View File

@ -310,19 +310,13 @@ class CategoryTree(TreeMixin, ListAPI):
model_class = PartCategory
queryset = PartCategory.objects.all()
serializer_class = part_serializers.CategoryTree
serializer_class = part_serializers.CategoryTreeSerializer
filterset_class = CategoryTreeFilter
def get_queryset(self, *args, **kwargs):
"""Return an annotated queryset for the CategoryTree endpoint."""
queryset = super().get_queryset(*args, **kwargs)
queryset = part_serializers.CategoryTree.annotate_queryset(queryset)
return queryset
def filter_queryset(self, queryset):
"""Filter the queryset, and include all ancestors of matched items when searching."""
queryset = super().filter_queryset(queryset)
queryset = part_serializers.CategoryTree.annotate_queryset(queryset)
queryset = part_serializers.CategoryTreeSerializer.annotate_queryset(queryset)
return queryset

View File

@ -181,7 +181,7 @@ class CategorySerializer(
parameters = common.filters.enable_parameters_filter()
class CategoryTree(InvenTree.serializers.InvenTreeModelSerializer):
class CategoryTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""Serializer for PartCategory tree."""
class Meta:

View File

@ -33,11 +33,11 @@ from InvenTree.api import (
BulkCreateMixin,
BulkUpdateMixin,
ListCreateDestroyAPIView,
TreeMixin,
meta_path,
)
from InvenTree.fields import InvenTreeOutputOption, OutputConfiguration
from InvenTree.filters import (
ORDER_FILTER,
SEARCH_ORDER_FILTER,
InvenTreeDateFilter,
NumberOrNullFilter,
@ -455,20 +455,33 @@ class StockLocationDetail(
)
class StockLocationTree(ListAPI):
class LocationTreeFilter(FilterSet):
"""Custom filterset class for the StockLocationTree endpoint."""
class Meta:
"""Metaclass options for this filterset."""
model = StockLocation
fields = ['parent', 'tree_id', 'level']
max_level = rest_filters.NumberFilter(
label=_('Max Level'),
method='filter_max_level',
help_text=_('Limit the depth of the category tree'),
)
def filter_max_level(self, queryset, name, value):
"""Filter by the maximum depth of the category tree."""
return queryset.filter(level__lte=value)
class StockLocationTree(TreeMixin, ListAPI):
"""API endpoint for accessing a list of StockLocation objects, ready for rendering as a tree."""
model_class = StockLocation
queryset = StockLocation.objects.all()
serializer_class = StockSerializers.LocationTreeSerializer
filter_backends = ORDER_FILTER
ordering_fields = ['level', 'name', 'sublocations']
# Order by tree level (top levels first) and then name
ordering = ['level', 'name']
ordering_field_aliases = {'level': ['level', 'name'], 'name': ['name', 'level']}
filterset_class = LocationTreeFilter
def get_queryset(self, *args, **kwargs):
"""Return annotated queryset for the StockLocationTree endpoint."""

View File

@ -1160,7 +1160,18 @@ class LocationTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""Metaclass options."""
model = StockLocation
fields = ['pk', 'name', 'parent', 'icon', 'structural', 'sublocations']
fields = [
'pk',
'name',
'description',
'pathstring',
'parent',
'tree_id',
'level',
'icon',
'structural',
'sublocations',
]
sublocations = serializers.IntegerField(label=_('Sublocations'), read_only=True)