2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-27 01:00:53 +00:00

[Refactor] Custom states (#8438)

* Enhancements for "custom state" form

- More intuitive form actions

* Improve back-end validation

* Improve table rendering

* Fix lookup for useStatusCodes

* Fix status display for SockDetail page

* Fix SalesOrder status display

* Refactor get_custom_classes

- Add StatusCode.custom_values method

* Fix for status table filters

* Cleanup (and note to self)

* Include custom state values in specific API endpoints

* Add serializer class definition

* Use same serializer for AllStatusView

* Fix API to match existing frontend type StatusCodeListInterface

* Enable filtering by reference status type

* Add option to duplicate an existing custom state

* Improved validation for the InvenTreeCustomUserStateModel class

* Code cleanup

* Fix default value in StockOperationsRow

* Use custom status values in stock operations

* Allow custom values

* Fix migration

* Bump API version

* Fix filtering of stock items by "status"

* Enhance status filter for orders

* Fix status code rendering

* Build Order API filter

* Update playwright tests for build filters

* Additional playwright tests for stock table filters

* Add 'custom' attribute

* Fix unit tests

* Add custom state field validation

* Implement StatusCodeMixin for setting status code values

* Clear out 'custom key' if the base key does not match

* Updated playwright testing

* Remove timeout

* Refactor detail pages which display status

* Update old migrations - add field validator

* Remove dead code

* Simplify API query filtering

* Revert "Simplify API query filtering"

This reverts commit 06c858ae7c.

* Fix save method

* Unit test fixes

* Fix for ReturnOrderLineItem

* Reorganize code

* Adjust unit test
This commit is contained in:
Oliver
2024-12-29 08:45:23 +11:00
committed by GitHub
parent c582ca0afd
commit 964984ccac
42 changed files with 916 additions and 262 deletions

View File

@ -1,9 +1,9 @@
import { test } from '../baseFixtures.ts';
import { baseUrl } from '../defaults.ts';
import {
clickButtonIfVisible,
clearTableFilters,
getRowFromCell,
openFilterDrawer
setTableChoiceFilter
} from '../helpers.ts';
import { doQuickLogin } from '../login.ts';
@ -266,6 +266,24 @@ test('Build Order - Filters', async ({ page }) => {
await page.goto(`${baseUrl}/manufacturing/index/buildorders`);
await openFilterDrawer(page);
await clickButtonIfVisible(page, 'Clear Filters');
await clearTableFilters(page);
await page.getByText('1 - 24 / 24').waitFor();
// Toggle 'Outstanding' filter
await setTableChoiceFilter(page, 'Outstanding', 'Yes');
await page.getByText('1 - 18 / 18').waitFor();
await clearTableFilters(page);
await setTableChoiceFilter(page, 'Outstanding', 'No');
await page.getByText('1 - 6 / 6').waitFor();
await clearTableFilters(page);
// Filter by custom status code
await setTableChoiceFilter(page, 'Status', 'Pending Approval');
// Single result - navigate through to the build order
await page.getByText('1 - 1 / 1').waitFor();
await page.getByRole('cell', { name: 'BO0023' }).click();
await page.getByText('On Hold').first().waitFor();
await page.getByText('Pending Approval').first().waitFor();
});

View File

@ -1,6 +1,11 @@
import { test } from '../baseFixtures.js';
import { baseUrl } from '../defaults.js';
import { clickButtonIfVisible, openFilterDrawer } from '../helpers.js';
import {
clearTableFilters,
clickButtonIfVisible,
openFilterDrawer,
setTableChoiceFilter
} from '../helpers.js';
import { doQuickLogin } from '../login.js';
test('Stock - Basic Tests', async ({ page }) => {
@ -84,9 +89,15 @@ test('Stock - Filters', async ({ page }) => {
.getByRole('cell', { name: 'A round table - with blue paint' })
.waitFor();
// Clear filters (ready for next set of tests)
await openFilterDrawer(page);
await clickButtonIfVisible(page, 'Clear Filters');
// Filter by custom status code
await clearTableFilters(page);
await setTableChoiceFilter(page, 'Status', 'Incoming goods inspection');
await page.getByText('1 - 8 / 8').waitFor();
await page.getByRole('cell', { name: '1551AGY' }).first().waitFor();
await page.getByRole('cell', { name: 'widget.blue' }).first().waitFor();
await page.getByRole('cell', { name: '002.01-PCBA' }).first().waitFor();
await clearTableFilters(page);
});
test('Stock - Serial Numbers', async ({ page }) => {
@ -158,47 +169,58 @@ test('Stock - Serial Numbers', async ({ page }) => {
test('Stock - Stock Actions', async ({ page }) => {
await doQuickLogin(page);
// Find an in-stock, untracked item
await page.goto(
`${baseUrl}/stock/location/index/stock-items?in_stock=1&serialized=0`
);
await page.getByText('530470210').first().click();
await page.goto(`${baseUrl}/stock/item/1225/details`);
// Helper function to launch a stock action
const launchStockAction = async (action: string) => {
await page.getByLabel('action-menu-stock-operations').click();
await page.getByLabel(`action-menu-stock-operations-${action}`).click();
};
const setStockStatus = async (status: string) => {
await page.getByLabel('action-button-change-status').click();
await page.getByLabel('choice-field-status').click();
await page.getByRole('option', { name: status }).click();
};
// Check for required values
await page.getByText('Status', { exact: true }).waitFor();
await page.getByText('Custom Status', { exact: true }).waitFor();
await page.getByText('Attention needed').waitFor();
await page
.locator('div')
.filter({ hasText: /^Quantity: 270$/ })
.first()
.getByLabel('Stock Details')
.getByText('Incoming goods inspection')
.waitFor();
await page.getByText('123').first().waitFor();
// Check for expected action sections
await page.getByLabel('action-menu-barcode-actions').click();
await page.getByLabel('action-menu-barcode-actions-link-barcode').click();
await page.getByRole('banner').getByRole('button').click();
await page.getByLabel('action-menu-printing-actions').click();
await page.getByLabel('action-menu-printing-actions-print-labels').click();
await page.getByRole('button', { name: 'Cancel' }).click();
await page.getByLabel('action-menu-stock-operations').click();
await page.getByLabel('action-menu-stock-operations-count').waitFor();
await page.getByLabel('action-menu-stock-operations-add').waitFor();
await page.getByLabel('action-menu-stock-operations-remove').waitFor();
await page.getByLabel('action-menu-stock-operations-transfer').click();
await page.getByLabel('text-field-notes').fill('test notes');
// Add stock, and change status
await launchStockAction('add');
await page.getByLabel('number-field-quantity').fill('12');
await setStockStatus('Lost');
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByText('This field is required.').first().waitFor();
// Set the status field
await page.getByLabel('action-button-change-status').click();
await page.getByLabel('choice-field-status').click();
await page.getByText('Attention needed').click();
await page.getByText('Lost').first().waitFor();
await page.getByText('Unavailable').first().waitFor();
await page.getByText('135').first().waitFor();
// Set the packaging field
await page.getByLabel('action-button-adjust-packaging').click();
await page.getByLabel('text-field-packaging').fill('test packaging');
// Remove stock, and change status
await launchStockAction('remove');
await page.getByLabel('number-field-quantity').fill('99');
await setStockStatus('Damaged');
await page.getByRole('button', { name: 'Submit' }).click();
// Close the dialog
await page.getByRole('button', { name: 'Cancel' }).click();
await page.getByText('36').first().waitFor();
await page.getByText('Damaged').first().waitFor();
// Count stock and change status (reverting to original value)
await launchStockAction('count');
await page.getByLabel('number-field-quantity').fill('123');
await setStockStatus('Incoming goods inspection');
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByText('123').first().waitFor();
await page.getByText('Custom Status').first().waitFor();
await page.getByText('Incoming goods inspection').first().waitFor();
// Find an item which has been sent to a customer
await page.goto(`${baseUrl}/stock/item/1014/details`);
@ -220,7 +242,4 @@ test('Stock - Tracking', async ({ page }) => {
await page.getByText('- - Factory/Office Block/Room').first().waitFor();
await page.getByRole('link', { name: 'Widget Assembly' }).waitFor();
await page.getByRole('cell', { name: 'Installed into assembly' }).waitFor();
await page.waitForTimeout(1500);
return;
});