diff --git a/src/frontend/src/tables/build/BuildLineTable.tsx b/src/frontend/src/tables/build/BuildLineTable.tsx index 2e0a07a18ab3..5c0a96396b4b 100644 --- a/src/frontend/src/tables/build/BuildLineTable.tsx +++ b/src/frontend/src/tables/build/BuildLineTable.tsx @@ -1,3 +1,14 @@ +import { ActionButton } from '@lib/components/ActionButton'; +import { ProgressBar } from '@lib/components/ProgressBar'; +import { RowEditAction, RowViewAction } from '@lib/components/RowActions'; +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 { formatDecimal } from '@lib/functions/Formatting'; +import useTable from '@lib/hooks/UseTable'; +import type { TableFilter } from '@lib/types/Filters'; +import type { RowAction, TableColumn } from '@lib/types/Tables'; import { t } from '@lingui/core/macro'; import { Alert, Group, Paper, Text } from '@mantine/core'; import { @@ -13,18 +24,6 @@ import { import type { DataTableRowExpansionProps } from 'mantine-datatable'; import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; - -import { ActionButton } from '@lib/components/ActionButton'; -import { ProgressBar } from '@lib/components/ProgressBar'; -import { RowEditAction, RowViewAction } from '@lib/components/RowActions'; -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 { formatDecimal } from '@lib/functions/Formatting'; -import useTable from '@lib/hooks/UseTable'; -import type { TableFilter } from '@lib/types/Filters'; -import type { RowAction, TableColumn } from '@lib/types/Tables'; import OrderPartsWizard from '../../components/wizards/OrderPartsWizard'; import { useAllocateStockToBuildForm, @@ -736,7 +735,9 @@ export default function BuildLineTable({ !consumable && user.hasChangeRole(UserRoles.build) && required > 0 && - record.trackable == hasOutput; + (hasOutput ? trackable : true); + + const disableAllocation = !hasOutput && trackable; // Can de-allocate const canDeallocate = @@ -759,6 +760,10 @@ export default function BuildLineTable({ icon: , title: t`Allocate Stock`, hidden: !canAllocate, + disabled: disableAllocation, + tooltip: disableAllocation + ? t`Trackable parts must be allocated via the Build Outputs tab` + : t`Allocate Stock`, color: 'green', onClick: () => { setSelectedRows([record]); diff --git a/src/frontend/tests/pages/pui_build.spec.ts b/src/frontend/tests/pages/pui_build.spec.ts index bdc9cb34a95a..43a67902cfcb 100644 --- a/src/frontend/tests/pages/pui_build.spec.ts +++ b/src/frontend/tests/pages/pui_build.spec.ts @@ -349,6 +349,27 @@ test('Build Order - Allocation', async ({ browser }) => { await row.getByText(/150 \/ 150/).waitFor(); + // Trackable components cannot be allocated from the main line-item table + const mainRedWidget = await page.getByRole('cell', { name: 'Red Widget' }); + const mainRedRow = await getRowFromCell(mainRedWidget); + + await mainRedRow.getByLabel(/row-action-menu-/i).click(); + + const mainAllocateStockBtn = page.getByRole('menuitem', { + name: 'Allocate Stock', + exact: true + }); + await expect(mainAllocateStockBtn).toBeDisabled(); + + await mainAllocateStockBtn.hover(); + await expect( + page.getByText( + 'Trackable parts must be allocated via the Build Outputs tab' + ) + ).toBeVisible(); + + await page.keyboard.press('Escape'); + // Expand this row await cell.click(); await page.getByRole('cell', { name: '2022-4-27', exact: true }).waitFor(); @@ -425,9 +446,13 @@ test('Build Order - Allocation', async ({ browser }) => { const redRow = await getRowFromCell(redWidget); await redRow.getByLabel(/row-action-menu-/i).click(); - await page - .getByRole('menuitem', { name: 'Allocate Stock', exact: true }) - .waitFor(); + + const allocateStockBtn = page.getByRole('menuitem', { + name: 'Allocate Stock', + exact: true + }); + await expect(allocateStockBtn).toBeEnabled(); + await page .getByRole('menuitem', { name: 'Deallocate Stock', exact: true }) .waitFor();