Allow bulk-edit for ReturnOrderLineItem (#12635)

* Allow bulk-edit for ReturnOrderLineItem

- Allow bulk change of line item outcome

* Update API version documentation with pull request links
This commit is contained in:
Oliver
2026-08-13 20:10:10 +10:00
committed by GitHub
parent 695b9c1dc2
commit 9844a4805e
4 changed files with 71 additions and 3 deletions
@@ -1,11 +1,14 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 530
INVENTREE_API_VERSION = 531
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v531 -> 2026-08-13 : https://github.com/inventree/InvenTree/pull/12635
- Adds "bulk update" support for the ReturnOrderLineItem API endpoint
v530 -> 2026-07-28 : https://github.com/inventree/InvenTree/pull/12487
- Adds searching against ReportSnippet API endpoint
+1
View File
@@ -1793,6 +1793,7 @@ class ReturnOrderLineItemOutputOptions(OutputConfiguration):
class ReturnOrderLineItemList(
ReturnOrderLineItemMixin,
BulkUpdateMixin,
DataExportViewMixin,
OutputOptionsMixin,
ListCreateDestroyAPIView,
+36
View File
@@ -3716,6 +3716,42 @@ class ReturnOrderLineItemTests(InvenTreeAPITestCase):
self.assertEqual(models.ReturnOrderLineItem.objects.count(), n - 1)
def test_bulk_update(self):
"""Test that we can bulk update the 'outcome' field for multiple ReturnOrderLineItems via the API."""
ro = models.ReturnOrder.objects.get(pk=6)
# Create some extra line items against the same order, so we have multiple to update
models.ReturnOrderLineItem.objects.bulk_create([
models.ReturnOrderLineItem(order=ro, item_id=1006, quantity=1),
models.ReturnOrderLineItem(order=ro, item_id=1007, quantity=1),
])
items = list(
models.ReturnOrderLineItem.objects.filter(order=ro).values_list(
'pk', flat=True
)
)
self.assertEqual(len(items), 3)
for line in models.ReturnOrderLineItem.objects.filter(pk__in=items):
self.assertEqual(line.outcome, ReturnOrderLineStatus.PENDING)
url = reverse('api-return-order-line-list')
data = {'items': items, 'outcome': ReturnOrderLineStatus.REPAIR.value}
# Update should fail without the correct role
self.patch(url, data, expected_code=403)
self.assignRole('return_order.change')
response = self.patch(url, data, expected_code=200).data
self.assertEqual(len(response['items']), 3)
for line in models.ReturnOrderLineItem.objects.filter(pk__in=items):
self.assertEqual(line.outcome, ReturnOrderLineStatus.REPAIR.value)
def test_extra_line_bulk_delete(self):
"""Test that we can bulk delete multiple ReturnOrderExtraLine items via the API."""
ro = models.ReturnOrder.objects.first()
@@ -1,5 +1,5 @@
import { t } from '@lingui/core/macro';
import { IconSquareArrowRight } from '@tabler/icons-react';
import { IconFlag, IconSquareArrowRight } from '@tabler/icons-react';
import { useCallback, useMemo, useState } from 'react';
import { ActionButton } from '@lib/components/ActionButton';
@@ -16,6 +16,7 @@ import { apiUrl } from '@lib/functions/Api';
import useTable from '@lib/hooks/UseTable';
import type { TableFilter } from '@lib/types/Filters';
import type { TableColumn } from '@lib/types/Tables';
import { Alert } from '@mantine/core';
import {
DateColumn,
DescriptionColumn,
@@ -37,6 +38,7 @@ import {
useReturnOrderLineItemFields
} from '../../forms/ReturnOrderForms';
import {
useBulkEditApiFormModal,
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
@@ -110,6 +112,21 @@ export default function ReturnOrderLineItemTable({
table: table
});
const setOutcome = useBulkEditApiFormModal({
url: ApiEndpoints.return_order_line_list,
items: table.selectedIds,
title: t`Set Outcome`,
preFormContent: (
<Alert color='blue'>
{t`Adjust the outcome for the selected line items.`}
</Alert>
),
fields: {
outcome: {}
},
onFormSuccess: table.refreshTable
});
const tableColumns: TableColumn[] = useMemo(() => {
return [
LineItemColumn({}),
@@ -211,6 +228,16 @@ export default function ReturnOrderLineItemTable({
receiveLineItems.open();
}}
disabled={table.selectedRecords.length == 0}
/>,
<ActionButton
key='set-outcome'
tooltip={t`Set outcome for selected items`}
icon={<IconFlag />}
hidden={!editable || !user.hasChangeRole(UserRoles.return_order)}
onClick={() => {
setOutcome.open();
}}
disabled={table.selectedRecords.length == 0}
/>
];
}, [user, editable, inProgress, orderId, table.selectedRecords]);
@@ -266,6 +293,7 @@ export default function ReturnOrderLineItemTable({
{editLine.modal}
{deleteLine.modal}
{receiveLineItems.modal}
{setOutcome.modal}
<InvenTreeTable
url={apiUrl(ApiEndpoints.return_order_line_list)}
tableState={table}
@@ -279,7 +307,7 @@ export default function ReturnOrderLineItemTable({
},
defaultSortColumn: 'line',
enableSelection:
inProgress && user.hasChangeRole(UserRoles.return_order),
editable && user.hasChangeRole(UserRoles.return_order),
enableBulkDelete:
editable && user.hasDeleteRole(UserRoles.return_order),
afterBulkDelete: orderDetailRefresh,