mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Improve "issued by" filter for Build list API (#7900)
* Simplify build order filters * Improve labels for order filters * Bump API version
This commit is contained in:
parent
ed2ac0f1da
commit
7178b95657
@ -1,13 +1,17 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# 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."""
|
"""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 = """
|
||||||
|
|
||||||
|
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
|
v239 - 2024-08-15 : https://github.com/inventree/InvenTree/pull/7888
|
||||||
- Adds "testable" field to the Part model
|
- Adds "testable" field to the Part model
|
||||||
- Adds associated filters to various API endpoints
|
- Adds associated filters to various API endpoints
|
||||||
|
@ -37,7 +37,6 @@ class BuildFilter(rest_filters.FilterSet):
|
|||||||
'parent',
|
'parent',
|
||||||
'sales_order',
|
'sales_order',
|
||||||
'part',
|
'part',
|
||||||
'issued_by',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
status = rest_filters.NumberFilter(label='Status')
|
status = rest_filters.NumberFilter(label='Status')
|
||||||
@ -58,7 +57,10 @@ class BuildFilter(rest_filters.FilterSet):
|
|||||||
return queryset.filter(Build.OVERDUE_FILTER)
|
return queryset.filter(Build.OVERDUE_FILTER)
|
||||||
return queryset.exclude(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):
|
def filter_assigned_to_me(self, queryset, name, value):
|
||||||
"""Filter by orders which are assigned to the current user."""
|
"""Filter by orders which are assigned to the current user."""
|
||||||
@ -71,10 +73,33 @@ class BuildFilter(rest_filters.FilterSet):
|
|||||||
return queryset.filter(responsible__in=owners)
|
return queryset.filter(responsible__in=owners)
|
||||||
return queryset.exclude(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_responsible(self, queryset, name, value):
|
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, owner):
|
||||||
"""Filter by orders which are assigned to the specified owner."""
|
"""Filter by orders which are assigned to the specified owner."""
|
||||||
|
|
||||||
owners = list(Owner.objects.filter(pk=value))
|
owners = list(Owner.objects.filter(pk=value))
|
||||||
|
|
||||||
# if we query by a user, also find all ownerships through group memberships
|
# if we query by a user, also find all ownerships through group memberships
|
||||||
|
@ -77,7 +77,7 @@ class OrderFilter(rest_filters.FilterSet):
|
|||||||
"""Base class for custom API filters for the OrderList endpoint."""
|
"""Base class for custom API filters for the OrderList endpoint."""
|
||||||
|
|
||||||
# Filter against order status
|
# 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):
|
def filter_status(self, queryset, name, value):
|
||||||
"""Filter by integer status code."""
|
"""Filter by integer status code."""
|
||||||
@ -85,11 +85,11 @@ class OrderFilter(rest_filters.FilterSet):
|
|||||||
|
|
||||||
# Exact match for reference
|
# Exact match for reference
|
||||||
reference = rest_filters.CharFilter(
|
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(
|
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):
|
def filter_assigned_to_me(self, queryset, name, value):
|
||||||
@ -113,7 +113,7 @@ class OrderFilter(rest_filters.FilterSet):
|
|||||||
return queryset.exclude(self.Meta.model.overdue_filter())
|
return queryset.exclude(self.Meta.model.overdue_filter())
|
||||||
|
|
||||||
outstanding = rest_filters.BooleanFilter(
|
outstanding = rest_filters.BooleanFilter(
|
||||||
label='outstanding', method='filter_outstanding'
|
label=_('Outstanding'), method='filter_outstanding'
|
||||||
)
|
)
|
||||||
|
|
||||||
def filter_outstanding(self, queryset, name, value):
|
def filter_outstanding(self, queryset, name, value):
|
||||||
@ -123,11 +123,13 @@ class OrderFilter(rest_filters.FilterSet):
|
|||||||
return queryset.exclude(status__in=self.Meta.model.get_status_class().OPEN)
|
return queryset.exclude(status__in=self.Meta.model.get_status_class().OPEN)
|
||||||
|
|
||||||
project_code = rest_filters.ModelChoiceFilter(
|
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(
|
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):
|
def filter_has_project_code(self, queryset, name, value):
|
||||||
@ -137,7 +139,7 @@ class OrderFilter(rest_filters.FilterSet):
|
|||||||
return queryset.filter(project_code=None)
|
return queryset.filter(project_code=None)
|
||||||
|
|
||||||
assigned_to = rest_filters.ModelChoiceFilter(
|
assigned_to = rest_filters.ModelChoiceFilter(
|
||||||
queryset=Owner.objects.all(), field_name='responsible'
|
queryset=Owner.objects.all(), field_name='responsible', label=_('Responsible')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,28 +18,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Construct a dynamic API filter for the "issued by" field
|
// Construct a dynamic API filter for an "owner"
|
||||||
function constructIssuedByFilter() {
|
function constructOwnerFilter(title) {
|
||||||
return {
|
return {
|
||||||
title: '{% trans "Issued By" %}',
|
title: title,
|
||||||
options: function() {
|
options: function() {
|
||||||
let users = {};
|
var ownersList = {};
|
||||||
|
inventreeGet('{% url "api-owner-list" %}', {}, {
|
||||||
inventreeGet('{% url "api-user-list" %}', {}, {
|
|
||||||
async: false,
|
async: false,
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
for (let user of response) {
|
for (var key in response) {
|
||||||
users[user.pk] = {
|
let owner = response[key];
|
||||||
key: user.pk,
|
ownersList[owner.pk] = {
|
||||||
value: user.username
|
key: owner.pk,
|
||||||
|
value: `${owner.name} (${owner.label})`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return ownersList;
|
||||||
return users;
|
},
|
||||||
}
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a dynamic API filter for the "project" field
|
// Construct a dynamic API filter for the "project" field
|
||||||
@ -549,26 +548,8 @@ function getBuildTableFilters() {
|
|||||||
type: 'bool',
|
type: 'bool',
|
||||||
title: '{% trans "Assigned to me" %}',
|
title: '{% trans "Assigned to me" %}',
|
||||||
},
|
},
|
||||||
assigned_to: {
|
assigned_to: constructOwnerFilter('{% trans "Responsible" %}'),
|
||||||
title: '{% trans "Responsible" %}',
|
issued_by: constructOwnerFilter('{% trans "Issued By" %}'),
|
||||||
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(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (global_settings.PROJECT_CODES_ENABLED) {
|
if (global_settings.PROJECT_CODES_ENABLED) {
|
||||||
|
@ -8,11 +8,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useBuildOrderFields } from '../../forms/BuildForms';
|
import { useBuildOrderFields } from '../../forms/BuildForms';
|
||||||
import {
|
import { useOwnerFilters, useProjectCodeFilters } from '../../hooks/UseFilter';
|
||||||
useOwnerFilters,
|
|
||||||
useProjectCodeFilters,
|
|
||||||
useUserFilters
|
|
||||||
} from '../../hooks/UseFilter';
|
|
||||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -103,8 +99,7 @@ export function BuildOrderTable({
|
|||||||
const tableColumns = useMemo(() => buildOrderTableColumns(), []);
|
const tableColumns = useMemo(() => buildOrderTableColumns(), []);
|
||||||
|
|
||||||
const projectCodeFilters = useProjectCodeFilters();
|
const projectCodeFilters = useProjectCodeFilters();
|
||||||
const userFilters = useUserFilters();
|
const ownerFilters = useOwnerFilters();
|
||||||
const responsibleFilters = useOwnerFilters();
|
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@ -147,20 +142,16 @@ export function BuildOrderTable({
|
|||||||
name: 'issued_by',
|
name: 'issued_by',
|
||||||
label: t`Issued By`,
|
label: t`Issued By`,
|
||||||
description: t`Filter by user who issued this order`,
|
description: t`Filter by user who issued this order`,
|
||||||
choices: userFilters.choices
|
choices: ownerFilters.choices
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'assigned_to',
|
name: 'assigned_to',
|
||||||
label: t`Responsible`,
|
label: t`Responsible`,
|
||||||
description: t`Filter by responsible owner`,
|
description: t`Filter by responsible owner`,
|
||||||
choices: responsibleFilters.choices
|
choices: ownerFilters.choices
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [
|
}, [projectCodeFilters.choices, ownerFilters.choices]);
|
||||||
projectCodeFilters.choices,
|
|
||||||
userFilters.choices,
|
|
||||||
responsibleFilters.choices
|
|
||||||
]);
|
|
||||||
|
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user