diff --git a/docs/main.py b/docs/main.py index 97b28c98cc..76ddddb143 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 diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index e745c7cf66..dbe55006f2 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 diff --git a/src/backend/InvenTree/stock/api.py b/src/backend/InvenTree/stock/api.py index 0e25e47c11..bf576c6e92 100644 --- a/src/backend/InvenTree/stock/api.py +++ b/src/backend/InvenTree/stock/api.py @@ -1397,6 +1397,8 @@ class StockTrackingList(DataExportViewMixin, ListAPI): '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 f00192c0f3..81b08d21d4 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -425,7 +425,7 @@ class StockItemSerializer( 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) diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx index 1e9aceaad7..e1cc70e3d4 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 af474ccfe9..84e0449162 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; diff --git a/src/frontend/src/tables/stock/StockTrackingTable.tsx b/src/frontend/src/tables/stock/StockTrackingTable.tsx index f42c8a3bd1..3e615860d2 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`, diff --git a/src/frontend/tests/pages/pui_stock.spec.ts b/src/frontend/tests/pages/pui_stock.spec.ts index 24f807bd06..df72be3887 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; +});