From 9943384156a6cfbab869cf7d2d23f779d7caf316 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 13 Nov 2024 02:05:20 +0000 Subject: [PATCH 1/8] Fix for "installed in" display - Allow "details" field to be passed custom params --- src/frontend/src/components/details/Details.tsx | 5 ++++- src/frontend/src/pages/stock/StockDetail.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx index 1e9aceaad7fb..e1cc70e3d49c 100644 --- a/src/frontend/src/components/details/Details.tsx +++ b/src/frontend/src/components/details/Details.tsx @@ -67,6 +67,7 @@ type InternalLinkField = { model: ModelType; model_field?: string; model_formatter?: (value: any) => string; + model_filters?: any; backup_value?: string; }; @@ -234,7 +235,9 @@ function TableAnchorValue(props: Readonly) { const url = apiUrl(modelDef.api_endpoint, props.field_value); return api - .get(url) + .get(url, { + params: props.field_data.model_filters ?? undefined + }) .then((response) => { switch (response.status) { case 200: diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index af474ccfe92f..84e04491628a 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -211,10 +211,13 @@ export default function StockDetail() { type: 'link', name: 'belongs_to', label: t`Installed In`, + model_filters: { + part_detail: true + }, model_formatter: (model: any) => { let text = model?.part_detail?.full_name ?? model?.name; if (model.serial && model.quantity == 1) { - text += `# ${model.serial}`; + text += ` # ${model.serial}`; } return text; From 54da2f08b266e33b48e5cfacd39ddab8cd60ebc7 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 13 Nov 2024 02:25:53 +0000 Subject: [PATCH 2/8] Add extra debug to link checking --- docs/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/main.py b/docs/main.py index 84b91f7ad8c1..b65d99637a84 100644 --- a/docs/main.py +++ b/docs/main.py @@ -53,6 +53,8 @@ def check_link(url) -> bool: if url in cache: return True + print(f'Checking external URL: {url}') + attempts = 5 while attempts > 0: @@ -66,6 +68,8 @@ def check_link(url) -> bool: attempts -= 1 + print(f' - URL check failed with status code {response.status_code}') + return False From 9903ecb460cba0b474fbd855b3edeb84fea1f749 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 13 Nov 2024 04:25:30 +0000 Subject: [PATCH 3/8] API: fix for StockTrackingList entry --- src/backend/InvenTree/stock/api.py | 2 ++ src/backend/InvenTree/stock/serializers.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backend/InvenTree/stock/api.py b/src/backend/InvenTree/stock/api.py index 0e25e47c117a..bf576c6e92db 100644 --- a/src/backend/InvenTree/stock/api.py +++ b/src/backend/InvenTree/stock/api.py @@ -1397,6 +1397,8 @@ def get_delta_model_map(self) -> dict: 'salesorder': (SalesOrder, SalesOrderSerializer), 'returnorder': (ReturnOrder, ReturnOrderSerializer), 'buildorder': (Build, BuildSerializer), + 'item': (StockItem, StockSerializers.StockItemSerializer), + 'stockitem': (StockItem, StockSerializers.StockItemSerializer), } def list(self, request, *args, **kwargs): diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py index f00192c0f391..81b08d21d464 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -425,7 +425,7 @@ class Meta: def __init__(self, *args, **kwargs): """Add detail fields.""" - part_detail = kwargs.pop('part_detail', False) + part_detail = kwargs.pop('part_detail', True) location_detail = kwargs.pop('location_detail', False) supplier_part_detail = kwargs.pop('supplier_part_detail', False) tests = kwargs.pop('tests', False) From 98572f253ceaed1214658c3b746cf50bcfe86ae2 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 13 Nov 2024 04:25:49 +0000 Subject: [PATCH 4/8] Display links for stock items in tracking entry table --- src/frontend/src/tables/stock/StockTrackingTable.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/tables/stock/StockTrackingTable.tsx b/src/frontend/src/tables/stock/StockTrackingTable.tsx index f42c8a3bd191..3e615860d2a0 100644 --- a/src/frontend/src/tables/stock/StockTrackingTable.tsx +++ b/src/frontend/src/tables/stock/StockTrackingTable.tsx @@ -50,7 +50,17 @@ export function StockTrackingTable({ itemId }: Readonly<{ itemId: number }>) { key: 'stockitem', details: deltas.stockitem_detail && - RenderStockItem({ instance: deltas.stockitem_detail }) + RenderStockItem({ instance: deltas.stockitem_detail, link: true }) + }, + { + label: t`Stock Item`, + key: 'item', + details: + deltas.item_detail && + RenderStockItem({ + instance: deltas.item_detail, + link: true + }) }, { label: t`Status`, From 878fba91d0d689f49dfdee964827227fe574a66b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 13 Nov 2024 04:29:52 +0000 Subject: [PATCH 5/8] Generate absolute links for item renderers --- src/frontend/src/components/render/Build.tsx | 6 +++++- src/frontend/src/components/render/Company.tsx | 8 +++++--- src/frontend/src/components/render/Order.tsx | 8 +++++--- src/frontend/src/components/render/Part.tsx | 6 ++++-- src/frontend/src/components/render/Stock.tsx | 6 ++++-- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/frontend/src/components/render/Build.tsx b/src/frontend/src/components/render/Build.tsx index 04ce1e1bb686..f07537db2139 100644 --- a/src/frontend/src/components/render/Build.tsx +++ b/src/frontend/src/components/render/Build.tsx @@ -23,7 +23,11 @@ export function RenderBuildOrder( type: ModelType.build })} image={instance.part_detail?.thumbnail || instance.part_detail?.image} - url={props.link ? getDetailUrl(ModelType.build, instance.pk) : undefined} + url={ + props.link + ? getDetailUrl(ModelType.build, instance.pk, true) + : undefined + } /> ); } diff --git a/src/frontend/src/components/render/Company.tsx b/src/frontend/src/components/render/Company.tsx index d0d1c6c47ad2..1911208f7bf7 100644 --- a/src/frontend/src/components/render/Company.tsx +++ b/src/frontend/src/components/render/Company.tsx @@ -40,7 +40,9 @@ export function RenderCompany( primary={instance.name} secondary={instance.description} url={ - props.link ? getDetailUrl(ModelType.company, instance.pk) : undefined + props.link + ? getDetailUrl(ModelType.company, instance.pk, true) + : undefined } /> ); @@ -76,7 +78,7 @@ export function RenderSupplierPart( } url={ props.link - ? getDetailUrl(ModelType.supplierpart, instance.pk) + ? getDetailUrl(ModelType.supplierpart, instance.pk, true) : undefined } /> @@ -104,7 +106,7 @@ export function RenderManufacturerPart( image={manufacturer?.thumnbnail ?? manufacturer.image} url={ props.link - ? getDetailUrl(ModelType.manufacturerpart, instance.pk) + ? getDetailUrl(ModelType.manufacturerpart, instance.pk, true) : undefined } /> diff --git a/src/frontend/src/components/render/Order.tsx b/src/frontend/src/components/render/Order.tsx index 91012d92cf1c..b712e4bb3ac0 100644 --- a/src/frontend/src/components/render/Order.tsx +++ b/src/frontend/src/components/render/Order.tsx @@ -27,7 +27,7 @@ export function RenderPurchaseOrder( image={supplier.thumnbnail || supplier.image} url={ props.link - ? getDetailUrl(ModelType.purchaseorder, instance.pk) + ? getDetailUrl(ModelType.purchaseorder, instance.pk, true) : undefined } /> @@ -55,7 +55,7 @@ export function RenderReturnOrder( image={customer.thumnbnail || customer.image} url={ props.link - ? getDetailUrl(ModelType.returnorder, instance.pk) + ? getDetailUrl(ModelType.returnorder, instance.pk, true) : undefined } /> @@ -99,7 +99,9 @@ export function RenderSalesOrder( })} image={customer.thumnbnail || customer.image} url={ - props.link ? getDetailUrl(ModelType.salesorder, instance.pk) : undefined + props.link + ? getDetailUrl(ModelType.salesorder, instance.pk, true) + : undefined } /> ); diff --git a/src/frontend/src/components/render/Part.tsx b/src/frontend/src/components/render/Part.tsx index a5bb08bd5e29..f27293c2ddaa 100644 --- a/src/frontend/src/components/render/Part.tsx +++ b/src/frontend/src/components/render/Part.tsx @@ -44,7 +44,9 @@ export function RenderPart( secondary={instance.description} suffix={badge} image={instance.thumnbnail || instance.image} - url={props.link ? getDetailUrl(ModelType.part, instance.pk) : undefined} + url={ + props.link ? getDetailUrl(ModelType.part, instance.pk, true) : undefined + } /> ); } @@ -71,7 +73,7 @@ export function RenderPartCategory( secondary={instance.description} url={ props.link - ? getDetailUrl(ModelType.partcategory, instance.pk) + ? getDetailUrl(ModelType.partcategory, instance.pk, true) : undefined } /> diff --git a/src/frontend/src/components/render/Stock.tsx b/src/frontend/src/components/render/Stock.tsx index 99d6bad36390..4081f7a5e2b0 100644 --- a/src/frontend/src/components/render/Stock.tsx +++ b/src/frontend/src/components/render/Stock.tsx @@ -29,7 +29,7 @@ export function RenderStockLocation( secondary={instance.description} url={ props.link - ? getDetailUrl(ModelType.stocklocation, instance.pk) + ? getDetailUrl(ModelType.stocklocation, instance.pk, true) : undefined } /> @@ -70,7 +70,9 @@ export function RenderStockItem( suffix={{quantity_string}} image={instance.part_detail?.thumbnail || instance.part_detail?.image} url={ - props.link ? getDetailUrl(ModelType.stockitem, instance.pk) : undefined + props.link + ? getDetailUrl(ModelType.stockitem, instance.pk, true) + : undefined } /> ); From 521de8862028de38ef75d074df550b1a91b7ed3e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 13 Nov 2024 04:33:15 +0000 Subject: [PATCH 6/8] Revert "Generate absolute links for item renderers" This reverts commit 878fba91d0d689f49dfdee964827227fe574a66b. --- src/frontend/src/components/render/Build.tsx | 6 +----- src/frontend/src/components/render/Company.tsx | 8 +++----- src/frontend/src/components/render/Order.tsx | 8 +++----- src/frontend/src/components/render/Part.tsx | 6 ++---- src/frontend/src/components/render/Stock.tsx | 6 ++---- 5 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/frontend/src/components/render/Build.tsx b/src/frontend/src/components/render/Build.tsx index f07537db2139..04ce1e1bb686 100644 --- a/src/frontend/src/components/render/Build.tsx +++ b/src/frontend/src/components/render/Build.tsx @@ -23,11 +23,7 @@ export function RenderBuildOrder( type: ModelType.build })} image={instance.part_detail?.thumbnail || instance.part_detail?.image} - url={ - props.link - ? getDetailUrl(ModelType.build, instance.pk, true) - : undefined - } + url={props.link ? getDetailUrl(ModelType.build, instance.pk) : undefined} /> ); } diff --git a/src/frontend/src/components/render/Company.tsx b/src/frontend/src/components/render/Company.tsx index 1911208f7bf7..d0d1c6c47ad2 100644 --- a/src/frontend/src/components/render/Company.tsx +++ b/src/frontend/src/components/render/Company.tsx @@ -40,9 +40,7 @@ export function RenderCompany( primary={instance.name} secondary={instance.description} url={ - props.link - ? getDetailUrl(ModelType.company, instance.pk, true) - : undefined + props.link ? getDetailUrl(ModelType.company, instance.pk) : undefined } /> ); @@ -78,7 +76,7 @@ export function RenderSupplierPart( } url={ props.link - ? getDetailUrl(ModelType.supplierpart, instance.pk, true) + ? getDetailUrl(ModelType.supplierpart, instance.pk) : undefined } /> @@ -106,7 +104,7 @@ export function RenderManufacturerPart( image={manufacturer?.thumnbnail ?? manufacturer.image} url={ props.link - ? getDetailUrl(ModelType.manufacturerpart, instance.pk, true) + ? getDetailUrl(ModelType.manufacturerpart, instance.pk) : undefined } /> diff --git a/src/frontend/src/components/render/Order.tsx b/src/frontend/src/components/render/Order.tsx index b712e4bb3ac0..91012d92cf1c 100644 --- a/src/frontend/src/components/render/Order.tsx +++ b/src/frontend/src/components/render/Order.tsx @@ -27,7 +27,7 @@ export function RenderPurchaseOrder( image={supplier.thumnbnail || supplier.image} url={ props.link - ? getDetailUrl(ModelType.purchaseorder, instance.pk, true) + ? getDetailUrl(ModelType.purchaseorder, instance.pk) : undefined } /> @@ -55,7 +55,7 @@ export function RenderReturnOrder( image={customer.thumnbnail || customer.image} url={ props.link - ? getDetailUrl(ModelType.returnorder, instance.pk, true) + ? getDetailUrl(ModelType.returnorder, instance.pk) : undefined } /> @@ -99,9 +99,7 @@ export function RenderSalesOrder( })} image={customer.thumnbnail || customer.image} url={ - props.link - ? getDetailUrl(ModelType.salesorder, instance.pk, true) - : undefined + props.link ? getDetailUrl(ModelType.salesorder, instance.pk) : undefined } /> ); diff --git a/src/frontend/src/components/render/Part.tsx b/src/frontend/src/components/render/Part.tsx index f27293c2ddaa..a5bb08bd5e29 100644 --- a/src/frontend/src/components/render/Part.tsx +++ b/src/frontend/src/components/render/Part.tsx @@ -44,9 +44,7 @@ export function RenderPart( secondary={instance.description} suffix={badge} image={instance.thumnbnail || instance.image} - url={ - props.link ? getDetailUrl(ModelType.part, instance.pk, true) : undefined - } + url={props.link ? getDetailUrl(ModelType.part, instance.pk) : undefined} /> ); } @@ -73,7 +71,7 @@ export function RenderPartCategory( secondary={instance.description} url={ props.link - ? getDetailUrl(ModelType.partcategory, instance.pk, true) + ? getDetailUrl(ModelType.partcategory, instance.pk) : undefined } /> diff --git a/src/frontend/src/components/render/Stock.tsx b/src/frontend/src/components/render/Stock.tsx index 4081f7a5e2b0..99d6bad36390 100644 --- a/src/frontend/src/components/render/Stock.tsx +++ b/src/frontend/src/components/render/Stock.tsx @@ -29,7 +29,7 @@ export function RenderStockLocation( secondary={instance.description} url={ props.link - ? getDetailUrl(ModelType.stocklocation, instance.pk, true) + ? getDetailUrl(ModelType.stocklocation, instance.pk) : undefined } /> @@ -70,9 +70,7 @@ export function RenderStockItem( suffix={{quantity_string}} image={instance.part_detail?.thumbnail || instance.part_detail?.image} url={ - props.link - ? getDetailUrl(ModelType.stockitem, instance.pk, true) - : undefined + props.link ? getDetailUrl(ModelType.stockitem, instance.pk) : undefined } /> ); From 99218116df364a165a91098078ba8723da11b51a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 15 Nov 2024 22:40:23 +1100 Subject: [PATCH 7/8] Bump API version --- src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index e745c7cf66d4..dbe55006f2a3 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,13 +1,16 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 280 +INVENTREE_API_VERSION = 281 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v281 - 2024-11-15 : https://github.com/inventree/InvenTree/pull/8480 + - Fixes StockHistory API data serialization + v280 - 2024-11-10 : https://github.com/inventree/InvenTree/pull/8461 - Makes schema for API information endpoint more informing - Removes general not found endpoint From 980de394a1f4d6c649688b064ef1250f5592d314 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 15 Nov 2024 22:59:56 +1100 Subject: [PATCH 8/8] Add playwright tests --- src/frontend/tests/pages/pui_stock.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/frontend/tests/pages/pui_stock.spec.ts b/src/frontend/tests/pages/pui_stock.spec.ts index 24f807bd0635..df72be38874b 100644 --- a/src/frontend/tests/pages/pui_stock.spec.ts +++ b/src/frontend/tests/pages/pui_stock.spec.ts @@ -157,3 +157,20 @@ test('Stock - Stock Actions', async ({ page }) => { await page.waitForTimeout(2500); }); + +test('Stock - Tracking', async ({ page }) => { + await doQuickLogin(page); + + // Navigate to the "stock item" page + await page.goto(`${baseUrl}/stock/item/176/details/`); + await page.getByRole('link', { name: 'Widget Assembly # 2' }).waitFor(); + + // Navigate to the "stock tracking" tab + await page.getByRole('tab', { name: 'Stock Tracking' }).click(); + 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; +});