2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-03-13 23:53:35 +00:00

[Enhancement] Import by natural key fields (#11288)

* Data import flexibility

- Allow specification of alternative lookup fields for data import

* Observe field filters during data import

* Add alternative import fields for Part models

* More options for IMPORT_ID_FIELDS

* Update src/backend/InvenTree/importer/models.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Bump CHANGELOG

* Handle empty input values

* Add IMPORT_ID_FIELDS for more models

* PK field takes highest priority

* Update import docs

* Tweak return type

* Handle multiple date formats

* Add playwright testing

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Oliver
2026-02-20 15:30:00 +11:00
committed by GitHub
parent 1ac3f5e479
commit 14d6d2354f
11 changed files with 220 additions and 3 deletions

View File

@@ -172,3 +172,53 @@ test('Importing - Purchase Order', async ({ browser }) => {
await page.getByRole('cell', { name: 'Database Field' }).waitFor();
await page.getByRole('cell', { name: 'Field Description' }).waitFor();
});
test('Importing - Natural Keys', async ({ browser }) => {
const page = await doCachedLogin(browser, {
username: 'steven',
password: 'wizardstaff',
url: 'purchasing/purchase-order/15/line-items'
});
// Import line item data, but use natural keys as the import fields
await page
.getByRole('button', { name: 'action-button-import-line-' })
.click();
const fileInput = await page.locator('input[type="file"]');
await fileInput.setInputFiles('./tests/fixtures/po_data_natural_keys.csv');
await page.getByRole('button', { name: 'Submit' }).click();
// Attempt import with missing required fields
await page.getByRole('button', { name: 'Accept Column Mapping' }).click();
await page.getByText('Some required fields have not been mapped').waitFor();
// Select different columns for data import
// We will use the "SKU" field to map to the supplier part
await page.getByRole('textbox', { name: 'import-column-map-part' }).click();
await page.getByRole('option', { name: 'SKU' }).click();
// Other import fields will be left as default
await page.getByRole('button', { name: 'Accept Column Mapping' }).click();
// Check for expected values to be displayed
await page.getByText('PRO-ZEN').first().waitFor();
await page.getByText('Project Zenith').first().waitFor();
await page.getByText('my-custom-reference').first().waitFor();
await page.getByText('Factory/Mechanical Lab').first().waitFor();
await page.getByText('FUT-43861-DDU').first().waitFor();
await page.getByText('FUT-82092-CQB').first().waitFor();
await page.getByText('2026-01-30').first().waitFor();
// Let's import all the data
await page
.getByRole('row', { name: 'Select all records Row Not' })
.getByLabel('Select all records')
.click();
await page
.getByRole('button', { name: 'action-button-import-selected' })
.click();
await page.getByText('Data has been imported successfully').waitFor();
await page.getByRole('button', { name: 'Close' }).click();
});