Files
InvenTree/tasks.py
T
+22 a776c5d615 Update next breaking (#12666)
* build(docker): compile backend translations during image build (#12203)

* build(docker): compile backend trasnlations during image build

* test(docker): verify compiled backend translations exist in image

Add checks to the "Test Docker Image" step that assert the compiled
django.mo files are present for a few representative languages (de, fr,
ru, zh_Hans). This guards the newly added backend translation
compilation step in the production Dockerfile, ensuring the multilingual
artifacts are produced at the expected locale paths.

* test(docker): verify compiled frontend translations exist in image

* Add meaningful message on CSRF failure (#12216)

* Add meaningful message on CSRF failure

* Add link to CSRF_FAILURE_VIEW

* Add unit test for new CSRF feedback

* devops: fix chromium test uploads to flakiness.io (#12219)

Currently, only Firefox test results get uploaded to Flakiness.io.
This patch fixes the upload for chromium results as well, per
https://docs.flakiness.io/ci/github-actions-setup/

* Bump ty (#12211)

* bump ty

* various fixes

* fix settings

* bump stubs

* update pre-commit setup

* update ignore

* fix various issues

* fix style

* fix ignores

* fix wrong ty warnings

* color scheme: Use the users prefered mode by default (#12227)

* color scheme: Use the users prefered colour scheme if one isn't defined in the store

* fix style

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump the dependencies group with 3 updates (#12220)

Bumps the dependencies group with 3 updates: [oasdiff/oasdiff-action](https://github.com/oasdiff/oasdiff-action), [CodSpeedHQ/action](https://github.com/codspeedhq/action) and [crowdin/github-action](https://github.com/crowdin/github-action).


Updates `oasdiff/oasdiff-action` from 0.0.57 to 0.1.1
- [Release notes](https://github.com/oasdiff/oasdiff-action/releases)
- [Commits](https://github.com/oasdiff/oasdiff-action/compare/3530478ec30f84adedbfeb28f0d9527a290f50a9...5fbe96ede8d0c53aeadef122d7a0abb79152d493)

Updates `CodSpeedHQ/action` from 4.17.0 to 4.17.5
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/9d332c4d90b43981c3e55ae8e38e68709996240f...c145068895e045cc725ee76fcd2307624b65c3af)

Updates `crowdin/github-action` from 2.16.2 to 2.16.3
- [Release notes](https://github.com/crowdin/github-action/releases)
- [Commits](https://github.com/crowdin/github-action/compare/8868a33591d21088edfc398968173a3b98d51706...52aa776766211d83d975df51f3b9c53c2f8ba35f)

---
updated-dependencies:
- dependency-name: oasdiff/oasdiff-action
  dependency-version: 0.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 4.17.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: crowdin/github-action
  dependency-version: 2.16.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* extend barcode scans API (#12233)

* extend barcode scans with user perm check

* fix import

* fix call

* align error message

* add missing permissions to test

* remove erronous assign

* ensure permission erros knock through

* New Crowdin translations by GitHub Action (#12192)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* [UI] Tweak today color (#12235)

- Make "today" more obvious in calendar views

* [UI] Tweak "order parts" wizard (#12236)

- Order supplier parts by "primary" value
- Attempt to auto-fill primary supplier part

* [bug] Allocated query fix (#12234)

* Fix BuildLineFilter.filter_allocated

- Required for mysql backend

* Spoecify output field

* 1.5.0 (#12239)

* Add release entry for 1.4.0

* Add blank entry for 1.5.0

* Bump version to 1.5.0 dev

* [report] Tweak datamatrix helper (#12240)

* [report] Tweak datamatrix helper

- Add support for "rectangular" display
- Support different image output formats

* Fix unit tests

* !feat(backend): bump minimum python version (#12223)

* bump ci versions

* bump installer version

* bump tooling version ref

* bump doc refs

* bump / refactor code refs

* bump debug ref

* remove now unneeded deps

* bump release version

* remove distutils

* fix finder call

* remove old compat code

* add changelog entry

* lower cov target for now

* Update devcontainer Dockerfile (#12244)

- Update to python 3.14
- Fix base packages

* Allow stock transfer to merge into existing stock (optional) #6951 (#12022)

* working on merge transfer

* fix history when merging

* update messaging, add 'added' line in history

* reworked history logic

* removed old transfer logic

* remove formatting changes from vite file

* Bumped API version, added entry in docs for new global setting

* removed the tracking item overwrite, Use existing tracking event from transfer

* run pre-commit checks

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* New Crowdin translations by GitHub Action (#12238)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Revert devcontainer to python 3.12 (#12249)

* Project code active (#12250)

* Add 'active' field to the ProjectCode model

- Allows retiring of old project codes without deleting

* Update UI table

* Refactor ProjectCodeField

* Add unit test

* Bump API version and CHANGELOG

* fix js-yaml, esbuild vulns (#12190)

* fix js-yaml, esbuild vulns

* update bump

* upgrade vite

* Skip "many" fields in DataExport (#12255)

- Exporting multi-dimensional datasets requires a custom exporter

* [UI] Improve revision selector (#12254)

- Display upstream revisions too

* Bug fix for exception handler (#12257)

* chore(backend): typing fixes (#12247)

* bump ty

* various fixes

* fix settings

* bump stubs

* update pre-commit setup

* update ignore

* fix various issues

* fix style

* fix ignores

* fix wrong ty warnings

* ignore __class__ type checking errors
see https://github.com/astral-sh/ty/issues/3122

* fix exception logging

* update ignoring

* bump ty further

* add cleanup cmd

* Merge branch 'master' of https://github.com/inventree/InvenTree into typechecking-remove-ignore

* bump ty

* remove now unused class ignores

* chore(backend): harden gh setup (#12262)

* pin plugin creator version

* hard pin install script

* chore(backend): dep bump (#12258)

* general deps bump

* cleanup other dep files

* [UI] Stock column fix (#12268)

* [UI] Fix StockColumn component

* stock table rendering tweaks

* chore(backend): Remove devops (#12265)

* update sponsored ressources

* remove az devops

* update sponsored ressources (#12264)

* [UI] Table tweaks (#12271)

* [UI] Make part cell text copyable

* Reduce text size

* Reduce text size

* [UI] Fix stock dates (#12272)

* [UI] Fix stock dates

- Display creation date
- Display stocktake date

* Switch to date type

* fix: preserve supplier import stock workflow (#12215)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* Fix dashboard issue (#12275)

* chore(deps): bump the dependencies group with 5 updates (#12278)

* chore(deps): bump the dependencies group with 5 updates

Bumps the dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `6.0.3` | `7.0.0` |
| [oasdiff/oasdiff-action/diff](https://github.com/oasdiff/oasdiff-action) | `0.1.1` | `0.1.3` |
| [CodSpeedHQ/action](https://github.com/codspeedhq/action) | `4.17.5` | `4.17.6` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.6` | `0.5.7` |
| [pkgr/action/publish](https://github.com/pkgr/action) | `3bce081ae512c5020856e237d37b3f5479d4aa71` | `c5666febcd31750da6428042193fc5b2fb765435` |


Updates `actions/checkout` from 6.0.3 to 7.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

Updates `oasdiff/oasdiff-action/diff` from 0.1.1 to 0.1.3
- [Release notes](https://github.com/oasdiff/oasdiff-action/releases)
- [Commits](https://github.com/oasdiff/oasdiff-action/compare/5fbe96ede8d0c53aeadef122d7a0abb79152d493...ccc2442df0d99f8c419ed73e3de88641c91b3bc6)

Updates `CodSpeedHQ/action` from 4.17.5 to 4.17.6
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/c145068895e045cc725ee76fcd2307624b65c3af...63f3e98b61959fe67f146a3ff022e4136fe9bb9c)

Updates `zizmorcore/zizmor-action` from 0.5.6 to 0.5.7
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/5f14fd08f7cf1cb1609c1e344975f152c7ee938d...192e21d79ab29983730a13d1382995c2307fbcaa)

Updates `pkgr/action/publish` from 3bce081ae512c5020856e237d37b3f5479d4aa71 to c5666febcd31750da6428042193fc5b2fb765435
- [Release notes](https://github.com/pkgr/action/releases)
- [Commits](https://github.com/pkgr/action/compare/3bce081ae512c5020856e237d37b3f5479d4aa71...c5666febcd31750da6428042193fc5b2fb765435)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: oasdiff/oasdiff-action/diff
  dependency-version: 0.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 4.17.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.5.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: pkgr/action/publish
  dependency-version: c5666febcd31750da6428042193fc5b2fb765435
  dependency-type: direct:production
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update checkout action version comment in workflow

* fix pins

* change pin

* fix pin

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* [UI] Fix 'available' display (#12279)

- Hide entirely for items not "in_stock"

* Fix stocktake bug for counting serialized items (#12280)

* Fix stocktake bug for counting serialized items

* Add unit test

* [UI] Table field refactor (#12274)

* Use callback funcs

* Don't use idx to identify rows

* Add debug function for finding why a component re-rendered

* Do not pass 'control' through to each row

* Prevent unnecessary re-rendering of table rows

* Adjust order of operations for hooks

* Keep props hidden

* Use lightweight NumberInput

* Use NumberInput elsewhere

* Add comment

* use rowId instead of idx

* Generic row memos

* Compare errors too

* Fix for BomItemSubstituteRow

* Adjust more forms

* memoize quantity

* Memoize build lines

* Fix re-rendering issues for build allocation

* Fix for useConsumeBuildLinesForm

* Fix for transfer order table

* Fix useReceiveLineItems

* Remove memoized pattern

* Fix row keys

* Cleanup

* Create useStockItems hook for memoizing items

* Refactoring

* More refactoring

* Remove obj reference

- preventing shallow comparison from working

* Add error message to useWhyDidYouUpdate

* Cleanup

* Cleanup dead code

* Adjust modal width

* Change attr name

* Remove autoFillFilters prop

* Adjustments for serialized stock

* Fix typing

* Bump frontend version

* Adjustments for playwright testing

* Fix ref issue

* Remove debug entry

* Update CHANGELOG.md

* Reintroduce index to table header

* Refactor common component

* Fix for STOCK_COUNT event (#12281)

* Fix for STOCK_COUNT event

- Prevent double emission of event type string

* adjust unit test

* Allow stock adjustment from "category" detail view (#12256)

* New Crowdin translations by GitHub Action (#12251)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* [UI] Tree select in form fields (#12217)

* Add TreeField component

* Add chevrons in dropdown menu

* Custom node rendering

* Add childIdentifier

* Ensure full value gets displayed

* Fix for search results

* Refactor old renderers

* Override field types

* use definition filters

* Better location validation messages

* Tweaks

* Fix unit test

* Include icon

* Fix playwright test

* Fix call to onValueChange

* Updated playwright tests

* Use pathstring in selectedLabel (if available)

* Mark structural nodes

* Retain selected value when dropdown open

* Add better placeholder values

* Simplify field selection

* Check build complete (#12289)

* Display non-field errors in table field

* Refactor validation for build output completion

- Run validation BEFORE trying to complete (serializer validation)
- Refactor and simplify common code

* Adjust unit tests

* Fix typing

* Remove debug

* Display login errors to user (#12288)

* Improved error message extraction

* Updated playwright test

* Add playwright test for part image upload (#11597)

* fix pin syntax (#12287)

* fix pin syntax

* make pins precise

* update target name and version

* [UI] Fix imports (#12292)

- Adjust import structure
- Prevent wall-of-text warnings from vite

* [UI] Tweak unique keys (#12293)

- Reduce reliance on mutable idx

* chore(deps): bump the dependencies group across 1 directory with 27 updates (#12260)

* chore(deps): bump the dependencies group across 1 directory with 27 updates

Bumps the dependencies group with 27 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/search](https://github.com/codemirror/search) | `6.7.0` | `6.7.1` |
| [@fullcalendar/core](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/core) | `6.1.20` | `6.1.21` |
| [@fullcalendar/daygrid](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/daygrid) | `6.1.20` | `6.1.21` |
| [@fullcalendar/interaction](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/interaction) | `6.1.20` | `6.1.21` |
| [@fullcalendar/react](https://github.com/fullcalendar/fullcalendar-react) | `6.1.20` | `6.1.21` |
| [@mantine/carousel](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/carousel) | `9.2.1` | `9.3.2` |
| [@mantine/charts](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/charts) | `9.2.1` | `9.3.2` |
| [@mantine/core](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/core) | `9.2.1` | `9.3.2` |
| [@mantine/dates](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dates) | `9.2.1` | `9.3.2` |
| [@mantine/dropzone](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dropzone) | `9.2.1` | `9.3.2` |
| [@mantine/form](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/form) | `9.2.1` | `9.3.2` |
| [@mantine/hooks](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/hooks) | `9.2.1` | `9.3.2` |
| [@mantine/modals](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/modals) | `9.2.1` | `9.3.2` |
| [@mantine/notifications](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/notifications) | `9.2.1` | `9.3.2` |
| [@mantine/spotlight](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/spotlight) | `9.2.1` | `9.3.2` |
| [@mantine/vanilla-extract](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/vanilla-extract) | `9.2.1` | `9.3.2` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.57.0` | `10.58.0` |
| [mantine-contextmenu](https://github.com/icflorescu/mantine-contextmenu) | `9.2.1` | `9.3.0` |
| [mantine-datatable](https://github.com/icflorescu/mantine-datatable) | `9.2.2` | `9.3.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.78.0` | `7.79.0` |
| [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.29.7` | `8.0.1` |
| [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) | `7.29.7` | `8.0.1` |
| [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) | `7.29.7` | `8.0.1` |
| [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) | `7.29.7` | `8.0.0` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.60.0` | `1.61.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.9.2` | `25.9.3` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `5.2.0` | `6.0.2` |



Updates `@codemirror/search` from 6.7.0 to 6.7.1
- [Changelog](https://github.com/codemirror/search/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/search/commits)

Updates `@fullcalendar/core` from 6.1.20 to 6.1.21
- [Release notes](https://github.com/fullcalendar/fullcalendar/releases)
- [Changelog](https://github.com/fullcalendar/fullcalendar/blob/v6.1.21/CHANGELOG.md)
- [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.21/packages/core)

Updates `@fullcalendar/daygrid` from 6.1.20 to 6.1.21
- [Release notes](https://github.com/fullcalendar/fullcalendar/releases)
- [Changelog](https://github.com/fullcalendar/fullcalendar/blob/v6.1.21/CHANGELOG.md)
- [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.21/packages/daygrid)

Updates `@fullcalendar/interaction` from 6.1.20 to 6.1.21
- [Release notes](https://github.com/fullcalendar/fullcalendar/releases)
- [Changelog](https://github.com/fullcalendar/fullcalendar/blob/v6.1.21/CHANGELOG.md)
- [Commits](https://github.com/fullcalendar/fullcalendar/commits/v6.1.21/packages/interaction)

Updates `@fullcalendar/react` from 6.1.20 to 6.1.21
- [Release notes](https://github.com/fullcalendar/fullcalendar-react/releases)
- [Changelog](https://github.com/fullcalendar/fullcalendar-react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fullcalendar/fullcalendar-react/compare/v6.1.20...v6.1.21)

Updates `@mantine/carousel` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/carousel)

Updates `@mantine/charts` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/charts)

Updates `@mantine/core` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/core)

Updates `@mantine/dates` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/dates)

Updates `@mantine/dropzone` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/dropzone)

Updates `@mantine/form` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/form)

Updates `@mantine/hooks` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/hooks)

Updates `@mantine/modals` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/modals)

Updates `@mantine/notifications` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/notifications)

Updates `@mantine/spotlight` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/spotlight)

Updates `@mantine/vanilla-extract` from 9.2.1 to 9.3.2
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.3.2/packages/@mantine/vanilla-extract)

Updates `@sentry/react` from 10.57.0 to 10.58.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.57.0...10.58.0)

Updates `mantine-contextmenu` from 9.2.1 to 9.3.0
- [Changelog](https://github.com/icflorescu/mantine-contextmenu/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icflorescu/mantine-contextmenu/commits)

Updates `mantine-datatable` from 9.2.2 to 9.3.0
- [Changelog](https://github.com/icflorescu/mantine-datatable/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icflorescu/mantine-datatable/commits)

Updates `react-hook-form` from 7.78.0 to 7.79.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.78.0...v7.79.0)

Updates `@babel/core` from 7.29.7 to 8.0.1
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v8.0.1/packages/babel-core)

Updates `@babel/preset-react` from 7.29.7 to 8.0.1
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v8.0.1/packages/babel-preset-react)

Updates `@babel/preset-typescript` from 7.29.7 to 8.0.1
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v8.0.1/packages/babel-preset-typescript)

Updates `@babel/runtime` from 7.29.7 to 8.0.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v8.0.0/packages/babel-runtime)

Updates `@playwright/test` from 1.60.0 to 1.61.0
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.60.0...v1.61.0)

Updates `@types/node` from 25.9.2 to 25.9.3
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-react` from 5.2.0 to 6.0.2
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.2/packages/plugin-react)

---
updated-dependencies:
- dependency-name: "@codemirror/search"
  dependency-version: 6.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fullcalendar/core"
  dependency-version: 6.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fullcalendar/daygrid"
  dependency-version: 6.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fullcalendar/interaction"
  dependency-version: 6.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fullcalendar/react"
  dependency-version: 6.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/carousel"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/charts"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/core"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/dates"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/dropzone"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/form"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/hooks"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/modals"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/notifications"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/spotlight"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/vanilla-extract"
  dependency-version: 9.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.58.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: mantine-contextmenu
  dependency-version: 9.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: mantine-datatable
  dependency-version: 9.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.79.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@babel/core"
  dependency-version: 8.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@babel/preset-react"
  dependency-version: 8.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@babel/preset-typescript"
  dependency-version: 8.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@babel/runtime"
  dependency-version: 8.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@playwright/test"
  dependency-version: 1.61.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@types/node"
  dependency-version: 25.9.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* lower @vitejs/plugin-react

* fix matching

* temp fix for the non-loading of plugin settings

* remove loading badge for now

* fix test

* make test more precise

* fix syntax

* fix memo issues

* remove wasLoaded hack

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* fix test assumption (#12296)

* [API] Refactor API for duplicating objects (#12294)

* Implement generic serializer for custom model duplication

* Apply pattern to BuildOrder

* Add more generic options

* Bump API version

* Adjust default option

* Refactor existing implementations

* Dynamic class typing

* Add duplicate field to more model types

- Company
- ManufacturerPart
- SupplierPart
- SalesOrderShipment

* Implement parameter duplication for more models:

- Company
- ManufacturerPart
- SupplierPart

* Simplify code

* Refactor

* [UI] Snippet editor (#12299)

* Implement admin editor for report snippets

* Report asset management

* Add playwright test for report snippets

* Add playwright test for "Report Assets" panel

* Updated docs

* [UI] Add "IPN" column to installed items table (#12297)

* [docs] Report helper docs (#12300)

* [docs] Report helper docs

* Split out docs for assets and snippets

* Updates

* [db] Fix for UUID fields (#12301)

* Fix OpenAPI multipart file fields to use binary format (#12298)

* Fix OpenAPI multipart file fields to use binary format

Fixes #11246

* Update API version

* fix api version

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* reduce duplication (#12302)

* [UI] Pricing override (#12306)

* Correct display of pricing overrides

* Add min/max override reference lines

* Fix BarChart component

* [feature] Consumable part (#12295)

* Add "consumable" field to the Part model

* Add frontend integration

* Add badge

* Add docs

* Updated docs

* Add API filtering for new field

* Adjust API filters

* Update backend logic

* Adjust frontend

* Additional unit tests

* Update API version

* update test

* Add consumable icon

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* Order click-through on pricing panel (#12307)

* Pricing bugs (#12305)

* bug fix for get_price method

- Remove unused argument moq
- Allow case where 'multiples' = False

* Error handling for convert_to

* Error handling for PartPricing.save

* Remove unused function

* Revert function definition

* coverage ignore

* Add --keep option to setup-test task (#12308)

Allow keeping existing data

* Table refactor (#12309)

* Refactor table components

- Move underlying components into src/components/tables
- Actual table implementation stay in src/tables

* Fix vite warnings

* chore(deps): bump python in /contrib/container (#12276)

Bumps python from `44dd044` to `b877e50`.

---
updated-dependencies:
- dependency-name: python
  dependency-version: 3.14.6-slim-trixie
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group across 1 directory with 31 updates (#12316)

Bumps the dependencies group with 31 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/language](https://github.com/codemirror/language) | `6.12.3` | `6.12.4` |
| [@codemirror/state](https://github.com/codemirror/state) | `6.6.0` | `6.7.0` |
| [@codemirror/view](https://github.com/codemirror/view) | `6.43.1` | `6.43.4` |
| [@fortawesome/fontawesome-svg-core](https://github.com/FortAwesome/Font-Awesome) | `7.2.0` | `7.3.0` |
| [@fortawesome/free-regular-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `7.2.0` | `7.3.0` |
| [@fortawesome/free-solid-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `7.2.0` | `7.3.0` |
| [@mantine/carousel](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/carousel) | `9.3.2` | `9.4.1` |
| [@mantine/charts](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/charts) | `9.3.2` | `9.4.1` |
| [@mantine/core](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/core) | `9.3.2` | `9.4.1` |
| [@mantine/dates](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dates) | `9.3.2` | `9.4.1` |
| [@mantine/dropzone](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dropzone) | `9.3.2` | `9.4.1` |
| [@mantine/form](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/form) | `9.3.2` | `9.4.1` |
| [@mantine/hooks](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/hooks) | `9.3.2` | `9.4.1` |
| [@mantine/modals](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/modals) | `9.3.2` | `9.4.1` |
| [@mantine/notifications](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/notifications) | `9.3.2` | `9.4.1` |
| [@mantine/spotlight](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/spotlight) | `9.3.2` | `9.4.1` |
| [@mantine/vanilla-extract](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/vanilla-extract) | `9.3.2` | `9.4.1` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.58.0` | `10.62.0` |
| [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.101.0` | `5.101.2` |
| [@vanilla-extract/css](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/css) | `1.20.1` | `1.21.0` |
| [mantine-contextmenu](https://github.com/icflorescu/mantine-contextmenu) | `9.3.0` | `9.3.1` |
| [mantine-datatable](https://github.com/icflorescu/mantine-datatable) | `9.3.0` | `9.3.1` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.79.0` | `7.80.0` |
| [recharts](https://github.com/recharts/recharts) | `3.8.1` | `3.9.0` |
| [styled-components](https://github.com/styled-components/styled-components) | `6.4.2` | `6.4.3` |
| [@flakiness/playwright](https://github.com/flakiness/playwright) | `1.15.0` | `1.16.0` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.61.0` | `1.61.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.9.3` | `26.0.1` |
| [@vanilla-extract/vite-plugin](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/vite-plugin) | `5.2.2` | `5.2.3` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `7.3.5` | `7.3.6` |
| [vite-plugin-dts](https://github.com/qmhc/unplugin-dts/tree/HEAD/packages/vite-plugin-dts) | `5.0.2` | `5.0.3` |



Updates `@codemirror/language` from 6.12.3 to 6.12.4
- [Changelog](https://github.com/codemirror/language/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/language/commits)

Updates `@codemirror/state` from 6.6.0 to 6.7.0
- [Changelog](https://github.com/codemirror/state/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/state/commits)

Updates `@codemirror/view` from 6.43.1 to 6.43.4
- [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/view/commits)

Updates `@fortawesome/fontawesome-svg-core` from 7.2.0 to 7.3.0
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/7.2.0...7.3.0)

Updates `@fortawesome/free-regular-svg-icons` from 7.2.0 to 7.3.0
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/7.2.0...7.3.0)

Updates `@fortawesome/free-solid-svg-icons` from 7.2.0 to 7.3.0
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/7.2.0...7.3.0)

Updates `@mantine/carousel` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/carousel)

Updates `@mantine/charts` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/charts)

Updates `@mantine/core` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/core)

Updates `@mantine/dates` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/dates)

Updates `@mantine/dropzone` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/dropzone)

Updates `@mantine/form` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/form)

Updates `@mantine/hooks` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/hooks)

Updates `@mantine/modals` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/modals)

Updates `@mantine/notifications` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/notifications)

Updates `@mantine/spotlight` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/spotlight)

Updates `@mantine/vanilla-extract` from 9.3.2 to 9.4.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.4.1/packages/@mantine/vanilla-extract)

Updates `@sentry/react` from 10.58.0 to 10.62.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.58.0...10.62.0)

Updates `@tanstack/react-query` from 5.101.0 to 5.101.2
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.101.2/packages/react-query)

Updates `@vanilla-extract/css` from 1.20.1 to 1.21.0
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/css/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/css@1.21.0/packages/css)

Updates `mantine-contextmenu` from 9.3.0 to 9.3.1
- [Changelog](https://github.com/icflorescu/mantine-contextmenu/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icflorescu/mantine-contextmenu/commits)

Updates `mantine-datatable` from 9.3.0 to 9.3.1
- [Changelog](https://github.com/icflorescu/mantine-datatable/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icflorescu/mantine-datatable/commits)

Updates `react-hook-form` from 7.79.0 to 7.80.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.79.0...v7.80.0)

Updates `recharts` from 3.8.1 to 3.9.0
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.8.1...v3.9.0)

Updates `styled-components` from 6.4.2 to 6.4.3
- [Release notes](https://github.com/styled-components/styled-components/releases)
- [Commits](https://github.com/styled-components/styled-components/compare/styled-components@6.4.2...styled-components@6.4.3)

Updates `@flakiness/playwright` from 1.15.0 to 1.16.0
- [Release notes](https://github.com/flakiness/playwright/releases)
- [Commits](https://github.com/flakiness/playwright/compare/v1.15.0...v1.16.0)

Updates `@playwright/test` from 1.61.0 to 1.61.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.61.0...v1.61.1)

Updates `@types/node` from 25.9.3 to 26.0.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vanilla-extract/vite-plugin` from 5.2.2 to 5.2.3
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/vite-plugin/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/vite-plugin@5.2.3/packages/vite-plugin)

Updates `vite` from 7.3.5 to 7.3.6
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.6/packages/vite)

Updates `vite-plugin-dts` from 5.0.2 to 5.0.3
- [Release notes](https://github.com/qmhc/unplugin-dts/releases)
- [Changelog](https://github.com/qmhc/unplugin-dts/blob/main/packages/vite-plugin-dts/CHANGELOG.md)
- [Commits](https://github.com/qmhc/unplugin-dts/commits/vite-plugin-dts@5.0.3/packages/vite-plugin-dts)

---
updated-dependencies:
- dependency-name: "@codemirror/language"
  dependency-version: 6.12.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@codemirror/state"
  dependency-version: 6.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@codemirror/view"
  dependency-version: 6.43.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fortawesome/fontawesome-svg-core"
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@fortawesome/free-regular-svg-icons"
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@fortawesome/free-solid-svg-icons"
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/carousel"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/charts"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/core"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/dates"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/dropzone"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/form"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/hooks"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/modals"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/notifications"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/spotlight"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/vanilla-extract"
  dependency-version: 9.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.62.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.101.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/css"
  dependency-version: 1.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: mantine-contextmenu
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: mantine-datatable
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.80.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: recharts
  dependency-version: 3.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: styled-components
  dependency-version: 6.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@flakiness/playwright"
  dependency-version: 1.16.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@playwright/test"
  dependency-version: 1.61.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@types/node"
  dependency-version: 26.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/vite-plugin"
  dependency-version: 5.2.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: vite
  dependency-version: 7.3.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: vite-plugin-dts
  dependency-version: 5.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* New Crowdin translations by GitHub Action (#12284)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group with 4 updates (#12312)

Bumps the dependencies group with 4 updates: [actions/setup-python](https://github.com/actions/setup-python), [actions/cache](https://github.com/actions/cache), [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) and [CodSpeedHQ/action](https://github.com/codspeedhq/action).


Updates `actions/setup-python` from 6.2.0 to 6.3.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...ece7cb06caefa5fff74198d8649806c4678c61a1)

Updates `actions/cache` from 5.0.5 to 6.1.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9)

Updates `stefanzweifel/git-auto-commit-action` from 7.1.0 to 7.2.0
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/04702edda442b2e678b25b537cec683a1493fcb9...4a55954c782fc1ea30b9056cd3e7a2b40ca8887d)

Updates `CodSpeedHQ/action` from 4.17.6 to 4.18.1
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/63f3e98b61959fe67f146a3ff022e4136fe9bb9c...a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: actions/cache
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 4.18.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* [bug] Barcode bug fix (#12319)

* [bug] Check for null line_item when receiving items

* Additional unit testing

* Additional context

* Fix tests

* Fix for stocktake exporter (#12324)

* Robustify playwright tests (#12331)

* Robustify playwright tests

* More test tweaks

* [UI] Add form submission shortcut (#12328)

- Ctrl + enter submits the form

* Fix currency choices for PartPricing model (#12336)

* Fix currency choices for PartPricing model

- Remove dynamic choices from model definition
- Move validation step to the serializer
- Add validator to ensure only valid currencies can be used

* Add regression test

* Bump API version

* Fix notes on part creation (#12332)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* [bug] Plugin load fix (#12329)

* Update plugin name

* Backup accessor for plugin name

* Add null check for plg_db

* Adjust default behavior of "migrate" command (#12320)

* Adjust default behavior of "migrate" command

- Does not create new migration files automatically

* Add dummy field - ensure detected by CI

* Revert "Add dummy field - ensure detected by CI"

This reverts commit e7a101fe87.

* Fix typo

* Adjust contributing docs

* Add CHANGELOG entry

* Import internal price (#12341)

* Enable download from frontend panels

* Enable data import for part internal pricing

* Bump API version

* Update CHANGELOG

* [UI] Docs links (#12342)

* Simplify navigation links

* simplify version.py

* Simplify docs links

* Consolidate

* [docs]  Admin docs (#12345)

* Enhanced documentation for admin center and django-admin

* Fix links and wording

* remove placeholders

* Fix links

* Fix more links

* Currency options fix (#12343)

- Ensure currency options are loaded dynamically

* Add IPN column to BOM pricing panel (#12344)

* [UI] Form fix (#12348)

* Refactor API form fields

- Prevent reconstruction of all fields when single value changes
- Memoize components more intelligently
- Fix enter key callback ref

* memoize other field types too

* More memo

* Prevent duplicate API calls for related model field

* Add aria-label for IconField

* add playwright tests for form field coverage

* [UI] Page Load Improvements (#12334)

* Parallel initial requests

* Remove debouncing

* Refactor lazy loading of desktop / mobile view

* Reduce initial waiting for loadable components

* Fix duplication of API calls

* Further reduce duplicate calls

* Combine user roles into /user/me/ endpoint

* lazy load global import drawer

* lazy load table in plugin context

* Patch ScanButton

* Added playwright tests for login

* Adjust thresholds

* Bug fixes for PO receive (#12349)

* Bug fixes for PO receive

- Fix shadowed variable
- Notify listeners for all received items

* Cache part subs

* Improved error context (#12350)

- More useful error messaging if a task fails

* Fix data import bug (#12355)

- Fixes bug where imported data headers get out of sync
- Additional unit tests

* Remove dead pricing code on Part model (#12357)

* [refactor] Refactor StockItem methods (#12358)

* Refactor StockItem methods

- Refactor out common functionality
- Code cleanup

* Cleanup

* Prevent override of existing deltas

* [feature] Break apart assemblies (#12310)

* Implement API endpoint for stock disassembly

* Add basic frontend implementation

* Adjust required user permission

* Add preFormContent

* Read-only if serialized

* Adjust location and status of each subcomponent

* Handle null value

* display installed items in frontend form

* More unit tests

* Traceability

* Add docs

* Exclude virtual / consumable stock

* Additional docs

* Added bundled items docs

* More docs

* more docs tweaks

* Updated part docs

* Add playwright tests

* Robustify test

* suppress certain warnings in schema

* Adjust playwright tests

* bug fix

* Tweak playwright tests

* [refactor] Bulk actions (#12359)

* Add helper to bulk offload task

* bulk offload events

* Add unit test for bulk_offload_task

* Add context wrapper for bulk event creation inside looped funcs

* Add batching for stock tracking events

* Context wrapper for capturing offloaded tasks

* apply batching to other stock adjustment endpoints

* Add benchmarking tests for other API endpoints

* Benchmark test for serialize stock

* Reduce commet verbosity

* Apply benchmark to PO receive

* Refactor benchmarking

* PrefetchedPrimaryKeyRelatedField

- Provides O(1) lookup for serializer validation
- Significant improvements for large datasets

* Adjust unit test code

* Check for correct order of tracking operations

* [UI] Preview Drawer (#12117)

* Add <GlobalPreviewDrawer> component

* Allow plugins to interact

* provide either pk or instance data

* open preview drawer from calendar views

* Launch preview drawer directly from tables

* Add preview types

* Fix types

* CLear data on close

* Fix transition

* Allow caller to pass preview component

* AttributeGrid

* Use a table component

* Display info items

* Navigate to detail page from drawer

* Updates

* Refactor to use part detail view

* Display parameters

* Fix image caching

* Apply same to StockItem

* Remove old component

* Refactor details grid component

* Preview panel for PurchaseOrder model

* Implement for SalesOrder

* Support ReturnOrder

* SupplierPart and ManufacturerPart

* Support preview in parameteric tables

* support Company and BuildOrder

* Fix numbervalue

* BuildOrder and SalesOrderShipment

* location and category

* add user setting

* Fix typing

* Handle link clicks within preview drawer

* fixes

* Implement onClose callback

* Handle row click when panel preview is disabled

* Support custom detail links

* update playwright tests

* UI tweaks

* Add CHANGELOG entry

* docs

* define default API params per model type

* Split out more docs pages

* Simplify state ref

* Refactoring

* Simplify PreviewDrawer component

* observe user setting in calendar view

* Enable PreviewDrawer from RowViewAction

* Push render functions onto ModelInformation dict

* Fix lib compilation

* Refactor internal uses of RowViewAction

* typescript fixes

* Simplify PreviewDrawer component structure

* remove TODO placeholders

* [bug] prevent double-complete of shipments (#12366)

* [bug] Transfer order fixes (#12367)

* Handle failed transfer order transaction

* Prevent duplicate completion of transfer order

* Progressive falloff for delay (#12369)

* Prevent duplicate receive operation on ReturnOrder (#12368)

* [refactor] Remove MPTT mixin from StockItem model (#12360)

* Remove MPTT from StockItem model

* cleanup stock fixture file

* Remove tree rebuild code for StockItem

* Adjust API

* Update CHANGELOG  and API version

* remove tree references

* Additional checks

* Remove unused tests

* Add data migration test

* fix fk fields

* Cleanup

* Tweak unit test

* Revert bulk-create in unit test

* Don't rebuild StockItem models

* Add bulk_create_and_fetch helper model

- Overcome limitations of mysql

* Add unit test for new bulk-create helper

* Apply new helper to codebase

* Adjust unit test

* bug fix

* Adjust query limits

* Remove assert

* [bug] Child fix (#12374)

* Remove outdated helper

* Fix children prop and add regression test

* Hardening build outputs (#12376)

- ensure outputs cannot be double completed

* fix concurrent update issues (#12380)

- Ensure database values are used for delta updates
- Regression tests

* use new helper func (#12373)

* Uninstall fix (#12378)

* Prevent uninstall into structural location

* Regression tests

* [bug] Quantity fixes (#12375)

- Ensure valid quantity values on stock operations
- Regression testing

* [refactor] SalesOrder allocation fixes (#12379)

* Use API for unit test

* Refactor SalesOrderSerialAllocationSerializer

- Move business logic into the SalesOrder model

* Add unit testing for serial allocation

* Apply row-level locking when updating stock item quantity (#12385)

* Prevent duplication completion of ReturnOrder (#12386)

* Fix for BuildItem with zero quantity (#12387)

* [feature] Unique parameters (#12388)

* Add uniqueness requirement for parameter values

* Add documentation

* Do not copy unique parameters

* Updated playwright tests

* Enhanced validation checks for uniqueness

* Update documentation

* Update CHANGELOG

* Bump API version

* Bug fixes (#12365)

* Bug fixes:

- Enforce serial number requirements when receiving items
- Stricter merge checking
- Fix count-into-location bug
- Unit testing

* Additional unit tests

* Fix StockItem parent update on delete (#12377)

* Fix StockItem parent update on delete

* Check for null parents

* Add revision to SO and BO tables (#12398)

* Add a Revision column renderer

* Add Revision to SO and BO tables

* Move Description column after IPN and Revision to be consistent with other tables

* [bug] Tree parent fix (#12401)

* Refactor

* row locking on bulk-update

* Rebuild tree in background task

* Regression testing

* Fix unit test

* Allow more generous timeout

* Bulk delete line items (#12391)

* Add bulk-delete mixin for order line items

* Add unit tests

* Enable frontend support

* Add CHANGELOG entry

* Add locking control for TransferOrder

* Fix playwright tests

* Fix playwright tests

* prevent duplicate save event when creating a part (#12406)

* Bulk create events (#12405)

* Add initial benchmark test

* Enable event batching for BulkdCreate API mixin

* Fix duplicate save event for Parameter

* Apply event batching for bulk_update

* Similar testing for bulk_delete

* [UI] Display error information in boundary (#12403)

* Display error information in boundary

* Fix SecurityContext

* New Crowdin translations by GitHub Action (#12318)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix docs reqs (#12407)

* bump soupsieve

* general deps bump

* feat(ui): show variant stock indicator in parts table (#5959) (#12413)

* Fix update notification deduplication and release link (#12424)

* New Crowdin translations by GitHub Action (#12408)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Fix creation date formatting on part detail page (#12423)

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* fix(ui): show initial stock fields when PART_CREATE_INITIAL enabled (#12415)

* fix(ui): show initial stock fields when PART_CREATE_INITIAL enabled (#12266)

* Fix Docker setup for local Windows deployment.

Disable Redis disk persistence to avoid bind-mount permission errors that caused login 500s, and configure localhost as the default site URL.

* Apply Biome formatting to Playwright test file.

Fixes Style [prek] CI failure on PR #12415.

* Use specific locators in initial stock Playwright tests.

Avoid strict-mode violations from getByText('Initial Stock') matching multiple form elements.

* Scope initial stock Playwright test to part detail Stock tab.

Avoid strict-mode violations from duplicate Stock tabs on the part page.

* Use raw SQL inserts in MPTT migration test setup.

Avoid duplicate status_custom_key ORM bug in historical StockItem models.

* [feature] Line discount (#12393)

* Add "discount" support to order line items

* Fix total_price annotation for ExtraLineItem

* Add regression tests

* Add frontend support

* Updated documentation

* Added docs

* Bump API version and CHANGELOG

* Remove 'total_price' annotation

- Can be achieved using in-memory python methods

* Apply fix for migration testing

* Revert "Apply fix for migration testing"

This reverts commit 8d9f2dce8c.

* Different approach

* Adjust playwright threshold

* Improve request caching for plugin config objects (#12430)

* Improve request caching for plugin config objects

* Cache configs dict further

* New Crowdin translations by GitHub Action (#12425)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* [bug] Bom table fix (#12436)

* Fix logic for table context menu

* Memoize handleCellContextMenu

* Locking fixes (#12435)

* Secure row locks when trimming allocated stock

* Secure row locks when completing a SalesOrder

* Regression testing

* Further improvements and regression testing

* Ignore locking test for sqlite

* chore(deps): bump the dependencies group across 1 directory with 9 updates (#12428)

Bumps the dependencies group with 9 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [dorny/paths-filter](https://github.com/dorny/paths-filter) | `4.0.1` | `4.0.2` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `4.1.0` | `4.2.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.1.0` | `4.2.0` |
| [docker/login-action](https://github.com/docker/login-action) | `4.2.0` | `4.4.0` |
| [docker/metadata-action](https://github.com/docker/metadata-action) | `6.1.0` | `6.2.0` |
| [oasdiff/oasdiff-action/diff](https://github.com/oasdiff/oasdiff-action) | `3e9d440d37f468355457604348009f50e0cddbf3` | `024f6c399f9a21ada1addb0f9a36ce1bfac995f1` |
| [CodSpeedHQ/action](https://github.com/codspeedhq/action) | `4.18.1` | `4.18.5` |
| [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.36.2` | `4.37.0` |
| [actions/stale](https://github.com/actions/stale) | `10.3.0` | `10.4.0` |



Updates `dorny/paths-filter` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dorny/paths-filter/compare/fbd0ab8f3e69293af611ebaee6363fc25e6d187d...7b450fff21473bca461d4b92ce414b9d0420d706)

Updates `docker/setup-qemu-action` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/06116385d9baf250c9f4dcb4858b16962ea869c3...96fe6ef7f33517b61c61be40b68a1882f3264fb8)

Updates `docker/setup-buildx-action` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c)

Updates `docker/login-action` from 4.2.0 to 4.4.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/650006c6eb7dba73a995cc03b0b2d7f5ca915bee...af1e73f918a031802d376d3c8bbc3fe56130a9b0)

Updates `docker/metadata-action` from 6.1.0 to 6.2.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9...dc802804100637a589fabce1cb79ff13a1411302)

Updates `oasdiff/oasdiff-action/diff` from 3e9d440d37f468355457604348009f50e0cddbf3 to 024f6c399f9a21ada1addb0f9a36ce1bfac995f1
- [Release notes](https://github.com/oasdiff/oasdiff-action/releases)
- [Commits](https://github.com/oasdiff/oasdiff-action/compare/3e9d440d37f468355457604348009f50e0cddbf3...024f6c399f9a21ada1addb0f9a36ce1bfac995f1)

Updates `CodSpeedHQ/action` from 4.18.1 to 4.18.5
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f...f99becdce5e5d51fd556489ebef684f4ecfd6286)

Updates `github/codeql-action/upload-sarif` from 4.36.2 to 4.37.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...99df26d4f13ea111d4ec1a7dddef6063f76b97e9)

Updates `actions/stale` from 10.3.0 to 10.4.0
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899...1e223db275d687790206a7acac4d1a11bd6fe629)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-version: 4.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: docker/setup-qemu-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: docker/login-action
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: docker/metadata-action
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: oasdiff/oasdiff-action/diff
  dependency-version: 024f6c399f9a21ada1addb0f9a36ce1bfac995f1
  dependency-type: direct:production
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 4.18.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: actions/stale
  dependency-version: 10.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Read report/label templates in binary mode (#12432)

* Read report/label templates in binary mode

file_from_template read the template in text mode and wrapped the string
in a ContentFile. The ContentFile size then reflected the character count,
which differs from the UTF-8 byte length for any template that contains
multi-byte characters. Strict S3 implementations such as Backblaze B2
validate the Content-Length header and reject the upload with an
IncompleteBody error. AWS S3 tolerates the mismatch, so the problem is
not visible there.

inventree_transfer_order_report.html is 1458 characters but 1460 bytes.
Its upload fails during create_default_reports, the transaction rolls
back, and the default template is recreated and fails again on every
startup.

Use Path.read_bytes() so the ContentFile size matches the uploaded bytes
and the file handle is closed. Add a regression test asserting the size
equals the file's byte length.

* Test file_from_template across text encodings

* chore(deps): bump brace-expansion from 5.0.6 to 5.0.7 in /src/frontend (#12439)

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.6 to 5.0.7.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v5.0.6...v5.0.7)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 5.0.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump pillow from 12.2.0 to 12.3.0 in /src/backend (#12438)

* chore(deps): bump pillow from 12.2.0 to 12.3.0 in /src/backend

Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.2.0 to 12.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.2.0...12.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump the dependencies group across 2 directories with 22 updates (#12417)

* chore(deps): bump the dependencies group across 2 directories with 22 updates

Bumps the dependencies group with 1 update in the /docs directory: [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings).
Bumps the dependencies group with 21 updates in the /src/backend directory:

| Package | From | To |
| --- | --- | --- |
| [blessed](https://github.com/jquast/blessed) | `1.44.0` | `1.47.0` |
| [boto3](https://github.com/boto/boto3) | `1.43.36` | `1.43.45` |
| [botocore](https://github.com/boto/botocore) | `1.43.36` | `1.43.45` |
| [cffi](https://github.com/python-cffi/cffi) | `2.0.0` | `2.1.0` |
| [charset-normalizer](https://github.com/jawah/charset_normalizer) | `3.4.7` | `3.4.9` |
| [drf-spectacular](https://github.com/tfranzel/drf-spectacular) | `0.29.0` | `0.30.0` |
| [dulwich](https://github.com/dulwich/dulwich) | `1.2.6` | `1.2.10` |
| [fido2](https://github.com/Yubico/python-fido2) | `2.2.0` | `2.2.1` |
| [grpcio](https://github.com/grpc/grpc) | `1.81.1` | `1.82.1` |
| [jinxed](https://github.com/Rockhopper-Technologies/jinxed) | `2.0.4` | `2.1.0` |
| [pillow](https://github.com/python-pillow/Pillow) | `12.2.0` | `12.3.0` |
| [python-fsutil](https://github.com/fabiocaccamo/python-fsutil) | `0.16.1` | `0.17.0` |
| [rpds-py](https://github.com/crate-py/rpds) | `2026.5.1` | `2026.6.3` |
| [sentry-sdk](https://github.com/getsentry/sentry-python) | `2.63.0` | `2.64.0` |
| [setuptools](https://github.com/pypa/setuptools) | `82.0.1` | `83.0.0` |
| [tqdm](https://github.com/tqdm/tqdm) | `4.68.3` | `4.68.4` |
| [typing-extensions](https://github.com/python/typing_extensions) | `4.15.0` | `4.16.0` |
| [tzdata](https://github.com/python/tzdata) | `2026.2` | `2026.3` |
| [wcwidth](https://github.com/jquast/wcwidth) | `0.8.1` | `0.8.2` |
| [coverage](https://github.com/coveragepy/coveragepy) | `7.14.3` | `7.15.0` |
| [prek](https://github.com/j178/prek) | `0.4.5` | `0.4.8` |



Updates `mkdocstrings` from 1.0.4 to 1.0.5
- [Release notes](https://github.com/mkdocstrings/mkdocstrings/releases)
- [Changelog](https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/mkdocstrings/compare/1.0.4...1.0.5)

Updates `blessed` from 1.44.0 to 1.47.0
- [Release notes](https://github.com/jquast/blessed/releases)
- [Changelog](https://github.com/jquast/blessed/blob/master/docs/history.rst)
- [Commits](https://github.com/jquast/blessed/commits)

Updates `boto3` from 1.43.36 to 1.43.45
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.36...1.43.45)

Updates `botocore` from 1.43.36 to 1.43.45
- [Commits](https://github.com/boto/botocore/compare/1.43.36...1.43.45)

Updates `cffi` from 2.0.0 to 2.1.0
- [Release notes](https://github.com/python-cffi/cffi/releases)
- [Commits](https://github.com/python-cffi/cffi/compare/v2.0.0...v2.1.0)

Updates `charset-normalizer` from 3.4.7 to 3.4.9
- [Release notes](https://github.com/jawah/charset_normalizer/releases)
- [Changelog](https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jawah/charset_normalizer/compare/3.4.7...3.4.9)

Updates `drf-spectacular` from 0.29.0 to 0.30.0
- [Release notes](https://github.com/tfranzel/drf-spectacular/releases)
- [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.29.0...0.30.0)

Updates `dulwich` from 1.2.6 to 1.2.10
- [Release notes](https://github.com/dulwich/dulwich/releases)
- [Changelog](https://github.com/jelmer/dulwich/blob/main/NEWS)
- [Commits](https://github.com/dulwich/dulwich/compare/dulwich-1.2.6...dulwich-1.2.10)

Updates `fido2` from 2.2.0 to 2.2.1
- [Release notes](https://github.com/Yubico/python-fido2/releases)
- [Changelog](https://github.com/Yubico/python-fido2/blob/main/NEWS)
- [Commits](https://github.com/Yubico/python-fido2/compare/2.2.0...2.2.1)

Updates `grpcio` from 1.81.1 to 1.82.1
- [Release notes](https://github.com/grpc/grpc/releases)
- [Commits](https://github.com/grpc/grpc/compare/v1.81.1...v1.82.1)

Updates `jinxed` from 2.0.4 to 2.1.0
- [Release notes](https://github.com/Rockhopper-Technologies/jinxed/releases)
- [Commits](https://github.com/Rockhopper-Technologies/jinxed/compare/2.0.4...2.1.0)

Updates `pillow` from 12.2.0 to 12.3.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.2.0...12.3.0)

Updates `python-fsutil` from 0.16.1 to 0.17.0
- [Release notes](https://github.com/fabiocaccamo/python-fsutil/releases)
- [Changelog](https://github.com/fabiocaccamo/python-fsutil/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fabiocaccamo/python-fsutil/compare/0.16.1...0.17.0)

Updates `rpds-py` from 2026.5.1 to 2026.6.3
- [Release notes](https://github.com/crate-py/rpds/releases)
- [Changelog](https://github.com/crate-py/rpds/blob/main/release.toml)
- [Commits](https://github.com/crate-py/rpds/compare/v2026.5.1...v2026.6.3)

Updates `sentry-sdk` from 2.63.0 to 2.64.0
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.63.0...2.64.0)

Updates `setuptools` from 82.0.1 to 83.0.0
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v82.0.1...v83.0.0)

Updates `tqdm` from 4.68.3 to 4.68.4
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.68.3...v4.68.4)

Updates `typing-extensions` from 4.15.0 to 4.16.0
- [Release notes](https://github.com/python/typing_extensions/releases)
- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/python/typing_extensions/compare/4.15.0...4.16.0)

Updates `tzdata` from 2026.2 to 2026.3
- [Release notes](https://github.com/python/tzdata/releases)
- [Changelog](https://github.com/python/tzdata/blob/master/NEWS.md)
- [Commits](https://github.com/python/tzdata/compare/2026.2...2026.3)

Updates `wcwidth` from 0.8.1 to 0.8.2
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.8.1...0.8.2)

Updates `coverage` from 7.14.3 to 7.15.0
- [Release notes](https://github.com/coveragepy/coveragepy/releases)
- [Changelog](https://github.com/coveragepy/coveragepy/blob/main/CHANGES.rst)
- [Commits](https://github.com/coveragepy/coveragepy/compare/7.14.3...7.15.0)

Updates `prek` from 0.4.5 to 0.4.8
- [Release notes](https://github.com/j178/prek/releases)
- [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md)
- [Commits](https://github.com/j178/prek/compare/v0.4.5...v0.4.8)

---
updated-dependencies:
- dependency-name: mkdocstrings
  dependency-version: 1.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: blessed
  dependency-version: 1.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: boto3
  dependency-version: 1.43.45
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: botocore
  dependency-version: 1.43.45
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: cffi
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: charset-normalizer
  dependency-version: 3.4.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: drf-spectacular
  dependency-version: 0.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: dulwich
  dependency-version: 1.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: fido2
  dependency-version: 2.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: grpcio
  dependency-version: 1.82.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: jinxed
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: python-fsutil
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: rpds-py
  dependency-version: 2026.6.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: sentry-sdk
  dependency-version: 2.64.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: setuptools
  dependency-version: 83.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: tqdm
  dependency-version: 4.68.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: typing-extensions
  dependency-version: 4.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: tzdata
  dependency-version: '2026.3'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: wcwidth
  dependency-version: 0.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: coverage
  dependency-version: 7.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: prek
  dependency-version: 0.4.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

* lower drf-spectacular to remove api diff

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* Fix typo in terminology.md (#12452)

Corrected the spelling of 'shelf life' in the IMS section.

* Fix admin search for Address and Contact models (#12440)

* chore(deps): bump dompurify from 3.4.11 to 3.4.12 in /src/frontend (#12448)

Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.11 to 3.4.12.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.11...3.4.12)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.12
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* general deps bump (#12409)

* chore(deps): bump the dependencies group across 1 directory with 13 updates

Bumps the dependencies group with 13 updates in the /src/backend directory:

| Package | From | To |
| --- | --- | --- |
| [coverage](https://github.com/coveragepy/coveragepy) | `7.14.3` | `7.15.0` |
| [prek](https://github.com/j178/prek) | `0.4.5` | `0.4.6` |
| [typing-extensions](https://github.com/python/typing_extensions) | `4.15.0` | `4.16.0` |
| [blessed](https://github.com/jquast/blessed) | `1.44.0` | `1.45.0` |
| [boto3](https://github.com/boto/boto3) | `1.43.36` | `1.43.40` |
| [botocore](https://github.com/boto/botocore) | `1.43.36` | `1.43.40` |
| [dulwich](https://github.com/dulwich/dulwich) | `1.2.6` | `1.2.7` |
| [fido2](https://github.com/Yubico/python-fido2) | `2.2.0` | `2.2.1` |
| [jinxed](https://github.com/Rockhopper-Technologies/jinxed) | `2.0.4` | `2.1.0` |
| [pillow](https://github.com/python-pillow/Pillow) | `12.2.0` | `12.3.0` |
| [rpds-py](https://github.com/crate-py/rpds) | `2026.5.1` | `2026.6.3` |
| [sentry-sdk](https://github.com/getsentry/sentry-python) | `2.63.0` | `2.64.0` |
| [wcwidth](https://github.com/jquast/wcwidth) | `0.8.1` | `0.8.2` |



Updates `coverage` from 7.14.3 to 7.15.0
- [Release notes](https://github.com/coveragepy/coveragepy/releases)
- [Changelog](https://github.com/coveragepy/coveragepy/blob/main/CHANGES.rst)
- [Commits](https://github.com/coveragepy/coveragepy/compare/7.14.3...7.15.0)

Updates `prek` from 0.4.5 to 0.4.6
- [Release notes](https://github.com/j178/prek/releases)
- [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md)
- [Commits](https://github.com/j178/prek/compare/v0.4.5...v0.4.6)

Updates `typing-extensions` from 4.15.0 to 4.16.0
- [Release notes](https://github.com/python/typing_extensions/releases)
- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/python/typing_extensions/compare/4.15.0...4.16.0)

Updates `blessed` from 1.44.0 to 1.45.0
- [Release notes](https://github.com/jquast/blessed/releases)
- [Changelog](https://github.com/jquast/blessed/blob/master/docs/history.rst)
- [Commits](https://github.com/jquast/blessed/commits)

Updates `boto3` from 1.43.36 to 1.43.40
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.36...1.43.40)

Updates `botocore` from 1.43.36 to 1.43.40
- [Commits](https://github.com/boto/botocore/compare/1.43.36...1.43.40)

Updates `dulwich` from 1.2.6 to 1.2.7
- [Release notes](https://github.com/dulwich/dulwich/releases)
- [Changelog](https://github.com/jelmer/dulwich/blob/main/NEWS)
- [Commits](https://github.com/dulwich/dulwich/compare/dulwich-1.2.6...dulwich-1.2.7)

Updates `fido2` from 2.2.0 to 2.2.1
- [Release notes](https://github.com/Yubico/python-fido2/releases)
- [Changelog](https://github.com/Yubico/python-fido2/blob/main/NEWS)
- [Commits](https://github.com/Yubico/python-fido2/compare/2.2.0...2.2.1)

Updates `jinxed` from 2.0.4 to 2.1.0
- [Release notes](https://github.com/Rockhopper-Technologies/jinxed/releases)
- [Commits](https://github.com/Rockhopper-Technologies/jinxed/compare/2.0.4...2.1.0)

Updates `pillow` from 12.2.0 to 12.3.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.2.0...12.3.0)

Updates `rpds-py` from 2026.5.1 to 2026.6.3
- [Release notes](https://github.com/crate-py/rpds/releases)
- [Changelog](https://github.com/crate-py/rpds/blob/main/release.toml)
- [Commits](https://github.com/crate-py/rpds/compare/v2026.5.1...v2026.6.3)

Updates `sentry-sdk` from 2.63.0 to 2.64.0
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.63.0...2.64.0)

Updates `wcwidth` from 0.8.1 to 0.8.2
- [Release notes](https://github.com/jquast/wcwidth/releases)
- [Commits](https://github.com/jquast/wcwidth/compare/0.8.1...0.8.2)

---
updated-dependencies:
- dependency-name: coverage
  dependency-version: 7.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: prek
  dependency-version: 0.4.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: typing-extensions
  dependency-version: 4.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: blessed
  dependency-version: 1.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: boto3
  dependency-version: 1.43.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: botocore
  dependency-version: 1.43.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: dulwich
  dependency-version: 1.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: fido2
  dependency-version: 2.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: jinxed
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: rpds-py
  dependency-version: 2026.6.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: sentry-sdk
  dependency-version: 2.64.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: wcwidth
  dependency-version: 0.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

* master bump

* api bump

* bump a bit further

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Improvements to `PrintingOptionsSerializer` (#12434)

* Fixed issue with default `driver_options on `InvenTreeLabelPlugin`

* Provide current `machine` to `LabelPrinterBaseDriver.get_printing_options_serializer`

* [docs] Report discovery (#12449)

* Adds decorator to mark an attribute for report context discovery

* Update context variables in docs

* Include fields captured against each model type

* Expose more properties

* Image URL tags

* Add more attributes

* Rearrange docs

* Simplify docs

* Enforce type hinting for reportable properties

* Expose more properties for the Order model

* Auto-discover related / linked models

* Remove extra text

* Collapsible blocks

* Reduce boilerplate

* Remove cruft

* Enhance documentation for filename generation

* Cleanup

* [bug] BOM checksum fix (#12455)

* Enforce ordering of BOM items

* Add prefetch to getRequiredParts

* Add regression test

* [refactor] Complete shipment API endpoint (#12363)

* Use API for unit test

* Loop unrolling is super effective

* Additional unit testing

* Fix for bulk_create - use bulk_create_and_fetch

* Fix unit tests

* Fix unit tests

* Adjust unit test

* Revert return type on helper func

* Evaluate returned QuerySet

* Adjust unit tests

* Adjust complete_allocations

* Fix for bulk_create in unit test

* Reimplement complete_allocation for compatibility

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* [bug] Attachment str fix (#12461)

* Fix stringify for Attachment model

* Add regression tests

* Bug fix for exporting SalesOrderAllocation data (#12463)

* Bug fix for exporting SalesOrderAllocation data

* Regression test

* Bump API version

* Bug fix for unit test

* chore(backend): major allauth bump (#12454)

* mayjor allauth bump

* add PR link

* [refactor] Build allocation endpoints (#12361)

* Create benchmark for completing a build and consuming all items

* Refactor build consume task

* Add benchmarking

* Unroll allocate-stock serializer

* Complete build only after allocations are consumed

* re-export batch_events

* Add BulkPrefetchSerializerMixin

* Reduce queries even further

* Refactoring

* Unroll code and use bulk operations

* Refactoring for auto-allocation

* Add more test coverage for auto-allocation

* Fix model_reference_fields

* adjust unit test

* Apply concurrency protection

* Additional unit tests

* Remove per-line validation

* Fix unit test

* Adjust unit test

* Use bulk_create_and_fetch

* Cleanup

* Reimplement wrapper func for backwards compatibility

* Fix unit test

* Increase max query time

* Fix serializer

* Enforce pk ordering

* FIx for mysql

* chore(deps): bump the dependencies group across 1 directory with 2 updates (#12465)

* chore(deps): bump the dependencies group across 1 directory with 2 updates

Bumps the dependencies group with 2 updates in the /docs directory: [mkdocs-material](https://github.com/squidfunk/mkdocs-material) and [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings).


Updates `mkdocs-material` from 9.7.6 to 9.7.7
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.7.6...9.7.7)

Updates `mkdocstrings` from 1.0.5 to 1.0.6
- [Release notes](https://github.com/mkdocstrings/mkdocstrings/releases)
- [Changelog](https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/mkdocstrings/compare/1.0.5...1.0.6)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-version: 9.7.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: mkdocstrings
  dependency-version: 1.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

* update pin

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump the dependencies group across 1 directory with 17 updates (#12427)

* chore(deps): bump the dependencies group across 1 directory with 17 updates

Bumps the dependencies group with 17 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/view](https://github.com/codemirror/view) | `6.43.4` | `6.43.6` |
| [@fortawesome/react-fontawesome](https://github.com/FortAwesome/react-fontawesome) | `3.3.1` | `3.4.0` |
| [@fullcalendar/core](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/core-types) | `6.1.21` | `7.0.0` |
| [@fullcalendar/react](https://github.com/fullcalendar/fullcalendar/tree/HEAD/packages/react) | `6.1.21` | `7.0.0` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.62.0` | `10.65.0` |
| [@uiw/codemirror-theme-vscode](https://github.com/uiwjs/react-codemirror) | `4.25.10` | `4.25.11` |
| [@uiw/react-codemirror](https://github.com/uiwjs/react-codemirror) | `4.25.10` | `4.25.11` |
| [@vanilla-extract/css](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/css) | `1.21.0` | `1.21.1` |
| [dompurify](https://github.com/cure53/DOMPurify) | `3.4.11` | `3.4.12` |
| [fuse.js](https://github.com/krisk/Fuse) | `7.4.2` | `7.5.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.80.0` | `7.81.0` |
| [recharts](https://github.com/recharts/recharts) | `3.9.0` | `3.9.2` |
| [undici](https://github.com/nodejs/undici) | `8.5.0` | `8.7.0` |
| [@flakiness/playwright](https://github.com/flakiness/playwright) | `1.16.0` | `1.18.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.0.1` | `26.1.1` |
| [@vanilla-extract/vite-plugin](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/vite-plugin) | `5.2.3` | `5.2.4` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.9.3` | `7.0.2` |



Updates `@codemirror/view` from 6.43.4 to 6.43.6
- [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/view/commits)

Updates `@fortawesome/react-fontawesome` from 3.3.1 to 3.4.0
- [Release notes](https://github.com/FortAwesome/react-fontawesome/releases)
- [Changelog](https://github.com/FortAwesome/react-fontawesome/blob/main/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/react-fontawesome/compare/v3.3.1...v3.4.0)

Updates `@fullcalendar/core` from 6.1.21 to 7.0.0
- [Release notes](https://github.com/fullcalendar/fullcalendar/releases)
- [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fullcalendar/fullcalendar/commits/v7.0.0/packages/core-types)

Updates `@fullcalendar/react` from 6.1.21 to 7.0.0
- [Release notes](https://github.com/fullcalendar/fullcalendar/releases)
- [Changelog](https://github.com/fullcalendar/fullcalendar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fullcalendar/fullcalendar/commits/v7.0.0/packages/react)

Updates `@sentry/react` from 10.62.0 to 10.65.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.62.0...10.65.0)

Updates `@uiw/codemirror-theme-vscode` from 4.25.10 to 4.25.11
- [Release notes](https://github.com/uiwjs/react-codemirror/releases)
- [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.25.10...v4.25.11)

Updates `@uiw/react-codemirror` from 4.25.10 to 4.25.11
- [Release notes](https://github.com/uiwjs/react-codemirror/releases)
- [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.25.10...v4.25.11)

Updates `@vanilla-extract/css` from 1.21.0 to 1.21.1
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/css/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/css@1.21.1/packages/css)

Updates `dompurify` from 3.4.11 to 3.4.12
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.11...3.4.12)

Updates `fuse.js` from 7.4.2 to 7.5.0
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v7.4.2...v7.5.0)

Updates `react-hook-form` from 7.80.0 to 7.81.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.80.0...v7.81.0)

Updates `recharts` from 3.9.0 to 3.9.2
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.9.0...v3.9.2)

Updates `undici` from 8.5.0 to 8.7.0
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v8.5.0...v8.7.0)

Updates `@flakiness/playwright` from 1.16.0 to 1.18.0
- [Release notes](https://github.com/flakiness/playwright/releases)
- [Commits](https://github.com/flakiness/playwright/compare/v1.16.0...v1.18.0)

Updates `@types/node` from 26.0.1 to 26.1.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vanilla-extract/vite-plugin` from 5.2.3 to 5.2.4
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/vite-plugin/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/vite-plugin@5.2.4/packages/vite-plugin)

Updates `typescript` from 5.9.3 to 7.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: "@codemirror/view"
  dependency-version: 6.43.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fortawesome/react-fontawesome"
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@fullcalendar/core"
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@fullcalendar/react"
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.65.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@uiw/codemirror-theme-vscode"
  dependency-version: 4.25.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@uiw/react-codemirror"
  dependency-version: 4.25.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/css"
  dependency-version: 1.21.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: dompurify
  dependency-version: 3.4.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: fuse.js
  dependency-version: 7.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.81.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: recharts
  dependency-version: 3.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: undici
  dependency-version: 8.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@flakiness/playwright"
  dependency-version: 1.18.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@types/node"
  dependency-version: 26.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/vite-plugin"
  dependency-version: 5.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: typescript
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix tsconfig

* fix setup for build - lower typescript

* fix resolution

* lower fullcalendar

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump gitpython from 3.1.52 to 3.1.54 in /docs (#12467)

* chore(deps): bump gitpython from 3.1.52 to 3.1.54 in /docs

Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.52 to 3.1.54.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.52...3.1.54)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-version: 3.1.54
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* Add order sorting for sales order allocation tables (#12468)

* Fix part SalesOrder table (#12469)

* Fix part SalesOrder table

- Show line item quantity, not number of lines

* add regression test

* Bump API version

* Fix Redis write failures on Windows Docker bind mounts (#12418)

* Fix Docker setup for local Windows deployment.

Disable Redis disk persistence to avoid bind-mount permission errors that caused login 500s, and configure localhost as the default site URL.

* Fix Redis write failures on Windows Docker bind mounts.

Disable RDB persistence for the cache container so login and other cache writes do not fail when the Redis data volume cannot be written on Windows hosts.

* Keep Redis volume mount while disabling disk persistence.

Addresses review feedback on #12418: retain the external /data volume from
#11100 but disable RDB/AOF writes so Windows bind mounts no longer trigger
MISCONF errors.

* Offfload email notification (#12470)

* Offfload email notification

* Run email sync in testing

* Add configurable default for PO line item merging (#12472)

* Add configurable default for PO line item merging

Introduce PURCHASEORDER_MERGE_LINE_ITEMS global setting to control the
default state of the merge_items option when creating purchase order lines.

Fixes #10947

* Apply ruff and biome formatting for CI

* On order filter (#12476)

* Add "on order" filter for Part model

- Added API filter
- Added table filter
- Added table column

* Bump API version

* Add table sorting

* Adjust API text

* [UI] Add search result preview (#12475)

* [UI] Add search result preview

* Updated search docs

* [UI] Display all error table field error messages (#12456)

* Display all error table field error messages

* Adjust playwright test

* Refactor sales order methods: (#12477)

- Cancel sales order
- Assign serial numbers

* chore(deps): bump python in /contrib/container (#12479)

Bumps python from `b877e50` to `cea0e60`.

---
updated-dependencies:
- dependency-name: python
  dependency-version: 3.14.6-slim-trixie
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(backend): registry install command (#11657)

* Unable to install plugins through web UI using custom registry and/or Python wheel files.
Fixes #11460

* use more fitting variable name

* add typing

* clean up logic flow - make easier to understand

* make check easier to understand

* reduce complexity

* ensure user is tested

* add more tests

* add user validation

* move test

* disable uninstall in test

* Update test_api.py

* style fix

* fix typing

* check if pip exsists

* fix gate

* fix typo

* reference pip instead

* make test more tolerant

* revert permission check change

* remove new test

---------

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* chore(deps): bump the dependencies group with 7 updates (#12480)

* chore(deps): bump the dependencies group with 7 updates

Bumps the dependencies group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` |
| [actions/setup-python](https://github.com/actions/setup-python) | `6.3.0` | `7.0.0` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.5` | `2.0.6` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.5.7` | `0.6.0` |
| [actions/attest](https://github.com/actions/attest) | `4.1.1` | `4.2.0` |
| [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.37.0` | `4.37.1` |
| [crowdin/github-action](https://github.com/crowdin/github-action) | `2.16.3` | `2.16.4` |


Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `actions/setup-python` from 6.3.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/ece7cb06caefa5fff74198d8649806c4678c61a1...5fda3b95a4ea91299a34e894583c3862153e4b97)

Updates `j178/prek-action` from 2.0.5 to 2.0.6
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](https://github.com/j178/prek-action/compare/e98a699c41eb69ab013a45817a0406469a748f8d...5337cb91e0fa35a7ff31b9ca345126d8bbbcdf16)

Updates `zizmorcore/zizmor-action` from 0.5.7 to 0.6.0
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/192e21d79ab29983730a13d1382995c2307fbcaa...6599ee8b7a49aef6a770f63d261d214911a7ce02)

Updates `actions/attest` from 4.1.1 to 4.2.0
- [Release notes](https://github.com/actions/attest/releases)
- [Changelog](https://github.com/actions/attest/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest/compare/a1948c3f048ba23858d222213b7c278aabede763...f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6)

Updates `github/codeql-action/upload-sarif` from 4.37.0 to 4.37.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/99df26d4f13ea111d4ec1a7dddef6063f76b97e9...7188fc363630916deb702c7fdcf4e481b751f97a)

Updates `crowdin/github-action` from 2.16.3 to 2.16.4
- [Release notes](https://github.com/crowdin/github-action/releases)
- [Commits](https://github.com/crowdin/github-action/compare/52aa776766211d83d975df51f3b9c53c2f8ba35f...e0c8f73cdc0fafde9396e056c5038217000a32d1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: actions/setup-python
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: j178/prek-action
  dependency-version: 2.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: actions/attest
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: crowdin/github-action
  dependency-version: 2.16.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix pin

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump postcss from 8.5.15 to 8.5.23 in /src/frontend (#12466)

Bumps [postcss](https://github.com/postcss/postcss) from 8.5.15 to 8.5.23.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.15...8.5.23)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.23
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump the dependencies group across 1 directory with 14 updates (#12485)

Bumps the dependencies group with 14 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@fortawesome/fontawesome-svg-core](https://github.com/FortAwesome/Font-Awesome) | `7.3.0` | `7.3.1` |
| [@fortawesome/free-regular-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `7.3.0` | `7.3.1` |
| [@fortawesome/free-solid-svg-icons](https://github.com/FortAwesome/Font-Awesome) | `7.3.0` | `7.3.1` |
| [@fortawesome/react-fontawesome](https://github.com/FortAwesome/react-fontawesome) | `3.4.0` | `3.5.0` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.65.0` | `10.67.0` |
| [@tabler/icons-react](https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react) | `3.44.0` | `3.45.0` |
| [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.101.2` | `5.101.3` |
| [mantine-contextmenu](https://github.com/icflorescu/mantine-contextmenu) | `9.3.1` | `9.4.0` |
| [mantine-datatable](https://github.com/icflorescu/mantine-datatable) | `9.3.1` | `9.4.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.81.0` | `7.82.0` |
| [recharts](https://github.com/recharts/recharts) | `3.9.2` | `3.10.0` |
| [styled-components](https://github.com/styled-components/styled-components) | `6.4.3` | `6.4.4` |
| [undici](https://github.com/nodejs/undici) | `8.7.0` | `8.8.0` |
| [@vanilla-extract/vite-plugin](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/vite-plugin) | `5.2.4` | `5.2.5` |



Updates `@fortawesome/fontawesome-svg-core` from 7.3.0 to 7.3.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/7.3.0...7.3.1)

Updates `@fortawesome/free-regular-svg-icons` from 7.3.0 to 7.3.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/7.3.0...7.3.1)

Updates `@fortawesome/free-solid-svg-icons` from 7.3.0 to 7.3.1
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/7.3.0...7.3.1)

Updates `@fortawesome/react-fontawesome` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/FortAwesome/react-fontawesome/releases)
- [Changelog](https://github.com/FortAwesome/react-fontawesome/blob/main/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/react-fontawesome/compare/v3.4.0...v3.5.0)

Updates `@sentry/react` from 10.65.0 to 10.67.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.65.0...10.67.0)

Updates `@tabler/icons-react` from 3.44.0 to 3.45.0
- [Release notes](https://github.com/tabler/tabler-icons/releases)
- [Commits](https://github.com/tabler/tabler-icons/commits/v3.45.0/packages/icons-react)

Updates `@tanstack/react-query` from 5.101.2 to 5.101.3
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.101.3/packages/react-query)

Updates `mantine-contextmenu` from 9.3.1 to 9.4.0
- [Changelog](https://github.com/icflorescu/mantine-contextmenu/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icflorescu/mantine-contextmenu/commits)

Updates `mantine-datatable` from 9.3.1 to 9.4.0
- [Changelog](https://github.com/icflorescu/mantine-datatable/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icflorescu/mantine-datatable/commits)

Updates `react-hook-form` from 7.81.0 to 7.82.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.81.0...v7.82.0)

Updates `recharts` from 3.9.2 to 3.10.0
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.9.2...v3.10.0)

Updates `styled-components` from 6.4.3 to 6.4.4
- [Release notes](https://github.com/styled-components/styled-components/releases)
- [Commits](https://github.com/styled-components/styled-components/compare/styled-components@6.4.3...styled-components@6.4.4)

Updates `undici` from 8.7.0 to 8.8.0
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v8.7.0...v8.8.0)

Updates `@vanilla-extract/vite-plugin` from 5.2.4 to 5.2.5
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/vite-plugin/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/vite-plugin@5.2.5/packages/vite-plugin)

---
updated-dependencies:
- dependency-name: "@fortawesome/fontawesome-svg-core"
  dependency-version: 7.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fortawesome/free-regular-svg-icons"
  dependency-version: 7.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fortawesome/free-solid-svg-icons"
  dependency-version: 7.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@fortawesome/react-fontawesome"
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.67.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@tabler/icons-react"
  dependency-version: 3.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.101.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: mantine-contextmenu
  dependency-version: 9.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: mantine-datatable
  dependency-version: 9.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.82.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: recharts
  dependency-version: 3.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: styled-components
  dependency-version: 6.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: undici
  dependency-version: 8.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/vite-plugin"
  dependency-version: 5.2.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* [bug] Fix concurrency issues for allocation (#12478)

* Fix concurrency issues for allocation

* Remove duplicate atomic call

* Reduce query count

* [bug] Unique constraint for serial numbers (#12483)

* Unique constraint for serial numbers

* Revert unrelated changes

* Updated tests

* Build output serial number docs (#12486)

* Remove serial number restriction when creating build outputs

* Updated docs

* additional docs

* [API] Refactor stock adjustment endpoints (#12488)

* Filtering for report snippets (#12487)

* Filtering for report snippets

* Bump API version

* Token save fix (#12491)

- Only update 'last_seen' field

* Improve validation for import session (#12492)

- Ensure that validated data is a dict shape

* Concurrency fix for scheduled tasks (#12493)

- Prevent multiple instances of scheduled tasks from plugins

* remove errant test report (#12496)

* Adjust demo-dataset for CI (#12500)

* New Crowdin translations by GitHub Action (#12437)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Fix admin search for PurchaseOrderLineItem (#12508)

Expand search_fields on PurchaseOrderLineItemAdmin to allow
searching by part name, part description, supplier SKU,
order reference, and supplier name.

Previously, only the optional 'reference' field was searchable,
making it impossible to find line items by part or order details.

- part__part__name: search by underlying Part name
- part__part__description: search by Part description
- part__SKU: search by Supplier SKU
- order__reference: search by Purchase Order reference
- order__supplier__name: search by Supplier name

Also adds a unit test to verify the search_fields are correctly
configured.

* Fix for data import "update" (#12513)

- Use partial update on serializer
- Mark other fields as not required (pk only)

* Handle report error on missing svg data (#12514)

* Handle report error on missing svg data

* Add regression tests

* Row locking for data import / update (#12515)

- Concurrency protection for data imports

* Fix for TreeFieldComponent (#12519)

- Prevent deselect by clicking on same entry
- Updated playwright tests

* Robustify playwright test (#12522)

* [UI] Keep Add Parts button visible in Parametric View (#12392)

* [UI] Keep Add Parts button visible in Parametric View

* [UI] Add PartCreationMenu component for shared part creation actions

* [UI] Fix unused imports and import ordering in PartTable and ParametricDataTable

* [UI] Fix ambiguous text locator in parametric view test

* [UI] Fix import formatting in PartTable

---------

Co-authored-by: Hana <hana@MacBook-Air-M1.local>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* New Crowdin translations by GitHub Action (#12512)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Demo ci check (#12530)

* Remove branch checking in workflow files

* Detect demo branch based on software version

* Fix typo

* Fix for N+1 issues in stock item serializing (#12534)

* chore(deps): bump the dependencies group across 1 directory with 9 updates (#12526)

* chore(deps): bump the dependencies group across 1 directory with 9 updates

Bumps the dependencies group with 9 updates in the /src/backend directory:

| Package | From | To |
| --- | --- | --- |
| [boto3](https://github.com/boto/boto3) | `1.43.53` | `1.43.55` |
| [botocore](https://github.com/boto/botocore) | `1.43.53` | `1.43.55` |
| [django-oauth-toolkit](https://github.com/django-oauth/django-oauth-toolkit) | `3.3.0` | `3.4.0` |
| [grpcio](https://github.com/grpc/grpc) | `1.82.1` | `1.83.0` |
| [s3transfer](https://github.com/boto/s3transfer) | `0.19.1` | `0.19.2` |
| [tqdm](https://github.com/tqdm/tqdm) | `4.69.0` | `4.69.1` |
| [prek](https://github.com/j178/prek) | `0.4.10` | `0.4.11` |
| [types-psycopg2](https://github.com/python/typeshed) | `2.9.21.20260712` | `2.9.21.20260724` |
| [types-pyyaml](https://github.com/python/typeshed) | `6.0.12.20260518` | `6.0.12.20260724` |



Updates `boto3` from 1.43.53 to 1.43.55
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.53...1.43.55)

Updates `botocore` from 1.43.53 to 1.43.55
- [Commits](https://github.com/boto/botocore/compare/1.43.53...1.43.55)

Updates `django-oauth-toolkit` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/django-oauth/django-oauth-toolkit/releases)
- [Changelog](https://github.com/django-oauth/django-oauth-toolkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/django-oauth/django-oauth-toolkit/compare/3.3.0...3.4.0)

Updates `grpcio` from 1.82.1 to 1.83.0
- [Release notes](https://github.com/grpc/grpc/releases)
- [Commits](https://github.com/grpc/grpc/compare/v1.82.1...v1.83.0)

Updates `s3transfer` from 0.19.1 to 0.19.2
- [Changelog](https://github.com/boto/s3transfer/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/s3transfer/compare/0.19.1...0.19.2)

Updates `tqdm` from 4.69.0 to 4.69.1
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.69.0...v4.69.1)

Updates `prek` from 0.4.10 to 0.4.11
- [Release notes](https://github.com/j178/prek/releases)
- [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md)
- [Commits](https://github.com/j178/prek/compare/v0.4.10...v0.4.11)

Updates `types-psycopg2` from 2.9.21.20260712 to 2.9.21.20260724
- [Commits](https://github.com/python/typeshed/commits)

Updates `types-pyyaml` from 6.0.12.20260518 to 6.0.12.20260724
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: botocore
  dependency-version: 1.43.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: django-oauth-toolkit
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: grpcio
  dependency-version: 1.83.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: s3transfer
  dependency-version: 0.19.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: tqdm
  dependency-version: 4.69.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: prek
  dependency-version: 0.4.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: types-psycopg2
  dependency-version: 2.9.21.20260724
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: types-pyyaml
  dependency-version: 6.0.12.20260724
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* [API] Optional field permissions (#12529)

* Add permissions check for OptionalField

* Adjust existing unit tests

* Add caching

* Additional tests

* Additional testing

* Add exclusions for owner and group models

* Bump CHANGELOG

* Detect demo branch based on software version

* Updated docstrings

* chore(deps): bump undici from 8.8.0 to 8.9.0 in /src/frontend (#12543)

Bumps [undici](https://github.com/nodejs/undici) from 8.8.0 to 8.9.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v8.8.0...v8.9.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 8.9.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump gitpython from 3.1.54 to 3.1.57 in /docs (#12545)

* chore(deps): bump gitpython from 3.1.54 to 3.1.57 in /docs

Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.54 to 3.1.57.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.54...3.1.57)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-version: 3.1.57
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump the dependencies group across 1 directory with 23 updates (#12547)

Bumps the dependencies group with 23 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/view](https://github.com/codemirror/view) | `6.43.6` | `6.43.7` |
| [@mantine/carousel](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/carousel) | `9.4.1` | `9.5.0` |
| [@mantine/charts](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/charts) | `9.4.1` | `9.5.0` |
| [@mantine/core](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/core) | `9.4.1` | `9.5.0` |
| [@mantine/dates](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dates) | `9.4.1` | `9.5.0` |
| [@mantine/dropzone](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dropzone) | `9.4.1` | `9.5.0` |
| [@mantine/form](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/form) | `9.4.1` | `9.5.0` |
| [@mantine/hooks](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/hooks) | `9.4.1` | `9.5.0` |
| [@mantine/modals](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/modals) | `9.4.1` | `9.5.0` |
| [@mantine/notifications](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/notifications) | `9.4.1` | `9.5.0` |
| [@mantine/spotlight](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/spotlight) | `9.4.1` | `9.5.0` |
| [@mantine/vanilla-extract](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/vanilla-extract) | `9.4.1` | `9.5.0` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.67.0` | `10.68.0` |
| [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.101.3` | `5.101.4` |
| [@vanilla-extract/css](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/css) | `1.21.1` | `1.21.2` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.82.0` | `7.83.0` |
| [react-is](https://github.com/react/react/tree/HEAD/packages/react-is) | `19.2.7` | `19.2.8` |
| [recharts](https://github.com/recharts/recharts) | `3.10.0` | `3.10.1` |
| [@flakiness/playwright](https://github.com/flakiness/playwright) | `1.18.0` | `2.0.0` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.61.1` | `1.62.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.1` | `26.1.2` |
| [@vanilla-extract/vite-plugin](https://github.com/vanilla-extract-css/vanilla-extract/tree/HEAD/packages/vite-plugin) | `5.2.5` | `5.2.6` |
| [rollup](https://github.com/rollup/rollup) | `4.62.2` | `4.62.3` |



Updates `@codemirror/view` from 6.43.6 to 6.43.7
- [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/view/commits)

Updates `@mantine/carousel` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/carousel)

Updates `@mantine/charts` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/charts)

Updates `@mantine/core` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/core)

Updates `@mantine/dates` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/dates)

Updates `@mantine/dropzone` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/dropzone)

Updates `@mantine/form` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/form)

Updates `@mantine/hooks` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/hooks)

Updates `@mantine/modals` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/modals)

Updates `@mantine/notifications` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/notifications)

Updates `@mantine/spotlight` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/spotlight)

Updates `@mantine/vanilla-extract` from 9.4.1 to 9.5.0
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.0/packages/@mantine/vanilla-extract)

Updates `@sentry/react` from 10.67.0 to 10.68.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/10.68.0/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.67.0...10.68.0)

Updates `@tanstack/react-query` from 5.101.3 to 5.101.4
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.101.4/packages/react-query)

Updates `@vanilla-extract/css` from 1.21.1 to 1.21.2
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/css/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/css@1.21.2/packages/css)

Updates `react-hook-form` from 7.82.0 to 7.83.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.82.0...v7.83.0)

Updates `react-is` from 19.2.7 to 19.2.8
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.2.8/packages/react-is)

Updates `recharts` from 3.10.0 to 3.10.1
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.10.0...v3.10.1)

Updates `@flakiness/playwright` from 1.18.0 to 2.0.0
- [Release notes](https://github.com/flakiness/playwright/releases)
- [Commits](https://github.com/flakiness/playwright/compare/v1.18.0...v2.0.0)

Updates `@playwright/test` from 1.61.1 to 1.62.0
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.61.1...v1.62.0)

Updates `@types/node` from 26.1.1 to 26.1.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vanilla-extract/vite-plugin` from 5.2.5 to 5.2.6
- [Release notes](https://github.com/vanilla-extract-css/vanilla-extract/releases)
- [Changelog](https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/vite-plugin/CHANGELOG.md)
- [Commits](https://github.com/vanilla-extract-css/vanilla-extract/commits/@vanilla-extract/vite-plugin@5.2.6/packages/vite-plugin)

Updates `rollup` from 4.62.2 to 4.62.3
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.62.2...v4.62.3)

---
updated-dependencies:
- dependency-name: "@codemirror/view"
  dependency-version: 6.43.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/carousel"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/charts"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/core"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/dates"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/dropzone"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/form"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/hooks"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/modals"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/notifications"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/spotlight"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@mantine/vanilla-extract"
  dependency-version: 9.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.68.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.101.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/css"
  dependency-version: 1.21.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.83.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: react-is
  dependency-version: 19.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: recharts
  dependency-version: 3.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@flakiness/playwright"
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: "@playwright/test"
  dependency-version: 1.62.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@types/node"
  dependency-version: 26.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@vanilla-extract/vite-plugin"
  dependency-version: 5.2.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: rollup
  dependency-version: 4.62.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump undici from 6.27.0 to 8.10.0 in /src/frontend (#12544)

Bumps [undici](https://github.com/nodejs/undici) from 6.27.0 to 8.10.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.27.0...v8.10.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 8.10.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group with 7 updates (#12541)

* chore(deps): bump the dependencies group with 7 updates

Bumps the dependencies group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [docker/login-action](https://github.com/docker/login-action) | `4.4.0` | `4.5.2` |
| [oasdiff/oasdiff-action/diff](https://github.com/oasdiff/oasdiff-action) | `0.1.6` | `0.1.10` |
| [CodSpeedHQ/action](https://github.com/codspeedhq/action) | `4.18.5` | `4.19.1` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.6.0` | `0.6.1` |
| [ossf/scorecard-action](https://github.com/ossf/scorecard-action) | `2.4.3` | `2.4.4` |
| [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.37.1` | `4.37.3` |
| [actions/stale](https://github.com/actions/stale) | `10.4.0` | `11.0.0` |


Updates `docker/login-action` from 4.4.0 to 4.5.2
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/af1e73f918a031802d376d3c8bbc3fe56130a9b0...371161bbe7024a29a25c5e19bfcbc0804fe9ad2c)

Updates `oasdiff/oasdiff-action/diff` from 0.1.6 to 0.1.10
- [Release notes](https://github.com/oasdiff/oasdiff-action/releases)
- [Commits](https://github.com/oasdiff/oasdiff-action/compare/024f6c399f9a21ada1addb0f9a36ce1bfac995f1...0ab8ad204b00d25acc5ae87106281433e288d0c1)

Updates `CodSpeedHQ/action` from 4.18.5 to 4.19.1
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/f99becdce5e5d51fd556489ebef684f4ecfd6286...f22792bfac16f3e14eb9fbea76f4a48e9cc22b93)

Updates `zizmorcore/zizmor-action` from 0.6.0 to 0.6.1
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/6599ee8b7a49aef6a770f63d261d214911a7ce02...6fc4b006235f201fdab3722e17240ab420d580e5)

Updates `ossf/scorecard-action` from 2.4.3 to 2.4.4
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/4eaacf0543bb3f2c246792bd56e8cdeffafb205a...2d1146689b8cda280b9bc96326124645441f03bc)

Updates `github/codeql-action/upload-sarif` from 4.37.1 to 4.37.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7188fc363630916deb702c7fdcf4e481b751f97a...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81)

Updates `actions/stale` from 10.4.0 to 11.0.0
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/1e223db275d687790206a7acac4d1a11bd6fe629...4391f3da665fdf50b6810c1a66712fb9ba21aa93)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.5.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: oasdiff/oasdiff-action/diff
  dependency-version: 0.1.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 4.19.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: ossf/scorecard-action
  dependency-version: 2.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: actions/stale
  dependency-version: 11.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update qc_checks.yaml

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump cryptography from 49.0.0 to 50.0.0 in /src/backend (#12546)

* chore(deps): bump cryptography from 49.0.0 to 50.0.0 in /src/backend

Bumps [cryptography](https://github.com/pyca/cryptography) from 49.0.0 to 50.0.0.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/49.0.0...50.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 50.0.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* Fix permissions for group and RuleSet endpoints (#12563)

- Require StaffRole in addition to is_staff

* Handle missing part (#12566)

Part instance may have already been deleted in post_delete hook for related models.

* Deduplicate part pricing updates per session (#12564)

* Barcode API bugs (#12565)

* Add explicit permission checks for barcode scanning

- Previous role_required attribute did not do anything

* Additional unit tests

* [API] Handle AppRegistryNotReady (#12571)

Explicit handling for AppRegistryNotReady error

* [refactor] Improve efficiency of check_missing_pricing (#12572)

* [bug] excel encoding for data import (#12576)

- Handle different encoding types for excel import
- Fail cleanly if cannot read file

* [bug] Fix post-delete actions (#12575)

- Check that underlying part is still available

* [bug] Fix getLogoImage helper (#12577)

* [bug] Fix getLogoImage helper

- Do not return a file:// URI

* cleanup code

* [bug] Fix part duplicate checks (#12574)

* [bug] Fix part duplicate checks

* Additional unit tests

* Fix flaky test on sqlite (#12582)

* [sentry] Do not report MethodNotAllowed (#12584)

* [bug] Handle deleted Part (#12578)

* [API] Restrict barcode scan history (#12569)

- A non-staff user can only view their own results

* [bug] Validate location when completing build outputs (#12570)

* [bug] Validate location when completing build outputs

- Cannot be structural

* Fix unit test

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* [bug] Fix PartStocktakeSerializer (#12587)

Closes https://github.com/inventree/InvenTree/issues/12555

* [docs] Improve setup guide for non-standard hosting (#12588)

* [docs] Updated docs for complex server setups

Ref: https://github.com/inventree/InvenTree/discussions/12538

* Add FAQ entry

* [docker] Include pip license file (#12583)

* [docker] Include pip license file

This file has been missing in production builds

* Add CI test

* Update contrib/container/Dockerfile

Co-authored-by: Matthias Mair <code@mjmair.com>

* Fix typo

* path fix

* More pathing fixes

---------

Co-authored-by: Matthias Mair <code@mjmair.com>

* [bug] Fix for plugin fetching (#12590)

- Prevent operation on stale plugin

* Data import fix (#12568)

* Specify JSON encoder for data import fields

- Fixes encoding issues when importing from XLSX file

* Add regression test

* Fix faulty error handler

* Fix for unit test

* Fix test result ordering by test timestamps (#12533)

* Fix test result ordering by test timestamps

* Refractor test result comparison helper

* Apply formatting fixes

* Fix frontend formatting

* Avoid mutating test result records

* Add migration for test result ordering

* Retry documentation build

---------

Co-authored-by: jayasree723 <confidentlehmann@tomorjerry.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* Fix Install Stock Items shows only selected parts (#12596)

* Bug Fix Install Stock Item showing variant stock when BOM disallows variants

* Add regression test for include_variants stock filter

---------

Co-authored-by: Siddhartha Ravilla <ravilla.si@northeastern.edu>

* [UI] Bulk Delete Enhancements (#12601)

* Add optional filtering for bulkDelete

* Enhanced pre-form content

* chore(deps): bump gitpython from 3.1.57 to 3.1.58 in /docs (#12593)

* chore(deps): bump gitpython from 3.1.57 to 3.1.58 in /docs

Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.57 to 3.1.58.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.57...3.1.58)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-version: 3.1.58
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* chore(deps): bump pypdf from 6.14.2 to 6.15.0 in /src/backend (#12594)

* chore(deps): bump pypdf from 6.14.2 to 6.15.0 in /src/backend

Bumps [pypdf](https://github.com/py-pdf/pypdf) from 6.14.2 to 6.15.0.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/6.14.2...6.15.0)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-version: 6.15.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* [security] Additional SSRF protections (#12595)

Tighten SSRF protections when fetching from external URLs

* feat(backend): add throtteling by default (#11951)

* feat(backend): add throtteling by default

* add changelog entry

* ignore throtetling in debug mode

* increase threshold

* chore(deps): bump the dependencies group across 1 directory with 10 updates (#12561)

* chore(deps): bump the dependencies group across 1 directory with 10 updates

Bumps the dependencies group with 10 updates in the /src/backend directory:

| Package | From | To |
| --- | --- | --- |
| [boto3](https://github.com/boto/boto3) | `1.43.55` | `1.43.61` |
| [botocore](https://github.com/boto/botocore) | `1.43.55` | `1.43.61` |
| [django-anymail](https://github.com/anymail/django-anymail) | `15.0` | `15.1` |
| [feedparser](https://github.com/kurtmckee/feedparser) | `6.0.12` | `6.0.14` |
| [markdown](https://github.com/Python-Markdown/markdown) | `3.10.2` | `3.10.3` |
| [redis](https://github.com/redis/redis-py) | `8.0.1` | `8.1.0` |
| [tablib](https://github.com/jazzband/tablib) | `3.9.0` | `3.10.0` |
| [tqdm](https://github.com/tqdm/tqdm) | `4.69.1` | `4.70.0` |
| [wrapt](https://github.com/GrahamDumpleton/wrapt) | `2.2.2` | `2.3.0` |
| [pip](https://github.com/pypa/pip) | `26.1.2` | `26.2` |



Updates `boto3` from 1.43.55 to 1.43.61
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.55...1.43.61)

Updates `botocore` from 1.43.55 to 1.43.61
- [Commits](https://github.com/boto/botocore/compare/1.43.55...1.43.61)

Updates `django-anymail` from 15.0 to 15.1
- [Release notes](https://github.com/anymail/django-anymail/releases)
- [Changelog](https://github.com/anymail/django-anymail/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/anymail/django-anymail/compare/v15.0...v15.1)

Updates `feedparser` from 6.0.12 to 6.0.14
- [Release notes](https://github.com/kurtmckee/feedparser/releases)
- [Changelog](https://github.com/kurtmckee/feedparser/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/kurtmckee/feedparser/compare/v6.0.12...v6.0.14)

Updates `markdown` from 3.10.2 to 3.10.3
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.10.2...3.10.3)

Updates `redis` from 8.0.1 to 8.1.0
- [Release notes](https://github.com/redis/redis-py/releases)
- [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES)
- [Commits](https://github.com/redis/redis-py/compare/v8.0.1...v8.1.0)

Updates `tablib` from 3.9.0 to 3.10.0
- [Release notes](https://github.com/jazzband/tablib/releases)
- [Changelog](https://github.com/jazzband/tablib/blob/master/HISTORY.md)
- [Commits](https://github.com/jazzband/tablib/compare/v3.9.0...v3.10.0)

Updates `tqdm` from 4.69.1 to 4.70.0
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.69.1...v4.70.0)

Updates `wrapt` from 2.2.2 to 2.3.0
- [Release notes](https://github.com/GrahamDumpleton/wrapt/releases)
- [Changelog](https://github.com/GrahamDumpleton/wrapt/blob/develop/docs/changes.rst)
- [Commits](https://github.com/GrahamDumpleton/wrapt/compare/2.2.2...2.3.0)

Updates `pip` from 26.1.2 to 26.2
- [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/pip/compare/26.1.2...26.2)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.61
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: botocore
  dependency-version: 1.43.61
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: django-anymail
  dependency-version: '15.1'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: feedparser
  dependency-version: 6.0.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: markdown
  dependency-version: 3.10.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: redis
  dependency-version: 8.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: tablib
  dependency-version: 3.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: tqdm
  dependency-version: 4.70.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: wrapt
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: pip
  dependency-version: '26.2'
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* Bump version number to 1.6.0-rev (#12603)

* Bump version number to 1.6.0-rev

* Add release date

* Add next version entry

* Fix for API exception_handler (#12604)

- Only log unhandled exceptions to sentry.io
- Check for valid handling first
- Report second

* chore(deps): bump dompurify from 3.4.12 to 3.4.13 in /src/frontend (#12592)

Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.12 to 3.4.13.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.12...3.4.13)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.13
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* chore(deps): bump the dependencies group with 7 updates (#12608)

Bumps the dependencies group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [docker/login-action](https://github.com/docker/login-action) | `4.5.2` | `4.6.0` |
| [j178/prek-action](https://github.com/j178/prek-action) | `2.0.6` | `3.0.0` |
| [tcort/github-action-markdown-link-check](https://github.com/tcort/github-action-markdown-link-check) | `1.1.2` | `1.1.3` |
| [CodSpeedHQ/action](https://github.com/codspeedhq/action) | `4.19.1` | `5.0.2` |
| [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) | `0.6.1` | `0.6.2` |
| [actions/attest](https://github.com/actions/attest) | `4.2.0` | `4.2.1` |
| [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.37.3` | `4.37.5` |


Updates `docker/login-action` from 4.5.2 to 4.6.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/371161bbe7024a29a25c5e19bfcbc0804fe9ad2c...dbcb813823bdd20940b903addbd779551569679f)

Updates `j178/prek-action` from 2.0.6 to 3.0.0
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](https://github.com/j178/prek-action/compare/5337cb91e0fa35a7ff31b9ca345126d8bbbcdf16...4e14d07f9231acabce116ccfca13b13dd9755ece)

Updates `tcort/github-action-markdown-link-check` from 1.1.2 to 1.1.3
- [Release notes](https://github.com/tcort/github-action-markdown-link-check/releases)
- [Changelog](https://github.com/tcort/github-action-markdown-link-check/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tcort/github-action-markdown-link-check/compare/e7c7a18363c842693fadde5d41a3bd3573a7a225...e047c5b37f24ab722bbef1a27b6fab7f96bc4068)

Updates `CodSpeedHQ/action` from 4.19.1 to 5.0.2
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/f22792bfac16f3e14eb9fbea76f4a48e9cc22b93...0ca9cbbf4623b599a6c3ed4fc8a922942705d9f1)

Updates `zizmorcore/zizmor-action` from 0.6.1 to 0.6.2
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/6fc4b006235f201fdab3722e17240ab420d580e5...3dc1ecc9bcb9e94e9b2c709687979e1298497054)

Updates `actions/attest` from 4.2.0 to 4.2.1
- [Release notes](https://github.com/actions/attest/releases)
- [Changelog](https://github.com/actions/attest/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest/compare/f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6...508db95dd578ae2727ebd6217d5ba78e4fbda05d)

Updates `github/codeql-action/upload-sarif` from 4.37.3 to 4.37.5
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81...d1ba80a13dd99fba24a470575428917156a28b43)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: j178/prek-action
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: tcort/github-action-markdown-link-check
  dependency-version: 1.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.6.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: actions/attest
  dependency-version: 4.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group across 1 directory with 18 updates (#12609)

Bumps the dependencies group with 18 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@mantine/carousel](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/carousel) | `9.5.0` | `9.5.1` |
| [@mantine/charts](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/charts) | `9.5.0` | `9.5.1` |
| [@mantine/core](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/core) | `9.5.0` | `9.5.1` |
| [@mantine/dates](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dates) | `9.5.0` | `9.5.1` |
| [@mantine/dropzone](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/dropzone) | `9.5.0` | `9.5.1` |
| [@mantine/form](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/form) | `9.5.0` | `9.5.1` |
| [@mantine/hooks](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/hooks) | `9.5.0` | `9.5.1` |
| [@mantine/modals](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/modals) | `9.5.0` | `9.5.1` |
| [@mantine/notifications](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/notifications) | `9.5.0` | `9.5.1` |
| [@mantine/spotlight](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/spotlight) | `9.5.0` | `9.5.1` |
| [@mantine/vanilla-extract](https://github.com/mantinedev/mantine/tree/HEAD/packages/@mantine/vanilla-extract) | `9.5.0` | `9.5.1` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.68.0` | `10.69.0` |
| [@tabler/icons-react](https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react) | `3.45.0` | `3.46.0` |
| [axios](https://github.com/axios/axios) | `1.18.1` | `1.19.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.83.0` | `7.84.0` |
| [@flakiness/playwright](https://github.com/flakiness/playwright) | `2.0.0` | `2.0.1` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.62.0` | `1.62.1` |
| [rollup](https://github.com/rollup/rollup) | `4.62.3` | `4.62.4` |



Updates `@mantine/carousel` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/carousel)

Updates `@mantine/charts` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/charts)

Updates `@mantine/core` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/core)

Updates `@mantine/dates` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/dates)

Updates `@mantine/dropzone` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/dropzone)

Updates `@mantine/form` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/form)

Updates `@mantine/hooks` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/hooks)

Updates `@mantine/modals` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/modals)

Updates `@mantine/notifications` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/notifications)

Updates `@mantine/spotlight` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/spotlight)

Updates `@mantine/vanilla-extract` from 9.5.0 to 9.5.1
- [Release notes](https://github.com/mantinedev/mantine/releases)
- [Changelog](https://github.com/mantinedev/mantine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mantinedev/mantine/commits/9.5.1/packages/@mantine/vanilla-extract)

Updates `@sentry/react` from 10.68.0 to 10.69.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/10.69.0/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.68.0...10.69.0)

Updates `@tabler/icons-react` from 3.45.0 to 3.46.0
- [Release notes](https://github.com/tabler/tabler-icons/releases)
- [Commits](https://github.com/tabler/tabler-icons/commits/v3.46.0/packages/icons-react)

Updates `axios` from 1.18.1 to 1.19.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.18.1...v1.19.0)

Updates `react-hook-form` from 7.83.0 to 7.84.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.83.0...v7.84.0)

Updates `@flakiness/playwright` from 2.0.0 to 2.0.1
- [Release notes](https://github.com/flakiness/playwright/releases)
- [Commits](https://github.com/flakiness/playwright/compare/v2.0.0...v2.0.1)

Updates `@playwright/test` from 1.62.0 to 1.62.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.62.0...v1.62.1)

Updates `rollup` from 4.62.3 to 4.62.4
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.62.3...v4.62.4)

---
updated-dependencies:
- dependency-name: "@mantine/carousel"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/charts"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/core"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/dates"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/dropzone"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/form"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/hooks"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/modals"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/notifications"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/spotlight"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@mantine/vanilla-extract"
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.69.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@tabler/icons-react"
  dependency-version: 3.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: axios
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.84.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@flakiness/playwright"
  dependency-version: 2.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@playwright/test"
  dependency-version: 1.62.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: rollup
  dependency-version: 4.62.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* [CI] Improve robustness for playwright test (#12612)

* Update version for @inventreedb/ui (#12611)

* Update version for @inventreedb/ui

* Revert yarn.lock changes

* Bump version number for UI (#12615)

* New Crowdin translations by GitHub Action (#12535)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(frontend): Improve flakiness issues (#12617)

* small improvements to reduce flakiness

* disable throtteling to fix flaking tests

* [bug] Handle duplicate email addresses for magic links (#12621)

* refactor(backend): remove network dep from test (#12624)

* feat(backend): switch to a more formal FSM approach (#12507)

* full fsm implementation

closes https://github.com/inventree/InvenTree/issues/12314

based on https://github.com/matmair/InvenTree/pull/721

* update assertations

* refactor to reduce duplication

* move for cleaner diff

* more moving stuff around

* fix assingment

* remove skip

* merge test classes

* re-enable transition plugin tests

* fix docstrings

* add depreciation warning

* fix type

* nitpicks

* small cleanup

* ensure we alwas pass a str

* add backport

* fix marker position

* full fsm implementation

closes https://github.com/inventree/InvenTree/issues/12314

based on https://github.com/matmair/InvenTree/pull/721

* update assertations

* refactor to reduce duplication

* move for cleaner diff

* more moving stuff around

* fix assingment

* remove skip

* merge test classes

* re-enable transition plugin tests

* fix docstrings

* add depreciation warning

* fix type

* nitpicks

* small cleanup

* ensure we alwas pass a str

* add backport

* fix marker position

* fix ty issue

* ignore this corner case

* ensure invalid transitions can raise a nice validation error

* compact code

* add depreciation mark

* make raise_error default (#754)

* fix merge

* adjust test as this is now not a no-op but a raised error

* fix assertations

* fix test to not take a broken path

* remove unused test statements

* converge

* add test branch for actually working transition

* reduce uneeded code

* ignore depreceated methods

* fix missing coverage

* add prefetch

* reduce diff

* refactor fail limit to match allauth defaults more closely (#12623)

* fix: support UUID notification references (#12616)

* fix: support UUID notification references

* test: update notification uid expectation

---------

Co-authored-by: FurinaDog <FurinaDog@users.noreply.github.com>

* [bug] OptionalField race condition (#12627)

* [bug] OptionalField race condition

Fixes subtle bug where OptionalField entries can be  silenty dropped from an API request due to concurrent requests / race conditions

* Additional unit tests

* Additional guard in metadata.py

* include extra kwargs

* Adjust import/exporting options

* Fix attribute sharing across class instances

* reset errors on update (#12550)

* reset errors on update

* add empty line

---------

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

* Add docs for return order (#12632)

* [bug] Fix ReturnOrder event registration (#12633)

* Allow bulk-edit for ReturnOrderLineItem (#12635)

* Allow bulk-edit for ReturnOrderLineItem

- Allow bulk change of line item outcome

* Update API version documentation with pull request links

* [bug] Fix broken user setting (#12638)

- Closes https://github.com/inventree/InvenTree/issues/12637

* try fixing this flaky test on firefox (#12640)

* feat: add piece_count and piece_size fields to BomItem for cut-to-length parts (#12422)

* feat: add piece_count and piece_size fields to BomItem for cut-to-length parts

Manufacturing BOMs frequently require multiple pieces of a specific size
cut from continuous stock (cables, tubing, structural profiles). Currently
the only way to express "10 pieces of 250mm cable" is to enter the total
length (2.5m) as quantity, which loses the piece-count information that
purchasing and production need.

This adds two optional fields to BomItem:
- piece_count: number of discrete pieces required (default: 1)
- piece_size: size/length of each piece (e.g. "250 mm")

When piece_size is specified, the total quantity is auto-calculated as
piece_count × piece_size, maintaining full backward compatibility (existing
items effectively have piece_count=1 and empty piece_size).

Changes:
- Backend: new model fields, migration, updated recalculate_quantity()
  logic, hash_fields for BOM validation
- API: serializer exposes piece_count and piece_size
- Frontend: BOM form includes the new fields, BOM table shows them as
  optional columns

Addresses #10274

* refactor: simplify to single piece_count field per reviewer feedback

Remove the piece_size field entirely. The existing quantity field already
represents the per-piece size/length, so piece_count multiplied by
quantity gives the total material requirement.

Example: quantity=200mm, piece_count=10 → total 2m of wire in 10 pieces.

Changes:
- Remove piece_size model field, serializer field, and frontend column/form
- Update migration to only add piece_count
- Update get_required_quantity() to multiply by piece_count
- Restore original recalculate_quantity() without piece_size logic

* test/docs: add unit tests and documentation for piece_count field

* style: replace ambiguous × with x to fix RUF002 lint error

* Address review feedback: api_version bump, changelog, style fix

- Bump INVENTREE_API_VERSION to 531 with entry for piece_count field
- Add CHANGELOG.md entry under Unreleased > Added
- Fix RUF001: replace ambiguous × with x in serializers.py help_text

* fix: align piece_count migration help_text with model (RUF001)

The 0153 AddField recorded help_text with a Unicode multiplication sign
(×), while the model field uses plain 'x' after the RUF001 fix. This
mismatch made makemigrations --check flag an unstaged
0154_alter_bomitem_piece_count migration, failing the DB test CI jobs.

Update the original migration's help_text (and docstring) to plain 'x'
so the field definition matches the model, keeping a single clean
migration instead of add-then-alter.

* fix: use set_quantity() in piece_count tests

BomItem.quantity is a derived field, recalculated from raw_amount on
every save() via recalculate_quantity(). Setting item.quantity directly
was overwritten back to the fixture value on save, so the tests computed
against quantity=3 and failed. Use set_quantity() (which sets raw_amount)
to match how quantity is meant to be updated.

* ci: re-trigger CI to confirm Firefox E2E failures are transient

---------

Co-authored-by: Aman Jain <jainamn@amazon.com>

* Improve error handling for unit registry (#12643)

* New Crowdin translations by GitHub Action (#12625)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group across 1 directory with 6 updates (#12651)

Bumps the dependencies group with 6 updates in the /src/frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/view](https://github.com/codemirror/view) | `6.43.7` | `6.43.8` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.69.0` | `10.70.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.84.0` | `7.85.0` |
| [styled-components](https://github.com/styled-components/styled-components) | `6.4.4` | `6.5.1` |
| [@flakiness/playwright](https://github.com/flakiness/playwright) | `2.0.1` | `2.0.2` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.2` | `26.2.0` |



Updates `@codemirror/view` from 6.43.7 to 6.43.8
- [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/view/commits)

Updates `@sentry/react` from 10.69.0 to 10.70.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/10.70.0/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.69.0...10.70.0)

Updates `react-hook-form` from 7.84.0 to 7.85.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.84.0...v7.85.0)

Updates `styled-components` from 6.4.4 to 6.5.1
- [Release notes](https://github.com/styled-components/styled-components/releases)
- [Commits](https://github.com/styled-components/styled-components/compare/styled-components@6.4.4...styled-components@6.5.1)

Updates `@flakiness/playwright` from 2.0.1 to 2.0.2
- [Release notes](https://github.com/flakiness/playwright/releases)
- [Commits](https://github.com/flakiness/playwright/compare/v2.0.1...v2.0.2)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@codemirror/view"
  dependency-version: 6.43.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@sentry/react"
  dependency-version: 10.70.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: react-hook-form
  dependency-version: 7.85.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: styled-components
  dependency-version: 6.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: "@flakiness/playwright"
  dependency-version: 2.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group with 5 updates (#12652)

Bumps the dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [dorny/paths-filter](https://github.com/dorny/paths-filter) | `4.0.2` | `4.0.3` |
| [oasdiff/oasdiff-action/diff](https://github.com/oasdiff/oasdiff-action) | `0.1.11` | `0.1.12` |
| [CodSpeedHQ/action](https://github.com/codspeedhq/action) | `5.0.2` | `5.0.3` |
| [actions/attest](https://github.com/actions/attest) | `4.2.1` | `4.2.2` |
| [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.37.5` | `4.37.6` |


Updates `dorny/paths-filter` from 4.0.2 to 4.0.3
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dorny/paths-filter/compare/7b450fff21473bca461d4b92ce414b9d0420d706...ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d)

Updates `oasdiff/oasdiff-action/diff` from 0.1.11 to 0.1.12
- [Release notes](https://github.com/oasdiff/oasdiff-action/releases)
- [Commits](https://github.com/oasdiff/oasdiff-action/compare/b7c3adeb54330db1903d27c61db520e5661ad55b...033c15c845bef10f148afb0fa781bf1b2a7fe1bf)

Updates `CodSpeedHQ/action` from 5.0.2 to 5.0.3
- [Release notes](https://github.com/codspeedhq/action/releases)
- [Changelog](https://github.com/CodSpeedHQ/action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codspeedhq/action/compare/0ca9cbbf4623b599a6c3ed4fc8a922942705d9f1...4296e51e7041e24dadb86d1d6e8b9320d223dbe8)

Updates `actions/attest` from 4.2.1 to 4.2.2
- [Release notes](https://github.com/actions/attest/releases)
- [Changelog](https://github.com/actions/attest/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest/compare/508db95dd578ae2727ebd6217d5ba78e4fbda05d...1e69f48acb82d1966a394da916b4c1698aa569d6)

Updates `github/codeql-action/upload-sarif` from 4.37.5 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/d1ba80a13dd99fba24a470575428917156a28b43...5595ccaf912efad79be6eef63a5619ff05969be3)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-version: 4.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: oasdiff/oasdiff-action/diff
  dependency-version: 0.1.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: CodSpeedHQ/action
  dependency-version: 5.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: actions/attest
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the dependencies group across 1 directory with 14 updates (#12642)

* chore(deps): bump the dependencies group across 1 directory with 14 updates

Bumps the dependencies group with 14 updates in the /src/backend directory:

| Package | From | To |
| --- | --- | --- |
| [cffi](https://github.com/python-cffi/cffi) | `2.1.0` | `2.1.1` |
| [coverage](https://github.com/coveragepy/coveragepy) | `7.15.2` | `7.15.4` |
| [django-stubs](https://github.com/typeddjango/django-stubs) | `6.0.7` | `6.0.9` |
| [django-stubs-ext](https://github.com/typeddjango/django-stubs) | `6.0.6` | `6.0.9` |
| [django-test-migrations](https://github.com/wemake-services/django-test-migrations) | `1.5.0` | `1.6.0` |
| [packaging](https://github.com/pypa/packaging) | `26.2` | `26.3` |
| [pip](https://github.com/pypa/pip) | `26.2` | `26.2.1` |
| [prek](https://github.com/j178/prek) | `0.4.11` | `0.4.12` |
| [pytest-django](https://github.com/pytest-dev/pytest-django) | `4.12.0` | `4.13.0` |
| [blessed](https://github.com/jquast/blessed) | `1.47.0` | `1.48.0` |
| [boto3](https://github.com/boto/boto3) | `1.43.61` | `1.43.66` |
| [botocore](https://github.com/boto/botocore) | `1.43.61` | `1.43.66` |
| [djangorestframework](https://github.com/encode/django-rest-framework) | `3.17.1` | `3.18.0` |
| [googleapis-common-protos](https://github.com/googleapis/google-cloud-python) | `1.75.0` | `1.75.1` |



Updates `cffi` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/python-cffi/cffi/releases)
- [Commits](https://github.com/python-cffi/cffi/compare/v2.1.0...v2.1.1)

Updates `coverage` from 7.15.2 to 7.15.4
- [Release notes](https://github.com/coveragepy/coveragepy/releases)
- [Changelog](https://github.com/coveragepy/coveragepy/blob/main/CHANGES.rst)
- [Commits](https://github.com/coveragepy/coveragepy/compare/7.15.2...7.15.4)

Updates `django-stubs` from 6.0.7 to 6.0.9
- [Release notes](https://github.com/typeddjango/django-stubs/releases)
- [Commits](https://github.com/typeddjango/django-stubs/compare/6.0.7...6.0.9)

Updates `django-stubs-ext` from 6.0.6 to 6.0.9
- [Release notes](https://github.com/typeddjango/django-stubs/releases)
- [Commits](https://github.com/typeddjango/django-stubs/compare/6.0.6...6.0.9)

Updates `django-test-migrations` from 1.5.0 to 1.6.0
- [Release notes](https://github.com/wemake-services/django-test-migrations/releases)
- [Changelog](https://github.com/wemake-services/django-test-migrations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wemake-services/django-test-migrations/compare/1.5.0...1.6.0)

Updates `packaging` from 26.2 to 26.3
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/26.2...26.3)

Updates `pip` from 26.2 to 26.2.1
- [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/pip/compare/26.2...26.2.1)

Updates `prek` from 0.4.11 to 0.4.12
- [Release notes](https://github.com/j178/prek/releases)
- [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md)
- [Commits](https://github.com/j178/prek/compare/v0.4.11...v0.4.12)

Updates `pytest-django` from 4.12.0 to 4.13.0
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.12.0...v4.13.0)

Updates `blessed` from 1.47.0 to 1.48.0
- [Release notes](https://github.com/jquast/blessed/releases)
- [Changelog](https://github.com/jquast/blessed/blob/master/docs/history.rst)
- [Commits](https://github.com/jquast/blessed/commits/1.48)

Updates `boto3` from 1.43.61 to 1.43.66
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.61...1.43.66)

Updates `botocore` from 1.43.61 to 1.43.66
- [Commits](https://github.com/boto/botocore/compare/1.43.61...1.43.66)

Updates `djangorestframework` from 3.17.1 to 3.18.0
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.17.1...3.18.0)

Updates `googleapis-common-protos` from 1.75.0 to 1.75.1
- [Release notes](https://github.com/googleapis/google-cloud-python/releases)
- [Changelog](https://github.com/googleapis/google-cloud-python/blob/main/packages/google-cloud-documentai/CHANGELOG.md)
- [Commits](https://github.com/googleapis/google-cloud-python/compare/googleapis-common-protos-v1.75.0...googleapis-common-protos-v1.75.1)

---
updated-dependencies:
- dependency-name: cffi
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: coverage
  dependency-version: 7.15.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: django-stubs
  dependency-version: 6.0.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: django-stubs-ext
  dependency-version: 6.0.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: django-test-migrations
  dependency-version: 1.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: packaging
  dependency-version: '26.3'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: pip
  dependency-version: 26.2.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: prek
  dependency-version: 0.4.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: pytest-django
  dependency-version: 4.13.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: blessed
  dependency-version: 1.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: boto3
  dependency-version: 1.43.66
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: botocore
  dependency-version: 1.43.66
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
- dependency-name: djangorestframework
  dependency-version: 3.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: googleapis-common-protos
  dependency-version: 1.75.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* Fix issue 10769 (#12286)

* fix: Show badges for flagged stock items

* Updated badge logic to only display on build order and sales order

* refactor: Remove unused modelRenderer for RenderStockItem in BuildForms and SalesOrderForms

* chore(deps): bump python in /contrib/container (#12650)

Bumps python from 3.14.6-slim-trixie to 3.14.7-slim-trixie.

---
updated-dependencies:
- dependency-name: python
  dependency-version: 3.14.7-slim-trixie
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump sqlparse from 0.5.5 to 0.6.0 in /src/backend (#12653)

* chore(deps): bump sqlparse from 0.5.5 to 0.6.0 in /src/backend

Bumps [sqlparse](https://github.com/andialbrecht/sqlparse) from 0.5.5 to 0.6.0.
- [Changelog](https://github.com/andialbrecht/sqlparse/blob/master/CHANGELOG)
- [Commits](https://github.com/andialbrecht/sqlparse/compare/0.5.5...0.6.0)

---
updated-dependencies:
- dependency-name: sqlparse
  dependency-version: 0.6.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix style

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>

* [FR] stop shipping docs with packages (#12657)

Fixes #12610

* feat(frontend): Add persistant filtered detail navigation in the url (#12585)

* Add filtered detail navigation

* Satisfy navigation lint checks

* Fix missing Fragment import in PageDetail

* Address detail navigation review feedback

* Move detail navigation into breadcrumb bar

* Address URL and layout review feedback

* Address detail navigation review feedback

* fix doclinks

* test: update stock return validation assertion

* fix: keep detail navigation actions stable

* style: apply biome formatting

* fix: use ActionIcon disabled state

* test: use ActionIcon disabled state

* fix: isolate detail navigation query params

---------

Co-authored-by: Matthias Mair <code@mjmair.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: 开源斗士 <43269525+geekcj12@users.noreply.github.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
Co-authored-by: Andrey Lushnikov <aslushnikov@gmail.com>
Co-authored-by: Phil <preid@electromag.com.au>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Neil Beukes <neilbeukes8@gmail.com>
Co-authored-by: suzunn <suzun2@ogr.iu.edu.tr>
Co-authored-by: Miklós Márton <martonmiklosqdev@gmail.com>
Co-authored-by: Petr Ledvina <ledvinap@gmail.com>
Co-authored-by: gunstr <41468206+gunstr@users.noreply.github.com>
Co-authored-by: br413 <br198064@gmail.com>
Co-authored-by: Leonid Zaliubovskyi <Leopoldius@users.noreply.github.com>
Co-authored-by: Λamir <86316974+aamirasmal15@users.noreply.github.com>
Co-authored-by: Alex K <alex@sengine.cloud>
Co-authored-by: snipe <snipe@snipe.net>
Co-authored-by: Bhumin Paladiya <139330832+bhumin18@users.noreply.github.com>
Co-authored-by: Dean <me@dgardiner.net>
Co-authored-by: Hana Lee <47701469+hanielee@users.noreply.github.com>
Co-authored-by: Hana <hana@MacBook-Air-M1.local>
Co-authored-by: Jayasree <srimadjaysnenis@gmail.com>
Co-authored-by: jayasree723 <confidentlehmann@tomorjerry.com>
Co-authored-by: siddhartha28 <31231363+siddhartha928@users.noreply.github.com>
Co-authored-by: Siddhartha Ravilla <ravilla.si@northeastern.edu>
Co-authored-by: FurinaDog <feixiang130214@outlook.com>
Co-authored-by: FurinaDog <FurinaDog@users.noreply.github.com>
Co-authored-by: ribsey <lukas.ribi@gmail.com>
Co-authored-by: amanjain57-gif <aman.jain57@gmail.com>
Co-authored-by: Aman Jain <jainamn@amazon.com>
Co-authored-by: Alonso Lopez-Valdez <alonsl1@uci.edu>
Co-authored-by: Jɤ KέϞϞψ <dalvidjr2022@gmail.com>
2026-08-19 22:25:54 +02:00

2586 lines
79 KiB
Python

"""Tasks for automating certain actions and interacting with InvenTree from the CLI."""
import datetime
import json
import os
import pathlib
import re
import shlex
import shutil
import subprocess
import sys
import tempfile
import time
from functools import wraps
from pathlib import Path
from platform import python_version
from typing import Optional
import invoke
from invoke import Collection, task
from invoke.exceptions import Exit, UnexpectedExit
def safe_value(fnc):
"""Helper function to safely get value from function, catching import exceptions."""
try:
return fnc()
except (ModuleNotFoundError, ImportError):
return wrap_color('N/A', '93') # Yellow color for "Not Available"
def is_true(x):
"""Shortcut function to determine if a value "looks" like a boolean."""
return str(x).strip().lower() in ['1', 'y', 'yes', 't', 'true', 'on']
def is_devcontainer_environment():
"""Check if the InvenTree environment is running in a development container."""
return is_true(os.environ.get('INVENTREE_DEVCONTAINER', 'False'))
def is_docker_environment():
"""Check if the InvenTree environment is running in a Docker container."""
return is_true(os.environ.get('INVENTREE_DOCKER', 'False'))
def is_rtd_environment():
"""Check if the InvenTree environment is running on ReadTheDocs."""
return is_true(os.environ.get('READTHEDOCS', 'False'))
def is_debug_environment():
"""Check if the InvenTree environment is running in a debug environment."""
return is_true(os.environ.get('INVENTREE_DEBUG', 'False')) or is_true(
os.environ.get('RUNNER_DEBUG', 'False')
)
def get_django_version():
"""Return the current Django version."""
from src.backend.InvenTree.InvenTree.version import (
inventreeDjangoVersion, # type: ignore[import]
)
return safe_value(inventreeDjangoVersion)
def get_inventree_version():
"""Return the current InvenTree version."""
from src.backend.InvenTree.InvenTree.version import (
inventreeVersion, # type: ignore[import]
)
return safe_value(inventreeVersion)
def get_inventree_api_version():
"""Return the current InvenTree API version."""
from src.backend.InvenTree.InvenTree.version import (
inventreeApiVersion, # type: ignore[import]
)
return safe_value(inventreeApiVersion)
def get_commit_hash():
"""Return the current git commit hash."""
from src.backend.InvenTree.InvenTree.version import (
inventreeCommitHash, # type: ignore[import]
)
return safe_value(inventreeCommitHash)
def get_commit_date():
"""Return the current git commit date."""
from src.backend.InvenTree.InvenTree.version import (
inventreeCommitDate, # type: ignore[import]
)
return safe_value(inventreeCommitDate)
def get_version_vals():
"""Get values from the VERSION file."""
version_file = local_dir().joinpath('VERSION')
if not version_file.exists():
return {}
try:
from dotenv import dotenv_values
return dotenv_values(version_file)
except ImportError:
error(
'ERROR: dotenv package not installed. You might not be running in the right environment.'
)
return {}
def is_pkg_installer(content: Optional[dict] = None, load_content: bool = False):
"""Check if the current environment is a package installer by VERSION/environment."""
if load_content:
content = get_version_vals()
return get_installer(content) == 'PKG'
def is_pkg_installer_by_path():
"""Check if the current environment is a package installer by checking the path."""
return len(sys.argv) >= 1 and sys.argv[0].startswith(
'/opt/inventree/env/bin/invoke'
)
def get_installer(content: Optional[dict] = None):
"""Get the installer for the current environment or a content dict."""
if content is None:
content = dict(os.environ)
return content.get('INVENTREE_PKG_INSTALLER')
# region execution logging helpers
def task_exception_handler(t, v, tb):
"""Handle exceptions raised by tasks.
The intent here is to provide more 'useful' error messages when tasks fail.
"""
sys.__excepthook__(t, v, tb)
if t is ModuleNotFoundError:
mod_name = str(v).split(' ')[-1].strip("'")
error(f'Error importing required module: {mod_name}')
warning('- Ensure the correct Python virtual environment is active')
warning(
'- Ensure that the invoke tool is installed in the active Python environment'
)
warning(
"- Ensure all required packages are installed by running 'invoke install'"
)
sys.excepthook = task_exception_handler
def wrap_color(text: str, color: str) -> str:
"""Wrap text in a color code."""
return f'\033[{color}m{text}\033[0m'
def success(*args):
"""Print a success message to the console."""
msg = ' '.join(map(str, args))
print(wrap_color(msg, '92'))
def error(*args):
"""Print an error message to the console."""
msg = ' '.join(map(str, args))
print(wrap_color(msg, '91'))
def warning(*args):
"""Print a warning message to the console."""
msg = ' '.join(map(str, args))
print(wrap_color(msg, '93'))
def info(*args):
"""Print an informational message to the console."""
msg = ' '.join(map(str, args))
print(wrap_color(msg, '94'))
def state_logger(fn=None, method_name=None):
"""Decorator to log state markers before/after function execution, optionally accepting arguments."""
def decorator(func):
func.method_name = method_name or func.__name__
@wraps(func)
def wrapped(c, *args, **kwargs):
do_log = is_debug_environment()
if do_log:
info(f'# task | {func.method_name} | start')
t1 = time.time()
try:
func(c, *args, **kwargs)
except KeyboardInterrupt:
error('INVE-W15: Process interrupted by user.')
sys.exit(1)
except UnexpectedExit:
error(f"Task '{func.method_name}' failed with an error.")
raise
t2 = time.time()
if do_log:
info(f'# task | {func.method_name} | done | elapsed: {t2 - t1:.2f}s')
return wrapped
if fn and callable(fn):
return decorator(fn)
elif fn and isinstance(fn, str):
method_name = fn
return decorator
# endregion
# region environment checks
def envcheck_invoke_version():
"""Check that the installed invoke version meets minimum requirements."""
MIN_INVOKE_VERSION: str = '2.0.0'
min_version = tuple(map(int, MIN_INVOKE_VERSION.split('.')))
invoke_version = tuple(map(int, invoke.__version__.split('.'))) # noqa: RUF048
if invoke_version < min_version:
error(f'The installed invoke version ({invoke.__version__}) is not supported!')
error(f'InvenTree requires invoke version {MIN_INVOKE_VERSION} or above')
sys.exit(1)
def envcheck_invoke_path():
"""Check that the path of the used invoke is correct."""
if is_docker_environment() or is_rtd_environment():
return
invoke_path: Path = Path(invoke.__file__)
env_path: Path = Path(sys.prefix).resolve()
loc_path: Path = Path(__file__).parent.resolve()
if not invoke_path.is_relative_to(loc_path) and not invoke_path.is_relative_to(
env_path
):
error('INVE-E2 - Wrong Invoke Path')
error(
f'The invoke tool `{invoke_path}` is not correctly located, ensure you are using the invoke installed in an environment in `{loc_path}` or `{env_path}`'
)
sys.exit(1)
def envcheck_python_version():
"""Check that the installed python version meets minimum requirements.
If the python version is not sufficient, exits with a non-zero exit code.
"""
REQ_MAJOR: int = 3
REQ_MINOR: int = 9
version = sys.version.split(' ')[0]
valid: bool = True
if sys.version_info.major < REQ_MAJOR or (
sys.version_info.major == REQ_MAJOR and sys.version_info.minor < REQ_MINOR
):
valid = False
if not valid:
error(f'The installed python version ({version}) is not supported!')
error(f'InvenTree requires Python {REQ_MAJOR}.{REQ_MINOR} or above')
sys.exit(1)
def envcheck_invoke_cmd():
"""Checks if the rights invoke command for the current environment is used."""
first_cmd = sys.argv[0].replace(sys.prefix, '')
intendded = ['/bin/invoke', '/bin/inv']
correct_cmd: Optional[str] = None
if is_rtd_environment() or is_docker_environment() or is_devcontainer_environment():
return # Skip invoke command check for Docker/RTD/DevContainer environments
elif is_pkg_installer(load_content=True) and not is_pkg_installer_by_path():
correct_cmd = 'inventree run invoke'
else:
warning('Unknown environment, not checking used invoke command')
if first_cmd not in intendded:
correct_cmd = correct_cmd if correct_cmd else 'invoke'
error('INVE-W9 - Wrong Invoke Environment')
error(
f'The detected invoke command `{first_cmd}` is not the intended one for this environment, ensure you are using one of the following command(s) `{correct_cmd}`'
)
def main():
"""Main function to check the execution environment."""
envcheck_invoke_version()
envcheck_python_version()
envcheck_invoke_path()
envcheck_invoke_cmd()
# endregion
def builtin_apps():
"""Returns a list of installed apps."""
return [
'build',
'common',
'company',
'importer',
'machine',
'order',
'part',
'report',
'stock',
'users',
'plugin',
'InvenTree',
'generic',
'machine',
'web',
]
def content_excludes(
allow_auth: bool = True,
allow_email: bool = False,
allow_plugins: bool = True,
allow_session: bool = True,
allow_sso: bool = True,
allow_tokens: bool = True,
):
"""Returns a list of content types to exclude from import / export.
Arguments:
allow_auth (bool): Allow user authentication data to be exported / imported
allow_email (bool): Allow email log data to be exported / imported
allow_plugins (bool): Allow plugin information to be exported / imported
allow_session (bool): Allow user session data to be exported / imported
allow_sso (bool): Allow SSO tokens to be exported / imported
allow_tokens (bool): Allow tokens to be exported / imported
"""
excludes = [
'contenttypes',
'auth.permission',
'error_report.error',
'admin.logentry',
'django_q.schedule',
'django_q.task',
'django_q.ormq',
'exchange.rate',
'exchange.exchangebackend',
'common.dataoutput',
'common.newsfeedentry',
'common.notificationentry',
'common.notificationmessage',
'importer.dataimportsession',
'importer.dataimportcolumnmap',
'importer.dataimportrow',
]
# Optional exclude email message logs
if not allow_email:
excludes.extend(['common.emailmessage', 'common.emailthread'])
# Optionally exclude user auth data
if not allow_auth:
excludes.extend(['auth.group', 'auth.user', 'users.userprofile'])
# Optionally exclude user token information
if not allow_tokens:
excludes.extend(['users.apitoken'])
# Optionally exclude plugin information
if not allow_plugins:
excludes.extend([
'plugin.pluginconfig',
'plugin.pluginsetting',
'plugin.pluginusersetting',
])
# Optionally exclude SSO application information
if not allow_sso:
excludes.extend(['socialaccount.socialapp', 'socialaccount.socialtoken'])
# Optionally exclude user session information
if not allow_session:
excludes.extend(['sessions.session', 'usersessions.usersession'])
return ' '.join([f'--exclude {e}' for e in excludes])
# region file helpers
def local_dir() -> Path:
"""Returns the directory of *THIS* file.
Used to ensure that the various scripts always run
in the correct directory.
"""
return Path(__file__).parent.resolve()
def manage_py_dir():
"""Returns the directory of the manage.py file."""
return local_dir().joinpath('src', 'backend', 'InvenTree')
def manage_py_path():
"""Return the path of the manage.py file."""
return manage_py_dir().joinpath('manage.py')
def _frontend_info():
"""Return the path of the frontend info directory."""
return manage_py_dir().joinpath('web', 'static', 'web', '.vite')
def version_target_pth():
"""Return the path of the target version file."""
return _frontend_info().joinpath('tag.txt')
def version_sha_pth():
"""Return the path of the SHA version file."""
return _frontend_info().joinpath('sha.txt')
def version_source_pth():
"""Return the path of the source version file."""
return _frontend_info().joinpath('source.txt')
# endregion
if __name__ in ['__main__', 'tasks']:
main()
def run(
c, cmd, path: Optional[Path] = None, pty: bool = False, hide: bool = False, env=None
):
"""Runs a given command a given path.
Args:
c: Command line context.
cmd: Command to run.
path: Path to run the command in.
pty (bool, optional): Run an interactive session. Defaults to False.
hide (bool, optional): Hide the command output. Defaults to False.
env (dict, optional): Environment variables to pass to the command. Defaults to None.
"""
env = env or {}
path = path or local_dir()
try:
result = c.run(f'cd "{path}" && {cmd}', pty=pty, env=env, hide=hide)
except UnexpectedExit as e:
error(f"ERROR: InvenTree command failed: '{cmd}'")
warning('- Refer to the error messages in the log above for more information')
raise e
return result
def manage(c, cmd, pty: bool = False, env=None, verbose: bool = False, **kwargs):
"""Runs a given command against django's "manage.py" script.
Args:
c: Command line context.
cmd: Django command to run.
pty (bool, optional): Run an interactive session. Defaults to False.
env (dict, optional): Environment variables to pass to the command. Defaults to None.
verbose (bool, optional): Print verbose output from the command. Defaults to False.
"""
if verbose:
info(f'Running command: python3 manage.py {cmd}')
cmd += ' -v 1'
else:
cmd += ' -v 0'
return run(
c, f'python3 manage.py {cmd}', manage_py_dir(), pty=pty, env=env, **kwargs
)
def manage_interactive(cmd: str, env=None, verbose: bool = False):
"""Run a Django management command with inherited stdio.
This bypasses Invoke PTY mediation and mirrors direct shell usage, which is
required for some interactive commands in Docker environments.
Args:
cmd: Django management command and arguments.
env: Optional environment variables to add for command execution.
verbose: If True, print the resolved command before execution.
Raises:
Exit: If the subprocess returns a non-zero exit code.
"""
args = ['python3', 'manage.py', *shlex.split(cmd)]
# Keep behavior aligned with `manage`: default to quiet output.
if '-v' not in cmd and '--verbosity' not in cmd:
args.extend(['-v', '1' if verbose else '0'])
if verbose:
info(f'Running interactive command: {" ".join(args)}')
cmd_env = dict(os.environ)
if env:
cmd_env.update(env)
# Avoid Invoke's PTY stdin mediation for interactive commands; run with
# inherited stdio to match direct `manage.py` behavior in Docker TTYs.
result = subprocess.run(args, cwd=manage_py_dir(), env=cmd_env, check=False)
if result.returncode != 0:
error(f"ERROR: InvenTree command failed: '{' '.join(args)}'")
warning('- Refer to the error messages in the log above for more information')
raise Exit(code=result.returncode)
def installed_apps(c) -> list[str]:
"""Returns a list of all installed apps, including plugins."""
result = manage(c, 'list_apps', pty=False, hide=True)
output = result.stdout.strip()
# Look for the expected pattern
match = re.findall(r'>>> (.*) <<<', output)
if not match:
raise ValueError(f"Unexpected output from 'list_apps' command: {output}")
return match[0].split(',')
def run_install(
c,
uv: bool,
install_file: Path,
run_preflight=True,
version_check=False,
pinned=True,
verbose: bool = False,
):
"""Run the installation of python packages from a requirements file.
Arguments:
c: Command line context.
uv: Whether to use UV (experimental package manager) instead of pip.
install_file: Path to the requirements file to install from.
run_preflight: Whether to run the preflight installation step (installing pip/uv itself). Default is True.
version_check: Whether to check for a version-specific requirements file. Default is False.
pinned: Whether to use the --require-hashes option when installing packages. Default is True.
verbose: Whether to print verbose output from pip install commands. Default is False.
"""
if version_check:
# Test if there is a version specific requirements file
sys_ver_s = python_version().split('.')
sys_string = f'{sys_ver_s[0]}.{sys_ver_s[1]}'
install_file_vers = install_file.parent.joinpath(
f'{install_file.stem}-{sys_string}{install_file.suffix}'
)
if install_file_vers.exists():
install_file = install_file_vers
info(f"Using version-specific requirements file '{install_file_vers}'")
info(f"Installing required python packages from '{install_file}'")
if not Path(install_file).is_file():
raise FileNotFoundError(f"Requirements file '{install_file}' not found")
# Install required Python packages with PIP
if not uv:
# Optionally run preflight first
if run_preflight:
run(
c,
f'pip3 install --no-cache-dir --disable-pip-version-check -U pip setuptools {"" if verbose else "--quiet"}',
)
info('Installed package manager')
run(
c,
f'pip3 install --no-cache-dir --disable-pip-version-check -U {"--require-hashes" if pinned else ""} -r {install_file} {"" if verbose else "--quiet"}',
)
else:
if run_preflight:
run(
c,
f'pip3 install --no-cache-dir --disable-pip-version-check -U uv setuptools {"" if verbose else "--quiet"}',
)
info('Installed package manager')
run(
c,
f'uv pip install -U {"--require-hashes" if pinned else ""} -r {install_file} {"" if verbose else "--quiet"}',
)
def yarn(c, cmd):
"""Runs a given command against the yarn package manager.
Args:
c: Command line context.
cmd: Yarn command to run.
"""
path = local_dir().joinpath('src', 'frontend')
run(c, cmd, path, False)
def node_available(versions: bool = False, bypass_yarn: bool = False):
"""Checks if the frontend environment (ie node and yarn in bash) is available."""
def ret(val, val0=None, val1=None):
if versions:
return val, val0, val1
return val
def check(cmd):
try:
return str(
subprocess.check_output([cmd], stderr=subprocess.STDOUT, shell=True),
encoding='utf-8',
).strip()
except subprocess.CalledProcessError:
return None
except FileNotFoundError:
return None
yarn_version = check('yarn --version')
node_version = check('node --version')
# Either yarn is available or we don't care about yarn
yarn_passes = bypass_yarn or yarn_version
# Print a warning if node is available but yarn is not
if node_version and not yarn_passes:
warning(
'Node is available but yarn is not. Install yarn if you wish to build the frontend.'
)
# Return the result
return ret(yarn_passes and node_version, node_version, yarn_version)
@state_logger
def check_file_existence(filename: Path, overwrite: bool = False):
"""Checks if a file exists and asks the user if it should be overwritten.
Args:
filename (str): Name of the file to check.
overwrite (bool, optional): Overwrite the file without asking. Defaults to False.
"""
if filename.is_file() and overwrite is False:
response = input(
'Warning: file already exists. Do you want to overwrite? [y/N]: '
)
response = str(response).strip().lower()
if response not in ['y', 'yes']:
error('Cancelled export operation')
sys.exit(1)
@task(help={'verbose': 'Print verbose output from the command'})
@state_logger
def wait(c, verbose: bool = False):
"""Wait until the database connection is ready."""
return manage(c, 'wait_for_db', verbose=verbose)
# Install tasks
# region tasks
@task(
help={
'uv': 'Use UV (experimental package manager)',
'verbose': 'Print verbose output from installation commands',
}
)
@state_logger
def plugins(c, uv: bool = False, verbose: bool = False):
"""Installs all plugins as specified in 'plugins.txt'."""
from src.backend.InvenTree.InvenTree.config import ( # type: ignore[import]
get_plugin_file,
)
run_install(
c, uv, get_plugin_file(), run_preflight=False, pinned=False, verbose=verbose
)
# Collect plugin static files
manage(c, 'collectplugins', verbose=verbose)
@task(
help={
'uv': 'Use UV package manager (experimental)',
'skip_plugins': 'Skip plugin installation',
'dev': 'Install development requirements instead of production requirements',
'verbose': 'Print verbose output from pip install commands',
}
)
@state_logger
def install(
c,
uv: bool = False,
skip_plugins: bool = False,
dev: bool = False,
verbose: bool = False,
):
"""Install required python packages for InvenTree.
Arguments:
c: Command line context.
uv: Use UV package manager (experimental) instead of pip. Default is False.
skip_plugins: Skip plugin installation. Default is False.
dev: Install development requirements instead of production requirements. Default is False.
verbose: Print verbose output from pip install commands. Default is False.
"""
info('Installing required python packages...')
if dev:
run_install(
c,
uv,
local_dir().joinpath('src/backend/requirements-dev.txt'),
version_check=True,
verbose=verbose,
)
success('Dependency installation complete')
return
# Ensure path is relative to *this* directory
run_install(
c,
uv,
local_dir().joinpath('src/backend/requirements.txt'),
version_check=True,
verbose=verbose,
)
# Run plugins install
if not skip_plugins:
plugins(c, uv=uv, verbose=verbose)
# Compile license information
lic_path = manage_py_dir().joinpath('InvenTree', 'licenses.txt')
run(
c,
f'pip-licenses --format=json --with-license-file --no-license-path > {lic_path}',
)
if not lic_path.exists() or lic_path.stat().st_size == 0:
raise FileNotFoundError(f"License file was not generated at '{lic_path}'")
success('Dependency installation complete')
@task(
help={
'tests': 'Set up test dataset at the end',
'verbose': 'Print verbose output from commands',
}
)
def setup_dev(c, tests: bool = False, verbose: bool = False):
"""Sets up everything needed for the dev environment."""
# Install required Python packages with PIP
install(c, uv=False, skip_plugins=True, dev=True, verbose=verbose)
# Install prek hook
info('Installing prek for checks before git commits...')
run(c, 'prek install')
success('prek set up complete')
# Set up test-data if flag is set
if tests:
setup_test(c, verbose=verbose)
# Setup / maintenance tasks
@task
def shell(c):
"""Launch a Django shell."""
manage(c, 'shell', pty=True)
@task
def superuser(c):
"""Create a superuser/admin account for the database."""
manage_interactive('createsuperuser')
@task
def rebuild_models(c):
"""Rebuild database models with MPTT structures."""
info('Rebuilding internal database structures')
manage(c, 'rebuild_models', pty=True)
@task
def rebuild_thumbnails(c):
"""Rebuild missing image thumbnails."""
from src.backend.InvenTree.InvenTree.config import ( # type: ignore[import]
get_media_dir,
)
info(f'Rebuilding image thumbnails in {get_media_dir()}')
manage(c, 'rebuild_thumbnails', pty=True)
@task
@state_logger
def clean_settings(c):
"""Clean the setting tables of old settings."""
info('Cleaning old settings from the database...')
manage(c, 'clean_settings')
success('Settings cleaned successfully')
@task(
help={
'mail': "mail of the user who's MFA should be disabled",
'username': "username of the user who's MFA should be disabled",
}
)
def remove_mfa(c, mail='', username=''):
"""Remove MFA for a user."""
if not mail and not username:
warning('You must provide a users mail or username')
return
manage(c, f'remove_mfa --mail {mail} --username {username}')
@task(
help={
'frontend': 'Build the frontend',
'clear': 'Remove existing static files',
'skip_plugins': 'Ignore collection of plugin static files',
}
)
@state_logger
def static(c, frontend=False, clear=True, skip_plugins=False):
"""Copies required static files to the STATIC_ROOT directory, as per Django requirements."""
if frontend and node_available():
frontend_compile(c)
info('Collecting static files...')
cmd = 'collectstatic --no-input --verbosity 0'
if clear:
cmd += ' --clear'
manage(c, cmd)
# Collect plugin static files
if not skip_plugins:
manage(c, 'collectplugins')
success('Static files collected successfully')
@task
def translate(c, ignore_static=False, no_frontend=False):
"""Rebuild translation source files. Advanced use only!
Note: This command should not be used on a local install,
it is performed as part of the InvenTree translation toolchain.
"""
info('Building translation files')
# Translate applicable .py / .html / .js files
manage(c, 'makemessages --all -e py,html,js --no-wrap')
manage(c, 'compilemessages')
if not no_frontend and node_available():
frontend_compile(c, extract=True)
# Update static files
if not ignore_static:
static(c)
success('Translation files built successfully')
@task(help={'verbose': 'Print verbose output'})
@state_logger('backend_trans')
def backend_trans(c, verbose: bool = False):
"""Compile backend Django translation files."""
info('Compiling backend translations...')
manage(c, 'compilemessages', verbose=verbose)
success('Backend translations compiled successfully')
@task(help={'verbose': 'Print verbose output'})
@state_logger('backend_compilemessages')
def backend_compilemessages(c, verbose: bool = False):
"""Compile backend Django translation files without loading InvenTree settings."""
info('Compiling backend translations...')
cmd = 'python3 -m django compilemessages'
if verbose:
cmd += ' -v 1'
else:
cmd += ' -v 0'
run(c, cmd, manage_py_dir())
success('Backend translations compiled successfully')
@task(
help={
'clean': 'Clean up old backup files',
'compress': 'Compress the backup files',
'encrypt': 'Encrypt the backup files (requires GPG recipient to be set)',
'path': 'Specify path for generated backup files (leave blank for default path)',
'quiet': 'Suppress informational output (only show errors)',
'skip_db': 'Skip database backup step (only backup media files)',
'skip_media': 'Skip media backup step (only backup database files)',
}
)
@state_logger
def backup(
c,
clean: bool = False,
compress: bool = True,
encrypt: bool = False,
path=None,
quiet: bool = False,
skip_db: bool = False,
skip_media: bool = False,
):
"""Backup the database and media files."""
cmd = '--noinput -v 2'
if compress:
cmd += ' --compress'
if encrypt:
cmd += ' --encrypt'
# A path to the backup dir can be specified here
# If not specified, the default backup dir is used
if path:
path = Path(path)
if not os.path.isabs(path):
path = local_dir().joinpath(path).resolve()
cmd += f' -O {path}'
if clean:
cmd += ' --clean'
if quiet:
cmd += ' --quiet'
if skip_db:
info('Skipping database backup...')
else:
info('Backing up InvenTree database...')
manage(c, f'dbbackup {cmd}')
if skip_media:
info('Skipping media backup...')
else:
info('Backing up InvenTree media files...')
manage(c, f'mediabackup {cmd}')
if not skip_db or not skip_media:
success('Backup completed successfully')
@task(
help={
'path': 'Specify path to locate backup files (leave blank for default path)',
'db_file': 'Specify filename of compressed database archive (leave blank to use most recent backup)',
'decrypt': 'Decrypt the backup files (requires GPG recipient to be set)',
'media_file': 'Specify filename of compressed media archive (leave blank to use most recent backup)',
'skip_db': 'Do not import database archive (media restore only)',
'skip_media': 'Do not import media archive (database restore only)',
'uncompress': 'Uncompress the backup files before restoring (default behavior)',
'restore_allow_newer_version': 'Allow restore from a newer version backup (use with caution)',
}
)
def restore(
c,
path=None,
db_file=None,
media_file=None,
decrypt: bool = False,
skip_db: bool = False,
skip_media: bool = False,
uncompress: bool = True,
restore_allow_newer_version: bool = False,
):
"""Restore the database and media files."""
base_cmd = '--noinput -v 2'
env = {}
if restore_allow_newer_version:
env['INVENTREE_BACKUP_RESTORE_ALLOW_NEWER_VERSION'] = 'True'
if uncompress:
base_cmd += ' --uncompress'
if decrypt:
base_cmd += ' --decrypt'
if path:
# Resolve the provided path
path = Path(path)
if not os.path.isabs(path):
path = local_dir().joinpath(path).resolve()
base_cmd += f' -I {path}'
if skip_db:
info('Skipping database archive...')
else:
info('Restoring InvenTree database')
cmd = f'dbrestore {base_cmd}'
if db_file:
cmd += f' -i {db_file}'
manage(c, cmd, env=env)
if skip_media:
info('Skipping media restore...')
else:
info('Restoring InvenTree media files')
cmd = f'mediarestore {base_cmd}'
if media_file:
cmd += f' -i {media_file}'
manage(c, cmd, env=env)
@task()
@state_logger
def listbackups(c):
"""List available backup files."""
info('Finding available backup files...')
manage(c, 'listbackups')
@task(
pre=[wait],
post=[rebuild_models, rebuild_thumbnails],
help={
'verbose': 'Print verbose output from migration commands',
'detect': 'Detect and create new migrations based on changes to models',
},
)
@state_logger
def migrate(c, detect: bool = False, verbose: bool = False):
"""Performs database migrations. This is a critical step if the database schema has been altered.
Arguments:
c: Command line context.
detect: Whether to detect and create new migrations based on changes to models. Default is False.
verbose: Whether to print verbose output from migration commands. Default is False.
"""
info('Running InvenTree database migrations...')
if detect:
manage(c, 'makemigrations', verbose=verbose)
manage(c, 'runmigrations', pty=True, verbose=verbose)
manage(c, 'migrate --run-syncdb', verbose=verbose)
manage(
c,
'remove_stale_contenttypes --include-stale-apps --no-input',
pty=True,
verbose=verbose,
)
success('InvenTree database migrations completed')
@task(help={'app': 'Specify an app to show migrations for (leave blank for all apps)'})
def showmigrations(c, app=''):
"""Show the migration status of the database."""
manage(c, f'showmigrations {app}', pty=True)
@task(
post=[clean_settings],
help={
'skip_backup': 'Skip database backup step (advanced users)',
'backend': 'Force backend translation compilation step (ignores INVENTREE_DOCKER)',
'no_backend': 'Skip backend translation compilation step',
'frontend': 'Force frontend compilation/download step (ignores INVENTREE_DOCKER)',
'no_frontend': 'Skip frontend compilation/download step',
'skip_static': 'Skip static file collection step',
'uv': 'Use UV (experimental package manager)',
'verbose': 'Print verbose output from installation commands',
},
)
@state_logger
def update(
c,
skip_backup: bool = False,
backend: bool = False,
no_backend: bool = False,
frontend: bool = False,
no_frontend: bool = False,
skip_static: bool = False,
uv: bool = False,
verbose: bool = False,
):
"""Update InvenTree installation.
This command should be invoked after source code has been updated,
e.g. downloading new code from GitHub.
The following tasks are performed, in order:
- install
- backend_trans (optional)
- backup (optional)
- migrate
- frontend_compile or frontend_download (optional)
- static (optional)
- clean_settings
"""
info('Updating InvenTree installation...')
# Ensure required components are installed
install(c, uv=uv, verbose=verbose)
# Skip backend translation compilation on docker, unless explicitly requested.
# Users can also forcefully disable the step via `--no-backend`.
if (is_docker_environment() and not backend) or no_backend:
if no_backend:
info('Skipping backend translation compilation (no_backend flag set)')
else:
info('Skipping backend translation compilation (INVENTREE_DOCKER flag set)')
else:
backend_trans(c, verbose=verbose)
if not skip_backup:
backup(c)
# Perform database migrations
migrate(c)
# Stop here if we are not building/downloading the frontend
# If:
# - INVENTREE_DOCKER is set (by the docker image eg.) and not overridden by `--frontend` flag
# - `--no-frontend` flag is set
if (is_docker_environment() and not frontend) or no_frontend:
if no_frontend:
info('Skipping frontend update (no_frontend flag set)')
else:
info('Skipping frontend update (INVENTREE_DOCKER flag set)')
frontend = False
no_frontend = True
else:
info('Updating frontend...')
# Decide if we should compile the frontend or try to download it
if node_available(bypass_yarn=True):
frontend_compile(c)
else:
frontend_download(c)
if not skip_static:
# Collect static files
# Note: frontend has already been compiled if required
static(c, frontend=False)
success('InvenTree update complete')
# Data tasks
@task(
help={
'filename': "Output filename (default = 'data.json')",
'overwrite': 'Overwrite existing files without asking first (default = False)',
'include_email': 'Include email logs in the output file (default = False)',
'include_permissions': 'Include user and group permissions in the output file (default = False)',
'include_tokens': 'Include API tokens in the output file (default = False)',
'exclude_plugins': 'Exclude plugin data from the output file (default = False)',
'include_sso': 'Include SSO token data in the output file (default = False)',
'include_session': 'Include user session data in the output file (default = False)',
'verbose': 'Print verbose output from management commands',
}
)
def export_records(
c,
filename='data.json',
overwrite: bool = False,
include_email: bool = False,
include_permissions: bool = False,
include_tokens: bool = False,
exclude_plugins: bool = False,
include_sso: bool = False,
include_session: bool = False,
verbose: bool = False,
):
"""Export all database records to a file."""
# Get an absolute path to the file
target = Path(filename)
if not target.is_absolute():
target = local_dir().joinpath(filename).resolve()
info(f"Exporting database records to file '{target}'")
wait(c, verbose=verbose)
check_file_existence(target, overwrite)
excludes = content_excludes(
allow_email=include_email,
allow_tokens=include_tokens,
allow_plugins=not exclude_plugins,
allow_session=include_session,
allow_sso=include_sso,
)
with tempfile.NamedTemporaryFile(
suffix='.json', encoding='utf-8', mode='w+t', delete=True
) as tmpfile:
cmd = f"dumpdata --natural-foreign --indent 2 --output '{tmpfile.name}' {excludes}"
# Dump data to temporary file
manage(c, cmd, pty=True, verbose=verbose)
info('Running data post-processing step...')
# Post-process the file, to remove any "permissions" specified for a user or group
tmpfile.seek(0)
data = json.loads(tmpfile.read())
data_out = [
{
'metadata': True,
'comment': 'This file contains a dump of the InvenTree database',
'exported_at': datetime.datetime.now().isoformat(),
'exported_at_utc': datetime.datetime.utcnow().isoformat(),
'source_version': get_inventree_version(),
'api_version': get_inventree_api_version(),
'django_version': get_django_version(),
'python_version': python_version(),
'source_commit': get_commit_hash(),
'installed_apps': installed_apps(c),
}
]
for entry in data:
model_name = entry.get('model', None)
# Ignore any temporary settings (start with underscore)
if model_name in ['common.inventreesetting', 'common.inventreeusersetting']:
if entry['fields'].get('key', '').startswith('_'):
continue
if include_permissions is False:
if model_name == 'auth.group':
entry['fields']['permissions'] = []
if model_name == 'auth.user':
entry['fields']['user_permissions'] = []
data_out.append(entry)
# Write the processed data to file
with open(target, 'w', encoding='utf-8') as f_out:
f_out.write(json.dumps(data_out, indent=2))
success('Data export completed')
def validate_import_metadata(
c, metadata: dict, strict: bool = False, apps: bool = True, verbose: bool = False
) -> bool:
"""Validate the metadata associated with an import file.
Arguments:
c: The context or connection object
metadata (dict): The metadata to validate
apps (bool): If True, validate that all apps listed in the metadata are installed in the current environment.
strict (bool): If True, the import process will fail if any issues are detected.
verbose (bool): If True, print detailed information during validation.
"""
if verbose:
info('Validating import metadata...')
valid = True
def metadata_issue(message: str):
"""Handle an issue with the metadata."""
nonlocal valid
valid = False
if strict:
error(f'INVE-E16 Data Import Error: {message}')
sys.exit(1)
else:
warning(f'INVE-W13 Data Import Warning: {message}')
if not metadata:
metadata_issue(
'No metadata found in the import file - cannot validate source version'
)
return False
source_version = metadata.get('source_version')
if source_version != get_inventree_version():
metadata_issue(
f"Source version '{source_version}' does not match the current InvenTree version '{get_inventree_version()}' - this may lead to issues with the import process"
)
if apps:
local_apps = set(installed_apps(c))
source_apps = set(metadata.get('installed_apps', []))
for app in source_apps:
if app not in local_apps:
metadata_issue(
f"Source app '{app}' is not installed in the current environment - this may break the import process"
)
if verbose and valid:
success('Metadata validation succeeded - no issues detected')
return valid
@task(
help={
'filename': 'Input filename',
'clear': 'Clear existing data before import',
'strict': 'Strict mode - fail if any issues are detected with the metadata (default = False)',
'ignore_nonexistent': 'Ignore non-existent database models (default = False)',
'exclude_plugins': 'Exclude plugin data from the import process (default = False)',
'skip_migrations': 'Skip the migration step after clearing data (default = False)',
'verbose': 'Print verbose output from management commands',
},
pre=[wait],
post=[rebuild_models, rebuild_thumbnails],
)
def import_records(
c,
filename='data.json',
clear: bool = False,
strict: bool = False,
exclude_plugins: bool = False,
ignore_nonexistent: bool = False,
skip_migrations: bool = False,
verbose: bool = False,
):
"""Import database records from a file."""
# Get an absolute path to the supplied filename
target = Path(filename)
if not target.is_absolute():
target = local_dir().joinpath(filename)
if not target.exists():
error(f"ERROR: File '{target}' does not exist")
sys.exit(1)
if clear:
delete_data(c, force=True, migrate=True, verbose=verbose)
if not skip_migrations:
migrate(c, verbose=verbose)
info(f"Importing database records from '{target}'")
with open(target, encoding='utf-8') as f_in:
try:
data = json.loads(f_in.read())
except json.JSONDecodeError as exc:
error(f'ERROR: Failed to decode JSON file: {exc}')
sys.exit(1)
# Separate out the data into different categories, to ensure they are loaded in the correct order
auth_data = []
common_data = []
plugin_data = []
all_data = []
# A dict containing metadata associated with the data file
metadata = {}
def load_data(
title: str,
data: list[dict],
app: Optional[str] = None,
excludes: Optional[list[str]] = None,
) -> tempfile.NamedTemporaryFile:
"""Helper function to save data to a temporary file, and then load into the database."""
nonlocal ignore_nonexistent
nonlocal verbose
nonlocal c
# Skip if there is no data to load
if len(data) == 0:
return
info(f'Loading {len(data)} {title} records...')
with tempfile.NamedTemporaryFile(
suffix='.json', mode='w', encoding='utf-8', delete=False
) as f_out:
f_out.write(json.dumps(data, indent=2))
cmd = f'loaddata {f_out.name} -v 0 --force-color'
if app:
cmd += f' --app {app}'
if ignore_nonexistent:
cmd += ' --ignorenonexistent'
# A set of content types to exclude from the import process
if excludes:
cmd += f' -i {excludes}'
manage(c, cmd, pty=True, verbose=verbose)
# Iterate through each entry in the provided data file, and separate out into different categories based on the model type
for entry in data:
# Metadata needs to be extracted first
if entry.get('metadata', False):
metadata = entry
continue
if model := entry.get('model', None):
# Clear out any permissions specified for a group
if model == 'auth.group':
entry['fields']['permissions'] = []
# Clear out any permissions specified for a user
if model == 'auth.user':
entry['fields']['user_permissions'] = []
# Handle certain model types separately, to ensure they are loaded in the correct order
if model.startswith('auth.'):
auth_data.append(entry)
if model.startswith('users.'):
auth_data.append(entry)
elif model.startswith('common.'):
common_data.append(entry)
elif model.startswith('plugin.'):
plugin_data.append(entry)
else:
all_data.append(entry)
else:
error(
f'{"ERROR" if strict else "WARNING"}: Invalid entry in data file - missing "model" key'
)
print(entry)
if strict:
sys.exit(1)
# Check the metadata associated with the imported data
# Do not validate the 'apps' list yet - as the plugins have not yet been loaded
validate_import_metadata(c, metadata, strict=strict, apps=False)
# Load the temporary files in order
load_data('auth', auth_data)
load_data('common', common_data, app='common')
if not exclude_plugins:
load_data('plugins', plugin_data, app='plugin')
if len(plugin_data) > 0 and not skip_migrations:
# Now that the plugins have been loaded, run database migrations again to ensure any new plugins have their database schema up to date
migrate(c)
# Run validation again - ensure that the plugin apps have been loaded correctly
validate_import_metadata(c, metadata, strict=strict, apps=True)
load_data('remaining', all_data, excludes=content_excludes(allow_auth=False))
success('Data import completed')
@task(
help={
'force': 'Force deletion of all data without confirmation',
'migrate': 'Run migrations before deleting data (default = False)',
'verbose': 'Print verbose output from management commands',
}
)
def delete_data(c, force: bool = False, migrate: bool = False, verbose: bool = False):
"""Delete all database records!
Warning: This will REALLY delete all records in the database!!
"""
info('Deleting existing data from InvenTree database...')
if migrate:
manage(c, 'migrate --run-syncdb', verbose=verbose)
if force:
manage(c, 'flush --noinput', verbose=verbose)
else:
manage_interactive('flush', verbose=verbose)
success('Existing data deleted')
@task(post=[rebuild_models, rebuild_thumbnails])
def import_fixtures(c):
"""Import fixture data into the database.
This command imports all existing test fixture data into the database.
Warning:
- Intended for testing / development only!
- Running this command may overwrite existing database data!!
- Don't say you were not warned...
"""
fixtures = [
# Build model
'build',
# Common models
'settings',
# Company model
'company',
'price_breaks',
'supplier_part',
# Order model
'order',
# Part model
'bom',
'category',
'params',
'part',
'test_templates',
# Stock model
'location',
'stock_tests',
'stock',
# Users
'users',
]
command = 'loaddata ' + ' '.join(fixtures)
manage(c, command, pty=True)
# Execution tasks
@task(
pre=[wait],
help={
'address': 'Server address:port (default=0.0.0.0:8000)',
'workers': 'Specify number of worker threads (override config file)',
},
)
def gunicorn(c, address='0.0.0.0:8000', workers=None):
"""Launch a gunicorn webserver.
Note: This server will not auto-reload in response to code changes.
"""
config_file = local_dir().joinpath('contrib', 'container', 'gunicorn.conf.py')
cmd = f'gunicorn -c {config_file} InvenTree.wsgi -b {address} --chdir {manage_py_dir()}'
if workers:
cmd += f' --workers={workers}'
info(f'Starting Gunicorn Server: {cmd}')
run(c, cmd, pty=True)
@task(
pre=[wait],
help={
'address': 'Server address:port (default=0.0.0.0:8000)',
'no_reload': 'Do not automatically reload the server in response to code changes',
'no_threading': 'Disable multi-threading for the development server',
},
)
def server(c, address='0.0.0.0:8000', no_reload=False, no_threading=False):
"""Launch a (development) server using Django's in-built webserver.
- This is *not* sufficient for a production installation.
- The default address exposes the server on all network interfaces.
"""
cmd = f'runserver {address}'
if no_reload:
cmd += ' --noreload'
if no_threading:
cmd += ' --nothreading'
manage(c, cmd, pty=True)
@task(pre=[wait], help={'verbose': 'Print verbose output from the command'})
def worker(c, verbose: bool = False):
"""Run the InvenTree background worker process.
Launches a django-q2 cluster to process background tasks.
Ref: https://django-q2.readthedocs.io
"""
manage(c, 'qcluster', pty=True, verbose=verbose)
@task(help={'timeout': 'Maximum minutes since last heartbeat (default: 3)'})
def worker_health(c, timeout: int = 3):
"""Check if the background worker is healthy by reading the heartbeat file.
Exits 0 if the worker has run within the last TIMEOUT minutes, 1 otherwise.
No Django startup or database access is required.
"""
heartbeat_file = Path(tempfile.gettempdir()) / 'inventree_worker_heartbeat'
if heartbeat_file.exists():
try:
age_seconds = time.time() - float(heartbeat_file.read_text().strip())
if age_seconds < timeout * 60:
success(
f'Worker is healthy (last heartbeat {int(age_seconds) // 60}m {int(age_seconds) % 60}s ago)'
)
return
warning(
f'Heartbeat file is stale ({int(age_seconds) // 60}m {int(age_seconds) % 60}s old)'
)
except Exception as e:
warning(f'Could not read heartbeat file: {e}')
else:
warning(f'Heartbeat file not found: {heartbeat_file}')
error('Worker health check failed')
raise Exit(code=1)
@task(
help={
'address': 'Server address to check (default: http://localhost:8000)',
'timeout': 'Request timeout in seconds (default: 5)',
}
)
def server_health(c, address: str = 'http://localhost:8000', timeout: int = 5):
"""Check if the web server is healthy by requesting /api/system/health/.
Exits 0 on HTTP 200, 1 otherwise.
No Django startup required.
"""
import urllib.error
import urllib.request
url = f'{address.rstrip("/")}/api/system/health/'
try:
with urllib.request.urlopen(url, timeout=timeout) as response:
if response.status == 200:
success(f'Server is healthy ({url})')
return
warning(f'Unexpected status {response.status} from {url}')
except urllib.error.URLError as e:
warning(f'Could not reach server at {url}: {e.reason}')
except Exception as e:
warning(f'Unexpected error checking {url}: {e}')
error('Server health check failed')
raise Exit(code=1)
@task(post=[static, server])
def test_translations(c):
"""Add a fictional language to test if each component is ready for translations."""
import django
from django.conf import settings
# setup django
base_path = Path.cwd()
new_base_path = pathlib.Path('InvenTree').resolve()
sys.path.append(str(new_base_path))
os.chdir(new_base_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'InvenTree.settings')
django.setup()
# Add language
info('Add dummy language...')
manage(c, 'makemessages -e py,html,js --no-wrap -l xx')
# change translation
info('Fill in dummy translations...')
file_path = pathlib.Path(settings.LOCALE_PATHS[0], 'xx', 'LC_MESSAGES', 'django.po')
new_file_path = Path(str(file_path) + '_new')
# compile regex
reg = re.compile(
r'[a-zA-Z0-9]{1}' # match any single letter and number
+ r'(?![^{\(\<]*[}\)\>])' # that is not inside curly brackets, brackets or a tag
+ r'(?<![^\%][^\(][)][a-z])' # that is not a specially formatted variable with singles
+ r'(?![^\\][\n])' # that is not a newline
)
last_string = ''
# loop through input file lines
with open(file_path, encoding='utf-8') as file_org:
with open(new_file_path, 'w', encoding='utf-8') as file_new:
for line in file_org:
if line.startswith('msgstr "'):
# write output -> replace regex matches with x in the read in (multi)string
file_new.write(f'msgstr "{reg.sub("x", last_string[7:-2])}"\n')
last_string = '' # reset (multi)string
elif line.startswith('msgid "'):
last_string = (
last_string + line
) # a new translatable string starts -> start append
file_new.write(line)
else:
if last_string:
last_string = (
last_string + line
) # a string is being read in -> continue appending
file_new.write(line)
# change out translation files
file_path.rename(str(file_path) + '_old')
new_file_path.rename(file_path)
# compile languages
info('Compile languages ...')
manage(c, 'compilemessages')
# reset cwd
os.chdir(base_path)
# set env flag
os.environ['TEST_TRANSLATIONS'] = 'True'
@task(
help={
'check': 'Run sanity check on the django install (default = False)',
'disable_pty': 'Disable PTY',
'runtest': 'Specify which tests to run, in format <module>.<file>.<class>.<method>',
'migrations': 'Run migration unit tests',
'report': 'Display a report of slow tests',
'coverage': 'Run code coverage analysis (requires coverage package)',
'translations': 'Compile translations before running tests',
'keepdb': 'Keep the test database after running tests (default = False)',
'pytest': 'Use pytest to run tests',
'verbosity': 'Verbosity level for test output (default = 1)',
}
)
def test(
c,
check: bool = False,
disable_pty: bool = False,
runtest: str = '',
migrations: bool = False,
report: bool = False,
coverage: bool = False,
translations: bool = False,
keepdb: bool = False,
pytest: bool = False,
verbosity: int = 1,
):
"""Run unit-tests for InvenTree codebase.
To run only certain test, use the argument --runtest.
This can filter all the way down to:
<module>.<file>.<class>.<method>
Example:
test --runtest=company.test_api
will run tests in the company/test_api.py file.
"""
# Run sanity check on the django install
if check:
manage(c, 'check')
if translations:
try:
manage(c, 'compilemessages', pty=True)
except Exception:
warning('Failed to compile translations')
pty = not disable_pty
tested_apps = ' '.join(builtin_apps())
cmd = 'test'
if runtest:
# Specific tests to run
cmd += f' {runtest}'
else:
# Run all tests
cmd += f' {tested_apps}'
if report:
cmd += ' --slowreport'
if keepdb:
cmd += ' --keepdb'
if migrations:
cmd += ' --tag migration_test'
else:
cmd += ' --exclude-tag migration_test'
cmd += ' --exclude-tag performance_test'
cmd += f' --verbosity {verbosity}'
if coverage:
# Run tests within coverage environment, and generate report
run(c, f'coverage run {manage_py_path()} {cmd}')
run(c, 'coverage xml -i')
elif pytest:
# Use pytest to run the tests
migrate(c)
run(c, f'pytest {manage_py_path().parent.parent} --codspeed')
else:
# Run simple test runner, without coverage
manage(c, cmd, pty=pty)
@task(
help={
'dev': 'Set up development environment at the end',
'keep': 'Keep existing demo dataset (do not re-clone)',
'validate_files': 'Validate media files are correctly copied',
'use_ssh': 'Use SSH protocol for cloning the demo dataset (requires SSH key)',
'branch': 'Specify branch of demo-dataset to clone',
'verbose': 'Print verbose output from management commands',
}
)
def setup_test(
c,
ignore_update: bool = False,
dev: bool = False,
keep: bool = False,
validate_files: bool = False,
use_ssh: bool = False,
verbose: bool = False,
path: str = 'inventree-demo-dataset',
branch: Optional[str] = None,
):
"""Setup a testing environment."""
from src.backend.InvenTree.InvenTree.config import ( # type: ignore[import]
get_media_dir,
)
if not ignore_update:
update(c, verbose=verbose)
template_dir = local_dir().joinpath(path)
if not keep:
# Remove old data directory
if template_dir.exists():
run(c, f'rm {template_dir} -r')
URL = 'https://github.com/inventree/demo-dataset'
if use_ssh:
# Use SSH protocol for cloning the demo dataset
URL = 'git@github.com:inventree/demo-dataset.git'
if not branch:
# No branch specified - determine the InvenTree version
version = get_inventree_version()
# If the version is a stable release (e.g. "1.4.3")
# then we can try to use the corresponding branch in the demo-dataset repository
# (e.g. "1.4.x")
if re.match(r'^\d+\.\d+\.\d+$', version):
branch = f'{version.rsplit(".", 1)[0]}.x'
# InvenTree's trunk branch is named "master", but the demo-dataset
# repository uses "main" as its trunk branch - map this automatically
# so CI can pass through the detected target branch unmodified.
if not branch or branch == 'master':
branch = 'main'
if branch != 'main':
# Stable release branches (e.g. "1.4.x") may not yet exist in the
# demo-dataset repository (e.g. it has not been backported yet).
# Fall back to "main" in that case, rather than failing the clone.
result = c.run(
f'git ls-remote --heads {URL} {branch}', hide=True, warn=True
)
if not result.ok or not result.stdout.strip():
warning(
f"Demo dataset has no branch named '{branch}' - falling back to 'main'"
)
branch = 'main'
# Get test data
info(f"Cloning demo dataset (branch '{branch}') ...")
run(c, f'git clone {URL} {template_dir} -b {branch} -v --depth=1')
# Make sure migrations are done - might have just deleted sqlite database
if not ignore_update:
migrate(c, verbose=verbose)
# Load data
info('Loading database records ...')
import_records(
c,
filename=template_dir.joinpath('inventree_data.json'),
clear=True,
ignore_nonexistent=True,
verbose=verbose,
)
# Copy media files
src = template_dir.joinpath('media')
dst = get_media_dir()
info(f'Copying media files - "{src}" to "{dst}"')
shutil.copytree(src, dst, dirs_exist_ok=True)
if validate_files:
info(' - Validating media files')
missing = False
# Check that the media files are correctly copied across
for dirpath, _dirnames, filenames in os.walk(src):
rel_path = os.path.relpath(dirpath, src)
dst_path = os.path.join(dst, rel_path)
if not os.path.exists(dst_path):
error(f' - Missing directory: {dst_path}')
missing = True
continue
for filename in filenames:
dst_file = os.path.join(dst_path, filename)
if not os.path.exists(dst_file):
missing = True
error(f' - Missing file: {dst_file}')
if missing:
raise FileNotFoundError('Media files not correctly copied')
else:
success(' - All media files correctly copied')
info('Done setting up test environment...')
# Set up development setup if flag is set
if dev:
setup_dev(c, verbose=verbose)
@task(
help={
'filename': "Output filename (default = 'schema.yml')",
'overwrite': 'Overwrite existing files without asking first (default = off/False)',
'no_default': 'Do not use default settings for schema (default = off/False)',
}
)
@state_logger
def schema(
c, filename='schema.yml', overwrite=False, ignore_warnings=False, no_default=False
):
"""Export current API schema."""
filename = Path(filename).resolve()
check_file_existence(filename, overwrite)
info(f"Exporting schema file to '{filename}'")
cmd = f'schema --file {filename} --validate --color'
if not ignore_warnings:
cmd += ' --fail-on-warn'
envs = {}
if not no_default:
envs['INVENTREE_SITE_URL'] = (
'http://localhost:8000' # Default site URL - to ensure server field is stable
)
envs['INVENTREE_PLUGINS_ENABLED'] = (
'False' # Disable plugins to ensure they are kep out of schema
)
envs['INVENTREE_CURRENCY_CODES'] = (
'AUD,CAD,CNY,EUR,GBP,JPY,NZD,USD' # Default currency codes to ensure they are stable
)
manage(c, cmd, pty=True, env=envs)
assert filename.exists()
success(f'Schema export completed: {filename}')
@task
def export_settings_definitions(c, filename='inventree_settings.json', overwrite=False):
"""Export settings definition to a JSON file."""
filename = Path(filename).resolve()
check_file_existence(filename, overwrite)
info(f"Exporting settings definition to '{filename}'...")
manage(c, f'export_settings_definitions {filename}', pty=True)
@task(help={'basedir': 'Export to a base directory (default = False)'})
def export_definitions(c, basedir: str = ''):
"""Export various definitions."""
if basedir != '' and basedir.endswith('/') is False:
basedir += '/'
base_path = Path(basedir, 'generated').resolve()
if not base_path.exists():
info(f'Creating export directory: {base_path}')
base_path.mkdir(parents=True, exist_ok=True)
filenames = [
base_path.joinpath('inventree_settings.json'),
base_path.joinpath('inventree_tags.yml'),
base_path.joinpath('inventree_filters.yml'),
base_path.joinpath('inventree_report_context.json'),
]
info('Exporting definitions...')
export_settings_definitions(c, overwrite=True, filename=filenames[0])
check_file_existence(filenames[1], overwrite=True)
manage(c, f'export_tags {filenames[1]}', pty=True)
check_file_existence(filenames[2], overwrite=True)
manage(c, f'export_filters {filenames[2]}', pty=True)
check_file_existence(filenames[3], overwrite=True)
manage(c, f'export_report_context {filenames[3]}', pty=True)
info('Exporting definitions complete')
@task(default=True)
def version(c):
"""Show the current version of InvenTree."""
from src.backend.InvenTree.InvenTree.config import ( # type: ignore[import]
get_backup_dir,
get_config_file,
get_media_dir,
get_plugin_file,
get_static_dir,
)
# Gather frontend version information
_, node, yarn = node_available(versions=True)
invoke_path = Path(invoke.__file__).resolve()
# Special output messages
NOT_SPECIFIED = wrap_color('NOT SPECIFIED', '91')
NA = wrap_color('N/A', '93')
platform = NOT_SPECIFIED
if is_pkg_installer():
platform = 'Package Installer'
elif is_docker_environment():
platform = 'Docker'
elif is_devcontainer_environment():
platform = 'Devcontainer'
elif is_rtd_environment():
platform = 'ReadTheDocs'
print(
f"""
InvenTree - inventree.org
The Open-Source Inventory Management System\n
Python paths:
Executable {sys.executable}
Environment {sys.prefix}
Invoke Tool {invoke_path}
Installation paths:
Base {local_dir()}
Config {safe_value(get_config_file)}
Plugin File {safe_value(get_plugin_file) or NOT_SPECIFIED}
Media {safe_value(lambda: get_media_dir(error=False)) or NOT_SPECIFIED}
Static {safe_value(lambda: get_static_dir(error=False)) or NOT_SPECIFIED}
Backup {safe_value(lambda: get_backup_dir(error=False)) or NOT_SPECIFIED}
Versions:
InvenTree {get_inventree_version() or NOT_SPECIFIED}
API {get_inventree_api_version() or NOT_SPECIFIED}
Python {python_version()}
Django {get_django_version() or NOT_SPECIFIED}
Node {node if node else NA}
Yarn {yarn if yarn else NA}
Environment:
Platform {platform}
Debug {is_debug_environment()}
Commit hash: {get_commit_hash() or NOT_SPECIFIED}
Commit date: {get_commit_date() or NOT_SPECIFIED}"""
)
if is_pkg_installer_by_path():
print(
"""
You are probably running the package installer / single-line installer. Please mention this in any bug reports!
Use '--list' for a list of available commands
Use '--help' for help on a specific command"""
)
@task()
def frontend_check(c):
"""Check if frontend is available."""
print(node_available())
@task(help={'extract': 'Extract translation strings. Default: False'})
@state_logger
def frontend_compile(c, extract: bool = False):
"""Generate react frontend.
Arguments:
c: Context variable
extract (bool): Whether to extract translations from source code. Defaults to False.
"""
info('Compiling frontend code...')
frontend_install(c)
frontend_trans(c, extract=extract)
frontend_build(c)
success('Frontend compilation complete')
@task
def frontend_install(c):
"""Install frontend requirements.
Args:
c: Context variable
"""
info('Installing frontend dependencies')
yarn(c, 'yarn install')
@task(help={'extract': 'Extract translations (changes sourcecode), default: True'})
def frontend_trans(c, extract: bool = True):
"""Compile frontend translations.
Args:
c: Context variable
extract (bool): Whether to extract translations from source code. Defaults to True.
"""
info('Compiling frontend translations')
if extract:
yarn(c, 'yarn run extract')
yarn(c, 'yarn run compile')
@task
def frontend_build(c):
"""Build frontend.
Args:
c: Context variable
"""
info('Building frontend...')
yarn(c, 'yarn run build')
def write_info(path: Path, content: str):
"""Helper function to write version content to file after cleaning it if it exists."""
if path.exists():
path.unlink()
path.write_text(content, encoding='utf-8')
# Write version marker
try:
import src.backend.InvenTree.InvenTree.version as InvenTreeVersion # type: ignore[import]
if version_hash := InvenTreeVersion.inventreeCommitHash():
write_info(version_sha_pth(), version_hash)
elif version_tag := InvenTreeVersion.inventreeVersion():
write_info(version_target_pth(), version_tag)
else:
warning('No version information available to write frontend version marker')
# Write source marker
write_info(
version_source_pth(),
f'local build on {datetime.datetime.now().isoformat()}',
)
except Exception:
warning('Failed to write frontend version marker')
success('Frontend build complete')
@task
def frontend_server(c):
"""Start frontend development server.
Args:
c: Context variable
"""
info('Starting frontend development server')
yarn(c, 'yarn run compile')
yarn(c, 'yarn run dev --host')
@task
def frontend_test(c, host: str = '0.0.0.0'):
"""Start the playwright test runner for the frontend code."""
info('Starting frontend test runner')
frontend_path = local_dir().joinpath('src', 'frontend').resolve()
cmd = 'npx playwright test --ui'
if host:
cmd += f' --ui-host={host}'
run(c, cmd, path=frontend_path)
@task(
help={
'ref': 'git ref, default: current git ref',
'tag': 'git tag to look for release',
'file': 'destination to frontend-build.zip file',
'repo': 'GitHub repository, default: InvenTree/inventree',
'extract': 'Also extract and place at the correct destination, default: True',
'clean': 'Delete old files from InvenTree/web/static/web first, default: True',
}
)
@state_logger
def frontend_download(
c,
ref=None,
tag=None,
file=None,
repo='InvenTree/inventree',
extract=True,
clean=True,
):
"""Download a pre-build frontend from GitHub if you dont want to install nodejs on your machine.
There are 3 possibilities to install the frontend:
1. invoke frontend-download --ref 01f2aa5f746a36706e9a5e588c4242b7bf1996d5
if ref is omitted, it tries to auto detect the current git ref via `git rev-parse HEAD`.
Note: GitHub doesn't allow workflow artifacts to be downloaded from anonymous users, so
this will output a link where you can download the frontend with a signed in browser
and then continue with option 3
2. invoke frontend-download --tag 0.13.0
Downloads the frontend build from the releases.
3. invoke frontend-download --file /home/vscode/Downloads/frontend-build.zip
This will extract your zip file and place the contents at the correct destination
"""
import functools
import subprocess
from tempfile import NamedTemporaryFile
from zipfile import ZipFile
import requests
info('Downloading frontend...')
# globals
default_headers = {'Accept': 'application/vnd.github.v3+json'}
# helper functions
def find_resource(resource, key, value):
for obj in resource:
if obj[key] == value:
return obj
return None
def handle_extract(file):
# if no extract is requested, exit here
if not extract:
return
dest_path = manage_py_dir().joinpath('web', 'static', 'web')
# if clean, delete static/web directory
if clean:
shutil.rmtree(dest_path, ignore_errors=True)
dest_path.mkdir(parents=True, exist_ok=True)
info(f'Cleaned directory: {dest_path}')
# unzip build to static folder
with ZipFile(file, 'r') as zip_ref:
zip_ref.extractall(dest_path)
info(f'Unzipped downloaded frontend build to: {dest_path}')
def handle_download(url):
# download frontend-build.zip to temporary file
with (
requests.get(
url, headers=default_headers, stream=True, allow_redirects=True
) as response,
NamedTemporaryFile(suffix='.zip') as dst,
):
response.raise_for_status()
# auto decode the gzipped raw data
response.raw.read = functools.partial(
response.raw.read, decode_content=True
)
with open(dst.name, 'wb') as f:
shutil.copyfileobj(response.raw, f)
info(f'Downloaded frontend build to temporary file: {dst.name}')
handle_extract(dst.name)
def check_already_current(tag=None, sha=None):
"""Check if the currently available frontend is already the requested one."""
ref = 'tag' if tag else 'commit'
if tag:
current = version_target_pth()
elif sha:
current = version_sha_pth()
else:
raise ValueError('Either tag or sha needs to be set')
if not current.exists():
warning(
f'Current frontend information for {ref} is not available in {current!s} - this is expected in some cases'
)
return False
current_content = current.read_text().strip()
ref_value = tag or sha
if current_content == ref_value:
info(f'Frontend {ref} is already `{ref_value}`')
return True
else:
info(
f'Frontend {ref} is not expected `{ref_value}` but `{current_content}` - new version will be downloaded'
)
return False
# if zip file is specified, try to extract it directly
if file:
handle_extract(file)
static(c, frontend=False, skip_plugins=True)
return
# check arguments
if ref is not None and tag is not None:
error('ERROR: Do not set ref and tag.')
return
if ref is None and tag is None:
try:
ref = subprocess.check_output(
['git', 'rev-parse', 'HEAD'], encoding='utf-8'
).strip()
except Exception:
# .deb Packages contain extra information in the VERSION file
content: dict = get_version_vals()
if is_pkg_installer(content):
ref = content.get('INVENTREE_COMMIT_SHA')
info(
f'[INFO] Running in package environment, got commit "{ref}" from VERSION file'
)
else:
error("ERROR: Cannot get current ref via 'git rev-parse HEAD'")
return
if ref is None and tag is None:
error('ERROR: Either ref or tag needs to be set.')
if tag:
tag = tag.lstrip('v')
try:
if check_already_current(tag=tag):
return
handle_download(
f'https://github.com/{repo}/releases/download/{tag}/frontend-build.zip'
)
except Exception as e:
if not isinstance(e, requests.HTTPError):
raise e
error(
f"""ERROR: An Error occurred. Unable to download frontend build, release or build does not exist,
try downloading the frontend-build.zip yourself via: https://github.com/{repo}/releases
Then try continuing by running: invoke frontend-download --file <path-to-downloaded-zip-file>"""
)
return
if ref:
if check_already_current(sha=ref):
return
# get workflow run from all workflow runs on that particular ref
workflow_runs = requests.get(
f'https://api.github.com/repos/{repo}/actions/runs?head_sha={ref}',
headers=default_headers,
).json()
if not (qc_run := find_resource(workflow_runs['workflow_runs'], 'name', 'QC')):
error(f'ERROR: Cannot find any workflow runs for current SHA {ref}')
return
info(
f'Found workflow {qc_run["name"]} (run {qc_run["run_number"]}-{qc_run["run_attempt"]})'
)
# get frontend-build artifact from all artifacts available for this workflow run
artifacts = requests.get(
qc_run['artifacts_url'], headers=default_headers
).json()
if not (
frontend_artifact := find_resource(
artifacts['artifacts'], 'name', 'frontend-build'
)
):
error('[ERROR] Cannot find frontend-build.zip attachment for current sha')
return
info(
f'Found artifact {frontend_artifact["name"]} with id {frontend_artifact["id"]} ({frontend_artifact["size_in_bytes"] / 1e6:.2f}MB).'
)
print(
f"""
GitHub doesn't allow artifact downloads from anonymous users. Either download the following file
via your signed in browser, or consider using a point release download via invoke frontend-download --tag <git-tag>
Download: https://github.com/{repo}/suites/{qc_run['check_suite_id']}/artifacts/{frontend_artifact['id']} manually and
continue by running: invoke frontend-download --file <path-to-downloaded-zip-file>"""
)
def doc_schema(c):
"""Generate schema documentation for the API."""
schema(
c, ignore_warnings=True, overwrite=True, filename='docs/generated/schema.yml'
)
run(c, 'python docs/extract_schema.py docs/generated/schema.yml')
@task(
help={
'address': 'Host and port to run the server on (default: localhost:8080)',
'compile_schema': 'Compile the API schema documentation first (default: False)',
'export_settings': 'Export settings definitions before starting the server (default: True)',
}
)
def docs_server(
c,
address='localhost:8080',
compile_schema: bool = False,
export_settings: bool = True,
):
"""Start a local mkdocs server to view the documentation."""
# Extract settings definitions
if export_settings:
export_definitions(c, basedir='docs')
if compile_schema:
doc_schema(c)
run(c, f'mkdocs serve -a {address} -f docs/mkdocs.yml')
@task(
help={'mkdocs': 'Build the documentation using mkdocs at the end (default: False)'}
)
def build_docs(c, mkdocs=False):
"""Build the required documents for building the docs. Optionally build the documentation using mkdocs."""
migrate(c)
export_definitions(c, basedir='docs')
doc_schema(c)
if mkdocs:
run(c, 'mkdocs build -f docs/mkdocs.yml')
info('Documentation build complete')
else:
info('Documentation build complete, but mkdocs not requested')
@task
def clear_generated(c):
"""Clear generated files from `invoke update`."""
# pyc/pyo files
run(c, 'find src -name "*.pyc" -exec rm -f {} +')
run(c, 'find src -name "*.pyo" -exec rm -f {} +')
# cache folders
run(c, 'find src -name "__pycache__" -exec rm -rf {} +')
# Generated translations
run(c, 'find src -name "django.mo" -exec rm -f {} +')
run(c, 'find src -name "messages.mo" -exec rm -f {} +')
@task(pre=[wait])
def monitor(c):
"""Monitor the worker performance."""
manage(c, 'qmonitor', pty=True)
# endregion tasks
# Collection sorting
development = Collection(
delete_data,
docs_server,
frontend_server,
frontend_test,
gunicorn,
import_fixtures,
schema,
server,
setup_dev,
setup_test,
shell,
test,
test_translations,
translate,
)
internal = Collection(
clean_settings,
clear_generated,
export_settings_definitions,
export_definitions,
backend_compilemessages,
frontend_build,
frontend_check,
frontend_compile,
frontend_install,
frontend_trans,
rebuild_models,
rebuild_thumbnails,
showmigrations,
)
ns = Collection(
backend_trans,
backup,
export_records,
frontend_download,
import_records,
install,
listbackups,
migrate,
plugins,
remove_mfa,
restore,
static,
superuser,
update,
version,
wait,
worker,
worker_health,
server_health,
monitor,
build_docs,
)
ns.add_collection(development, 'dev')
ns.add_collection(internal, 'int')