2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-11-14 03:46:44 +00:00

Build order consume (#8191)

* Adds "consumed" field to BuildLine model

* Expose new field to serializer

* Add "consumed" column to BuildLineTable

* Boolean column tweaks

* Increase consumed count when completing allocation

* Add comment

* Update migration

* Add serializer for consuming build items

* Improve build-line sub-table

* Refactor BuildItem.complete_allocation method

- Allow optional quantity to be specified
- Adjust the allocated quantity when consuming

* Perform consumption

* Add "BuildConsume" API endpoint

* Implement frontend form

* Fixes for serializer

* Enhance front-end form

* Fix rendering of BuildLineTable

* Further improve rendering

* Bump API version

* Update API description

* Add option to consume by specifying a list of BuildLine objects

* Add form to consume stock via BuildLine reference

* Fix api_version

* Fix backup colors

* Fix typo

* Fix migrations

* Fix build forms

* Forms fixes

* Fix formatting

* Fixes for BuildLineTable

* Account for consumed stock in requirements calculation

* Reduce API requirements for BuildLineTable

* Docs updates

* Updated playwright testing

* Update src/frontend/src/forms/BuildForms.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/frontend/src/tables/build/BuildLineTable.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Add unit test for filters

* Add functional tests

* Tweak query count

* Increase max query time for testing

* adjust unit test again

* Prevent consumption of "tracked" items

* Adjust playwright tests

* Fix table

* Fix rendering

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Oliver
2025-08-19 17:03:19 +10:00
committed by GitHub
parent ce6ffdac18
commit 49cc5fb137
24 changed files with 1079 additions and 142 deletions

View File

@@ -10,8 +10,11 @@ import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { ModelType } from '@lib/enums/ModelType';
import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api';
import { ActionButton } from '@lib/index';
import type { TableFilter } from '@lib/types/Filters';
import type { TableColumn } from '@lib/types/Tables';
import { IconCircleDashedCheck } from '@tabler/icons-react';
import { useConsumeBuildItemsForm } from '../../forms/BuildForms';
import type { StockOperationProps } from '../../forms/StockForms';
import {
useDeleteApiFormModal,
@@ -160,10 +163,10 @@ export default function BuildAllocatedStockTable({
];
}, []);
const [selectedItem, setSelectedItem] = useState<number>(0);
const [selectedItemId, setSelectedItemId] = useState<number>(0);
const editItem = useEditApiFormModal({
pk: selectedItem,
pk: selectedItemId,
url: ApiEndpoints.build_item_list,
title: t`Edit Stock Allocation`,
fields: {
@@ -176,12 +179,23 @@ export default function BuildAllocatedStockTable({
});
const deleteItem = useDeleteApiFormModal({
pk: selectedItem,
pk: selectedItemId,
url: ApiEndpoints.build_item_list,
title: t`Delete Stock Allocation`,
table: table
});
const [selectedItems, setSelectedItems] = useState<any[]>([]);
const consumeStock = useConsumeBuildItemsForm({
buildId: buildId ?? 0,
allocatedItems: selectedItems,
onFormSuccess: () => {
table.clearSelectedRecords();
table.refreshTable();
}
});
const stockOperationProps: StockOperationProps = useMemo(() => {
// Extract stock items from the selected records
// Note that the table is actually a list of BuildItem instances,
@@ -216,17 +230,28 @@ export default function BuildAllocatedStockTable({
const rowActions = useCallback(
(record: any): RowAction[] => {
return [
{
color: 'green',
icon: <IconCircleDashedCheck />,
title: t`Consume`,
tooltip: t`Consume Stock`,
hidden: !user.hasChangeRole(UserRoles.build),
onClick: () => {
setSelectedItems([record]);
consumeStock.open();
}
},
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.build),
onClick: () => {
setSelectedItem(record.pk);
setSelectedItemId(record.pk);
editItem.open();
}
}),
RowDeleteAction({
hidden: !user.hasDeleteRole(UserRoles.build),
onClick: () => {
setSelectedItem(record.pk);
setSelectedItemId(record.pk);
deleteItem.open();
}
})
@@ -236,13 +261,28 @@ export default function BuildAllocatedStockTable({
);
const tableActions = useMemo(() => {
return [stockAdjustActions.dropdown];
}, [stockAdjustActions.dropdown]);
return [
stockAdjustActions.dropdown,
<ActionButton
key='consume-stock'
icon={<IconCircleDashedCheck />}
tooltip={t`Consume Stock`}
hidden={!user.hasChangeRole(UserRoles.build)}
disabled={table.selectedRecords.length == 0}
color='green'
onClick={() => {
setSelectedItems(table.selectedRecords);
consumeStock.open();
}}
/>
];
}, [user, table.selectedRecords, stockAdjustActions.dropdown]);
return (
<>
{editItem.modal}
{deleteItem.modal}
{consumeStock.modal}
{stockAdjustActions.modals.map((modal) => modal.modal)}
<InvenTreeTable
tableState={table}