mirror of
https://github.com/inventree/InvenTree.git
synced 2026-05-17 23:08:28 +00:00
Support physical units for BOM lines (#11631)
* Add new "raw_amount" field to BomItem model * Batch process data migration * Update migration * Calculate 'quantity' from 'raw_amount' field * Improve decimal formatting in migration * Allow raw_amount in serializer * Adjust frontend form * API validation and unit tests * Additional playwright tests * Update API version and CHANGELOG * Updated docs * Fix docstring * Better handling of empty values * Tweak unit tests * Tweak unit test * Fix unit test * Adjust form field text * Adjust migration file * Tweak playwright tests * Fix unit test * Adjust serializers / import-export / playwright * Fix migration * Fix validation * Loosen comparison --------- Co-authored-by: Matthias Mair <code@mjmair.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '../baseFixtures';
|
||||
import {
|
||||
clearTableFilters,
|
||||
@@ -219,6 +220,53 @@ test('Parts - BOM', async ({ browser }) => {
|
||||
await page.getByRole('button', { name: 'Add Substitute' }).waitFor();
|
||||
await page.getByRole('button', { name: 'Close' }).click();
|
||||
|
||||
// Let's try a BOM which has a "raw amount" which considers the units of the underlying part
|
||||
await navigate(page, 'part/109/bom');
|
||||
|
||||
await page.getByRole('button', { name: 'action-button-edit-bom' }).click();
|
||||
|
||||
const paintCell = await page.getByRole('cell', {
|
||||
name: 'Thumbnail Green Paint'
|
||||
});
|
||||
await clickOnRowMenu(paintCell);
|
||||
await page.getByRole('menuitem', { name: 'Edit', exact: true }).click();
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'text-field-raw_amount' })
|
||||
).toHaveValue(/quart/);
|
||||
|
||||
// Try to assign invalid units to this item, which should be rejected by validation
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-raw_amount' })
|
||||
.fill('2 cm');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
await page.getByText('Errors exist for one or more').waitFor();
|
||||
await page.getByText('Could not convert 2 cm to litres').waitFor();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
|
||||
// Create a new BOM item with valid units
|
||||
await page.getByRole('button', { name: 'action-menu-add-bom-items' }).click();
|
||||
await page
|
||||
.getByRole('menuitem', { name: 'action-menu-add-bom-items-add' })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('combobox', { name: 'related-field-sub_part' })
|
||||
.fill('red wire');
|
||||
await page
|
||||
.getByRole('option', { name: 'Thumbnail Silicon Wire 12AWG' })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-reference' })
|
||||
.fill('my-ref');
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-raw_amount' })
|
||||
.fill('3/4 inches');
|
||||
await page.getByRole('switch', { name: 'boolean-field-optional' }).click();
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
// Check for the value converted back to [m]
|
||||
await page.getByRole('cell', { name: '0.01905' }).first().waitFor();
|
||||
await page.getByRole('cell', { name: 'my-ref' }).first().waitFor();
|
||||
// Finish editing the BOM
|
||||
await page
|
||||
.getByRole('button', { name: 'action-button-finish-editing-' })
|
||||
@@ -240,13 +288,15 @@ test('Parts - BOM Validation', async ({ browser }) => {
|
||||
.waitFor();
|
||||
|
||||
// Edit line item, to ensure BOM is not valid
|
||||
const cell = await page.getByRole('cell', { name: 'Thumbnail Red Paint' });
|
||||
const cell = await page.getByRole('cell', { name: 'paint', exact: true });
|
||||
|
||||
// await cell.click({ button: 'right' });
|
||||
// await page.getByRole('button', { name: 'Edit', exact: true }).click();
|
||||
await clickOnRowMenu(cell);
|
||||
await page.getByRole('menuitem', { name: 'Edit', exact: true }).click();
|
||||
|
||||
const input = await page.getByRole('textbox', {
|
||||
name: 'number-field-quantity'
|
||||
name: 'text-field-raw_amount'
|
||||
});
|
||||
|
||||
const value = await input.inputValue();
|
||||
@@ -901,7 +951,7 @@ test('Parts - Parameter Filtering', async ({ browser }) => {
|
||||
test('Parts - Test Results', async ({ browser }) => {
|
||||
const page = await doCachedLogin(browser, { url: '/part/74/test_results' });
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
await page.getByText(/1 - \d+ \/ 1\d\d/).waitFor();
|
||||
await page.getByText('Blue Paint Applied').waitFor();
|
||||
|
||||
Reference in New Issue
Block a user