mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-17 09:48:30 +00:00
[UI] Suggested pricing (#10867)
* Refactor NumberField into separate component * Add helper func to ensure a number is a number * Use placeholder value for suggested sale price * Fix for auto-fill * Tweak price calculation * Add UI testing for sales order price breaks * Fix aria label name * Annotate price breaks to supplier part * Fetch price break data * Support price breaks for purchase order pricing * Fix required to prevent circular imports * Add playwright tests for purchase order price breaks * Bump API version * Re-add output options for SupplierPriceBreakList * Revert change * Simplify unit test
This commit is contained in:
@@ -253,7 +253,7 @@ test('Build Order - Build Outputs', async ({ browser }) => {
|
||||
|
||||
// Accept the suggested batch code
|
||||
await page
|
||||
.getByRole('img', { name: 'text-field-batch_code-accept-placeholder' })
|
||||
.getByRole('img', { name: 'field-batch_code-accept-placeholder' })
|
||||
.click();
|
||||
|
||||
await page.getByLabel('related-field-location').click();
|
||||
|
||||
@@ -514,10 +514,13 @@ test('Parts - Parameters', async ({ browser }) => {
|
||||
// Submit with "false" value
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
const cell = await page.getByRole('cell', {
|
||||
name: 'Is this part polarized?'
|
||||
});
|
||||
|
||||
// Check for the expected values in the table
|
||||
let row = await getRowFromCell(
|
||||
await page.getByRole('cell', { name: 'Polarized', exact: true })
|
||||
);
|
||||
const row = await getRowFromCell(cell);
|
||||
|
||||
await row.getByRole('cell', { name: 'No', exact: true }).waitFor();
|
||||
await row.getByRole('cell', { name: 'allaccess' }).waitFor();
|
||||
await row.getByLabel(/row-action-menu-/i).click();
|
||||
@@ -532,13 +535,6 @@ test('Parts - Parameters', async ({ browser }) => {
|
||||
.click();
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
row = await getRowFromCell(
|
||||
await page.getByRole('cell', { name: 'Polarized', exact: true })
|
||||
);
|
||||
await row.getByRole('cell', { name: 'Yes', exact: true }).waitFor();
|
||||
|
||||
await page.getByText('1 - 1 / 1').waitFor();
|
||||
|
||||
// Finally, delete the parameter
|
||||
await row.getByLabel(/row-action-menu-/i).click();
|
||||
await page.getByRole('menuitem', { name: 'Delete' }).click();
|
||||
|
||||
@@ -216,6 +216,44 @@ test('Purchase Orders - Filters', async ({ browser }) => {
|
||||
await page.getByRole('option', { name: 'Target Date After' }).waitFor();
|
||||
});
|
||||
|
||||
test('Purchase Orders - Price Breaks', async ({ browser }) => {
|
||||
const page = await doCachedLogin(browser, {
|
||||
url: 'purchasing/purchase-order/14/line-items'
|
||||
});
|
||||
|
||||
await page
|
||||
.getByRole('button', { name: 'action-button-add-line-item' })
|
||||
.click();
|
||||
await page.getByLabel('related-field-part').fill('002.01');
|
||||
await page.getByRole('option', { name: 'PCBWOY PCB-002.01' }).click();
|
||||
|
||||
// Expected price-break values
|
||||
const priceBreaks = {
|
||||
1: 500,
|
||||
8: 500,
|
||||
10: 565,
|
||||
99: 565,
|
||||
999: 205
|
||||
};
|
||||
|
||||
for (const [qty, expectedPrice] of Object.entries(priceBreaks)) {
|
||||
await page.getByLabel('number-field-quantity').fill(qty);
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'number-field-purchase_price' })
|
||||
).toHaveAttribute('placeholder', expectedPrice.toString(), {
|
||||
timeout: 500
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-fill the suggested sale price
|
||||
await page.getByLabel('field-purchase_price-accept-placeholder').click();
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'number-field-purchase_price' })
|
||||
).toHaveValue('205', { timeout: 500 });
|
||||
});
|
||||
|
||||
test('Purchase Orders - Order Parts', async ({ browser }) => {
|
||||
const page = await doCachedLogin(browser);
|
||||
|
||||
|
||||
@@ -279,3 +279,45 @@ test('Sales Orders - Duplicate', async ({ browser }) => {
|
||||
await page.getByText('Complete').first().waitFor();
|
||||
await page.getByText('2 / 2').waitFor();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test auto-calculation of price breaks on sales order line items
|
||||
*/
|
||||
test('Sales Orders - Price Breaks', async ({ browser }) => {
|
||||
const page = await doCachedLogin(browser, {
|
||||
url: 'sales/sales-order/14/line-items'
|
||||
});
|
||||
|
||||
await page
|
||||
.getByRole('button', { name: 'action-button-add-line-item' })
|
||||
.click();
|
||||
await page.getByLabel('related-field-part').fill('software');
|
||||
await page.getByRole('option', { name: 'Software License' }).click();
|
||||
|
||||
const priceBreaks = {
|
||||
1: 123,
|
||||
2: 123,
|
||||
10: 104,
|
||||
49: 104,
|
||||
56: 96,
|
||||
104: 78
|
||||
};
|
||||
|
||||
for (const [qty, expectedPrice] of Object.entries(priceBreaks)) {
|
||||
await page.getByLabel('number-field-quantity').fill(qty);
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'number-field-sale_price' })
|
||||
).toHaveAttribute('placeholder', expectedPrice.toString(), {
|
||||
timeout: 500
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-fill the suggested sale price
|
||||
await page.getByLabel('field-sale_price-accept-placeholder').click();
|
||||
|
||||
// The sale price field should now contain the suggested value
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'number-field-sale_price' })
|
||||
).toHaveValue('78', { timeout: 500 });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user