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:
@ -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();
|
||||
});
|
||||
|
@ -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;
|
||||
});
|
||||
|
Reference in New Issue
Block a user