2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-04-04 10:31:03 +00:00

Supplier Part Updates (#11303)

* Add "primary" field to SupplierPart model

* Remove "default_supplier" field from the Part model

* Ensure only one SupplierPart can be "primary" for a given Part

* Update references to "default_supplier"

* Add 'primary' field to the SupplierPart API serializer

* update SupplierPart table

* Use bulk-update operations

* Bug fix for data migration

* Allow ordering by 'primary' field

* Tweak import message

* Edit 'primary' field in UI

* Fix checks in save() methods

* Better table updates

* Update CHANGELOG

* Bump API version

* Fix unit test

* Add unit test for API

* Playwright tests
This commit is contained in:
Oliver
2026-02-20 18:25:26 +11:00
committed by GitHub
parent 14d6d2354f
commit 3910cc5a50
21 changed files with 216 additions and 65 deletions

View File

@@ -71,6 +71,7 @@ export function useSupplierPartFields({
packaging: {
icon: <IconPackage />
},
primary: {},
active: {}
};

View File

@@ -55,14 +55,6 @@ export function usePartFields({
structural: false
}
},
default_supplier: {
hidden: !partId || !purchaseable,
filters: {
part: partId,
part_detail: true,
supplier_detail: true
}
},
default_expiry: {},
minimum_stock: {},
responsible: {

View File

@@ -692,16 +692,6 @@ export default function PartDetail() {
badge: 'owner',
hidden: !part.responsible
},
{
type: 'link',
name: 'default_supplier',
label: t`Default Supplier`,
model: ModelType.supplierpart,
model_formatter: (model: any) => {
return model.SKU;
},
hidden: !part.default_supplier
},
{
name: 'default_expiry',
label: t`Default Expiry`,

View File

@@ -99,6 +99,12 @@ export function SupplierPartTable({
title: t`MPN`,
render: (record: any) => record?.manufacturer_part_detail?.MPN
},
BooleanColumn({
accessor: 'primary',
sortable: true,
switchable: true,
defaultVisible: false
}),
BooleanColumn({
accessor: 'active',
title: t`Active`,
@@ -176,7 +182,9 @@ export function SupplierPartTable({
supplier: supplierId,
manufacturer_part: manufacturerPartId
},
table: table,
onFormSuccess: (response: any) => {
table.refreshTable();
},
successMessage: t`Supplier part created`
});
@@ -215,6 +223,11 @@ export function SupplierPartTable({
label: t`Active`,
description: t`Show active supplier parts`
},
{
name: 'primary',
label: t`Primary`,
description: t`Show primary supplier parts`
},
{
name: 'part_active',
label: t`Active Part`,
@@ -243,7 +256,9 @@ export function SupplierPartTable({
pk: selectedSupplierPart?.pk,
title: t`Edit Supplier Part`,
fields: useMemo(() => editSupplierPartFields, [editSupplierPartFields]),
table: table
onFormSuccess: (response: any) => {
table.refreshTable();
}
});
const duplicateSupplierPart = useCreateApiFormModal({
@@ -252,9 +267,12 @@ export function SupplierPartTable({
fields: useMemo(() => editSupplierPartFields, [editSupplierPartFields]),
initialData: {
...selectedSupplierPart,
primary: false,
active: true
},
table: table,
onFormSuccess: (response: any) => {
table.refreshTable();
},
successMessage: t`Supplier part created`
});

View File

@@ -1,8 +1,10 @@
import { test } from '../baseFixtures.js';
import {
clearTableFilters,
clickOnParamFilter,
loadTab,
navigate,
setTableChoiceFilter,
showParametricView
} from '../helpers.js';
import { doCachedLogin } from '../login.js';
@@ -63,3 +65,24 @@ test('Company - Parameters', async ({ browser }) => {
await page.getByRole('cell', { name: 'Arrow Electronics' }).waitFor();
await page.getByRole('cell', { name: 'PCB assembly house' }).waitFor();
});
test('Company - Supplier Parts', async ({ browser }) => {
const page = await doCachedLogin(browser, {
username: 'steven',
password: 'wizardstaff',
url: 'purchasing/index/suppliers'
});
await loadTab(page, 'Supplier Parts');
await clearTableFilters(page);
await page.getByText('- 25 / 777').waitFor();
await setTableChoiceFilter(page, 'Primary', 'Yes');
await page.getByText('- 25 / 318').waitFor();
await clearTableFilters(page);
await setTableChoiceFilter(page, 'Primary', 'No');
await page.getByText('- 25 / 459').waitFor();
});