mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-17 18:26:32 +00:00
BOM filter by category (#9989)
* Add "category" filter for BomItem API endpoint * Filter BOM table by part category * Tweak filter label * Bump API version * Schema annotation * Fix playwright test
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 365
|
INVENTREE_API_VERSION = 366
|
||||||
|
|
||||||
"""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 = """
|
||||||
|
|
||||||
|
v366 -> 2025-07-09 : https://github.com/inventree/InvenTree/pull/9987
|
||||||
|
- Adds "category" filter to BomItem API endpoint
|
||||||
|
|
||||||
v365 -> 2025-07-09 : https://github.com/inventree/InvenTree/pull/9984
|
v365 -> 2025-07-09 : https://github.com/inventree/InvenTree/pull/9984
|
||||||
- Allow filtering of DataOutput API by "user" field
|
- Allow filtering of DataOutput API by "user" field
|
||||||
- Allow individual deletion of DataOutput objects via the API
|
- Allow individual deletion of DataOutput objects via the API
|
||||||
|
@@ -1631,10 +1631,24 @@ class BomFilter(rest_filters.FilterSet):
|
|||||||
queryset=Part.objects.all(), method='filter_part', label=_('Part')
|
queryset=Part.objects.all(), method='filter_part', label=_('Part')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@extend_schema_field(OpenApiTypes.INT)
|
||||||
def filter_part(self, queryset, name, part):
|
def filter_part(self, queryset, name, part):
|
||||||
"""Filter the queryset based on the specified part."""
|
"""Filter the queryset based on the specified part."""
|
||||||
return queryset.filter(part.get_bom_item_filter())
|
return queryset.filter(part.get_bom_item_filter())
|
||||||
|
|
||||||
|
category = rest_filters.ModelChoiceFilter(
|
||||||
|
queryset=PartCategory.objects.all(),
|
||||||
|
method='filter_category',
|
||||||
|
label=_('Category'),
|
||||||
|
)
|
||||||
|
|
||||||
|
@extend_schema_field(OpenApiTypes.INT)
|
||||||
|
def filter_category(self, queryset, name, category):
|
||||||
|
"""Filter the queryset based on the specified PartCategory."""
|
||||||
|
cats = category.get_descendants(include_self=True)
|
||||||
|
|
||||||
|
return queryset.filter(sub_part__category__in=cats)
|
||||||
|
|
||||||
uses = rest_filters.ModelChoiceFilter(
|
uses = rest_filters.ModelChoiceFilter(
|
||||||
queryset=Part.objects.all(), method='filter_uses', label=_('Uses')
|
queryset=Part.objects.all(), method='filter_uses', label=_('Uses')
|
||||||
)
|
)
|
||||||
|
@@ -343,7 +343,7 @@ export function IssuedByFilter(): TableFilter {
|
|||||||
export function PartCategoryFilter(): TableFilter {
|
export function PartCategoryFilter(): TableFilter {
|
||||||
return {
|
return {
|
||||||
name: 'category',
|
name: 'category',
|
||||||
label: t`Category`,
|
label: t`Part Category`,
|
||||||
description: t`Filter by part category`,
|
description: t`Filter by part category`,
|
||||||
apiUrl: apiUrl(ApiEndpoints.category_list),
|
apiUrl: apiUrl(ApiEndpoints.category_list),
|
||||||
model: ModelType.partcategory,
|
model: ModelType.partcategory,
|
||||||
|
@@ -42,6 +42,7 @@ import {
|
|||||||
NoteColumn,
|
NoteColumn,
|
||||||
ReferenceColumn
|
ReferenceColumn
|
||||||
} from '../ColumnRenderers';
|
} from '../ColumnRenderers';
|
||||||
|
import { PartCategoryFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
import { type RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
|
import { type RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
|
||||||
import { TableHoverCard } from '../TableHoverCard';
|
import { TableHoverCard } from '../TableHoverCard';
|
||||||
@@ -369,7 +370,8 @@ export function BomTable({
|
|||||||
name: 'has_pricing',
|
name: 'has_pricing',
|
||||||
label: t`Has Pricing`,
|
label: t`Has Pricing`,
|
||||||
description: t`Show items with pricing`
|
description: t`Show items with pricing`
|
||||||
}
|
},
|
||||||
|
PartCategoryFilter()
|
||||||
];
|
];
|
||||||
}, [partId, params]);
|
}, [partId, params]);
|
||||||
|
|
||||||
|
@@ -109,7 +109,9 @@ test('Build Order - Calendar', async ({ browser }) => {
|
|||||||
await page.getByLabel('calendar-select-filters').click();
|
await page.getByLabel('calendar-select-filters').click();
|
||||||
await page.getByRole('button', { name: 'Add Filter' }).click();
|
await page.getByRole('button', { name: 'Add Filter' }).click();
|
||||||
await page.getByPlaceholder('Select filter').fill('category');
|
await page.getByPlaceholder('Select filter').fill('category');
|
||||||
await page.getByRole('option', { name: 'Category', exact: true }).click();
|
await page
|
||||||
|
.getByRole('option', { name: 'Part Category', exact: true })
|
||||||
|
.click();
|
||||||
await page.getByLabel('related-field-filter-category').click();
|
await page.getByLabel('related-field-filter-category').click();
|
||||||
await page.getByText('Part category, level 1').waitFor();
|
await page.getByText('Part category, level 1').waitFor();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user