mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 19:46:46 +00:00
Top level cascade (#7514)
* Add "top_level" filter for PartCategory API endpoint * Update CUI tables * Update PUI table * Similar updates for stock location table * Fix "parent" field label * Bump API version
This commit is contained in:
parent
81ae9026b2
commit
937824dceb
@ -1,11 +1,15 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 208
|
INVENTREE_API_VERSION = 209
|
||||||
|
|
||||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
INVENTREE_API_TEXT = """
|
||||||
|
v209 - 2024-06-26 : https://github.com/inventree/InvenTree/pull/7514
|
||||||
|
- Add "top_level" filter to PartCategory API endpoint
|
||||||
|
- Add "top_level" filter to StockLocation API endpoint
|
||||||
|
|
||||||
v208 - 2024-06-19 : https://github.com/inventree/InvenTree/pull/7479
|
v208 - 2024-06-19 : https://github.com/inventree/InvenTree/pull/7479
|
||||||
- Adds documentation for the user roles API endpoint (no functional changes)
|
- Adds documentation for the user roles API endpoint (no functional changes)
|
||||||
|
|
||||||
|
@ -779,7 +779,7 @@ class InvenTreeTree(MetadataMixin, PluginValidationMixin, MPTTModel):
|
|||||||
on_delete=models.DO_NOTHING,
|
on_delete=models.DO_NOTHING,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name=_('parent'),
|
verbose_name='parent',
|
||||||
related_name='children',
|
related_name='children',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -137,6 +137,21 @@ class CategoryFilter(rest_filters.FilterSet):
|
|||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
top_level = rest_filters.BooleanFilter(
|
||||||
|
label=_('Top Level'),
|
||||||
|
method='filter_top_level',
|
||||||
|
help_text=_('Filter by top-level categories'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def filter_top_level(self, queryset, name, value):
|
||||||
|
"""Filter by top-level categories."""
|
||||||
|
cascade = str2bool(self.data.get('cascade', False))
|
||||||
|
|
||||||
|
if value and not cascade:
|
||||||
|
return queryset.filter(parent=None)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
cascade = rest_filters.BooleanFilter(
|
cascade = rest_filters.BooleanFilter(
|
||||||
label=_('Cascade'),
|
label=_('Cascade'),
|
||||||
method='filter_cascade',
|
method='filter_cascade',
|
||||||
@ -148,10 +163,11 @@ class CategoryFilter(rest_filters.FilterSet):
|
|||||||
|
|
||||||
Note: If the "parent" filter is provided, we offload the logic to that method.
|
Note: If the "parent" filter is provided, we offload the logic to that method.
|
||||||
"""
|
"""
|
||||||
parent = self.data.get('parent', None)
|
parent = str2bool(self.data.get('parent', None))
|
||||||
|
top_level = str2bool(self.data.get('top_level', None))
|
||||||
|
|
||||||
# If the parent is *not* provided, update the results based on the "cascade" value
|
# If the parent is *not* provided, update the results based on the "cascade" value
|
||||||
if not parent:
|
if not parent or top_level:
|
||||||
if not value:
|
if not value:
|
||||||
# If "cascade" is False, only return top-level categories
|
# If "cascade" is False, only return top-level categories
|
||||||
queryset = queryset.filter(parent=None)
|
queryset = queryset.filter(parent=None)
|
||||||
|
@ -111,6 +111,14 @@ class CategorySerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
|||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
parent = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=PartCategory.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
label=_('Parent Category'),
|
||||||
|
help_text=_('Parent part category'),
|
||||||
|
)
|
||||||
|
|
||||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||||
|
|
||||||
part_count = serializers.IntegerField(read_only=True, label=_('Parts'))
|
part_count = serializers.IntegerField(read_only=True, label=_('Parts'))
|
||||||
|
@ -317,6 +317,8 @@
|
|||||||
params: {
|
params: {
|
||||||
{% if category %}
|
{% if category %}
|
||||||
parent: {{ category.pk }},
|
parent: {{ category.pk }},
|
||||||
|
{% else %}
|
||||||
|
top_level: true,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
},
|
},
|
||||||
allowTreeView: true,
|
allowTreeView: true,
|
||||||
|
@ -326,6 +326,21 @@ class StockLocationFilter(rest_filters.FilterSet):
|
|||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
top_level = rest_filters.BooleanFilter(
|
||||||
|
label=_('Top Level'),
|
||||||
|
method='filter_top_level',
|
||||||
|
help_text=_('Filter by top-level locations'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def filter_top_level(self, queryset, name, value):
|
||||||
|
"""Filter by top-level locations."""
|
||||||
|
cascade = str2bool(self.data.get('cascade', False))
|
||||||
|
|
||||||
|
if value and not cascade:
|
||||||
|
return queryset.filter(parent=None)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
cascade = rest_filters.BooleanFilter(
|
cascade = rest_filters.BooleanFilter(
|
||||||
label=_('Cascade'),
|
label=_('Cascade'),
|
||||||
method='filter_cascade',
|
method='filter_cascade',
|
||||||
@ -338,9 +353,10 @@ class StockLocationFilter(rest_filters.FilterSet):
|
|||||||
Note: If the "parent" filter is provided, we offload the logic to that method.
|
Note: If the "parent" filter is provided, we offload the logic to that method.
|
||||||
"""
|
"""
|
||||||
parent = self.data.get('parent', None)
|
parent = self.data.get('parent', None)
|
||||||
|
top_level = str2bool(self.data.get('top_level', None))
|
||||||
|
|
||||||
# If the parent is *not* provided, update the results based on the "cascade" value
|
# If the parent is *not* provided, update the results based on the "cascade" value
|
||||||
if not parent:
|
if not parent or top_level:
|
||||||
if not value:
|
if not value:
|
||||||
# If "cascade" is False, only return top-level location
|
# If "cascade" is False, only return top-level location
|
||||||
queryset = queryset.filter(parent=None)
|
queryset = queryset.filter(parent=None)
|
||||||
|
@ -1077,6 +1077,15 @@ class LocationSerializer(InvenTree.serializers.InvenTreeTagModelSerializer):
|
|||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
parent = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=StockLocation.objects.all(),
|
||||||
|
many=False,
|
||||||
|
allow_null=True,
|
||||||
|
required=False,
|
||||||
|
label=_('Parent Location'),
|
||||||
|
help_text=_('Parent stock location'),
|
||||||
|
)
|
||||||
|
|
||||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||||
|
|
||||||
items = serializers.IntegerField(read_only=True, label=_('Stock Items'))
|
items = serializers.IntegerField(read_only=True, label=_('Stock Items'))
|
||||||
|
@ -280,6 +280,8 @@
|
|||||||
params: {
|
params: {
|
||||||
{% if location %}
|
{% if location %}
|
||||||
parent: {{ location.pk }},
|
parent: {{ location.pk }},
|
||||||
|
{% else %}
|
||||||
|
top_level: true,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
},
|
},
|
||||||
allowTreeView: true,
|
allowTreeView: true,
|
||||||
|
@ -130,7 +130,8 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) {
|
|||||||
props={{
|
props={{
|
||||||
enableDownload: true,
|
enableDownload: true,
|
||||||
params: {
|
params: {
|
||||||
parent: parentId
|
parent: parentId,
|
||||||
|
top_level: parentId === undefined ? true : undefined
|
||||||
},
|
},
|
||||||
tableFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
tableActions: tableActions,
|
tableActions: tableActions,
|
||||||
|
@ -145,7 +145,8 @@ export function StockLocationTable({ parentId }: { parentId?: any }) {
|
|||||||
enableLabels: true,
|
enableLabels: true,
|
||||||
enableReports: true,
|
enableReports: true,
|
||||||
params: {
|
params: {
|
||||||
parent: parentId
|
parent: parentId,
|
||||||
|
top_level: parentId === undefined ? true : undefined
|
||||||
},
|
},
|
||||||
tableFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
tableActions: tableActions,
|
tableActions: tableActions,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user