2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-12-14 08:19:54 +00:00

Barcode scan tweaks (#10992)

* Remove duplicate tooltip

* Adjust default value

* docs update

* Tweak unit test

* Fix playwright tests
This commit is contained in:
Oliver
2025-12-11 16:19:47 +11:00
committed by GitHub
parent 0723c74567
commit 20c7a5b5b8
9 changed files with 49 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -69,7 +69,7 @@ To access this page, select *Scan Barcode* from the main navigation menu:
{{ image("barcode/barcode_nav_menu.png", "Barcode menu item") }} {{ image("barcode/barcode_nav_menu.png", "Barcode menu item") }}
{{ image("barcode/barcode_scan_page.png", "Barcode scan page") }} {{ image("barcode/barcode_scan_page.png", "Barcode scan page") }}
### Barcodes in Forms ## Barcodes in Forms
The InvenTree user interface supports direct scanning of barcodes within certain forms in the web UI. This means that any form field which points to a model which supports barcodes can accept barcode input. If barcode scanning is supported for a particular field, a barcode icon will be displayed next to the input field: The InvenTree user interface supports direct scanning of barcodes within certain forms in the web UI. This means that any form field which points to a model which supports barcodes can accept barcode input. If barcode scanning is supported for a particular field, a barcode icon will be displayed next to the input field:
@@ -83,6 +83,14 @@ Once scanned, the form field will be automatically populated with the correct it
{{ image("barcode/barcode_field_filled.png", "Barcode field populated") }} {{ image("barcode/barcode_field_filled.png", "Barcode field populated") }}
Any field which supports barcode input will have this functionality, such as allocating stock items to an order:
{{ image("barcode/barcode_allocate_stock.png", "Allocate stock via barcode") }}
### User Configuration
By default, barcode scanning in form fields is disabled. Each user can enable this feature via their [user preferences](../settings/user.md#display-settings).
## App Integration ## App Integration
Barcode scanning is a key feature of the [companion mobile app](../app/barcode.md). When running on a device with an integrated camera, the app can scan barcodes directly from the camera feed. Barcode scanning is a key feature of the [companion mobile app](../app/barcode.md). When running on a device with an integrated camera, the app can scan barcodes directly from the camera feed.

View File

@@ -44,7 +44,7 @@ USER_SETTINGS: dict[str, InvenTreeSettingsKeyType] = {
'BARCODE_IN_FORM_FIELDS': { 'BARCODE_IN_FORM_FIELDS': {
'name': _('Barcode Scanner in Form Fields'), 'name': _('Barcode Scanner in Form Fields'),
'description': _('Allow barcode scanner input in form fields'), 'description': _('Allow barcode scanner input in form fields'),
'default': True, 'default': False,
'validator': bool, 'validator': bool,
}, },
'SEARCH_PREVIEW_SHOW_PARTS': { 'SEARCH_PREVIEW_SHOW_PARTS': {

View File

@@ -29,7 +29,6 @@ export function ScanButton({
aria-label={`barcode-scan-button-${modelType ?? 'any'}`} aria-label={`barcode-scan-button-${modelType ?? 'any'}`}
onClick={open} onClick={open}
variant='transparent' variant='transparent'
title={t`Open Barcode Scanner`}
> >
<IconQrcode /> <IconQrcode />
</ActionIcon> </ActionIcon>

View File

@@ -1,10 +1,16 @@
import { request } from '@playwright/test'; import { request } from '@playwright/test';
import { adminuser, apiUrl } from './defaults'; import { adminuser, apiUrl } from './defaults';
export const createApi = () => export const createApi = ({
username,
password
}: {
username?: string;
password?: string;
}) =>
request.newContext({ request.newContext({
baseURL: apiUrl, baseURL: apiUrl,
extraHTTPHeaders: { extraHTTPHeaders: {
Authorization: `Basic ${btoa(`${adminuser.username}:${adminuser.password}`)}` Authorization: `Basic ${btoa(`${username || adminuser.username}:${password || adminuser.password}`)}`
} }
}); });

View File

@@ -152,7 +152,7 @@ export const globalSearch = async (page: Page, query: string) => {
}; };
export const deletePart = async (name: string) => { export const deletePart = async (name: string) => {
const api = await createApi(); const api = await createApi({});
const parts = await api const parts = await api
.get('part/', { .get('part/', {
params: { search: name } params: { search: name }

View File

@@ -1,4 +1,5 @@
import type { Page } from '@playwright/test'; import type { Page } from '@playwright/test';
import { createApi } from '../api';
import { test } from '../baseFixtures'; import { test } from '../baseFixtures';
import { doCachedLogin } from '../login'; import { doCachedLogin } from '../login';
@@ -128,9 +129,33 @@ test('Barcode Scanning - Build', async ({ browser }) => {
test('Barcode Scanning - Forms', async ({ browser }) => { test('Barcode Scanning - Forms', async ({ browser }) => {
const page = await doCachedLogin(browser, { const page = await doCachedLogin(browser, {
username: 'admin',
password: 'inventree',
url: '/stock/location/index/stock-items' url: '/stock/location/index/stock-items'
}); });
// Ensure the user setting is enabled
const api = await createApi({});
let patched = false;
await api
.patch('/api/settings/user/BARCODE_IN_FORM_FIELDS/', {
data: {
value: true
}
})
.then((response) => {
patched = response.status() === 200;
});
// Assert that the setting was patched successfully
if (!patched) {
throw new Error('Could not patch user setting: BARCODE_IN_FORM_FIELDS');
}
await page.reload();
// Open the "Add Stock Item" form // Open the "Add Stock Item" form
await page await page
.getByRole('button', { name: 'action-button-add-stock-item' }) .getByRole('button', { name: 'action-button-add-stock-item' })

View File

@@ -332,7 +332,7 @@ test('Settings - Admin - Barcode History', async ({ browser }) => {
// Scan some barcodes (via API calls) // Scan some barcodes (via API calls)
const barcodes = ['ABC1234', 'XYZ5678', 'QRS9012']; const barcodes = ['ABC1234', 'XYZ5678', 'QRS9012'];
const api = await createApi(); const api = await createApi({});
for (let i = 0; i < barcodes.length; i++) { for (let i = 0; i < barcodes.length; i++) {
const barcode = barcodes[i]; const barcode = barcodes[i];
@@ -349,8 +349,8 @@ test('Settings - Admin - Barcode History', async ({ browser }) => {
}, },
timeout: 5000 timeout: 5000
}) })
.then(() => { .then((response) => {
result = true; result = response.status() === 200;
}); });
if (result) { if (result) {
@@ -478,8 +478,6 @@ test('Settings - Admin - Parameter', async ({ browser }) => {
await page.getByRole('option', { name: 'my custom parameter' }).click(); await page.getByRole('option', { name: 'my custom parameter' }).click();
await page.getByLabel('choice-field-data').fill('2'); await page.getByLabel('choice-field-data').fill('2');
await page.getByRole('button', { name: 'Submit' }).click(); await page.getByRole('button', { name: 'Submit' }).click();
await page.waitForTimeout(2500);
}); });
test('Settings - Admin - Unauthorized', async ({ browser }) => { test('Settings - Admin - Unauthorized', async ({ browser }) => {

View File

@@ -16,7 +16,7 @@ export const setSettingState = async ({
type?: 'global' | 'plugin'; type?: 'global' | 'plugin';
plugin?: string; plugin?: string;
}) => { }) => {
const api = await createApi(); const api = await createApi({});
const url = const url =
type === 'global' type === 'global'
? `settings/global/${setting}/` ? `settings/global/${setting}/`
@@ -37,7 +37,7 @@ export const setPluginState = async ({
plugin: string; plugin: string;
state: boolean; state: boolean;
}) => { }) => {
const api = await createApi(); const api = await createApi({});
const response = await api.patch(`plugins/${plugin}/activate/`, { const response = await api.patch(`plugins/${plugin}/activate/`, {
data: { data: {
active: state active: state