diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index c21e67059c47..98733ffa68a0 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,13 +1,17 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 239 +INVENTREE_API_VERSION = 240 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v240 - 2024-08-16 : https://github.com/inventree/InvenTree/pull/7900 + - Adjust "issued_by" filter for the BuildOrder list endpoint + - Adjust "assigned_to" filter for the BuildOrder list endpoint + v239 - 2024-08-15 : https://github.com/inventree/InvenTree/pull/7888 - Adds "testable" field to the Part model - Adds associated filters to various API endpoints diff --git a/src/backend/InvenTree/build/api.py b/src/backend/InvenTree/build/api.py index 7c848281a531..67a7b0ef1770 100644 --- a/src/backend/InvenTree/build/api.py +++ b/src/backend/InvenTree/build/api.py @@ -37,7 +37,6 @@ class Meta: 'parent', 'sales_order', 'part', - 'issued_by', ] status = rest_filters.NumberFilter(label='Status') @@ -58,7 +57,10 @@ def filter_overdue(self, queryset, name, value): return queryset.filter(Build.OVERDUE_FILTER) return queryset.exclude(Build.OVERDUE_FILTER) - assigned_to_me = rest_filters.BooleanFilter(label='assigned_to_me', method='filter_assigned_to_me') + assigned_to_me = rest_filters.BooleanFilter( + label=_('Assigned to me'), + method='filter_assigned_to_me' + ) def filter_assigned_to_me(self, queryset, name, value): """Filter by orders which are assigned to the current user.""" @@ -71,10 +73,33 @@ def filter_assigned_to_me(self, queryset, name, value): return queryset.filter(responsible__in=owners) return queryset.exclude(responsible__in=owners) - assigned_to = rest_filters.NumberFilter(label='responsible', method='filter_responsible') + issued_by = rest_filters.ModelChoiceFilter( + queryset=Owner.objects.all(), + label=_('Issued By'), + method='filter_issued_by' + ) + + def filter_issued_by(self, queryset, name, owner): + """Filter by 'owner' which issued the order.""" + + if owner.label() == 'user': + user = User.objects.get(pk=owner.owner_id) + return queryset.filter(issued_by=user) + elif owner.label() == 'group': + group = User.objects.filter(groups__pk=owner.owner_id) + return queryset.filter(issued_by__in=group) + else: + return queryset.none() + + assigned_to = rest_filters.ModelChoiceFilter( + queryset=Owner.objects.all(), + field_name='responsible', + label=_('Assigned To') + ) - def filter_responsible(self, queryset, name, value): + def filter_responsible(self, queryset, name, owner): """Filter by orders which are assigned to the specified owner.""" + owners = list(Owner.objects.filter(pk=value)) # if we query by a user, also find all ownerships through group memberships diff --git a/src/backend/InvenTree/order/api.py b/src/backend/InvenTree/order/api.py index d5618d26d702..7e08d72e7398 100644 --- a/src/backend/InvenTree/order/api.py +++ b/src/backend/InvenTree/order/api.py @@ -77,7 +77,7 @@ class OrderFilter(rest_filters.FilterSet): """Base class for custom API filters for the OrderList endpoint.""" # Filter against order status - status = rest_filters.NumberFilter(label='Order Status', method='filter_status') + status = rest_filters.NumberFilter(label=_('Order Status'), method='filter_status') def filter_status(self, queryset, name, value): """Filter by integer status code.""" @@ -85,11 +85,11 @@ def filter_status(self, queryset, name, value): # Exact match for reference reference = rest_filters.CharFilter( - label='Filter by exact reference', field_name='reference', lookup_expr='iexact' + label=_('Order Reference'), field_name='reference', lookup_expr='iexact' ) assigned_to_me = rest_filters.BooleanFilter( - label='assigned_to_me', method='filter_assigned_to_me' + label=_('Assigned to me'), method='filter_assigned_to_me' ) def filter_assigned_to_me(self, queryset, name, value): @@ -113,7 +113,7 @@ def filter_overdue(self, queryset, name, value): return queryset.exclude(self.Meta.model.overdue_filter()) outstanding = rest_filters.BooleanFilter( - label='outstanding', method='filter_outstanding' + label=_('Outstanding'), method='filter_outstanding' ) def filter_outstanding(self, queryset, name, value): @@ -123,11 +123,13 @@ def filter_outstanding(self, queryset, name, value): return queryset.exclude(status__in=self.Meta.model.get_status_class().OPEN) project_code = rest_filters.ModelChoiceFilter( - queryset=common.models.ProjectCode.objects.all(), field_name='project_code' + queryset=common.models.ProjectCode.objects.all(), + field_name='project_code', + label=_('Project Code'), ) has_project_code = rest_filters.BooleanFilter( - label='has_project_code', method='filter_has_project_code' + method='filter_has_project_code', label=_('Has Project Code') ) def filter_has_project_code(self, queryset, name, value): @@ -137,7 +139,7 @@ def filter_has_project_code(self, queryset, name, value): return queryset.filter(project_code=None) assigned_to = rest_filters.ModelChoiceFilter( - queryset=Owner.objects.all(), field_name='responsible' + queryset=Owner.objects.all(), field_name='responsible', label=_('Responsible') ) diff --git a/src/backend/InvenTree/templates/js/translated/table_filters.js b/src/backend/InvenTree/templates/js/translated/table_filters.js index bb6d049a6fe9..f45c14e0b01c 100644 --- a/src/backend/InvenTree/templates/js/translated/table_filters.js +++ b/src/backend/InvenTree/templates/js/translated/table_filters.js @@ -18,28 +18,27 @@ */ -// Construct a dynamic API filter for the "issued by" field -function constructIssuedByFilter() { +// Construct a dynamic API filter for an "owner" +function constructOwnerFilter(title) { return { - title: '{% trans "Issued By" %}', + title: title, options: function() { - let users = {}; - - inventreeGet('{% url "api-user-list" %}', {}, { + var ownersList = {}; + inventreeGet('{% url "api-owner-list" %}', {}, { async: false, success: function(response) { - for (let user of response) { - users[user.pk] = { - key: user.pk, - value: user.username + for (var key in response) { + let owner = response[key]; + ownersList[owner.pk] = { + key: owner.pk, + value: `${owner.name} (${owner.label})`, }; } } }); - - return users; - } - } + return ownersList; + }, + }; } // Construct a dynamic API filter for the "project" field @@ -549,26 +548,8 @@ function getBuildTableFilters() { type: 'bool', title: '{% trans "Assigned to me" %}', }, - assigned_to: { - title: '{% trans "Responsible" %}', - options: function() { - var ownersList = {}; - inventreeGet('{% url "api-owner-list" %}', {}, { - async: false, - success: function(response) { - for (var key in response) { - let owner = response[key]; - ownersList[owner.pk] = { - key: owner.pk, - value: `${owner.name} (${owner.label})`, - }; - } - } - }); - return ownersList; - }, - }, - issued_by: constructIssuedByFilter(), + assigned_to: constructOwnerFilter('{% trans "Responsible" %}'), + issued_by: constructOwnerFilter('{% trans "Issued By" %}'), }; if (global_settings.PROJECT_CODES_ENABLED) { diff --git a/src/frontend/src/tables/build/BuildOrderTable.tsx b/src/frontend/src/tables/build/BuildOrderTable.tsx index 2041bd091515..ef7a9fec5065 100644 --- a/src/frontend/src/tables/build/BuildOrderTable.tsx +++ b/src/frontend/src/tables/build/BuildOrderTable.tsx @@ -8,11 +8,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { useBuildOrderFields } from '../../forms/BuildForms'; -import { - useOwnerFilters, - useProjectCodeFilters, - useUserFilters -} from '../../hooks/UseFilter'; +import { useOwnerFilters, useProjectCodeFilters } from '../../hooks/UseFilter'; import { useCreateApiFormModal } from '../../hooks/UseForm'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; @@ -103,8 +99,7 @@ export function BuildOrderTable({ const tableColumns = useMemo(() => buildOrderTableColumns(), []); const projectCodeFilters = useProjectCodeFilters(); - const userFilters = useUserFilters(); - const responsibleFilters = useOwnerFilters(); + const ownerFilters = useOwnerFilters(); const tableFilters: TableFilter[] = useMemo(() => { return [ @@ -147,20 +142,16 @@ export function BuildOrderTable({ name: 'issued_by', label: t`Issued By`, description: t`Filter by user who issued this order`, - choices: userFilters.choices + choices: ownerFilters.choices }, { name: 'assigned_to', label: t`Responsible`, description: t`Filter by responsible owner`, - choices: responsibleFilters.choices + choices: ownerFilters.choices } ]; - }, [ - projectCodeFilters.choices, - userFilters.choices, - responsibleFilters.choices - ]); + }, [projectCodeFilters.choices, ownerFilters.choices]); const user = useUserState();