From 3625b8f14c7057efdfda564f0a0e8b881db62b2c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 20:46:00 +1100 Subject: [PATCH] Use ref pattern on PO duplicate (#9100) (#9147) * use ref pattern on PO duplicate * use ref patterns on duplicate for other types of orders * revert unintentional change to pre-commit * add playwright tests --------- Co-authored-by: Oliver (cherry picked from commit 2cabd02c6b447bed7ec8bccbdcd6115f427a451e) Co-authored-by: Jacob Felknor --- src/frontend/src/pages/build/BuildDetail.tsx | 14 +++++++++---- .../pages/purchasing/PurchaseOrderDetail.tsx | 14 +++++++++---- .../src/pages/sales/ReturnOrderDetail.tsx | 14 +++++++++---- .../src/pages/sales/SalesOrderDetail.tsx | 14 +++++++++---- src/frontend/tests/pages/pui_build.spec.ts | 20 +++++++++++++++++++ .../tests/pages/pui_purchase_order.spec.ts | 20 +++++++++++++++++++ .../tests/pages/pui_sales_order.spec.ts | 20 +++++++++++++++++++ 7 files changed, 100 insertions(+), 16 deletions(-) diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index a2de259fdc..c0934fba20 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -362,14 +362,20 @@ export default function BuildDetail() { onFormSuccess: refreshInstance }); + const duplicateBuildOrderInitialData = useMemo(() => { + const data = { ...build }; + // if we set the reference to null/undefined, it will be left blank in the form + // if we omit the reference altogether, it will be auto-generated via reference pattern + // from the OPTIONS response + delete data.reference; + return data; + }, [build]); + const duplicateBuild = useCreateApiFormModal({ url: ApiEndpoints.build_order_list, title: t`Add Build Order`, fields: buildOrderFields, - initialData: { - ...build, - reference: undefined - }, + initialData: duplicateBuildOrderInitialData, follow: true, modelType: ModelType.build }); diff --git a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx index 74b0727346..4de604ba00 100644 --- a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx +++ b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx @@ -94,14 +94,20 @@ export default function PurchaseOrderDetail() { } }); + const duplicatePurchaseOrderInitialData = useMemo(() => { + const data = { ...order }; + // if we set the reference to null/undefined, it will be left blank in the form + // if we omit the reference altogether, it will be auto-generated via reference pattern + // from the OPTIONS response + delete data.reference; + return data; + }, [order]); + const duplicatePurchaseOrder = useCreateApiFormModal({ url: ApiEndpoints.purchase_order_list, title: t`Add Purchase Order`, fields: duplicatePurchaseOrderFields, - initialData: { - ...order, - reference: undefined - }, + initialData: duplicatePurchaseOrderInitialData, follow: true, modelType: ModelType.purchaseorder }); diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index bd68d5d3e9..b4202be69d 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -329,14 +329,20 @@ export default function ReturnOrderDetail() { } }); + const duplicateReturnOrderInitialData = useMemo(() => { + const data = { ...order }; + // if we set the reference to null/undefined, it will be left blank in the form + // if we omit the reference altogether, it will be auto-generated via reference pattern + // from the OPTIONS response + delete data.reference; + return data; + }, [order]); + const duplicateReturnOrder = useCreateApiFormModal({ url: ApiEndpoints.return_order_list, title: t`Add Return Order`, fields: duplicateReturnOrderFields, - initialData: { - ...order, - reference: undefined - }, + initialData: duplicateReturnOrderInitialData, modelType: ModelType.returnorder, follow: true }); diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx index 7964094520..9bb246d381 100644 --- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx @@ -272,14 +272,20 @@ export default function SalesOrderDetail() { duplicateOrderId: order.pk }); + const duplicateSalesOrderInitialData = useMemo(() => { + const data = { ...order }; + // if we set the reference to null/undefined, it will be left blank in the form + // if we omit the reference altogether, it will be auto-generated via reference pattern + // from the OPTIONS response + delete data.reference; + return data; + }, [order]); + const duplicateSalesOrder = useCreateApiFormModal({ url: ApiEndpoints.sales_order_list, title: t`Add Sales Order`, fields: duplicateOrderFields, - initialData: { - ...order, - reference: undefined - }, + initialData: duplicateSalesOrderInitialData, follow: true, modelType: ModelType.salesorder }); diff --git a/src/frontend/tests/pages/pui_build.spec.ts b/src/frontend/tests/pages/pui_build.spec.ts index 2d0bf5558a..f5f4aee2b4 100644 --- a/src/frontend/tests/pages/pui_build.spec.ts +++ b/src/frontend/tests/pages/pui_build.spec.ts @@ -1,3 +1,4 @@ +import { expect } from '@playwright/test'; import { test } from '../baseFixtures.ts'; import { baseUrl } from '../defaults.ts'; import { @@ -271,3 +272,22 @@ test('Build Order - Filters', async ({ page }) => { await page.waitForTimeout(2500); }); + +test('Build Order - Duplicate', async ({ page }) => { + await doQuickLogin(page); + + await navigate(page, 'manufacturing/build-order/24/details'); + await page.getByLabel('action-menu-build-order-').click(); + await page.getByLabel('action-menu-build-order-actions-duplicate').click(); + + // Ensure a new reference is suggested + await expect(page.getByLabel('text-field-reference')).not.toBeEmpty(); + + // Submit the duplicate request and ensure it completes + await page.getByRole('button', { name: 'Submit' }).isEnabled(); + await page.getByRole('button', { name: 'Submit' }).click(); + await page.getByRole('tab', { name: 'Build Details' }).waitFor(); + await page.getByRole('tab', { name: 'Build Details' }).click(); + + await page.getByText('Pending').first().waitFor(); +}); diff --git a/src/frontend/tests/pages/pui_purchase_order.spec.ts b/src/frontend/tests/pages/pui_purchase_order.spec.ts index 90d753c7dc..b2a09521cc 100644 --- a/src/frontend/tests/pages/pui_purchase_order.spec.ts +++ b/src/frontend/tests/pages/pui_purchase_order.spec.ts @@ -1,3 +1,4 @@ +import { expect } from '@playwright/test'; import { test } from '../baseFixtures.ts'; import { baseUrl } from '../defaults.ts'; import { clickButtonIfVisible, openFilterDrawer } from '../helpers.ts'; @@ -186,3 +187,22 @@ test('Purchase Orders - Receive Items', async ({ page }) => { await page.getByRole('button', { name: 'Cancel' }).click(); }); + +test('Purchase Orders - Duplicate', async ({ page }) => { + await doQuickLogin(page); + + await navigate(page, 'purchasing/purchase-order/13/detail'); + await page.getByLabel('action-menu-order-actions').click(); + await page.getByLabel('action-menu-order-actions-duplicate').click(); + + // Ensure a new reference is suggested + await expect(page.getByLabel('text-field-reference')).not.toBeEmpty(); + + // Submit the duplicate request and ensure it completes + await page.getByRole('button', { name: 'Submit' }).isEnabled(); + await page.getByRole('button', { name: 'Submit' }).click(); + await page.getByRole('tab', { name: 'Order Details' }).waitFor(); + await page.getByRole('tab', { name: 'Order Details' }).click(); + + await page.getByText('Pending').first().waitFor(); +}); diff --git a/src/frontend/tests/pages/pui_sales_order.spec.ts b/src/frontend/tests/pages/pui_sales_order.spec.ts index fb1ebe2355..d8a65149ac 100644 --- a/src/frontend/tests/pages/pui_sales_order.spec.ts +++ b/src/frontend/tests/pages/pui_sales_order.spec.ts @@ -1,3 +1,4 @@ +import { expect } from '@playwright/test'; import { test } from '../baseFixtures.ts'; import { baseUrl } from '../defaults.ts'; import { clearTableFilters, setTableChoiceFilter } from '../helpers.ts'; @@ -149,3 +150,22 @@ test('Purchase Orders', async ({ page }) => { await page.getByRole('button', { name: 'Issue Order' }).waitFor(); }); + +test('Sales Orders - Duplicate', async ({ page }) => { + await doQuickLogin(page); + + await navigate(page, 'sales/sales-order/11/detail'); + await page.getByLabel('action-menu-order-actions').click(); + await page.getByLabel('action-menu-order-actions-duplicate').click(); + + // Ensure a new reference is suggested + await expect(page.getByLabel('text-field-reference')).not.toBeEmpty(); + + // Submit the duplicate request and ensure it completes + await page.getByRole('button', { name: 'Submit' }).isEnabled(); + await page.getByRole('button', { name: 'Submit' }).click(); + await page.getByRole('tab', { name: 'Order Details' }).waitFor(); + await page.getByRole('tab', { name: 'Order Details' }).click(); + + await page.getByText('Pending').first().waitFor(); +});