* 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>
* 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
* 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
* 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
* 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
* 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
* 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>
* 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>
* 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
* Optional 'locale' arg to format_money
- Allows override of system locale when generating reports
* Updated documentation
* Add unit tests
* Handle invalid locale
* Handle invalid locale
* Add new global setting to control currency locale in reports
* Use setting in reports
* Add CHANGELOG entry
* Further unit tests
* Add unit tests for new setting
* Update docs
* More docs
* Refactoring:
- Change REPORT_CURRENCY_LOCALE to REPORT_LOCALE
* Extend unit testing
* Refactor format_number
* Add unit tests for explicit format strings
* Update examples for format_date
* Updated unit tests
* Cleanup unit tests
* Fix more tests
* Adjust wording
* Remove global setting - simplify code
* Simplify unit tests
* Revert 'min_digits' to 'leading'
* Fix docs
* Refactor the render_currency function
- Move all functionality into report.py
* Cleanup duplicate code
* Updated docs
* Allow user to specify date_format
* Add support for 'leading' digits in render_currency
* Bug fix
* Fix unit test
* Add tests for "include_symbol"
* Hide expand icon for items without children
* Add searching to CategoryTree API
* Add "level" filter
* Automatically include parent tree when searching
* Include tree_id field
* Add search input to NavigationTree
* Add more API filters
* Load child nodes iteratively
* Fix dynamic loading of nodes
* Highlight selected item
* Include pathstring
* Fix insertion order
* Auto-expand to the selected ID
* Add "no results" message
* Refactor into generic components
* Expand to multi level
* Use async node loading functionality
* Add hovercard
* Implement same functionality for StockLocationTree API endpoint
* Adjust spacing
* Add connecting lines
* Add playwright test
* Bump API version
* Add CHANGELOG entry
* Update docs
* Update screenshot
* [API] Adjust permissions for machine restart
Can only be actioned by a staff user
* Fix import
* Wrong class
* Extend unit test
* Bump API version
* Update CHANGELOG
* Prevent double-save when creating an order
* Prevent double-save for BuildOrder
* More fixes
* Additional unit tests
* Revert code, remove create method against StockTrackingList
* Fix mixins
* add storage for historic import metadata for reporting and display purposes
fixes breakage fromhttps://github.com/inventree/InvenTree/pull/12169
* add api bump
* re-enable test
* fix migration
* ensure session is not overwritten
* fix statusrender without custom key
* Set custom_status_key via API
Refactor `custom_status_key` to be writable via the API and validate that the proposed value is valid for the current order status
* Refactor status_text serializer to consider custom status label
* Update api_version.py
* Additional unit testagainst N + 1
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
Co-authored-by: Oliver Walters <oliver.henry.walters@gmail.com>
* Raise error on multiple matches
* add new field to handle lookup_field selection
* Add unit tests
* Update frontend
* Bump API version
* Ensure string-iness of lookup field
* Tighten API permissions
- Require authenticated user for NotFoundView
- Hide 'active_plugins' behind is_authenticated
* Patch permissions hole in GlobalSettingsPermissions
* Additional API unit tests
* Require auth for observability endpoint
* Add explicit permission for PluginAdminDetail
* Bump API version
* Update unit tests
* Revert changes
* Update data importer child permissions
- Row data
- Column data
* Add unit tests
* Cleanup session data after import is completed
* Further scope narrowing
NotificationMessage.target_object_id and source_object_id were typed as
PositiveIntegerField, which overflows when the referenced model uses a
UUID primary key (e.g. MachineConfig). Django's GenericForeignKey stores
the PK as a string in the database, so the field type should be
CharField to accommodate any PK type (int, UUID, slug, etc.).
Changes:
- common/models.py: change target_object_id and source_object_id from
PositiveIntegerField to CharField(max_length=255) on NotificationMessage
- common/migrations/0044: AlterField migration for both columns
- order/tests.py: update assertion from integer 1 to str(1) since
CharField will now store the PK as a string
Fixes#12131
Signed-off-by: kaizeenn <khairil0153@gmail.com>
* Adjust panel layout
* edit list on click
* Optionally fetch selection list items
* Display in DetailDrawer
* Fix component locations
* Refactor entry table
* Add new entry
* Disable if locked
* Only validate choices if provided via API
* Mark "choices" as read-only
* Prevent delete of locked items
* Add more API unit tests
* Bump API version
* Adjust unit tests
* Default include choices
* Updated playwright test
* Improve test robustness
* Add custom URL fetcher for PDF rendering
* Fix for report helper functions
* Use new fetcher
* Additional unit tests
* Add new setting to control remote URL fetching
* validate URLs against SSRF
* Add global setting to disable URL fetching entirely
* Update docs
* Fix capitalization
* Fix logging backend
* Update CHANGELOG
* add admin button hotkey
* add duplicate hotkey
* generalised hotkeys for actions
* move to fnc
* fix type checking
* more hotkeys!
* add the first primary action to the hotkeys
* small fixes
* use capital hotkeys
* add keys for navigation
* add panel navigation hotkeys
* remove admin hotkey - navigating to attachments is imo more helpful
* address conflict on macos
* Remember last used label template and printer plugin per model type
* Added playwright test for printing preference persistence and format code
* Used waitFor for react-select assertions for test case fixing and persist plugin key correctly
* Updated the problem resolution code and the tests
* Fixed printing test assertion to avoid word boundary failure with concatenated text
* Handle missing machine location
- e.g. if location PK is invalid or has been deleted
* Add spotlight action for machine management panel
* Add unit test for code change
* Enable in-column filtering for model type
* Enable sorting by label size
* Enable backend ordering
* Improve filtering for report template table
* Update API version
* Make plugin registry hash independent of plugin discovery order
calculate_plugin_hash() iterates self.plugins.items() in insertion
order, which is the plugin discovery order of the local process. Two
processes can hold the same registry state (same plugins, versions,
active flags) in a different order and compute different hashes,
ping-ponging the _PLUGIN_REGISTRY_HASH setting and triggering endless
registry reloads in check_reload().
Sort by slug before hashing so the hash represents the registry state
rather than the iteration order of any particular process. Add a
regression test that reverses the plugin dict and asserts the hash is
unchanged.
* Address review comments: explicit sort key, guard against vacuous test
---------
Co-authored-by: Nasawa <christopher@anigeek.com>
* Check model permissions for printing
* Add unit tests
* Prevent printing of disabled reports
* Updated unit test
* Adjust unit test for printing
* Update API and CHANGELOG
* bump container deps
* specific n version
* switch to nvm as n is not officially supported
* fix bash script
* fix corepack
* move yarn config inline
* revert nvm usage
* UX: Disable standard allocation for trackable parts and add tooltip (#11811)
* Test: Update Playwright tests for disabled trackable allocation
* Fix: Align trackable allocation logic and tests based on review
* Test: Fix incorrect assumption of trackable Red Widget in pui_build.spec.ts
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Expose HMR plugin
* Expose function for localizing a plugin component
* Update npm version
* better docs
* Plugin provides i18n instance
* Expose HMR plugin on different path
* Bump version (again)
* Ensure HMR plugin is properly built
* Bump (again)
* Specify callback function
* Bump package version
* Improved docstrings
* Stricter type hinting
* Expose properties for column based filtering
* Adjust renderers
* Hide filter if name does not match
* Allow multiple filters on same column
* Better formatting
* Add filtering support for multiple tables
* Revert yarn.lock changes
* Fix date input props
* Updated column
* Add filter to PartTable
* Add playwright tests for new column filters
* Update CHANGELOG
* Updated docs
* Reduce padding
* Update more table filters
* More filter columns
* Adjust playwright test
* Simplify playwright test
* Robustify playwright tests
* Add some delay
* Add some buffer time
* fix(tasks): bypass Invoke PTY for interactive superuser/flush commands
Docker TTY sessions could drop the first keypress and stall at the username prompt when using invoke superuser (and interactive flush).
Run these interactive management commands via direct subprocess stdio instead of Invoke PTY mediation.
Refs #11751.
* chore: remove changelog entry per review
* Framework for overriding plugin settings
* Update serializer
* Prevent writing of plugin setting values
* Unit tests
* Update API version and CHANGELOG
* Update docs
* Vertical scrolling calendar view
* Add new setting to control calendar horizon
* Keep refetching data as user scrolss
* Adjust view based on configured setting
* Reduce padding
* Simplify calendar layout
* Docs tweak
* Split out display settings
* Adjust playwright test
* Reduce reliance on transient dialogs
* Add HMR and React Fast Refresh support
* Run pre-commit hooks
* Fix 'hmrSetModule' module loading
The incoming module needs to include the URL from which it was loaded,
so that it's possible to enforce only loading modules imported from the same
pathname as the current module.
* Add error handling and improvements
- Add error handling to `useRemotePlugin` and simplify `RemoteComponent`
- Improve HMR to use a registry instead of a single global callback.
This should now handle two legacy plugin entry points being used at
the same time via RemoteComponent.
* Update docs
* Update CHANGELOG
* Remove use of LanguageContext from RemoteComponent
LanguageContext should not be necessary here, as it's provided in
ThemeContext, which is used in InvenTree's frontend entry.
* Fix incorrect import.meta.hot access
* Update Playwright test to match UI text changes
---------
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
* Add Tag API endpoints
* Enable filtering by model type
* Remove old tags filters against Part endpoint
* Add generic tags filter for filtering against tagged items
* Add API unit tests for the tags API endpoints
* Create generic mixin class for adding tags support
* Update existing tagged models
* Add tags to more model types
* Enable new tags API filtering for multiple models
* Add support for tag filtering in part table
* Update transfer table filters
* Add tags filter to more places
* Allow multiple values to be selected as filters
* Add a new 'tags' type form field
* Display tags on part page
* tags support for orders
* Add support for SalesOrderShipment
* build order
* Company support
* SupplierPart and ManufacturerPart
* support StockItem
* Enable tag filtering for attachments
* Make tagslist readonly
* docs
* Mark props as read only
* Update API version
* Update CHANGELOG
* force tags to be case insensitive
* Add playwright test for build order tags
* more playwright testing
* Fix docs link
* Fix for RenderInstance
- Do not call useNavigate within RenderInstance
- This breaks any plugins which try to use RenderInstance
- Pass navigate func through to <RenderInstance />
* Add playwright test for hover in forms
* Add translated plugin test
* Improve playwright tests
* Further unit test fixes
* Update docstring
* [bug] Various fixes
- Add get_api_url to EmailThread model
- Prevent setting creation during import
- Tweak BarcodeScanHistoryTable
* Tweak barcode history table tests
* Bump API version
* Update Dockerfile
* Update Dockerfile
* Added More Info In Barcode API Scans
Added DebugResponse
Added Suppliers Tested
Added Suppliers Errors
* Add NotFound to base Response
* Added Simple Plugin Debug
Changed "NotFound" to 'No_Match'
different style for Debug response
* Added finishing touches for API Error
* clean up + comments
* Added No Supplier Plugin error
* fix style
* Formatting and fixing comments
Added more variables
updated formatting
Added more in depth explanation block for Debug response
* duplicate code fix
* fixed some variable names
* Small move of variables
* Updated To Nested Debug Dictionary
fixed some issues with comments made in original PR
added more comments and small adjustments
got rid of "line item" in debug response
* Added notes to documentation
* Update docs/docs/app/barcode.md
adding matmirs comments
Co-authored-by: Matthias Mair <code@mjmair.com>
* Updated JSON plugin debug name
also added 'plugin_slug' variable
* fix style
* DNE style fix
* Style fix(again)
* Add unit tests
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
* Add CustomStatusSerializerMixin
- Caches custom status values
* Add unit test for PurchaseOrder model
* Implement changes for StockItemSerializer
* Implement changes for BuildOrder
* Fix unit test
* Bump API version
* Add serializer field type hint
* Tweak task offloading
- Improved function splitting
- Remove call to eval
* Read-only ScheduledTask admin
- Prevent admin users creating / editing / deleting scheduled tasks
* Add action for immediate trigger
* Prevent editing of UserSession via django admin
- Allow only read or delete
- No create or edit permissions
* Make StockTrackingAdmin read-only
* Reduce permission scope on common admin models
* Additional unit tests for task offloading
* Only superuser can change certain user fields
* Adjust unit test
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Adjust default postgres connection settings
* Support tcp_user_timeout
* Set application name based on running context
* Add CONN_MAX_AGE and CONN_HEALTH_CHECKS
* Add connection timeout option for mysql
* Migrations
* Add to serializer
* Set the "creation_date" field to auto_now_add
* Ordering and filtering
* Add unit test
* Add "has_stocktake" filter
* Add test for data migration
* Additional unit tests for StockItem API endpoint
* Udpate API and CHANGELOG
* Add basic auto-allocate functionality
- backend code
- background task
- API endpoint
* Add new endpoint enum
* add frontend components
* Tweak auto-allocate output
* Allow specifying of individual line items
* Tweak error boundary
* Enable bulk-delete of allocated items against sales order
* Refactor stock sorting options
* Allow user to select how to handle serialized stock
* Backport new functionality to BuildOrder allocation
* Refactor sorting options to use enumerated values
* Implement functional unit tests for new feature
* Update API and CHANGELOG
* Additional unit test
* Add playwright testing
* Documentation
* Update docs for build auto-allocate
* Fix dependencies
* Adjust build line filtering
* Fix serializer
* Offload build output functions:
- cancel output
- scrap output
- complete output
Perform these in the background worker, and monitor for progress on the frontend.
* Refactor "build cancel"
- Offload expensive ops to background worker
* Offload build complete task
* Remove @atomic decorator from functions
- Allows operations to be performed "incrementally"
- If one task times out, the next task will get the rest
* Bug fix
* Bump API version
* Fix isInTestMode check
* Handle case where task returns immediately
* Fix docstring
* fix test_api
* Tweak order of operations
* additional unit testing for further coverage
* Adjust unit tests
* Offload order completion tasks
* Remove bad code
* Updated playwright test
* Robustify playwright tests
* Bump number of allowed queries
* Revert "Remove bad code"
This reverts commit 3a3ac3bdc7.
* Revert "Offload order completion tasks"
This reverts commit 6066dabe43.
* Add new global setting
* Update lock checks
* Bug fix for task comparison
* Update user interface
* Hide locked field if locking not enabled
* Update existing unit tests
* Update docs
* Add new Attachment model fields:
- is_image
- thumbnail
* Cache if the attachment is an image
* Add new setting for controlling max upload size
* Validate uploaded attachment file
* Add tqdm for progress bars
* Refactor migrations
- Don't need is_image field
- Can introspect from the thumbnail
* Data migration for existing attachments
* Bump API version
* Update tests and validators
* Add "is_image" field to the Attachment model
* Offload to background task
* Implement unit tests
* Docs
* Add unit test for data migration
* Additional unit test
* Omit migration tests from code coverage
* Additional unit tests
* initial skel commit for transfer orders
* initial transfer order backend model
* add some serializers, rename PLACED to ISSUED for TransferOrders
* adding from admin console works
* simple table list almost working, but we need to add order line items....
* add other cols to table
* add Transfer Order from table view
* moving towards a detail view
* wip: adding detail view
* add take from and destination serializer details
* add other detail grid items
* edit/duplicate transfer order
* more action buttons
* first crack at adding line items
* add to line item
* add filters
* starting work on row actions
* more action buttons for line items
* fix copy lines in duplicate
* basic allocation works
* allocations table actions
* allocate serials
* allocated serial row expansion
* add transferred qty to serializers
* move items on complete, show in tracking
* change panel to transferred stock upon complete
* allow incomplete line items
* disable edit allocations when completed
* add ref pattern and to settings
* add admin to line item inline
* add calendar and parametric view
* basic transfer order report
* add transfer order ruleset
* starting allocation buisness logic throughout for TOs
* disable accept incomplete logic, which was incorrect, until I fix
* fix incomplete allocation option
* add transferred col to default report
* add transfer order to calendar ics view
* chain condition for readability
* add transfer order allocations table to stockitem view
* don't account TO allocations in availability
* add transfer orders table for a part
* 'consume' option by doing take_stock
* squash migrations
* starting to test transfer order
* more transfer order tests
* add transfer order consume test
* wip, more tests
* more transfer order tests
* had to refresh_from_db
* switch "to" to "transfer-order" in url paths
* only select non-virtual parts from transfer order
* add transfer order docs
* deconflict migrations
* fix frontend build error
* fix validation on transfer order reference pattern
* add oath2 scope for transfer order
* fix state test to include transfer order state
* add barcode_model_type_code for transfer order
* bump api version
* check view role for transfer order, remove debug/commented out lines
* add serialized allocation test
* Fix migrations
* Frontend fixes
* Implement required 'company' attribute
* transfer order report context
* attempt to fix tests
* delete transfer order allocations on cancel
* add a few playwright tests, more incoming
* more playwright
* add source and destination locations to table
* deconflict migrations
* Fix build issue
* attempt to fix flaky transfer order test
* duplicate transfer order before running tests
* Adjust playwright tests
* Fix migration dependency order
---------
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
Co-authored-by: Matthias Mair <code@mjmair.com>
* Add API serializer for deleting a location
* Add serializer for part category delete
* Bump API version
* Fix unit tests
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* realign user API endpoints to make it clearer which one are only applicable to the current user
* fix name
* bump api
* fix test
* fix reference
* fix test exception
* update ref
* reduce breakage
* re-add legacy urls till next `breaking`
* Remove image download support
- Helper function remains (it is used in the supplier plugin mixin)
- No longer available to user
- Close massive security hole entirely
- Will be defunct soon anyway (moving to generic attachments)
* Update CHANGELOG.md
* Bump API version
* Fix for unit tests
* Implementation
* Update API and CHANGELOG
* Annotate response type
* Simplify attachment renaming
- Use the existing API endpoint
* Capture the actual saved path
* Tweak attachment table fields
* Use built-in validation
* Update docs
* Unit testing
* Ignore some lines from coverage
* Check if file exists before deleting
* Enhance: Auto-select items tab for final stock locations/categories
* Fix biome formatting in PanelGroup.tsx
* Change default setting to False per review
* Refactor: Rename setting to DISPLAY_ITEMS_FINAL_LEVEL to apply generically to both locations and categories per review
---------
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
* Refactor panel indicator dots
- Allow indicator status to be fetched async
* Add indicator dot for attachments
* Support parameters panel
* Refactor
- Expose more types to @lib
- Define new PanelIndicatorType type
- Support old interface
* Provide explicit user information to report context
* Pass user information through to offloaded task
* Pass user information back to the plugin
* Fix user passing
* Add more complex unit test for report printing
- Test debug ON / OFF
- Test merge ON / OFF
- Check generated data output
* Unit testing for label generation
* Further refactoring
- Remove "request" from printing context entirely
* Simplify argument drilling
* Robustify unit tests
* Refactor build order filters
- Common set of filters for build order views
* Refactor PurchaseOrder filters
* Update company table
* Refactor SalesOrder filters
* Refactor common filters
* Refactor ReturnOrder table filters
* Add new "raw_amount" field to BomItem model
* Batch process data migration
* Update migration
* Calculate 'quantity' from 'raw_amount' field
* Improve decimal formatting in migration
* Allow raw_amount in serializer
* Adjust frontend form
* API validation and unit tests
* Additional playwright tests
* Update API version and CHANGELOG
* Updated docs
* Fix docstring
* Better handling of empty values
* Tweak unit tests
* Tweak unit test
* Fix unit test
* Adjust form field text
* Adjust migration file
* Tweak playwright tests
* Fix unit test
* Adjust serializers / import-export / playwright
* Fix migration
* Fix validation
* Loosen comparison
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Allow deletion of serialized build output
- If calling "delete_output" on a BuildOrder
- Only will delete an in_production output
- Ignore the global setting in this case
Co-authored-by: Copilot <copilot@github.com>
* Add unit test
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: Copilot <copilot@github.com>
* Fix: preserve existing widget sizes when adding a dashboard widget
When adding a new widget from the drawer, addWidget called
updateLayoutForWidget with overrideSize=true on every existing layout
key. That flag forces w/h on every layout entry to the widget's
minWidth/minHeight, which silently reset all user-customised widget
sizes back to their minimums.
Pass overrideSize=false instead. Existing widgets retain their layout
entries (and therefore their user-set sizes); the newly added widget
has no entry yet, so react-grid-layout auto-places it at default size.
Adds a Playwright regression test that resizes a widget, adds a second
widget, and asserts the first widget's height is preserved.
* Make widget-resize regression test reliable
Replace the previous drag-based test with a deterministic check that
manipulates the persisted layout directly. The resize handles only
exist when isResizable={editing} is true, so the previous test's
attempt to grab .react-resizable-handle returned null in CI.
The new test inflates the first widget's layout entry in
localStorage, reloads to rehydrate zustand, then adds a second widget
via the menu and asserts the first widget retained its enlarged
dimensions. This directly exercises the addWidget code path without
needing edit mode or mouse simulation.
* Apply biome formatting
* Patch backend profile to inflate widget; fix unused non-null assertion
Updating localStorage was wiped out by observeProfile() on reload, so
inflate the widget on the backend user profile instead.
---------
Co-authored-by: tigger2000ttfn <tigger2000ttfn@users.noreply.github.com>
* Fix "issued_by" for BuildOrder model
- Automatically capture user information
- Mark field as read-only
- Remove from frontend forms
* Add "created_by" property
* Update unit test
* Update API and CHANGELOG
* Further adjustments to unit tests
* Adjust system settings
- Rearrange settings to match major menu groups
- Split long settings panels into separate lists
Co-authored-by: Copilot <copilot@github.com>
* Adjust playwright tests
---------
Co-authored-by: Copilot <copilot@github.com>
* Fix ApiFormFIeldType docstring
* Case fix
* Add sub-forms for company creation
* Tweak component def
* Add new company for manufacturer-part and supplier-part
* Create new parameter template directly from parameter view
* Add tooltip
* Add playwright tests
* Consolidate translation
* Revert to left side
* Fix title case
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Ensure a new BOM item triggers check_bom_valid
* Ensure BOM validation is properly recomputed on a BOM item update
* Add unit tests
* Tweak unit tests
* Update 'clear_bom' method
* Move useFilterSet state to the @lib
* Refactor useTable hook into @lib
* Refactor string helper functions
* Refactor constructFormUrl func
* Refactor Boundary component
* Refactor StoredTableState
* More refactoring
* Refactor CopyButton and CopyableCell
* Pass table render func to plugins
* Provide internal wrapper function, while allowing the "api" and "navigate" functions to be provided by the caller
* Adds <InvenTreeTable /> component which is exposed to plugins
* Update frontend versioning
* Update docs
* Handle condition where UI does not provide table rendering function
* Move queryFilters out of custom state
* Fix exported type
* Extract searchParams
- Cannot be used outside of router component
- Only provide when the table is generated internally
* Bump UI version
* Fix for right-click context menu
- Function needs to be defined with the context menu provider
* move action to post endpoint
* use default return code
* remove custom permissions on notifications endpoint
* add api bump
* update link
* fix assertation
* fix test to use post - this was refactored
* Lazy evaluation of optional serializer fields
- Add OptionalField dataclass
- Pass serializer class and kwargs separately
* Refactor BuildLineSerializer class
* Simplify gathering
* Refactor BuildSerializer
* Refactor other Build serializers
* Refactor Part serializers
* Refactoring more serializers to use OptionalField
* More refactoring
* Cleanup for mixin class
* Ensure any optional fields we added in are not missed
* Fixes
* Rehydrate optional fields for metadata
* Add TreePathSerializer class
* Further improvements:
- Handle case where optional field shadows model property
- Consider read_only and write_only fields
* Adjust unit tests
* Fix for "build_relational_field"
- Handle case where optional field shadows model relation
* Fix case where multiple fields can share same filter
* additional unit tests
* Bump API version
* Remove top-level detection
- Request object is only available for the top-level serializer anyway
* Cache serializer to prevent multiple __init__ calls
* Revert caching change
- Breaks search results
* Simplify field removal
* Adjust unit test
* Remove docstring comment which is no longer true
* Ensure read-only fields are skipped for data import
* Use SAFE_METHODS
* Do not convert to lowercase
* Updated docstring
* Remove FilterableSerializerField mixin
- Annotation now performed using OptionalField
- Code can be greatly simplified
* Ensure all fields are returned when generating schema
* Fix order of operations
* Add assertion to unit test
* fix style
* Fix api_version
* Remove duplicate API entries
* Remove duplicate API entries
* Fix formatting in api_version.py
* Tweak ManufacturerPart serializer
* Revert formatting change
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* move to router based path building
* fix url names
* fix import
* fix test helper
* fix test
* more test fixes
* fix api response
* remove url patch
* bump api version
* reduce diff
* Fix version tag
* fix schema generation errors
* adjust texts
* fix tests
* add test for notification behavior / readakk
* add todo for wrong endpoint
* rename
* adjust docstring
* fix outstanding permission todo - this pattern should be changed in the API
* Add debugging info for background workers to the devcontainer docs
* Add debugging info the the EventMixin docs
* Add an option to set sync=True to launch.json
* Add search capability to selection list entry endpoint
* Use API lookup for selection entries
* Add renderer func
* Allow API filtering
* Fetch selectionentry data related to the selected data item
* remove now unneeded entry
* add missing modelinfo
* fix ref
* add api bump
* Provide optional single fetch function to API forms
- Useful if we need to perform a custom API call for initial data
* django-admin support for SelectionList
* Docstring improvements
* Apply 'active' filter
* Tweak api version entry
* Playwright tests
* Tweak docs wording
* Fix incorrect docstring
* Adjust playwright tests
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Reduce verbosity of invoke tasks
- Suppress some django messages which are not useful to most users
- Verbosity can be added with --verbose flag
* Further improvements
* Better messaging
* Extra options
* No!
* Display filename pattern in template tables
* Add user update tracking to template models
* Update API / serializers
* Capture user information via API
* Display update information in tables
* Bump API version and CHANGELOG.md
* Prevent double increment of revision
* Fix
* [UI] Pass custom fields through to the importer session
* Support custom model rendering within the data import wizard
* Update CHANGELOG.md
* Update UI version
* Add "line number" field for external orders
* Updated serializers
* Add columns to UI tables
* Update form fields
* Adds API ordering
* Bump API version
* Update CHANGELOG.md
* Ensure the MeUserSerializer correctly marks fields as read-only
* Bump API version
* Add unit tests for the "me" endpoint
* Additional unit tests
* Add OPTIONS test
* fix(security): use SandboxedEnvironment for PART_NAME_FORMAT rendering
- Switch jinja2.Environment to jinja2.sandbox.SandboxedEnvironment in
part/helpers.py to prevent SSTI via template tags in PART_NAME_FORMAT.
- Set pk=1 on the dummy Part instance in the validator to ensure
conditional expressions like {% if part.pk %} are properly evaluated
during validation, closing the sandbox bypass vector.
Fixes GHSA-84jh-x777-8pqq
* Style fixes
---------
Co-authored-by: Paul <morimori-dev@github.com>
Co-authored-by: Oliver Walters <oliver.henry.walters@gmail.com>
* Add note to plugin docs.
* Adjust logic for PluginListTable
* Add superuser scope to PluginInstall API endpoint
* Update unit test for API endpoint
* Explicitly set PLUGINS_INSTALL_DISABLED if PLUGINS_ENABLED = False
* Check for superuser permission in installer.py
* Additional user checks
* Sanitize package name to protect against OS command injection
* Fix SSRF in remote image download
Add IP address validation to prevent Server-Side Request Forgery
when downloading images from remote URLs. The resolved IP is now
checked against private, loopback, link-local, and reserved ranges
before connecting.
Redirects are followed manually (up to 5 hops) with SSRF validation
at each step, preventing redirect-based bypass of URL format checks.
* Style fix
---------
Co-authored-by: tikket1 <chrisveres1@gmail.com>
* Refactor ImporterDrawer
- Use a single, globally accessible object
- Provide global state management
* Expose global importer state to the plugin interface
* Improve registration of data import serializers
* Update frontend version / docs
* Bump API version
* docs: add more details around staff / superuser roles and their dangers
* make clear that staff users are dangerous
* make distinction clearer in API
* add error code and frontend warning about running with staff / admin user
* fix test
* bump api
* adapt banner warning
* make banner locally disableable
* add global option to disable elevated user alert
* Prevent creation of PluginConfig during migrations
* Refactor data import process
- Split into multiple separate steps
* Load plugins during data load / dump
- Required, otherwise we cannot dump the data
* Refactor export_records
- Use temporary file
- Cleanup docstring
* Force apps check on second validation step
* Improve import sequencing
* Update CI script
* Update migration docs
* CI pipeline for running import/export test
* Fix workflow naming
* Fix env vars
* Add placeholder script
* Fix matrix env vars
* Fix missing env var
* Install required packages
* Fix typo
* Tweak tasks.py
* Install dummy plugin as part of the
* Updated CI workflow
* Validate exported data
* Additional CI process
* Log mandatory plugins to INFO
* Force global setting
* Refactor CI pipeline
* Tweak file test
* Workflow updates
* Enable auto-update
* Test if import/export test should run
* Trigger if tasks.py changes
* Add 'parameter' support for SalesOrderShipment model
* Add "parameters" tab for shipment view
* Playwright test
* Update CHANGELOG
* Update API version
* Install gettext
* Try yaml format
* Revert "Try yaml format"
This reverts commit 394a5551c8.
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Update "date" field for StockItemTestResult
- Allow editing of date (via admin)
* Mark 'date' and 'user' as read-only unless importing
* Revert API field name
* Fix default value
* Fix migration
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Add management command to list installed apps
* Add metadata to exported data file
* Validate metadata for imported file
* Update CHANGELOG.md
* Update docs
* Use internal codes
* Refactor and add more metadata
* Adjust github action workflow
* Run with --force option to setup demo dataset
* Handle receive of virtual parts
- Update line item quantity
- Do not add any stock
* Add unit test
* Additional unit test
* UI form improvements
* Add playwright test
* Updated playwright tests
* Fix order of hooks for stabilizing table columns
Ref: https://github.com/icflorescu/mantine-datatable/issues/759
* Reset column ordering and widths when the component is mounted
---------
Co-authored-by: Matthias Mair <code@mjmair.com>
* Added keep open boolean field to Stock Location modal form
* Rewrite keep form open field feature to avoid calling methods in form field definitions
* Rewrite keep form open feature as common form property
* Removed unused artefact from previous implementation
* keepOpenOption removed as default option for all create forms. Instead it's enabled on selected forms.
* keepOpenOption field speed improvement
- using useRef instead of useState
- keepOpenSwitch moved to own component
* Added keep form open feature to changelog
* Updated documentation: keep form open feature added to concepts/user_interface docs
* Added test case for "keep form open" feature
* Changed switch selector in keep form open feature test
---------
Co-authored-by: spm <jan.krajdl@cecolo.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
Co-authored-by: Matthias Mair <code@mjmair.com>
* Update DataExport functionality
- Chunk queryset into memory
* Allow larger number of queries for chunked database fetching
* Handle possible exception in unit testing
* Restrict queryset for DataImportSession
- Only allow non-staff users to see their own sessions
* Add unit test
* raise PermissionDenied if no user info available
* Fixed issue where importing data from older versions of InvenTree+Postgres would fail
* Update tasks.py
Changed .startswith to exact matching for users.userprofile.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update tasks.py
Added validation checks to user primary key pairing dict.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Reverted tasks.py, disabled signals in user model when importing data
---------
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Refactoring for media file report helper functions
* Updated unit tests
* Improved error handling
* Generic path return for asset
* Fix return type annotations
* Fix existing test
* Tweaked unit test
* Collect static files in CI
* Run static step for all DB tests
* Update action.yaml
* Fix for action.yaml
* Updated unit tests
* Improvements for get_bulk_queryset
- Limit scope to base view queryset
- Remove ability to provide arbitrary filters
- Remove feedback if zero items are found
* Adjust unit test
* Remove filter test
* Update CHANGELOG.md
* Add helper to check the existence of a static file
* Log error if plugin static file does not exist
* Support cache busting for plugin files
* Use Pathlib instead
* Improve generic URL resolution
* Add unit test
* bump ty - there is better django support now
* more fixes
* fix usage of types
* add missing type
* fix access
* ensure itteration is safe
* fix uncombat decimal usage
* ?potential breaking: change access key
* remove now obsolete igtnore
* ignore errors on StdImageField
* remove usage of unkonw parameter
* fix diff error
* fix schema creation
* fix coverage quirk
* those are unneeded now?
* this seem to have been an issue with 3.12; not occuring on 3.14
* ignore pydantiics
* ignore edge cases for now
* include isGenerating fix
* make typing python 3.11 compatible
* fix more errors
* fix(plugin): use app_name instead of plugin_path when deregistering models
_deactivate_mixin uses plugin_path (the full dotted module path) as the
key into Django's apps.all_models when removing plugin models during
reload. However, Django registers models under the app_label (the short
app_name), not the full plugin_path.
For plugins with nested module paths (e.g. "myplugin.myplugin"),
plugin_path != app_name. Since apps.all_models is a defaultdict, looking
up plugin_path silently creates an empty OrderedDict, then .pop(model)
raises KeyError because the model was never in that dict — it was
registered under app_name.
This causes recurring KeyError crashes every plugin reload cycle
(~1 minute) for any external plugin with a nested package structure.
The fix:
- Use app_name (already computed at line 98) instead of plugin_path
- Add default None to .pop() for defensive safety
- Consistent with line 123 which already correctly uses app_name
* test(plugin): add unit test for nested plugin path model deregistration
Ensures _deactivate_mixin uses app_name (last path component) instead
of the full plugin_path when looking up models in apps.all_models,
preventing KeyError for external plugins with nested module structures.
* style: fix ruff format for context manager parenthesization
* Fix complete_sales_order_shipment task
- Perform allocation *before* marking shipment as complete
- Ensure task is not marked as complete before it is actually done
* Add unit test
* Provide task status tracking for shipment completion
* Add integration testing
* Address unit test issues
* Bump API version
* Enhance playwright test
* Add new build task
* Refactor background task for consuming build stock
- Run as a single task
- Improve query efficiency
* Refactor consuming stock against build via API
- Return task_id for monitoring
- Keep frontend updated
* Task tracking for auto-allocation
* Add e2e integration tests:
- Auto-allocate stock
- Consume stock
* Bump API version
* Playwright test fixes
* Adjust unit tests
* Robustify unit test
* Widen test scope
* Adjust playwright test
* Loosen test requirements again
* idk, another change :|
* Robustify test
* Enhance docstring
* Return the ID of an offloaded task
* Add API endpoint for background task detail
* Add UI hook for monitoring background task progress
* Handle queued tasks (not yet started)
* Improve UX
* Update frontend lib version
* Bump API version
* Fix notification
* Simplify UI interface
* Implement internal hook
* Fix API path sequence
* Add unit tests for task detail endpoint
* Refactor code into reusable model
* Explicit operation_id for API endpoints
* Further refactoring
* Use 200 response code
- axios does not like 202, simplify it
* Return task response for validation of part BOM
* Fix schema
* Cleanup
* Run background worker during playwright tests
- For full e2e integration testing
* Improve hooks and unit testing
* Rename custom hooks to meet react naming requirements
* [bug] Users cannot create their own API tokens
Fixes#11486
* fix detection of metadata
* make easier to read
* add handler for IsAuthenticated
* use correct method
* fix style see #11487
* add frontend test
* make test more reliable?
Required for label printing - pdf2image cannot convert PDFs to images without poppler's pdfinfo binary being present on the system.
Co-authored-by: Justyn Bell <justyn.bell@subinitial.com>
* Enhance MonitorDataOutput
- Optionally pass QueryClient
- Required when running outside of <ApiContext />
* Fix default base URL if not specified
* Remove "allow_null" from Mantine props
* Bump lib version to 0.8.2
* Bump CHANGELOG.md
When the plugin registry reloads during an active HTTP request,
create_default_labels() raises ValidationError on duplicate template
inserts. On PostgreSQL this aborts the entire outer atomic() block,
causing TransactionManagementError on all stock operations in that request.
Fixes#11469
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
* Copy parameters when duplicating an order
* Add unit test for order parameter duplication
* Bunmp API version
* Fix test reliability
* Disable image fetching for SampleSupplierPlugin
- Allow turning on manually
- Prevent CI issues due to rate limiting
* Revery pypdf.. ???
* re-enable codspeed
* fix style
* use 2 step check
* use more verbose syntax
* run performance even if not needed otherwise
* fix possible injection
* another possible injection
* fix syntax
* run python api instead of backend perf test forced
* only submit tests when running in correct enviroment
* Add unit test to detect unreliable pagination
* Enforce PK field ordering
- Append 'pk' ordering to InvenTreeOrderingFilter
* Use our ordering filter everywhere
* Simplify ordering options
* Enforce list
* Use last term for ordering checks
* Individual delete to fix mysql issue
* add "updated_at" field to PurchaseOrder model
* change to use abstract po instead
* add api filters
* add show, order and filter by po updated_at date to frontend
* add tests and increment api_version
* change updated_at to null by default
* never trust github conflict resolution
* bump docker image to python 3.14 (#11414)
* chore(deps): bump the dependencies group across 1 directory with 4 updates (#11416)
Bumps the dependencies group with 4 updates in the / directory: [depot/setup-action](https://github.com/depot/setup-action), [depot/build-push-action](https://github.com/depot/build-push-action), [anchore/sbom-action](https://github.com/anchore/sbom-action) and [actions/stale](https://github.com/actions/stale).
Updates `depot/setup-action` from 1.6.0 to 1.7.1
- [Release notes](https://github.com/depot/setup-action/releases)
- [Commits](b0b1ea4f69...15c09a5f77)
Updates `depot/build-push-action` from 1.16.2 to 1.17.0
- [Release notes](https://github.com/depot/build-push-action/releases)
- [Commits](9785b135c3...5f3b3c2e5a)
Updates `anchore/sbom-action` from 0.21.1 to 0.22.2
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](0b82b0b1a2...28d71544de)
Updates `actions/stale` from 10.1.1 to 10.2.0
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](997185467f...b5d41d4e1d)
---
updated-dependencies:
- dependency-name: depot/setup-action
dependency-version: 1.7.1
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: dependencies
- dependency-name: depot/build-push-action
dependency-version: 1.17.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: dependencies
- dependency-name: anchore/sbom-action
dependency-version: 0.22.2
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: dependencies
- dependency-name: actions/stale
dependency-version: 10.2.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>
* [UI] Copy cells expansion (#11410)
* Prevent copy button if copy value is null
* Add "link" columns to order tables
* Support copy for default column types
* Tweak padding to avoid flickering issues
* Refactor IPNColumn
* Adjust visual styling
* Copy for SKU and MPN columns
* Add more copy columns
* More tweaks
* Tweak playwright testing
* Further cleanup
* More copy cols
* Fix auto pricing overwriting manual purchase price #10846 (#11411)
* Fix auto pricing overwriting manual purchase price #10846
* Added entry to api_version.py
---------
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
* [UI] Default locale (#11412)
* [UI] Support default server language
* Handle faulty theme
* Add option for default language
* Improve language selection
* Brief docs entry
* Fix typo
* Fix yarn build
* Remove debug msg
* Fix calendar locale
* feat(backend): ensure restore of backups only works in correct enviroments (#11372)
* [FR] ensure restore of backups only works in correct enviroments
Fixes#11214
* update PR nbr
* fix wrong ty detection
* fix link
* ensure tracing does not enagage while running backup ops
* fix import
* remove debugging string
* add error codes
* add tests for backup and restore
* complete test for restore
* we do not need e2e on every matrix entry
there is no realy db dep here
* fix changelog format
* add flag to allow bypass
* update CHANGELOG.md
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
Co-authored-by: Matthias Mair <code@mjmair.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: JustusRijke <53965859+JustusRijke@users.noreply.github.com>
* [FR] ensure restore of backups only works in correct enviroments
Fixes#11214
* update PR nbr
* fix wrong ty detection
* fix link
* ensure tracing does not enagage while running backup ops
* fix import
* remove debugging string
* add error codes
* add tests for backup and restore
* complete test for restore
* we do not need e2e on every matrix entry
there is no realy db dep here
* fix changelog format
* add flag to allow bypass
* Prevent copy button if copy value is null
* Add "link" columns to order tables
* Support copy for default column types
* Tweak padding to avoid flickering issues
* Refactor IPNColumn
* Adjust visual styling
* Copy for SKU and MPN columns
* Add more copy columns
* More tweaks
* Tweak playwright testing
* Further cleanup
* More copy cols
* Support "default filters" for table views
- User overrides apply in preference
- Only when there is no stored value (null)
* Correctly handle partially constructed filters
- Reverse lookup on available filter set
* Add default filters for order tables
* Default filters for company tables
* More default filters
* Add some more default filters
* Bump CHANGELOG
* build fix
* Tweaks for playwright testing
* Tweak playwright test
* Improve test flexibility
* Add custom logo and splash to playwright fixtures
* Render custom logo in frontend
* Add playwright tests for customization settings
* Separate playwright run for customization
* Update ci file
* Update playwright config file
* Do not call get_custom_file from withing settings.py
- django app not fully initialized yet
- can cause loops
* Disable default tests (for now)
* Re-enable normal tests
* Update qc checks
* Order of operations?
* Debug output
* Use env
* Add more debug info
* More debug
* Further debug
* Add collectstatic check
* Run normal tests too
* Remove debug prints
* make INVENTREE_WEB_PORT more usefull
* Update contrib/container/docker-compose.yml
Co-authored-by: Philipp Fruck <dev@p-fruck.de>
* revert change
* Fix indentation for environment variable in docker-compose
---------
Co-authored-by: Philipp Fruck <dev@p-fruck.de>
* Add "primary" field to SupplierPart model
* Remove "default_supplier" field from the Part model
* Ensure only one SupplierPart can be "primary" for a given Part
* Update references to "default_supplier"
* Add 'primary' field to the SupplierPart API serializer
* update SupplierPart table
* Use bulk-update operations
* Bug fix for data migration
* Allow ordering by 'primary' field
* Tweak import message
* Edit 'primary' field in UI
* Fix checks in save() methods
* Better table updates
* Update CHANGELOG
* Bump API version
* Fix unit test
* Add unit test for API
* Playwright tests
* Data import flexibility
- Allow specification of alternative lookup fields for data import
* Observe field filters during data import
* Add alternative import fields for Part models
* More options for IMPORT_ID_FIELDS
* Update src/backend/InvenTree/importer/models.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Bump CHANGELOG
* Handle empty input values
* Add IMPORT_ID_FIELDS for more models
* PK field takes highest priority
* Update import docs
* Tweak return type
* Handle multiple date formats
* Add playwright testing
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Enhanced filtering for parameter templates
- Allow filtering by model ID as well as model type
* Enhanced filtering for ParameterTemplate
- Required for the parameteric data tables
- Enable filtering by base model ID
- Enable filtering by related model ID
* Bump API version
* Remove outdated comments
* Fix typo
* Remove debug statement
* Added unit tests
* Playwright tests
* Fix unit test
* Bump requirements
* Revert
* Prevent migration check if performing DB update operations
* Prevent settings write during data imports
* Prevent exchange rate update during migration processes
* Allow exchange rate updates during tests or shell session
* invoke command updates
- wait for db before migrating data
- improve task state reporting
- early return from isGeneratingSchema
* Disable warning message (for now)
* Fix typo
- This caused large delay when restoring data
* Remove debug statement
* Add warning message if isGeneratingSchema called falls through unexpectedly
* Bump version number to 1.2.0 (#11299)
* Bump version number to 1.2.0
* Update CHANGELOG.md
* Update base image in Dockerfile
Updated base image to the latest version as of 2026-02-12.
* Fix for devcontainer build (#11311) (#11312)
- Install yarn a different way
(cherry picked from commit 2a613809ec)
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
---------
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* Add spotlight action to navigate to data import screen
* Hide barcode action if disabled
* Sort actions
* Make spotlight scrollable
* Docs for spotlight
See [CONTRIBUTING.md](CONTRIBUTING.md) for codebase guidance.
Security reports must follow the security policy in [SECURITY.md](docs/docs/SECURITY.md) and provide how they interact with the [threat model](docs/docs/concepts/threat_model.md).
Do not open a pull request without manual review by a human. Do not file AI generated issues under any circumstances.
Using AI generated content in issue/PR discussions might lead to code of conduct violations and/or bans.
All notable changes to this project will be documented in this file (starting with 1.0.0).
All major notable changes to this project will be documented in this file (starting with 1.0.0).
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased - YYYY-MM-DD
## Unreleased - xxxx.xx.xx
### Breaking Changes
- [#10699](https://github.com/inventree/InvenTree/pull/10699) removes the `PartParameter` and `PartParameterTempalate` models (and associated API endpoints). These have been replaced with generic `Parameter` and `ParameterTemplate` models (and API endpoints). Any external client applications which made use of the old endpoints will need to be updated.
- [#12223](https://github.com/inventree/InvenTree/pull/12223) removes support for python 3.11 and stops providing packages for Debian 11 and Ubuntu 20.04.
### Added
- [#12250](https://github.com/inventree/InvenTree/pull/12250) adds "active" field to the ProjectCode model and API endpoints
### Changed
- [#12274](https://github.com/inventree/InvenTree/pull/12274) fixes a bug in rendering the "table field" component in frontend forms. Any plugins which make use of the "table field" component in their forms may be affected by this change, and will need to update their form definitions accordingly.
### Removed
## 1.4.0 - 2026-06-24
### Breaking Changes
- [#12160](https://github.com/inventree/InvenTree/pull/12160) changes the way that remote URIs are loaded into the PDF report generator. Remote URIs (e.g. `http://` and `https://`) are now blocked by default, and can be enabled via the `REPORT_FETCH_URLS` system setting. This change was made to improve the security of the report generation process, as allowing remote URL fetching can potentially expose internal network services to SSRF attacks. Additionally, file URIs (e.g. `file://`) are now always blocked, and assets must be embedded as `data:` URIs before reaching the PDF generator.
- [#12107](https://github.com/inventree/InvenTree/pull/12107) makes a breaking change to the `SalesOrderStatusGroups` enum, fixing a bug where the "shipped" status was not included in the "active" group. This change may affect any external client applications which make use of the `SalesOrderStatusGroups` enum, as the "shipped" status will now be included in the "active" group instead of the "complete" group. If you are using this enum in an external client application, you will need to update your application to account for this change.
- [#9604](https://github.com/inventree/InvenTree/pull/9604) refactors user API endpoint to be less ambiguous
- [#11893](https://github.com/inventree/InvenTree/pull/11893) bumps Node environment to version 24 LTS - this is only relevant if you build the frontend assets yourself
### Added
- [#12208](https://github.com/inventree/InvenTree/pull/12208) adds custom locale support for rendering currencies, dates and numbers within reports. This allows users to specify a custom locale for report rendering, which can be used to control the formatting of dates, numbers and currency values in the generated reports.
- [#12204](https://github.com/inventree/InvenTree/pull/12204) adds new filtering options to PartCategoryTree and StockLocationTree API endpoints, allowing tree data to be fetched dynamically
- [#12165](https://github.com/inventree/InvenTree/pull/12165) adds support for parameters against the PartCategory model
- [#12103](https://github.com/inventree/InvenTree/pull/12103) adds column-based filtering to table views in the user interface. This extends the existing table filtering functionality by allowing users to apply filters directly to individual columns.
- [#12093](https://github.com/inventree/InvenTree/pull/12093) adds "read_only" attribute to PluginSetting API endpoint, which indicates whether a particular plugin setting is read-only (i.e. cannot be modified via the API)
- [#12079](https://github.com/inventree/InvenTree/pull/12079) adds the ability to save filter groups for table and calendar views in the user interface. This allows users to save and reuse commonly used filter configurations, improving the usability and efficiency of the interface.
- [#12077](https://github.com/inventree/InvenTree/pull/12077) adds "tags" fields to multiple new model types and a /api/tag/ endpoint for fetching tags. Also adds the ability to filter various model types by tags.
- [#12019](https://github.com/inventree/InvenTree/pull/12019) adds a "location" field to the StockCount API endpoint, allowing users to specify a location when performing a stock count. This field is optional, and if not provided, the stock count will be performed without changing the location of the stock item. If a location is provided, the stock item(s) will be moved to the specified location as part of the stock count operation.
- [#12011](https://github.com/inventree/InvenTree/pull/12011) adds a "creation_date" field to the StockItem API endpoint, allowing users to track when each stock item was created. This field is read-only and is automatically set to the current date and time when a new stock item is created.
- [#12000](https://github.com/inventree/InvenTree/pull/12000) adds support for auto-allocation of stock items against sales orders. This includes both backend and frontend changes, allowing users to trigger auto-allocation via the API or through the UI. The auto-allocation process will attempt to allocate available stock items to the sales order line items, based on the specified stock sorting and allocation rules.
- [#11920](https://github.com/inventree/InvenTree/pull/11920) adds support for renaming attachments after they have been uploaded. This includes both backend and frontend changes, allowing users to rename attachments via the API or through the UI.
- [#11914](https://github.com/inventree/InvenTree/pull/11914) adds a "maximum_stock" field to the Part model, allowing users to specify a maximum preferred stock level for each part. This is used in conjunction with the existing "minimum_stock" field to allow users to define a preferred stock range for each part. The "high_stock" filter has also been added to the Part API endpoint, allowing users to filter parts which are above their maximum stock level.
- [#11631](https://github.com/inventree/InvenTree/pull/11631) adds "raw_amount" field to the BomItem model, allowing BOM quantities to account for the units of measure of the underlying part.
- [#11872](https://github.com/inventree/InvenTree/pull/11872) adds a global setting to allow or disallow the deletion of serialized stock items.
- [#11861](https://github.com/inventree/InvenTree/pull/11861) adds support for bulk-replacing a component in multiple BOMs simultaneously
- [#11853](https://github.com/inventree/InvenTree/pull/11853) adds BOM comparison functionality, allowing users to compare the BOM of one assembly with another assembly.
- [#11809](https://github.com/inventree/InvenTree/pull/11809) adds multi-level subassembly display mode to the BOM table, allowing users to view multiple levels of subassemblies in a single table view. This is an optional display mode which can be toggled on or off by the user.
- [#11778](https://github.com/inventree/InvenTree/pull/11778) adds inline supplier part creation to po line item addition dialog.
- [#11772](https://github.com/inventree/InvenTree/pull/11772) the UI now warns if you navigate away from a note panel with unsaved changes
- [#11788](https://github.com/inventree/InvenTree/pull/11788) adds support for custom permissions checks on database models defined in plugins. If a model defines a `check_user_permission` classmethod, this will be called to determine if a user has permission to view the model. This is required for plugin models which do not have the required ruleset definitions for the standard permission system.
- [#9570](https://github.com/inventree/InvenTree/pull/9570) adds support for defining primary actions via plugins
### Changed
- [#12197](https://github.com/inventree/InvenTree/pull/12197) requires staff permissions to restart machines via the API.
- [#12142](https://github.com/inventree/InvenTree/pull/12142) prevents users from printing reports or labels against models for which they do not have adequate permissions. This change improves the security of the system by ensuring that users cannot access or print reports or labels for models they do not have permission to view.
- [#11990](https://github.com/inventree/InvenTree/pull/11990) build output operations performed via the API now offload the work to a background task, and now return a task ID which can be used to monitor the progress of the task. This allows for better performance and responsiveness when performing build output operations, as the work is performed asynchronously in the background.
- [#11825](https://github.com/inventree/InvenTree/pull/11825) adds a new "bom" ruleset and associated permissions for BOM management, separate from the "part" ruleset which remains focused on part management. This allows for more granular control over user permissions, allowing users to have different levels of access to part management and BOM management functionality.
- [#11816](https://github.com/inventree/InvenTree/pull/11816) makes the `issued_by` field on the `Build` API read only, and instead sets the `issued_by` field to the current user when a build is created. This change was made to ensure that the `issued_by` field accurately reflects the user who created the build, and to prevent users from setting this field to an arbitrary value when creating or updating a build.
### Removed
- [#12071](https://github.com/inventree/InvenTree/pull/12071) removes the "review_needed" field on the StockItem model. Note that this field was never exposed to the API or any business logic, and is essentially a no-op field which is not used for anything. This field was removed to simplify the StockItem model and reduce confusion around its purpose.
- [#11962](https://github.com/inventree/InvenTree/pull/11962) removes the "remote_image" field from the Part API endpoint, which (previously) allowed the user to specify a remote URL for an image to be downloaded and associated with the part. This field was removed due to security concerns around downloading images from arbitrary URLs. If you were using this field in an external client application, you will need to update your application to use the new "download_image_from_url" API endpoint instead.
## 1.3.0 - 2026-04-11
### Breaking Changes
- [#11303](https://github.com/inventree/InvenTree/pull/11303) removes the `default_supplier` field from the `Part` model. Instead, the `SupplierPart` model now has a `primary` field which is used to indicate which supplier is the default for a given part. Any external client applications which made use of the old `default_supplier` field will need to be updated.
- [#11500](https://github.com/inventree/InvenTree/pull/11500) fixes a spelling mistake in the database configuration values, which may affect some users running the PostgreSQL database backend. The `tcp_keepalives_internal` option has been renamed to `tcp_keepalives_interval` to reflect the correct PostgreSQL configuration option name. If you are using PostgreSQL, and have set a custom value for the `tcp_keepalives_internal` option, you will need to update this to `tcp_keepalives_interval` in your configuration (either via environment variable or config file).
### Added
- [#11702](https://github.com/inventree/InvenTree/pull/11702) adds "last updated" and "updated by" fields for label and report templates, allowing users to track when a template was last modified and by whom.
- [#11685](https://github.com/inventree/InvenTree/pull/11685) exposes the data importer wizard to the plugin interface, allowing plugins to trigger the data importer wizard and perform custom data imports from the UI.
- [#11692](https://github.com/inventree/InvenTree/pull/11692) adds line item numbering for external orders (purchase, sales and return orders). This allows users to specify a line number for each line item on the order, which can be used for reference purposes. The line number is optional, and can be left blank if not required. The line number is stored as a string, to allow for more flexible formatting (e.g. "1", "1.1", "A", etc).
- [#11641](https://github.com/inventree/InvenTree/pull/11641) adds support for custom parameters against the SalesOrderShipment model.
- [#11527](https://github.com/inventree/InvenTree/pull/11527) adds a new API endpoint for monitoring the status of a particular background task. This endpoint allows clients to check the status of a background task and receive updates when the task is complete. This is useful for long-running tasks that may take some time to complete, allowing clients to provide feedback to users about the progress of the task.
- [#11405](https://github.com/inventree/InvenTree/pull/11405) adds default table filters, which hide inactive items by default. The default table filters are overridden by user filter selection, and only apply to the table view initially presented to the user. This means that users can still view inactive items if they choose to, but they will not be shown by default.
- [#11222](https://github.com/inventree/InvenTree/pull/11222) adds support for data import using natural keys, allowing for easier association of related objects without needing to know their internal database IDs.
- [#11383](https://github.com/inventree/InvenTree/pull/11383) adds "exists_for_model_id", "exists_for_related_model", and "exists_for_related_model_id" filters to the ParameterTemplate API endpoint. These filters allow users to check for the existence of parameters associated with specific models or related models, improving the flexibility and usability of the API.
- [#10887](https://github.com/inventree/InvenTree/pull/10887) adds the ability to auto-allocate tracked items against specific build outputs. Currently, this will only allocate items where the serial number of the tracked item matches the serial number of the build output, but in future this may be extended to allow for more flexible allocation rules.
- [#11372](https://github.com/inventree/InvenTree/pull/11372) adds backup metadata setter and restore metadata validator functions to ensure common footguns are harder to trigger when using the backup and restore functionality.
- [#11374](https://github.com/inventree/InvenTree/pull/11374) adds `updated_at` field on purchase, sales and return orders.
- [#11074](https://github.com/inventree/InvenTree/pull/11074) adds "Keep form open" option on create form which leaves dialog with form opened after form submitting.
### Changed
- [#11648](https://github.com/inventree/InvenTree/pull/11648) improves the import/export process, allowing data records defined by plugins to be loaded when importing a database from a file.
- [#11630](https://github.com/inventree/InvenTree/pull/11630) enhances the `import_records` and `export_records` system commands, by adding a metadata entry to the exported data file to allow for compatibility checks during data import.
### Removed
- [#11581](https://github.com/inventree/InvenTree/pull/11581) removes the ability to specify arbitrary filters when performing bulk operations via the API. This functionality represented a significant security risk, and was not required for any existing use cases. Bulk operations now only work with a provided list of primary keys.
## 1.2.0 - 2026-02-12
### Breaking Changes
- [#10699](https://github.com/inventree/InvenTree/pull/10699) removes the `PartParameter` and `PartParameterTemplate` models (and associated API endpoints). These have been replaced with generic `Parameter` and `ParameterTemplate` models (and API endpoints). Any external client applications which made use of the old endpoints will need to be updated.
- [#11035](https://github.com/inventree/InvenTree/pull/11035) moves to a single endpoint for all metadata operations. The previous endpoints for PartMetadata, SupplierPartMetadata, etc have been removed. Any external client applications which made use of the old endpoints will need to be updated.
### Added
@ -19,10 +112,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adds parameter support for multiple new model types in [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Allows report generator to produce PDF input controls in [#10969](https://github.com/inventree/InvenTree/pull/10969)
- UI overhaul of parameter management in [#10699](https://github.com/inventree/InvenTree/pull/10699)
- Allow input controls within generated PDF reports in [#10969](https://github.com/inventree/InvenTree/pull/10969)
### Changed
-
- Improved stocktake functionality in [#11257](https://github.com/inventree/InvenTree/pull/11257)
### Removed
- Removed python 3.9 / 3.10 support as part of Django 5.2 upgrade in [#10730](https://github.com/inventree/InvenTree/pull/10730)
See [CONTRIBUTING.md](CONTRIBUTING.md) for codebase guidance.
Security reports must follow the security policy in [SECURITY.md](docs/docs/SECURITY.md) and provide how they interact with the [threat model](docs/docs/concepts/threat_model.md).
Do not open a pull request without manual review by a human. Do not file AI generated issues under any circumstances.
Using AI generated content in issue/PR discussions might lead to code of conduct violations and/or bans.
Hi there, thank you for your interest in contributing!
Please read our contribution guidelines, before submitting your first pull request to the InvenTree codebase.
### Project File Structure
## About InvenTree
InvenTree is an open-source inventory management system designed for makers, engineers, and small manufacturers.
The codebase is split into two independently deployable layers:
**Backend — Django (Python)**
A REST API built with Django and Django REST Framework. It owns all business logic, the database schema, background task processing (Django-Q2), plugin execution, and report generation. The backend can be used standalone via the API without the frontend.
**Frontend — React (TypeScript)**
A single-page application built with React 19, Mantine 9, and Vite. It communicates exclusively through the backend REST API. It has its own build pipeline, test suite (Playwright), and i18n system (Lingui). The frontend lives entirely in `src/frontend/` and has no Django awareness.
When making changes, be clear about which layer you are working in — they have separate toolchains, test runners, and linting rules.
## Project File Structure
The InvenTree project is split into two main components: frontend and backend. This source is located in the `src` directory. All other files are used for project management, documentation, and testing.
```bash
```
InvenTree/
├─ .devops/ # Files for Azure DevOps
├─ .github/ # Files for GitHub
│ ├─ actions/ # Reused actions
│ ├─ ISSUE_TEMPLATE/ # Templates for issues and pull requests
@ -39,12 +52,209 @@ InvenTree/
│ │ ├─ tsconfig.json # Settings for frontend compilation
├─ .pkgr.yml # Build definition for Debian/Ubuntu packages
| `machine/` | Support for external machines and devices |
| `order/` | Purchase orders and sales orders |
| `part/` | Parts catalogue and categories |
| `stock/` | Stock items and locations |
| `report/` | Report templates and generation |
| `plugin/` | Plugin system |
| `users/` | User accounts and permissions |
| `web/` | Serves the React frontend static build to Django |
### Frontend layout
```
src/frontend/src/
components/ # Reusable React components
pages/ # Page-level route components
tables/ # Data table components
forms/ # Form components
hooks/ # Custom React hooks
states/ # Zustand global state
locales/ # i18n translation catalogues (Lingui)
```
## Development Setup
The project uses [Invoke](https://www.pyinvoketasks.com/) (`tasks.py`) as the task runner.
```bash
# One-time setup: creates venv at dev/venv/, installs deps, sets up pre-commit hooks
invoke dev.setup-dev
# Apply database migrations
invoke migrate
# Create an admin account (required to log in)
invoke superuser
# Terminal 1 — Django dev server (port 8000)
invoke dev.server
# Terminal 2 — Vite dev server with HMR (port 5173)
invoke dev.frontend-server
# Terminal 3 (optional) — Background task worker
invoke worker
```
A VS Code Dev Container configuration is available at `.devcontainer/` and includes PostgreSQL 15 and Redis 7 sidecar services.
To see all available tasks, run `invoke --list`.
## Running Backend Tests
Always pass `--keepdb` to backend test commands. It reuses the existing test database instead of rebuilding it from scratch on every run, which is significantly faster.
# Migration tests only (skip --keepdb here — migrations must run against a fresh DB)
invoke dev.test --migrations
```
## Running Frontend Tests
Frontend tests use [Playwright](https://playwright.dev/) and target Chromium and Firefox. The test runner automatically starts the Vite dev server (port 5173), the Django backend (port 8000), and the background worker — no manual server startup is needed.
```bash
# Open Playwright's interactive UI (recommended for local development)
invoke dev.frontend-test
# Run tests in headless mode from the frontend directory
cd src/frontend && npx playwright test
# Run a specific test file
cd src/frontend && npx playwright test tests/pui_login.spec.ts
# Run tests in a specific browser only
cd src/frontend && npx playwright test --project=chromium
```
Test files live in `src/frontend/tests/` and follow the `pui_*.spec.ts` naming convention.
Locally, tests run with a single worker (required for Vite HMR compatibility). In CI they run with multiple workers against a production build for speed.
## Code Style and Linting
All formatting and linting runs automatically on commit via pre-commit hooks. Never skip them.
### Python (Backend)
Tool: **Ruff** (replaces Black, isort, flake8, and others).
```bash
ruff check src/backend/ # Lint
ruff format src/backend/ # Format
```
- Google-style docstrings enforced
- Enabled rule sets: A, B, C, D, F, I, N, SIM, PIE, PLE, PLW, RUF, UP, W
- Type checking: `ty` (configured in `pyproject.toml`)
### Django Templates
Tool: **djLint**
```bash
djlint src/backend/ --check
```
### JavaScript / TypeScript (Frontend)
Tool: **Biome** (replaces ESLint + Prettier).
```bash
cd src/frontend
yarn biome check . # Lint + format check
yarn biome format . # Format only
```
- Single quotes, space indentation
- `noUnusedImports` is an error
## Making Changes
### Backend
- Each Django app has its own `models.py`, `serializers.py`, `views.py`, `urls.py`, and `filters.py`.
- API endpoints use Django REST Framework; document them with drf-spectacular decorators.
- After changing models, create a migration: `invoke dev.makemigrations`.
- Tests live in `test_*.py` files within each app directory.
- Background tasks go through Django-Q2; define them in the app's `tasks.py`.
### Frontend
- Pages register themselves in `src/frontend/src/router.tsx`.
- Server state fetching uses TanStack Query (React Query); avoid raw `useEffect` for data fetching.
- Global UI state uses Zustand stores in `states/`.
- UI components come from Mantine 9.x; use the Mantine component library before writing custom CSS.
- Add i18n strings with Lingui (`t` macro / `Trans` component); run `invoke int.frontend-trans` to extract from source and compile. (`invoke dev.translate` is for the full translation pipeline and is not intended for local use.)
- Playwright tests live in `src/frontend/tests/`.
### Dependencies
**Python:** Add packages to `src/backend/requirements.in` (or `requirements-dev.in` for dev-only tools). The pre-commit hook runs `pip-compile` automatically on commit to regenerate `requirements.txt`. Never edit `requirements.txt` directly.
**Frontend:** Add packages with `yarn add <package>` from `src/frontend/`.
### Migrations
- Never edit existing migration files; always generate new ones.
- Keep migrations reversible where possible.
- Migration tests run in CI under the tag `migration_test`.
## CI / CD
GitHub Actions workflows live in `.github/workflows/`. Key workflows:
| Workflow | Purpose |
|----------|---------|
| `qc_checks.yaml` | Lint, type-check, backend tests, API schema |
[](https://bestpractices.coreinfrastructure.org/projects/7179)
echo"# POI07| Python ${SETUP_PYTHON} not found - aborting!"
echo"# POI07| Please ensure python can be executed with the command '$SETUP_PYTHON' by the current user '$USER'."
echo"# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.11'."
echo"# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.12'."
@ -54,7 +54,7 @@ Each user is assigned an authentication token which can be used to access the AP
If a user does not know their access token, it can be requested via the API interface itself, using a basic authentication request.
To obtain a valid token, perform a GET request to `/api/user/token/`. No data are required, but a valid username / password combination must be supplied in the authentication headers.
To obtain a valid token, perform a GET request to `/api/user/me/token/`. No data are required, but a valid username / password combination must be supplied in the authentication headers.
!!! info "Credentials"
Ensure that a valid username:password combination are supplied as basic authorization headers.
@ -146,7 +146,7 @@ r:delete:stock
Users can only perform REST API actions which align with their assigned [role permissions](../settings/permissions.md#roles).
Once a user has *authenticated* via the API, a list of the available roles can be retrieved from:
`/api/user/roles/`
`/api/user/me/roles/`
For example, when accessing the API from a *superuser* account:
@ -67,6 +67,8 @@ Transfer the currently selected stock location into another location. Scanning a
Receive incoming purchase order items into the selected location. Scanning a *new* barcode which is associated with an item in an incoming purchase order will receive the item into the selected location.
*Note: Both purchase order number and supplier SKU's are required to be found on the barcode for this function to find the associated line item. Missing one will lead to an error.*
#### Scan Items Into Location
the *Scan Items Into Location* action allows you to scan items into the selected location. Scanning a valid barcode associated with a stock item (already in the database) will result in that item being transferred to the selected location.
@ -105,6 +107,8 @@ From the [Purchase Order detail page](./po.md#purchase-order-detail) page, the f
Receive incoming purchase order items against the selected purchase order. Scanning a *new* barcode which is associated with an item in an incoming purchase order will receive the item into stock.
*Note: supplier SKU's are required to be found on the barcode for this function to find the associated line item.*
### Sales Order Actions
The following barcode actions are available for [Sales Orders](./so.md):
File attachments allow users to upload files directly to InvenTree. These files are stored on the server and can be downloaded or viewed by users with appropriate permissions.
### Image Thumbnails
When a file attachment is uploaded, InvenTree automatically determines whether the file is a valid image. If it is, a thumbnail is generated and stored alongside the attachment.
- The thumbnail is created with a reduced image size, while preserving the original aspect ratio.
- Thumbnail generation is performed in the background after upload.
- The `is_image` flag on the attachment record is set to `True` for valid images, and `False` for all other file types.
- If the uploaded file has an image extension but contains invalid or corrupt image data, no thumbnail is generated and `is_image` remains `False`.
- Link attachments (external URLs) are never assigned a thumbnail.
!!! info "Supported Formats"
Any image format recognised by the [Pillow](https://pillow.readthedocs.io/) library (e.g. PNG, JPEG, GIF, BMP, WEBP) will be treated as a valid image and have a thumbnail generated automatically.
### Link Attachments
Link attachments allow users to associate external URLs with an object. This can be useful for linking to external documentation, resources, or other relevant web content.
## Adding Attachments
To add an attachment to an object, navigate to the object's detail page and click on the "Attachments" tab. From there, you can click the "Add attachment" button to upload a file or the "Add external link" button to add a link.
### Renaming Attachments
Once a file attachment has been uploaded, it can be renamed by clicking the "Edit" action associated with the attachment. This allows you to change the filename without needing to re-upload the file. The system will handle renaming the file on the server and updating the database record accordingly.
Several models within InvenTree support the use of custom states. The custom states are display only - the business logic is not affected by the state.
Several models within InvenTree support the use of *custom states*. Custom states extend the built-in status system by adding extra labels and colours that are displayed in the user interface.
States can be added in the [Admin Center](../settings/admin.md#admin-center) under the "Custom States" section. Each state has a name, label and a color that are used to display the state in the user interface. Changes to these settings will only be reflected in the user interface after a full reload of the interface.
!!! info "Display Only"
Custom states affect display only — they do not add new workflow steps or change business logic. Every custom state is mapped to an existing built-in state (its *logical key*), and the system uses that built-in state for all decisions such as availability counts, order transitions, and filtering.
States need to be assigned to a model, state (for example status on a StockItem) and a logical key - that will be used for business logic. These 3 values combined need to be unique throughout the system.
### Example
Custom states can be defined for the following models:
Suppose you want to track stock items that are physically present and available, but are waiting for a quality inspection before use. The built-in `OK` status is the closest match — the item is available — but you want it to appear distinctly in the interface.
InvenTree provides data export functionality for a variety of data types. Most data tables in the web interface include a *Download* button in the table toolbar, which allows the currently displayed data to be exported to a file.
!!! info "Filtered Data"
The export reflects the data currently visible in the table — any active filters, search terms, or sort order are carried through to the exported file. To export the full dataset, clear all filters before exporting.
!!! info "Paginated Data"
In the user interface, data tables are paginated to improve performance. When exporting data, the export will include **all** records that match the current filters and search terms, not just the records visible on the current page.
## How to Export
**Step 1** — In any table view, click the {{ icon("cloud-download") }} *Download* button in the table toolbar:
**Step 3** — The export runs in the background. A loading indicator is shown while the export is being processed. When the export is complete, the file is automatically downloaded to your browser.
## Supported File Formats
The following file formats are available for export:
| Format | Description |
|--------|-------------|
| CSV | Comma-separated values. Portable plain-text format, compatible with most tools. |
| Excel | Microsoft Excel format (`.xlsx`). Suitable for direct use in spreadsheet applications. |
| TSV | Tab-separated values. Similar to CSV but uses tab characters as delimiters. |
## Export Plugins
InvenTree uses a plugin-based export system. The export dialog lists all plugins that are available for the data type being exported. Selecting a different plugin may provide additional export options or a different output format.
### Built-in Exporters
InvenTree includes the following built-in export plugins:
| Plugin | Description |
|--------|-------------|
| [InvenTree Exporter](../plugins/builtin/inventree_exporter.md) | General-purpose exporter for any tabulated dataset. Always enabled. |
| [BOM Exporter](../plugins/builtin/bom_exporter.md) | Custom exporter for Bill of Materials data, with additional BOM-specific options. |
| [Parameter Exporter](../plugins/builtin/parameter_exporter.md) | Exports part data including all associated custom parameter values as additional columns. |
| [Stocktake Exporter](../plugins/builtin/stocktake_exporter.md) | Exports a comprehensive stock-level summary for parts, with optional pricing and variant data. |
Custom export plugins can also be developed using the [DataExportMixin](../plugins/mixins/export.md).
## API Export
Data can also be exported programmatically via the InvenTree REST API. To trigger an export, perform a `GET` request against any list endpoint with the following query parameters:
@ -19,6 +19,22 @@ External data can be imported via the admin interface, allowing for rapid integr
To import data, the user must have the appropriate permissions. The user must be a *staff* user, and have the `change` permission for the model in question.
### Mapping to Existing Data
Many data models in InvenTree have relationships to other models. When importing data, the user must ensure that the related data is correctly mapped to existing records in the database. For example, when importing a list of parts, the user must ensure that the *part category* data has already been imported, and that the part category field in the imported file is correctly mapped to the existing part category records in the database.
!!! warning "Multi Level Import"
Multi-level imports are explicitly not supported. Only one model can be imported at a time, and the user must ensure that any related data is imported beforehand.
### Primary Key Fields
The default field used to map to existing data (i.e. related models which have already been imported into the database) is using the `ID` (primary key) field. Thus, it is important to ensure that the imported data file contains the correct `ID` values for any related data, otherwise the import process will fail to correctly link the imported data to existing records in the database.
Some models allow for mapping based on other "natural key" fields (e.g. the `reference` field for orders, or the `name` field for part categories). In such cases, the user must ensure that the correct field is mapped to the relevant column in the imported data file.
!!! warning "Unique Identifiers"
If a unique identifier cannot be determined for any related field, the user must manually map the relevant field to the correct existing record in the database, during the import process.
## Import Session
Importing data is a multi-step process, which is managed via an *import session*. An import session is created when the user initiates a data import, and is used to track the progress of the data import process.
@ -27,12 +43,26 @@ Importing data is a multi-step process, which is managed via an *import session*
The import session is managed by the InvenTree server, and all import session data is stored on the server. As the import process can be time-consuming, the user can navigate away from the import page and return later to check on the progress of the import.
Import sessions can be managed from the [Admin Center](./admin.md#admin-center) page, which lists all available import sessions
Import sessions can be managed from the [Admin Center](../settings/admin.md#admin-center) page, which lists all available import sessions
### Context Sensitive Importing
Depending on the type of data being imported, an import session can be created from an appropriate page context in the user interface. In such cases, the import session will be automatically linked to the relevant data type being imported.
### Starting an Import Session
An import session can be initiated from a number of different contexts within the user interface:
### Admin Center
Staff users can create an import session from within the [Admin Center](../settings/admin.md#admin-center). This is a general-purpose import session, and the user will be required to select the type of data to import.
Users can quickly navigate to the data import management page from the [spotlight search](../concepts/user_interface.md#spotlight), by searching for "import" and selecting the "Import data" option.
### Data Tables
Some data tables allow the user to create an import session directly from the table view. In such cases, the import session will be automatically linked to the relevant data type being imported, and additional [context information](#context-sensitive-importing) will be automatically provided.
## Import Process
The following steps outline the process of importing data into InvenTree:
@ -93,7 +123,7 @@ The basic outline of this process is:
### Create Import Session
!!! note "Admin Center"
Updating existing records can only be performed when creating a new import session from the [Admin Center](./admin.md#admin-center).
Updating existing records can only be performed when creating a new import session from the [Admin Center](../settings/admin.md#admin-center).
Create a new import session, and ensure that the *Update Existing Records* option is selected. This will allow the import session to update existing records in the database.
@ -40,9 +40,9 @@ Parameter templates are created and edited via the [admin interface](../settings
To create a template:
- Navigate to the "Settings" page
- Click on the "Part Parameters" tab
- Click on the "Parameters" tab
- Click on the "New Parameter" button
- Fill out the `Create Part Parameter Template` form: `Name` (required) and `Units` (optional) fields
- Fill out the `Create Parameter Template` form: `Name` (required) and `Units` (optional) fields
- Click on the "Submit" button.
An existing template can be edited by clicking on the "Edit" button associated with that template:
@ -53,9 +53,9 @@ An existing template can be edited by clicking on the "Edit" button associated w
After [creating a template](#create-template) or using the existing templates, you can add parameters to any part.
To add a parameter, navigate to a specific part detail page, click on the "Parameters" tab then click on the "New Parameters" button, the `Create Part Parameter` form will be displayed:
To add a parameter, navigate to a specific part detail page, click on the "Parameters" tab then click on the "New Parameters" button, the `Create Parameter` form will be displayed:
{{ image("part/create_part_parameter.png", "Create Part Parameter Form") }}
Select the parameter `Template` you would like to use for this parameter, fill-out the `Data` field (value of this specific parameter) and click the "Submit" button.
@ -132,7 +132,7 @@ The in-built conversion functionality means that parameter values can be input i
### Incompatible Units
If a part parameter is created with a value which is incompatible with the units specified for the template, it will be rejected:
If a parameter is created with a value which is incompatible with the units specified for the template, it will be rejected:
@ -63,3 +63,9 @@ Currency exchange rates are updated periodically, using the configured currency
## Pricing Settings
Refer to the [global settings](../settings/global.md#pricing-and-currency) documentation for more information on available currency settings.
## Rendering Currencies in Reports
Currency values can be rendered in report templates using the [`render_currency`](../report/helpers.md#render_currency) helper function. This function formats a currency amount according to a locale, and supports currency conversion within the template.
See the [report helpers documentation](../report/helpers.md#currency-formatting) for full details and examples.
*Tags* are short, arbitrary labels that can be attached to InvenTree objects to group or classify them in flexible ways that don't require changes to the underlying data model. Unlike [parameters](./parameters.md), tags carry no typed value — they are simply names. A tag can be applied to objects of any supported model type, and tags are shared across the entire InvenTree instance.
!!! note "Shared Tag Namespace"
Tags are global: a tag named `prototype` applied to a Part and the same tag applied to a Build Order refer to the same underlying tag record. Renaming or deleting a tag affects every object to which it is attached.
### Supported Models
Tags can be attached to the following InvenTree objects:
- [Sales Order Shipments](../sales/sales_order.md#shipments)
## Managing Tags
### Adding and Removing Tags
Any object that supports tags will expose a *Tags* field in its detail and edit forms. Tags are entered as a comma-separated list of names and can be freely added or removed at any time. Tag names are case-insensitive — `Prototype`, `prototype`, and `PROTOTYPE` all refer to the same tag.
### Tag Names
Tag names must be unique within the InvenTree instance (case-insensitively). If you type a name that already exists under a different capitalisation, the existing tag is assigned rather than a new one created. Tag names may contain spaces, but leading and trailing whitespace is stripped automatically.
## Filtering by Tags
Tables that support tags can be filtered by one or more tag names. When multiple tags are specified, only objects that carry **all** of the specified tags are returned (AND logic).
For example, filtering a Parts table by the tags `approved` and `prototype` returns only parts tagged with both.
## API Access
### Tag Endpoints
The tag list is available at `/api/tag/`. Individual tags can be retrieved, updated, or deleted at `/api/tag/<id>/`.
The `model_type` query parameter narrows the tag list to tags currently applied to a specific model type:
```
GET /api/tag/?model_type=part
```
### Tags on Model Endpoints
For models that support tags, the `tags` field is returned in the detail endpoint response as a list of tag name strings:
```json
{
"pk": 42,
"name": "Widget",
"tags": ["approved", "prototype"]
}
```
Tags can be updated via a `PATCH` or `POST` request by supplying a JSON-encoded list of tag name strings. The full list of tags replaces the previous set — omitting a tag removes it:
```json
{
"tags": ["approved", "production"]
}
```
Tags can also be used as a filter parameter on list endpoints. Supply a comma-separated list of tag names to the `tags` query parameter:
```
GET /api/part/?tags=approved,prototype
```
This returns only parts tagged with **both**`approved` and `prototype`.
@ -16,7 +16,7 @@ Deploying InvenTree to production requires to knowledge of the security assumpti
2. All users are trusted - therefore user uploaded files can be assumed to be safe. There are basic checks in place to ensure that the files are not using common attack vectors but those are not exhaustive.
3. Superuser permissions are only given to trusted users and not used for daily operations. A superuser account can manipulate or extract all files on the server that the InvenTree server process have access to.
3. Superuser or staff permissions are only given to trusted users and not used for daily operations. A superuser account can manipulate or extract all files on the server that the InvenTree server process have access to. See [dangerous user flags](../settings/permissions.md#dangerous-user-flags) for more details on user permissions and flags.
@ -8,7 +8,7 @@ Support for real-world "physical" units of measure is implemented using the [pin
- Ensures consistent use of real units for your inventory management
- Convert between compatible units of measure from suppliers
- Enforce use of compatible units when creating part parameters
- Enforce use of compatible units when creating parameters
- Enable custom units as required
### Unit Conversion
@ -61,7 +61,7 @@ The [supplier part](../part/index.md/#supplier-parts) model uses real-world unit
### Parameter
The [parameter template](../concepts/parameters.md#parameter-templates) model can specify units of measure, and part parameters can be specified against these templates with compatible units
The [parameter template](../concepts/parameters.md#parameter-templates) model can specify units of measure, and parameters can be specified against these templates with compatible units
The navigation tree includes a search bar at the top of the panel. Typing into the search bar filters the tree to show only entries that match the search query. When a search is active, all matching results are expanded and displayed in a flat list. Clearing the search field returns the tree to its normal browsing mode.
#### Highlight Selected Entry
The currently selected entry in the navigation tree is highlighted with a distinct background color, making it easy to identify the active page or section within the hierarchy.
#### Auto-Expand to Selected Entry
When the navigation tree is opened, it automatically expands to reveal the currently selected entry. All ancestor nodes in the hierarchy are expanded so the active entry is immediately visible, without requiring manual navigation through the tree.
## Dashboard
The dashboard provides a customizable landing page for users when they log in to the system. The dashboard can be configured to display a variety of widgets and information panels, providing users with quick access to important data and actions.
@ -158,6 +170,41 @@ Select the "table filters" button to open the filter selection menu
Table filters are saved across browser sessions, allowing users to maintain their preferred filter settings when returning to the particular table view.
#### Column Filters
Many table columns expose an inline filter icon directly in the column header, providing a quick way to filter by that column without opening the full filter drawer. Columns that support filtering display a small filter icon alongside the column title. The icon is highlighted when a filter for that column is currently active, giving an at-a-glance indication of which columns have active filters.
Clicking the icon opens a compact popover anchored to the column header:
**Single-filter columns** — for columns linked to one filter (e.g. *Active*, *Has IPN*, *Status*), selecting a value immediately applies the filter and the popover closes automatically.
**Range columns** — for columns that represent a range concept (e.g. *Start Date*, *Target Date*, *Creation Date*), the popover stays open and presents multiple controls — for example *before* and *after* date pickers — so both bounds can be set in a single interaction.
Once a filter is active, the popover shows a badge with the current value and a remove button (red ×) instead of the value picker. Clicking the × clears only that column's filter.
!!! info "Column filters and the filter drawer share the same state"
Filters applied via a column popover appear immediately in the filter drawer's active-filter list, and filters added through the drawer are reflected in the column icons. Clearing all filters from the drawer also removes any filters set via column popovers.
#### Saved Filter Groups
Frequently used combinations of filters can be saved as a named *filter group*, allowing them to be quickly recalled later without having to re-add each filter individually.
The **Saved Filter Groups** panel is displayed at the bottom of the filter drawer. When one or more filters are active, a **Save current filters** button is available. Clicking it opens an inline name input — enter a name and press Enter (or click the confirm icon) to save the group. Press Escape or click the cancel icon to discard.
Previously saved filter groups are listed in the panel. Each entry shows the group name alongside two actions:
- **Load** (green reload icon): Replaces the current active filters with the filters stored in that group. The table immediately re-fetches data using the restored filters.
Saved filter groups are stored in the browser's local storage and are specific to each table or calendar view, so groups saved for one view are not available in another. They persist across local browser sessions until explicitly deleted. Filter groups are not shared to other devices.
!!! info "Loading a filter group replaces active filters"
Loading a saved filter group replaces all currently active filters with those stored in the group. Any unsaved active filters will be overwritten.
### Data Sorting
Some table columns support data sorting, allowing the dataset to be sorted in ascending or descending order based on the values in that column. To sort a column, click on the column header. Clicking the column header again will toggle the sort order between ascending and descending. The current sort order is indicated by an arrow icon in the column header.
@ -190,7 +237,7 @@ For tables which reference other objects within the system, clicking on a row wi
## Calendar Views
Some [table views](#table-views) can be switched to a calendar view, which provides a visual representation of data based on date fields. The calendar view allows users to easily see and interact with data that is organized by date, such as scheduled tasks, events, or deadlines.
Some [table views](#table-views) associated with various order types can be switched to a calendar view, which provides a visual representation of data based on date fields. The calendar view allows users to easily see and interact with data that is organized by date, such as scheduled tasks, events, or deadlines.
To switch to the "calendar view" (for a table which supports it), click on the "calendar view" button located above and to the right of the table view:
@ -200,6 +247,10 @@ This will display the data in a calendar format:
The calendar view provides a configurable "horizon" setting, which allows users to adjust the number of months displayed in the calendar view.
## Parametric Views
Some [table views](#table-views) can be switched to a parametric view, which provides a visual representation of data based on specific parameters or attributes. The parametric view allows users to easily see and interact with data that is organized by certain characteristics, such as categories, types, or other relevant attributes.
@ -224,6 +275,8 @@ Example: Creating a new part via the "Add Part" form:
{{ image("concepts/ui_form_add_part.png", "Add Part Button") }}
On several forms is displayed option "Keep form open" in bottom part of the form on left side of Submit button (option is visible on the screenshot above). When this switch is turned on, form window is not closed after submit and filled form data is not reset. This is useful for creating more entries at one time with similar properties (e.g. only different number in name).
### Data Editing
Example: Editing an existing purchase order via the "Edit Purchase Order" form:
@ -266,10 +319,37 @@ To remove a particular category of search results from the global search menu, c
## Spotlight
## Barcode Scanning
The user interface features a "spotlight" search functionality, which provides a quick and efficient way to access common actions or navigate to specific pages within the InvenTree system. The spotlight search is designed to enhance user productivity by allowing users to quickly find and execute actions without needing to navigate through menus or remember specific page locations.
To open the "spotlight" search, click on the "spotlight" icon located in the main menu at the top of the interface. This will open the spotlight search menu, allowing you to enter search queries and view available actions.
Alternatively, the spotlight search can be opened using the keyboard shortcut `Ctrl + K` (or `Cmd + K` on macOS), providing a quick and convenient way to access the spotlight functionality without needing to click on the menu icon.
### Disable Spotlight
Users may opt to disable the spotlight search functionality if they do not find it useful or prefer not to use it. To disable the spotlight search, navigate to your [user settings](../settings/user.md) and locate the option to disable the spotlight feature. Once disabled, the spotlight search will no longer be accessible from the main menu or via keyboard shortcuts.
## Copy Button
Many fields within the InvenTree user interface include a "copy" button, which allows users to quickly copy the value of that field to their clipboard. This is particularly useful for fields that contain important identifiers, such as part numbers, stock item codes, or other relevant data that may need to be easily copied and pasted elsewhere.
!!! important "Secure Context"
The "copy" button functionality relies on the browser's clipboard API, which may not be available in all contexts (e.g. if the user is accessing the InvenTree interface via a non-https connection, or through an embedded iframe or a non-standard browser). In such cases, the "copy" button may not function as intended.
## User Permissions
Many aspects of the user interface are controlled by user permissions, which determine what actions and features are available to each user based on their assigned roles and permissions within the system. This allows for a highly customizable user experience, where different users can have access to different features and functionality based on their specific needs and responsibilities within the organization.
If a user does not have permission to access a particular feature or section of the system, that feature will be hidden from their view in the user interface. This helps to ensure that users only see the features and information that are relevant to their role, reducing clutter and improving usability.
## Language Support
The InvenTree user interface supports multiple languages, allowing users to interact with the system in their preferred language.
The default system language can be configured by the system administrator in the [server configuration options](../start/config.md#basic-options).
Additionally, users can select their preferred language in their [user settings](../settings/user.md), allowing them to override the system default language with their own choice. This provides a personalized experience for each user, ensuring that they can interact with the system in the language they are most comfortable with.
InvenTree roughly follow the [GitLab flow](https://about.gitlab.com/topics/version-control/what-are-gitlab-flow-best-practices/) branching style, to allow simple management of multiple tagged releases, short-lived branches, and development on the main branch.
There are nominally 5 active branches:
- `master` - The main development branch
- `stable` - The latest stable release
- `l10n` - Translation branch: Source to Crowdin
- `l10_crowdin` - Translation branch: Source from Crowdin
- `y.y.x` - Release branch for the currently supported version (e.g. `0.5.x`)
All other branches are removed periodically by maintainers or core team members. This includes old release branches.
Do not use them as base for feature development or forks as patches from them might not be accepted without rebasing.
| Branch | Description |
| --- | --- |
| `master` | The main development branch |
| `stable` | The latest stable release |
| `next-breaking` | The next breaking release (e.g. 2.0, 3.0) with all deprecated features removed |
| `l10n` | Translation branch: Source to Crowdin |
| `l10_crowdin` | Translation branch: Source from Crowdin |
| `y.y.x` | Release branch for the currently supported version (e.g. `0.5.x`) |
All other branches are removed periodically by maintainers or core team members. This includes old release branches. Do not use them as base for feature development or forks as patches from them might not be accepted without rebasing.
### Version Numbering
@ -115,6 +118,23 @@ The translation process is as follows:
4. Translations made in Crowdin are automatically pushed back to the `l10_crowdin` branch by Crowdin once they are approved
5. The `l10_crowdin` branch is merged back into `master` by a maintainer periodically
### `next-breaking` Branch
Used for easier testing of plugins and integrations against the next major release. It is branched from master when a major release is cut and updated on minor release. The branch is not build into docker images or packages and not meant to be run in production.
All deprecated features (REST or python API endpoints mostly) are removed from this branch after each minor release. This allows plugin developers to test their plugins against the next major release early and identify any extensive changes before the major release is cut.
Only breaking changes are added to this branch. No new features should be added at any point to this branch, only breaking removals / changes.
Before a major release is cut (1.12.5 > 2.0.0), this branch is merged back into `master`.
During the life-time of a major release line (1.0.1, 1.1.x, 1.2.x, 1.3.x, ..., 1.12.5) all deprecation removals are collected in this branch.
On every minor release (1.11.8 > 1.12.0) the `master` is rebased onto the `next-breaking` branch.
Every time a change with depreations is merged into `master`, a follow up PR that removes the newly-introduced deprecation is created targeting the `next-breaking` branch. After the next minor is released and `master` was rebased into `next-breaking` all the PRs from the previous minor release line can be merged into the `next-breaking` branch. Deprecation removals for the - possibly - long running major release line can be collected this way without having a large number of deprecation removals PRs open.
## API versioning
The [API version]({{ sourcefile("src/backend/InvenTree/InvenTree/api_version.py") }}) needs to be bumped every time when the API is changed.
@ -144,7 +164,7 @@ The core software modules are targeting the following versions:
@ -60,7 +60,12 @@ If you only need a superuser, run the `superuser` task. It should prompt you for
#### Run background workers
If you need to process your queue with background workers, run the `worker` task. This is a foreground task which will execute in the terminal.
If you need to process your queue with background workers, open a new terminal and run the `worker` task with `invoke worker`. This is a foreground task which will execute in the terminal.
If you are developing functions that will be executed by background workers there are a two debugging options.
- If the workers are started with the `worker` task you can add `print` or `logger` statements to the code and monitor the output in the terminal.
- All tasks can be forced to run in the foreground worker by uncommenting the `--sync` and `--noreload` arguments under the `InvenTree Server - 3rd party` entry in `.vscode/launch.json`. With this setting you should not start a separate background worker, instead you start the `InvenTree Server - 3rd party` from the `Run and Debug` side panel. All task will now run in one single process and you can set breakpoints, inspect variables and single step also tasks that normally are offloaded to background workers. It should be noted that with this setting the GUI will be unresponsive while tasks are executed.
@ -35,7 +35,7 @@ If the installed version of invoke is too old, users may see error messages duri
Make sure you are running a stable or production release of InvenTree. The frontend panel is not included in development releases.
More Information: [Error Codes - INVE-E1](./settings/error_codes.md#inve-e1)
### No module named <xxx>
### No module named xyz
During the install or update process, you may be presented with an error like:
@ -195,3 +195,24 @@ This means that either:
- The docker user does not have write permission to the specified directory
In either case, ensure that the directory is available *on your local machine* and the user account has the required permissions.
## Error Rendering Component
Sometimes, following a software update, you may find that certain components of the web interface are not rendering correctly, and presented with a message similar to the screenshot below:
This is often due to a caching issue with your web browser. Try performing a hard refresh of the page to clear the cache, this should resolve the issue in most cases.
If the problem persists, refer to the [troubleshooting guide](./troubleshooting.md) for further assistance.
## Expression tree is too large
If you are running a large InvenTree deployment on an SQLite database, you may encounter an error similar to:
```
Expression tree is too large (maximum depth 1000)
```
This is a [known limitation of SQLite](https://www.sqlite.org/limits.html) which can occur when performing complex queries on a large database. Due to [structural limitations](./start/processes.md#sqlite-limitations) of SQLite, it is recommended to use a more robust database backend such as PostgreSQL for larger deployments.
@ -80,7 +80,16 @@ The *Deallocate Stock* button can be used to remove all allocations of untracked
## Automatic Stock Allocation
To speed up the allocation process, the *Auto Allocate* button can be used to allocate untracked stock items to the build. Automatic allocation of stock items does not work in every situation, as a number of criteria must be met.
To speed up the allocation process, the *Auto Allocate* button can be used to automatically allocate stock items to the build.
!!! info "Background Task"
Auto-allocation runs as a background task. The UI will display a progress indicator while the task is running.
#### Selecting Lines to Allocate
By default, auto-allocation processes **all eligible BOM line items** in the build order. To restrict allocation to a subset of lines, select the desired rows in the allocation table before pressing the button — the dialog will indicate how many lines are selected.
#### Auto Allocation Options
The *Automatic Allocation* dialog is presented as shown below:
@ -90,12 +99,16 @@ The *Automatic Allocation* dialog is presented as shown below:
Select the master location where stock items are to be allocated from. Leave this input blank to allocate stock items from any available location.
**Exclude Location**
Exclude stock from a specific location (and all of its sub-locations). Useful for reserving stock in a particular area.
**Interchangeable Stock**
Set this option to *True* to signal that stock items can be used interchangeably. This means that in the case where multiple stock items are available, the auto-allocation routine does not care which stock item it uses.
!!! warning "Take Care"
If the *Interchangeable Stock* option is enabled, and there are multiple stock items available, the results of the automatic allocation algorithm may somewhat unexpected.
If the *Interchangeable Stock* option is enabled, and there are multiple stock items available, the results of the automatic allocation algorithm may be somewhat unexpected.
!!! info "Example"
Let's say that we have 5 reels of our *C_100nF_0603* capacitor, each with 4,000 parts available. If we do not mind which of these reels the stock should be taken from, we enable the *Interchangeable Stock* option in the dialog above. In this case, the stock will be allocated from one of these reels, and eventually subtracted from stock when the build is completed.
@ -104,13 +117,39 @@ Set this option to *True* to signal that stock items can be used interchangeably
Set this option to *True* to allow substitute parts (as specified by the BOM) to be allocated, if the primary parts are not available.
**Optional Items**
Set this option to *True* to include optional BOM line items in the auto-allocation. By default, optional items are not automatically allocated.
**Item Type**
Controls which category of BOM line items is considered for auto-allocation:
| Option | Description |
| --- | --- |
| Untracked Items | Only untracked (non-serialized) BOM lines are allocated *(default)* |
| Tracked Items | Only tracked BOM lines are allocated |
| All Items | Both tracked and untracked BOM lines are allocated |
**Stock Priority**
Controls the order in which matching stock items are consumed:
| Option | Description |
| --- | --- |
| Oldest stock first (FIFO) | Stock items updated least recently are consumed first *(default)* |
| Newest stock first (LIFO) | Stock items updated most recently are consumed first |
| Smallest quantity first | Stock items with the lowest available quantity are consumed first |
| Largest quantity first | Stock items with the highest available quantity are consumed first |
| Soonest expiry date first | Stock items expiring earliest are consumed first; items with no expiry date are used last |
## Allocating Tracked Stock
Allocation of tracked stock items is slightly more complex. Instead of being allocated against the *Build Order*, tracked stock items must be allocated against an individual *Build Output*.
Allocating tracked stock items to particular build outputs is performed in the *Pending Items* tab:
Allocating tracked stock items to particular build outputs is performed in the *Incomplete Outputs* tab:
In the *Pending Items* tab, we can see that each build output has a stock allocation requirement which must be met before that build output can be completed:
In the *Incomplete Outputs* tab, we can see that each build output has a stock allocation requirement which must be met before that build output can be completed:
@ -126,6 +165,12 @@ Here we can see that the incomplete build outputs (serial numbers 15 and 14) now
!!! note "Example: Tracked Stock"
Let's say we have 5 units of "Tracked Part" in stock - with 1 unit allocated to the build output. Once we complete the build output, there will be 4 units of "Tracked Part" in stock, with 1 unit being marked as "installed" within the assembled part
### Automatic Stock Allocation
Tracked stock items can be automatically allocated to build outputs using the *Auto Allocate* button in the *Incomplete Outputs* tab. This will attempt to allocate tracked stock items to build outputs based on matching serial numbers.
For each build output, the auto-allocation routine will attempt to find a matching component item with the same serial number. If such a stock item is found, and it is available for use, it will be allocated to that build output.
## Consuming Stock
Allocating stock items to a build order does not immediately remove them from stock. Instead, the stock items are marked as "allocated" against the build order, and are only removed from stock when they are "consumed" by the build order.
A Bill of Materials (BOM) defines the list of component parts required to make an assembly, [create builds](./build.md) and allocate inventory.
A Bill of Materials (BOM) defines the list of component parts required to make an assembly, [create build orders](./build.md) and allocate inventory.
A part which can be built from other sub components is called an *Assembly*.
@ -18,7 +18,8 @@ A BOM for a particular assembly is comprised of a number (zero or more) of BOM "
| --- | --- |
| Part | A reference to another *Part* object which is required to build this assembly |
| Reference | Optional reference field to describe the BOM Line Item, e.g. part designator |
| Quantity | The quantity of *Part* required for the assembly |
| Raw Amount | The raw quantity of the part required for the assembly, which can be expressed in different units of measure, e.g. `2 cm`, `1/2 inch`, `200 kg`. |
| Quantity | The quantity of *Part* required for the assembly - this value is automatically calculated from the "raw amount" field, taking into account the units of measure associated with the underlying part. |
| Attrition | Estimated attrition losses for a production run. Expressed as a percentage of the base quantity (e.g. 2%) |
| Setup Quantity | An additional quantity of the part which is required to account for fixed setup losses during the production process. This is added to the base quantity of the BOM line item |
| Rounding Multiple | A value which indicates that the required quantity should be rounded up to the nearest multiple of this value. |
@ -27,6 +28,18 @@ A BOM for a particular assembly is comprised of a number (zero or more) of BOM "
| Optional | A boolean field which indicates if this BOM Line Item is "optional" |
| Note | Optional note field for additional information
### Units of Measure
The `raw_amount` field allows the user to specify the required quantity of a particular part in different [units of measure](../concepts/units.md). The units of measure are determined by the underlying part definition. For example, if the part is defined with a default unit of measure of "kg", the user can specify the required quantity in "g", "mg", "lb", etc.
The `raw_amount` field is stored as a string, and the `quantity` field is automatically calculated from the `raw_amount` field, taking into account the units of measure associated with the underlying part. This allows for greater flexibility in specifying the required quantity of a particular part, while still maintaining accurate tracking of inventory and production requirements.
If the underlying part does not have a defined unit of measure, the `raw_amount` field is not allowed to have any units of measure specified, and the `quantity` field is simply a numeric representation of the `raw_amount` field.
### Fractional Representation
The `raw_amount` field also allows for fractional representation of the required quantity. For example, if the required quantity is 0.5 kg, the user can specify this as `500 g`, `0.5 kg`, `1/2 kg`, etc. The `quantity` field will be automatically calculated as 0.5 kg, regardless of the specific representation used in the `raw_amount` field.
### Consumable BOM Line Items
If a BOM line item is marked as *consumable*, this means that while the part and quantity information is tracked in the BOM, this line item does not get allocated to a [Build Order](./build.md). This may be useful for certain items that the user does not wish to track through the build process, as they may be low value, in abundant stock, or otherwise complicated to track.
@ -37,6 +50,12 @@ In the example below, see that the *Wood Screw* line item is marked as consumabl
Further, in the [Build Order](./build.md) stock allocation table, we see that this line item cannot be allocated, as it is *consumable*.
### Optional BOM Line Items
If a BOM line item is marked as *optional*, this means that the part and quantity information is tracked in the BOM, but this line item is not required to be allocated to a [Build Order](./build.md). This may be useful for certain items which are not strictly required for the build process to be completed.
When completing a Build Order, the user can choose whether to include optional items in the build process or not. If optional items are included, they will be allocated to the Build Order as normal. If optional items are excluded, they will not be allocated to the Build Order, and the build process can be completed without them.
### Substitute BOM Line Items
Where alternative parts can be used when building an assembly, these parts are assigned as *Substitute* parts in the Bill of Materials. A particular line item may have multiple substitute parts assigned to it. When allocating stock to a [Build Order](./build.md), stock items associated with any of the substitute parts may be allocated against the particular line item.
@ -86,13 +105,20 @@ Note that inherited BOM Line Items only flow "downwards" in the variant inherita
!!! info "Editing Inherited Items"
When editing an inherited BOM Line Item for a template part, the changes are automatically reflected in the BOM of any variant parts.
## BOM Creation
## BOM Editing
BOMs can be created manually, by adjusting individual line items, or by uploading (importing) an existing BOM file.
Bills of Material (BOMs) can be created manually, by adjusting individual line items, or by uploading (importing) an existing BOM file.
### Editing Mode
By default, the BOM is displayed in "view" mode. To edit the BOM, click on the {{ icon("edit", color="blue", title="Edit") }} icon at the top of the BOM panel. This will enable editing mode, which allows you to add, adjust or delete BOM line items.
!!! warning "Permissions"
Only users with the appropriate permissions can edit BOMs. If you do not have permission to edit the BOM, the "Edit" icon will not be visible.
### Importing a BOM
BOM data can be imported from an existing file (such as CSV or Excel) from the *BOM* panel for a particular part/assembly. This process is a special case of the more general [data import process](../settings/import.md).
BOM data can be imported from an existing file (such as CSV or Excel) from the *BOM* panel for a particular part/assembly. This process is a special case of the more general [data import process](../concepts/data_import.md).
At the top of the *BOM* panel, click on the {{ icon("file-arrow-left", color="green", title="Import BOM Data") }} icon to open the import dialog.
@ -156,89 +182,40 @@ If the BOM requires revalidation, the status will be displayed as "Not Validated
{{ image("build/bom_invalid.png", "BOM Not Validated") }}
## Required Quantity Calculation
## BOM Comparison
When a new [Build Order](./build.md) is created, the required production quantity of each component part is calculated based on the BOM line items defined for the assembly being built. To calculate the required production quantity of a component part, the following considerations are made:
It is possible to compare the BOM of one assembly with another assembly. This comparison can highlight different component parts, quantities and other properties of the BOM line items.
### Base Quantity
To compare the BOM of one assembly with another, navigate to the "Bill of Materials" tab of the part detail page, then click on the {{ icon("git-compare", color="blue", title="Compare BOM") }} icon at the top of the BOM table:
The base quantity of a BOM line item is defined by the `Quantity` field of the BOM line item. This is the number of parts which are required to build one assembly. This value is multiplied by the number of assemblies which are being built to determine the total quantity of parts required.
Required Quantity = Base Quantity * Number of Assemblies
```
This will open the BOM comparison view, which allows you to select a secondary assembly to compare with the primary assembly. The BOM line items of the two assemblies will be displayed side by side, with differences highlighted:
The `Attrition` field of a BOM line item is used to account for expected losses during the production process. This is expressed as a percentage of the `Base Quantity` (e.g. 2%).
### Display Mode
If a non-zero attrition percentage is specified, it is applied to the calculated `Required Quantity` value.
When comparing BOMs from two different assemblies, the user can select from the following view modes:
| *Show all parts* | Display all BOM line items from both assemblies. Differences are highlighted. |
| *Show different parts* | Display only the BOM line items which are different between the two assemblies. |
| *Show common parts* | Display only the BOM line items which are common between the two assemblies. |
!!! info "Optional"
The attrition percentage is optional. If not specified, it defaults to 0%.
In each case, any differences between the BOM line items are highlighted in red.
### Setup Quantity
## Replacing Components
The `Setup Quantity` field of a BOM line item is used to account for fixed losses during the production process. This is an additional quantity of the part which is required to ensure that the production run can be completed successfully. This value is added to the calculated `Required Quantity`.
When a component is used in the BOM for multiple assemblies, it can be time consuming to update the BOM for each assembly when a change is required. InvenTree provides a "Replace Component" function which streamlines the process of replacing a component part with another part across multiple BOMs.
To replace a component part within multiple assemblies:
!!! info "Optional"
The setup quantity is optional. If not specified, it defaults to 0.
- Navigate to the [Used In](../part/views.md#used-in) tab of the component part detail page
- Select the assemblies you wish to update by ticking the checkbox next to each assembly
- Click on the {{ icon("replace", color="blue", title="Replace Component") }} icon to open the "Replace Component" dialog
### Rounding Multiple
The following dialog will be displayed, which allows the user to select a new component part to replace the existing component part in the BOM of the selected assemblies:
The `Rounding Multiple` field of a BOM line item is used to round the calculated `Required Quantity` value to the nearest multiple of the specified value. This is useful for ensuring that the required quantity is a whole number, or to meet specific packaging requirements.
When a new [Build Order](./build.md) is created, the required production quantity of each component part is calculated based on the BOM line items defined for the assembly being built. To calculate the required production quantity of a component part, the following considerations are made:
### Base Quantity
The base quantity of a BOM line item is defined by the `Quantity` field of the BOM line item. This is the number of parts which are required to build one assembly. This value is multiplied by the number of assemblies which are being built to determine the total quantity of parts required.
```
Required Quantity = Base Quantity * Number of Assemblies
```
### Attrition
The `Attrition` field of a BOM line item is used to account for expected losses during the production process. This is expressed as a percentage of the `Base Quantity` (e.g. 2%).
If a non-zero attrition percentage is specified, it is applied to the calculated `Required Quantity` value.
The attrition percentage is optional. If not specified, it defaults to 0%.
### Setup Quantity
The `Setup Quantity` field of a BOM line item is used to account for fixed losses during the production process. This is an additional quantity of the part which is required to ensure that the production run can be completed successfully. This value is added to the calculated `Required Quantity`.
The setup quantity is optional. If not specified, it defaults to 0.
### Rounding Multiple
The `Rounding Multiple` field of a BOM line item is used to round the calculated `Required Quantity` value to the nearest multiple of the specified value. This is useful for ensuring that the required quantity is a whole number, or to meet specific packaging requirements.
@ -20,7 +20,7 @@ New parts can be created manually by selecting the *Create Part* option from the
{{ image("part/part_create_form.png", "New part form") }}
Fill out the required part parameters and then press *Submit* to create the new part. If there are any form errors, you must fix these before the form can be successfully submitted.
Fill out the required attributes and then press *Submit* to create the new part. If there are any form errors, you must fix these before the form can be successfully submitted.
Once the form is completed, the browser window is redirected to the new part detail page.
@ -48,7 +48,7 @@ If the *Add Supplier Data* option is checked, then supplier part and manufacture
Parts can be imported from an external file, by selecting the *Import from File* option.
This action opens the [data import wizard](../settings/import.md), which steps the user through the process of importing parts from the selected file.
This action opens the [data import wizard](../concepts/data_import.md), which steps the user through the process of importing parts from the selected file.
The *Part* is the core element of the InvenTree ecosystem. A Part object is the archetype of any stock item in your inventory. Parts are arranged in hierarchical categories which are used to organize and filter parts by function.
## Part Stock
Each part can have multiple [stock items](../stock/index.md) associated with it, which represent the physical quantity of that part in various locations. The total stock level for a given part is the sum of all stock items associated with that part.
### Minimum Stock
A part may have a specified "minimum stock" level. This is a user-defined value which indicates the minimum quantity of that part which should be kept in stock at all times. If the total stock level for a given part falls below the minimum stock level, the part is flagged as "low stock" and can be easily identified in the interface.
### Maximum Stock
A part may also have a specified "maximum stock" level. This is a user-defined value which indicates the maximum quantity of that part which should be kept in stock at all times. If the total stock level for a given part exceeds the maximum stock level, the part is flagged as "overstocked" and can be easily identified in the interface.
## Part Category
Part categories are very flexible and can be easily arranged to match a particular user requirement. Each part category displays a list of all parts *under* that given category. This means that any part belonging to a particular category, or belonging to a sub-category, will be displayed.
@ -27,7 +39,7 @@ Clicking on the part name links to the [*Part Detail*](./views.md) view.
## Part Attributes
Each *Part* defined in the database provides a number of different attributes which determine how that part can be used. Configuring these attributes for a given part will impact the available functions that can be perform on (or using) that part).
Each *Part* defined in the database provides a number of different attributes which determine how that part can be used. Configuring these attributes for a given part will impact the available functions that can be perform on (or using) that part.
### Virtual
@ -75,13 +87,16 @@ A [Purchase Order](../purchasing/purchase_order.md) allows parts to be ordered f
If a part is designated as *Salable* it can be sold to external customers. Setting this flag allows parts to be added to sales orders.
## Locked Parts
Parts can be locked to prevent them from being modified. This is useful for parts which are in production and should not be changed. The following restrictions apply to parts which are locked:
- Locked parts cannot be deleted
- BOM items cannot be created, edited, or deleted when they are part of a locked assembly
- Part parameters linked to a locked part cannot be created, edited or deleted
- Parameters linked to a locked part cannot be created, edited or deleted
The part locking functionality can be enabled or disabled globally via the [Part Locking](../settings/global.md#parts) system setting (`PART_ENABLE_LOCKING`). When disabled, the locked state of a part is ignored and all operations are permitted.
## Active Parts
@ -145,4 +160,4 @@ The [InvenTree mobile app](../app/part.md#part-image-view) allows part images to
## Part Import
*Parts* can be imported by staff-members on the part-list-view (this feature must be enabled in the part-settings), in the part-settings or on the [admin-page for parts](../settings/import.md) (only accessible if you are also an admin). The first two options provide a multi-stage wizard that enables mapping fields from various spreadsheet or table-data formats while the latter requires a well-formatted file but is much more performant.
*Part* data can be imported using the [data import wizard](../concepts/data_import.md). This allows part data to be imported from an external file, which can be useful for bulk importing of part data.
@ -27,24 +27,22 @@ When creating a new revision of a part, there are some restrictions which must b
* **Circular References**: A part cannot be a revision of itself. This would create a circular reference which is not allowed.
* **Unique Revisions**: A part cannot have two revisions with the same revision number. Each revision (of a given part) must have a unique revision code.
* **Revisions of Revisions**: A single part can have multiple revisions, but a revision cannot have its own revision. This restriction is in place to prevent overly complex part relationships.
* **Template Revisions**: A part which is a [template part](./template.md) cannot have revisions. This is because the template part is used to create variants, and allowing revisions of templates would create disallowed relationship states in the database. However, variant parts are allowed to have revisions.
* **Template References**: A part which is a revision of a variant part must point to the same template as the original part. This is to ensure that the revision is correctly linked to the original part.
## Revision Settings
The following options are available to control the behavior of part revisions.
The following [global settings](../settings/global.md) are available to control the behavior of part revisions:
Note that these options can be changed in the InvenTree settings:
* **Enable Revisions**: If this setting is enabled, parts can have revisions. If this setting is disabled, parts cannot have revisions.
* **Assembly Revisions Only**: If this setting is enabled, only assembly parts can have revisions. This is useful if you only want to track revisions of assemblies, and not individual parts.
## Create a Revision
To create a new revision for a given part, navigate to the part detail page, and click on the "Revisions" tab.
To create a new revision for a given part, navigate to the part detail page, and click on the part actions menu (three vertical dots on the top right of the page).
Select the "Duplicate Part" action, to create a new copy of the selected part. This will open the "Duplicate Part" form:
@ -67,4 +65,5 @@ When multiple revisions exist for a particular part, you can navigate between re
{{ image("part/part_revision_select.png", "Select part revision") }}
!!! info "Revision Selector Visibility"
Note that this revision selector is only visible when multiple revisions exist for the part.
@ -14,8 +14,8 @@ This plugin is a *mandatory* plugin, and is always enabled.
This plugin provides selection of the barcode format to use when generating labels. The format can be selected from:
- **JSON Barcodes**: This format is used for generating barcodes in JSON format, which is a 'human readable' format.
- **Short Barcodes**: This format is used for generating barcodes in a short format, which is a more compact representation of the barcode data.
- **JSON Barcodes**: This format is used for generating barcodes in JSON format, which is a more verbose format. This format is not recommended for use in production environments, as it can be more difficult to parse and may not be supported by all barcode scanners. It is supported for legacy purposes, and is not recommended for use in new deployments.
Additionally, if the "Short Barcodes" format is selected, the user can specify the prefix used for the barcode. This prefix is used to identify the barcode format, and can be set to any value. The default value is `INV-` - although can be changed.
@ -214,10 +214,10 @@ The frontend code for your plugin is located in the `frontend/src` directory. Yo
Refer to the `./frontend/src/Panel.tsx` file as a starting point. This is where the custom panel for the part detail page is implemented. You can modify this file to change the content and behavior of the panel.
While the `npm dev` server is running, any changes you make to the frontend code will be automatically reloaded allowing for rapid development and testing of your plugin's frontend features. This avoids the need to rebuild the frontend code every time you make a change.
While the `npm dev` server is running, any changes to the frontend are reflected in the browser using React Fast Refresh, allowing for rapid development without rebuilding the frontend with every change.
!!! info "Page Reload"
Due to the way the InvenTree frontend is structured, you will need to manually refresh the page in your browser to see changes to the frontend code. The development server will automatically reload the frontend code, but the InvenTree server needs to be aware of the changes.
All exports in plugin modules that export React components must start with a capital letter. Otherwise, React Fast Refresh will fall back to a full page reload instead of performing a component-level update. Additionally, any render functions referenced from Python must also be capitalized.
@ -41,7 +41,7 @@ If you want to make your life easier, try to follow these guidelines; break wher
from plugin import InvenTreePlugin, registry
from plugin.mixins import APICallMixin, SettingsMixin, ScheduleMixin, BarcodeMixin
```
- Feliver as a package (see [below](#packaging))
- Deliver as a package (see [below](#packaging))
- If you need to use a private infrastructure, use the 'Releases' functions in GitHub or Gitlab. Point to the 'latest' release endpoint when installing to make sure the update function works
- Tag your GitHub repo with `inventree` and `inventreeplugins` to make discovery easier. A discovery mechanism using these tags is on the roadmap.
- Use GitHub actions to test your plugin regularly (you can [schedule actions](https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule)) against the 'latest' [docker-build](https://hub.docker.com/r/inventree/inventree) of InvenTree
@ -10,6 +10,9 @@ Plugins can inherit from the [UserInterfaceMixin](./mixins/ui.md) class to provi
Note that the [InvenTree plugin creator](./creator.md) can be used to scaffold a new plugin with the necessary structure for frontend integration. This will automatically set up the necessary files and configurations to get started with frontend development.
!!! info "Simplified Development"
Using the plugin creator can significantly simplify the process of developing a frontend plugin, as it provides a ready-made template with the necessary configurations for building and integrating the frontend code. Rolling your own frontend plugin from scratch is possible, but it requires a good understanding of the InvenTree frontend architecture and build process.
## Frontend Architecture
When designing a frontend plugin component, it is important to have at least a basic understanding of the InvenTree frontend architecture.
@ -76,20 +79,28 @@ The following properties are available in the `context` object:
| Property | Description |
| -------- | ----------- |
| `version` | An object containing the current InvenTree version information. |
| `api` | The Axios instance configured to communicate with the InvenTree API. |
| `queryClient` | The query client instance used for managing API calls in the frontend. |
| `user` | An object containing information about the currently logged-in user. |
| `userSettings` | An object containing user-specific settings. |
| `globalSettings` | An object containing global settings for the InvenTree instance. |
| `modelInformation` | An object containing information about the models available in the InvenTree instance. |
| `renderInstance` | A function to render a model instance |
| `host` | An object containing information about the current host (server) configuration. |
| `i18n` | An object containing internationalization (i18n) functions for translating text. |
| `locale` | The current locale being used for the user interface. |
| `api` | The Axios instance configured to communicate with the InvenTree API. |
| `queryClient` | The query client instance used for managing API calls in the frontend. |
| `navigate` | A function to navigate to a different page in the InvenTree web interface. |
| `globalSettings` | An object containing global settings for the InvenTree instance. |
| `userSettings` | An object containing user-specific settings. |
| `modelInformation` | An object containing information about the models available in the InvenTree instance. |
| `renderInstance` | A function to render a model instance |
| `theme` | The current Mantine theme being used in the InvenTree web interface. |
| `colorScheme` | The current color scheme being used in the InvenTree web interface. |
| `forms` | A set of functional components for rendering forms in the InvenTree web interface. |
| `tables` | A set of functional components for rendering tables in the InvenTree web interface. |
| `importer` | A set of functions for controlling the global importer drawer in the InvenTree web interface. |
| `model` | The model type associated with the rendered component (if applicable). |
| `id` | The ID (primary key) of the model instance being rendered (if applicable). |
| `instance` | The model instance data (if available). |
| `reloadContent` | A function which can be called to reload the plugin content. |
| `reloadInstance` | A function which can be called to reload the model instance. |
| `context` | Any additional context data which may be passed to the plugin. |
This set of components is passed through at render time to the plugin function, allowing the plugin code to hook directly into the InvenTree web interface and access the necessary context for rendering.
Only users with superuser privileges can manage plugins via the web interface.
#### Local Directory
Custom plugins can be placed in the `data/plugins/` directory, where they will be automatically discovered. This can be useful for developing and testing plugins, but can prove more difficult in production (e.g. when using Docker).
@ -8,3 +8,27 @@ If this mixin is added to a plugin the directory the plugin class is defined in
!!! warning "Danger Zone"
Only use this mixin if you have an understanding of Django's [app system]({% include "django.html" %}/ref/applications). Plugins with this mixin are deeply integrated into InvenTree and can cause difficult to reproduce or long-running errors. Use the built-in testing functions of Django to make sure your code does not cause unwanted behaviour in InvenTree before releasing.
## Custom Models
This mixin allows you to define custom database models within your plugin. These models will be automatically registered with the InvenTree server, and will be available for use within your plugin code.
### Model Permissions
Some database operations within the InvenTree ecosystem may require custom permissions checks - to determine which actions a user can perform against a given model. If your plugin defines custom models, you may need to implement a custom permission check method on your model class.
Each model class can implement a `check_user_permission` classmethod, which will be called by the InvenTree permission system when checking permissions for that model. This method should return `True` if the user has the required permissions, and `False` otherwise.
By default, if the `check_user_permission` method is not implemented, the InvenTree permission system will return `False` for all permission checks against that model. This is to ensure that no permissions are granted by default, and that the plugin developer must explicitly define the required permissions for their custom models.
As the events are offloaded to a background worker debugging the `process_event()` function need some extra consideration. Please see the [Run background workers](../../develop/devcontainer.md#run-background-workers) section for further information.
## Events
Events are passed through using a string identifier, e.g. `build.completed`
The `ReportMixin` class provides a plugin with the ability to extend the functionality of custom [report templates](../../report/report.md). A plugin which implements the ReportMixin mixin class can add custom context data to a report template for rendering.
The `ReportMixin` class provides a plugin with the ability to extend the functionality of custom [report templates](../../report/report.md). A plugin which implements the ReportMixin mixin class can add custom context data to a report template for rendering, and can also receive a callback when a report is generated.
### Add Report Context
A plugin which implements the ReportMixin mixin can define the `add_report_context` method, allowing custom context data to be added to a report template at time of printing.
This method is called each time a report is generated, and is passed the following arguments:
| Argument | Description |
| --- | --- |
| `report_instance` | The report template instance which is being rendered |
| `model_instance` | The model instance against which the report is being generated |
| `user` | The user who initiated the report generation |
| `context` | The context dictionary, which can be modified in-place |
Any data added to the provided `context` dictionary is made available to the report template, and can be rendered using standard django template syntax:
Additionally the `add_label_context` method, allowing custom context data to be added to a label template at time of printing.
Similarly, the `add_label_context` method allows custom context data to be added to a label template at time of printing:
| Argument | Description |
| --- | --- |
| `label_instance` | The label template instance which is being rendered |
| `model_instance` | The model instance against which the label is being generated |
| `user` | The user who initiated the label generation |
| `context` | The context dictionary, which can be modified in-place |
### Report Callback
The `report_callback` method is called after a report has been generated, and allows the plugin to perform custom actions with the generated report - for example, forwarding the report to an external system, or performing custom post-processing.
| Argument | Description |
| --- | --- |
| `template` | The report template instance which was used to generate the report |
| `instance` | The model instance against which the report was generated |
| `report` | The generated report (PDF file data) |
| `user` | The user who initiated the report generation |
@ -183,6 +183,20 @@ The `get_ui_template_previews` feature type can be used to provide custom templa
summary: False
members: []
### Primary Actions
The `get_ui_primary_actions` method can be used to provide custom primary action, which are rendered in the header of the page, next to the title/name and any status indicators. These primary actions are typically used to provide quick access to common actions related to the current page.
When rendering certain content in the user interface, the rendering functions are passed a `context` object which contains information about the current page being rendered. The type of the `context` object is defined in the `PluginContext` file:
Users can upload asset files (e.g. images) which can be used when generating reports. For example, you may wish to generate a report with your company logo in the header.
Asset files are managed from the [Admin Center](../settings/admin.md#admin-center), via the *Report Assets* panel. Staff users can upload new asset files, and remove assets which are no longer required.
Asset files can be rendered directly into the template as follows
```html
{% raw %}
<!-- Need to include the report template tags at the start of the template file -->
If the requested asset name does not match the name of an uploaded asset, the template will continue without loading the image.
!!! info "Assets location"
Upload new assets via the *Report Assets* panel in the [Admin Center](../settings/admin.md#admin-center) to ensure they are uploaded to the correct location on the server.
There are various [helper functions](./helpers.md#report-assets) available to assist with embedding assets into templates.
@ -69,12 +69,14 @@ Templates (whether for generating [reports](./report.md) or [labels](./labels.md
| Model Type | Description |
| --- | --- |
| company | A Company instance |
| [company](#company) | A Company instance |
| [build](#build-order) | A [Build Order](../manufacturing/build.md) instance |
| [buildline](#build-line) | A [Build Order Line Item](../manufacturing/build.md) instance |
| [salesorder](#sales-order) | A [Sales Order](../sales/sales_order.md) instance |
| [salesordershipment](#sales-order-shipment) | A [Sales Order Shipment](../sales/sales_order.md#sales-order-shipments) instance |
| [returnorder](#return-order) | A [Return Order](../sales/return_order.md) instance |
| [purchaseorder](#purchase-order) | A [Purchase Order](../purchasing/purchase_order.md) instance |
| [transferorder](#transfer-order) | A [Transfer Order](../stock/transfer_order.md) instance |
| [stockitem](#stock-item) | A [StockItem](../stock/index.md#stock-item) instance |
| [stocklocation](#stock-location) | A [StockLocation](../stock/index.md#stock-location) instance |
| [part](#part) | A [Part](../part/index.md) instance |
@ -141,6 +143,16 @@ When printing a report or label against a [PurchaseOrder](../purchasing/purchase
{{ report_context("models", "purchaseorder") }}
### Transfer Order
When printing a report or label against a [TransferOrder](../stock/transfer_order.md) object, the following context variables are available:
{{ report_context("models", "transferorder") }}
::: order.models.TransferOrder.report_context
options:
show_source: True
### Stock Item
When printing a report or label against a [StockItem](../stock/index.md#stock-item) object, the following context variables are available:
@ -173,7 +185,7 @@ When printing a report or label against a [Part](../part/index.md) object, the f
## Model Variables
Additional to the context variables provided directly to each template, each model type has a number of attributes and methods which can be accessedd via the template.
Additional to the context variables provided directly to each template, each model type has a number of attributes and methods which can be accessed via the template.
For each model type, a subset of the most commonly used attributes are listed below. For a full list of attributes and methods, refer to the source code for the particular model type.
@ -187,7 +199,6 @@ Each part object has access to a lot of context variables about the part. The fo
|----------|-------------|
| name | Brief name for this part |
| full_name | Full name for this part (including IPN, if not null and including variant, if not null) |
| variant | Optional variant number for this part - Must be unique for the part name
| category | The [PartCategory](#part-category) object to which this part belongs
| description | Longer form description of the part
| keywords | Optional keywords for improving part search results
@ -244,7 +255,6 @@ Each part object has access to a lot of context variables about the part. The fo
| Variable | Description |
|----------|-------------|
| parent | Link to another [StockItem](#stock-item) from which this StockItem was created |
| uid | Field containing a unique-id which is mapped to a third-party identifier (e.g. a barcode) |
| part | Link to the master abstract [Part](#part) that this [StockItem](#stock-item) is an instance of |
| supplier_part | Link to a specific [SupplierPart](#supplierpart) (optional) |
| location | The [StockLocation](#stock-location) Where this [StockItem](#stock-item) is located |
@ -256,7 +266,6 @@ Each part object has access to a lot of context variables about the part. The fo
| expiry_date | Expiry date of the [StockItem](#stock-item) (optional) |
| stocktake_date | Date of last stocktake for this item |
| stocktake_user | User that performed the most recent stocktake |
| review_needed | Flag if [StockItem](#stock-item) needs review |
| delete_on_deplete | If True, [StockItem](#stock-item) will be deleted when the stock level gets to zero |
| status | Status of this [StockItem](#stock-item) (ref: InvenTree.status_codes.StockStatus) |
| status_label | Textual representation of the status e.g. "OK" |
@ -264,7 +273,6 @@ Each part object has access to a lot of context variables about the part. The fo
| build | Link to a Build (if this stock item was created from a build) |
| is_building | Boolean field indicating if this stock item is currently being built (or is "in production") |
| purchase_order | Link to a [PurchaseOrder](#purchase-order) (if this stock item was created from a PurchaseOrder) |
| infinite | If True this [StockItem](#stock-item) can never be exhausted |
| sales_order | Link to a [SalesOrder](#sales-order) object (if the StockItem has been assigned to a SalesOrder) |
| purchase_price | The unit purchase price for this [StockItem](#stock-item) - this is the unit price at time of purchase (if this item was purchased from an external supplier) |
| packaging | Description of how the StockItem is packaged (e.g. "reel", "loose", "tape" etc) |
@ -342,7 +350,6 @@ Each part object has access to a lot of context variables about the part. The fo
| note | Longer form note field |
| base_cost | Base charge added to order independent of quantity e.g. "Reeling Fee" |
| multiple | Multiple that the part is provided in |
| lead_time | Supplier lead time |
| packaging | packaging that the part is supplied in, e.g. "Reel" |
| pretty_name | The IPN, supplier name, supplier SKU and (if not null) manufacturer string joined by `|`. Ex. `P00037 | Company | 000021` |
| unit_pricing | The price for one unit. |
@ -355,7 +362,7 @@ Each part object has access to a lot of context variables about the part. The fo
@ -173,8 +173,144 @@ Generate a list of all active customers:
More advanced database filtering should be achieved using a [report plugin](../plugins/mixins/report.md), and adding custom context data to the report template.
## List Helpers
The following helper functions are available for working with list (or list-like) data structures:
### length
Return the length of a list (or list-like) data structure. Note that this will also work for other data structures which support the `len()` function, such as strings, dictionaries or querysets:
::: report.templatetags.report.length
options:
show_docstring_description: false
show_source: False
### first
Return the first element of a list (or list-like) data structure:
::: report.templatetags.report.first
options:
show_docstring_description: false
show_source: False
### last
Return the last element of a list (or list-like) data structure:
::: report.templatetags.report.last
options:
show_docstring_description: false
show_source: False
### reverse
Return a list (or list-like) data structure in reverse order:
::: report.templatetags.report.reverse
options:
show_docstring_description: false
show_source: False
### truncate
Return a truncated version of a list (or list-like) data structure, containing only the first N elements:
::: report.templatetags.report.truncate
options:
show_docstring_description: false
show_source: False
## String Formatting
### strip
Return a string with leading and trailing whitespace removed:
::: report.templatetags.report.strip
options:
show_docstring_description: false
show_source: False
### lstrip
Return a string with leading whitespace removed:
::: report.templatetags.report.lstrip
options:
show_docstring_description: false
show_source: False
### rstrip
Return a string with trailing whitespace removed:
::: report.templatetags.report.rstrip
options:
show_docstring_description: false
show_source: False
### split
Return a list of substrings by splitting a string based on a specified separator:
::: report.templatetags.report.split
options:
show_docstring_description: false
show_source: False
### join
Return a string by joining a list of strings into a single string, using a specified separator:
::: report.templatetags.report.join
options:
show_docstring_description: false
show_source: False
### replace
Return a string where occurrences of a specified substring are replaced with another substring:
::: report.templatetags.report.replace
options:
show_docstring_description: false
show_source: False
### lowercase
Return a string with all characters converted to lowercase:
::: report.templatetags.report.lowercase
options:
show_docstring_description: false
show_source: False
### uppercase
Return a string with all characters converted to uppercase:
::: report.templatetags.report.uppercase
options:
show_docstring_description: false
show_source: False
### titlecase
Return a string with the first character of each word converted to uppercase and the remaining characters converted to lowercase:
::: report.templatetags.report.titlecase
options:
show_docstring_description: false
show_source: False
## Number Formatting
A number of helper functions are available for formatting numbers in a particular way. These can be used to format numbers according to a particular number of decimal places, or to add leading zeros, for example.
### format_number
The helper function `format_number` allows for some common number formatting options. It takes a number (or a number-like string) as an input, as well as some formatting arguments. It returns a *string* containing the formatted number:
@ -184,15 +320,86 @@ The helper function `format_number` allows for some common number formatting opt
The `fmt` argument accepts a [Unicode number pattern](https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns) string (the same syntax used by [Babel](https://babel.pocoo.org/en/latest/numbers.html)). When `fmt` is provided it takes complete priority over the `decimal_places`, `max_decimal_places`, `leading`, and `separator` arguments — those arguments are silently ignored.
The `integer` and `multiplier` arguments **are** still applied to the number before the format string is used.
| Symbol | Meaning |
| --- | --- |
| `0` | Required digit — always rendered, even if zero |
| `#` | Optional digit — suppressed when not significant |
| `,` | Grouping separator (position defines group size) |
| `.` | Decimal separator |
Common patterns:
| Pattern | Example output |
| --- | --- |
| `0` | `1235` |
| `#,##0` | `1,235` |
| `0.00` | `1234.57` |
| `#,##0.00` | `1,234.57` |
| `000` | `007` |
```html
{% raw %}
{% load report %}
<!-- Two decimal places, no grouping -->
{% format_number 1234.5678 fmt='0.00' %}
<!-- output: 1234.57 -->
<!-- Two decimal places with thousands separator -->
{% format_number 1234.5678 fmt='#,##0.00' %}
<!-- output: 1,234.57 -->
<!-- Same pattern, German locale: dot thousands, comma decimal -->
@ -200,6 +407,25 @@ The helper function `format_number` allows for some common number formatting opt
For rendering date and datetime information, the following helper functions are available:
Both functions resolve their output using the following priority order:
1. **`fmt=` argument** — a [strftime format string](https://docs.python.org/3/library/datetime.html#format-codes). When provided, this takes full priority; `locale` and `date_format` are ignored.
2. **`locale=` argument** — when no `fmt` is given, Babel formats the value using the style set by `date_format` (default `medium`).
3. **Server `LANGUAGE_CODE`** — used as the locale when no `locale=` argument is supplied.
#### Date Format Styles
The `date_format` argument controls how Babel renders the date when locale-aware formatting is used. The four named styles are:
| Style | `format_date` example (en-us, 2025-01-12) | `format_datetime` example (en-us, 2025-01-12 14:30) |
| --- | --- | --- |
| `full` | `Sunday, January 12, 2025` | `Sunday, January 12, 2025 at 2:30:00 PM UTC` |
@ -214,20 +469,31 @@ For rendering date and datetime information, the following helper functions are
show_docstring_description: false
show_source: False
### Date Formatting
If not specified, these methods return a result which uses ISO formatting. Refer to the [datetime format codes](https://docs.python.org/3/library/datetime.html#format-codes) for more information! |
### Example
A simple example of using the date formatting helper functions:
The helper function `render_currency` allows for simple rendering of currency data. This function can also convert the specified amount of currency into a different target currency:
::: InvenTree.helpers_model.render_currency
::: report.templatetags.report.render_currency
options:
show_docstring_description: false
show_source: False
#### Decimal Places
When no decimal place arguments are provided, the locale/currency standard is used (e.g. 2 places for USD, 0 for JPY).
`decimal_places` and `max_decimal_places` work the same way as in [`format_number`](#format_number):
| Argument | Effect |
| --- | --- |
| `decimal_places=N` | Forces exactly N decimal digits (zero-padded) |
| `max_decimal_places=M` | Allows up to M decimal digits, suppressing trailing zeros beyond `decimal_places` |
| Both set | Forced minimum of `decimal_places`, optional up to `max_decimal_places` |
| Neither set | Locale/currency default (e.g. 2 for USD) |
The `leading` argument specifies the minimum number of digits to render before the decimal point (zero-padded). This works identically to `leading` in [`format_number`](#format_number):
The `fmt` argument accepts a [Unicode number pattern](https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns) string (same syntax as [`format_number`](#custom-format-strings)). **When `fmt` is provided, it takes complete priority over `decimal_places`, `max_decimal_places`, and `leading`** — those arguments are ignored.
The `locale`, `currency`, `multiplier`, and `include_symbol` arguments are still applied when `fmt` is set.
To include the currency symbol in a `fmt` pattern, use the `¤` placeholder. Without it, no symbol appears regardless of `include_symbol`.
@ -256,8 +626,12 @@ The helper function `render_currency` allows for simple rendering of currency da
{% endfor %}
</ul>
<!-- Force 2 decimal places, convert to NZD -->
Total Price: {% render_currency order.total_price currency='NZD' decimal_places=2 %}
<!-- US-style symbol, regardless of server locale -->
Total Price: {% render_currency order.total_price currency='USD' locale='en-us' %}
{% endraw %}
```
@ -533,7 +907,7 @@ If you have a custom logo, but explicitly wish to load the InvenTree logo itself
## Report Assets
[Report Assets](./index.md#report-assets) are files specifically uploaded by the user for inclusion in generated reports and labels.
[Report Assets](./assets.md) are files specifically uploaded by the user for inclusion in generated reports and labels.
You can add asset images to the reports and labels by using the `{% raw %}{% asset ... %}{% endraw %}` template tag:
@ -547,14 +921,18 @@ You can add asset images to the reports and labels by using the `{% raw %}{% ass
## Parameters
If you need to load a parameter value for a particular model instance, within the context of your template, you can use the `parameter` template tag:
If you need to reference a parameter for a particular model instance, within the context of your template, you can use the `parameter` template tag:
### parameter
This returns a [Parameter](../concepts/parameters.md) object which contains the value of the parameter, as well as any associated metadata (e.g. units, description, etc).
::: report.templatetags.report.parameter
options:
show_docstring_description: false
show_source: False
### Example
#### Example
The following example assumes that you have a report or label which contains a valid [Part](../part/index.md) instance:
@ -580,6 +958,27 @@ A [Parameter](../concepts/parameters.md) has the following available attributes:
| Units | The *units* of the parameter (e.g. "km") |
| Template | A reference to a [ParameterTemplate](../concepts/parameters.md#parameter-templates) |
### parameter_value
To access just the value of a parameter, use the `parameter_value` template tag:
::: report.templatetags.report.parameter_value
options:
show_docstring_description: false
show_source: False
#### Example
```
{% raw %}
{% load report %}
{% parameter_value part "length" backup_value="3"as length_value %}
Part: {{ part.name }}<br>
Length: {{ length_value }}
{% endraw %}
```
## Rendering Markdown
Some data fields (such as the *Notes* field available on many internal database models) support [markdown formatting](https://en.wikipedia.org/wiki/Markdown). To render markdown content in a custom report, there are template filters made available through the [django-markdownify](https://github.com/erwinmatijsen/django-markdownify) library. This library provides functionality for converting markdown content to HTML representation, allowing it to be then rendered to PDF by the InvenTree report generation pipeline.
@ -53,29 +53,43 @@ To read more about the capabilities of the report templating engine, and how to
## Creating Templates
Report and label templates can be created (and edited) via the [admin interface](../settings/admin.md), under the *Report* section.
Report and label templates are managed from the [Admin Center](../settings/admin.md#admin-center), which provides dedicated panels (under the *Reporting* group) for each template type:
Select the type of template you are wanting to create (a *Report Template* or *Label Template*) and press the *Add* button in the top right corner:
- **Label Templates** - Create and edit [label templates](./labels.md)
- **Report Templates** - Create and edit [report templates](./report.md)
Label and report templates are created and edited using the built-in [template editor](./template_editor.md), which allows templates to be written directly within the browser, with a live preview of the rendered output.
!!! tip "Staff Access Only"
Only users with staff access can upload or edit report template files.
Only users with staff access can create, upload or edit templates, snippets and assets.
!!! info "Editing Reports"
Existing reports can be edited from the admin interface, in the same location as described above. To change the contents of the template, re-upload a template file, to override the existing template data.
!!! tip "Template Editor"
InvenTree also provides a powerful [template editor](./template_editor.md) which allows for the creation and editing of report templates directly within the browser.
!!! info "Backend Admin Interface"
Templates can also be managed at a lower level via the [backend admin interface](../settings/admin.md#backend-admin-interface), under the *Report* section. This is recommended for advanced users only.
### Name and Description
Each report template requires a name and description, which identify and describe the report template.
### Revision
Each template has a revision number, which is automatically incremented each time the template is updated. This provides a simple mechanism for tracking changes to a template over time. The revision number is read-only, and cannot be edited directly.
!!! info "Template Revision Context"
The revision number of the template is made available when rendering, via the `template_revision` [context variable](./context_variables.md#global-context).
### Enabled Status
Boolean field which determines if the specific report template is enabled, and available for use. Reports can be disabled to remove them from the list of available templates, but without deleting them from the database.
### Attach to Model
If the *Attach to Model on Print* option is enabled, a copy of the generated report is automatically saved as a file attachment against the item (model instance) for which it was generated, each time the template is printed.
!!! warning "Attachment Support"
The report output is only attached if the target model type supports file attachments.
### Filename Pattern
The filename pattern used to generate the output `.pdf` file. Defaults to "report.pdf".
@ -147,86 +161,44 @@ Setting the *Debug Mode* option renders the template as raw HTML instead of PDF,
## Report Assets
User can upload asset files (e.g. images) which can be used when generating reports. For example, you may wish to generate a report with your company logo in the header. Asset files are uploaded via the admin interface.
Asset files can be rendered directly into the template as follows
```html
{% raw %}
<!-- Need to include the report template tags at the start of the template file -->
If the requested asset name does not match the name of an uploaded asset, the template will continue without loading the image.
!!! info "Assets location"
Upload new assets via the [admin interface](../settings/admin.md) to ensure they are uploaded to the correct location on the server.
User can upload asset files (e.g. images) which can be used when generating reports. For example, you may wish to generate a report with your company logo in the header.
Refer to the [report assets](./assets.md) documentation for further information.
## Report Snippets
A powerful feature provided by the django / WeasyPrint templating framework is the ability to include external template files. This allows commonly used template features to be broken out into separate files and reused across multiple templates.
InvenTree provides report "snippets" - reusable template files which cannot be rendered by themselves, but can be included in other templates.
To support this, InvenTree provides report "snippets" - short (or not so short) template files which cannot be rendered by themselves, but can be called from other templates.
Refer to the [report snippets](./snippets.md) documentation for further information.
Similar to assets files, snippet template files are uploaded via the admin interface.
## Security
Snippets are included in a template as follows:
Report templates are powerful by design — they have access to the full Django template language and to model data across the InvenTree database. For this reason, **template upload is restricted to staff users only**.
```
{% raw %}{% include 'snippets/<snippet_name.html>' %}{% endraw %}
```
### URL Fetching
For example, consider a custom stocktake report for a particular stock location, where we wish to render a table with a row for each item in that location.
When WeasyPrint renders a template to PDF it can make outbound requests to load images, stylesheets, and fonts referenced in the HTML. InvenTree restricts this through a custom URL fetcher with the following rules:
| `file://` | Always blocked — assets and images must be inlined as `data:` URIs before reaching WeasyPrint |
| `http` / `https` | Disabled by default, but can be enabled - see *Remote URL Fetching* below |
| Any other scheme | Always blocked |
<tableclass='stock-table'>
<thead>
<!-- table header data -->
</thead>
<tbody>
{% for item in location.stock_items %}
{% include 'snippets/stock_row.html' with item=item %}
{% endfor %}
</tbody>
HTTP redirects are also disabled: a URL that passes validation cannot redirect to an internal address.
{% endraw %}
```
### Remote URL Fetching
!!! info "Snippet Arguments"
Note above that named argument variables can be passed through to the snippet!
The **Report URL Fetching** system setting (`REPORT_FETCH_URLS`) controls whether `http://` and `https://` URLs in templates are permitted. It defaults to **disabled**.
And the snippet file `stock_row.html` may be written as follows:
When enabled, URLs are still validated against private, loopback, link-local, and reserved IP ranges before the request is made, preventing templates from being used as a vector for [Server-Side Request Forgery (SSRF)](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) attacks against internal network services.
```html
{% raw %}
<!-- stock_row snippet -->
<tr>
<td>{{ item.part.full_name }}</td>
<td>{{ item.quantity }}</td>
</tr>
{% endraw %}
```
!!! warning "Enable with care"
Enabling remote URL fetching allows report templates to trigger outbound HTTP requests from the InvenTree server. Only enable this if your templates genuinely require it, and ensure that templates are reviewed before deployment.
### Asset Files
[Asset files](./assets.md) uploaded through the admin interface are embedded directly into the rendered PDF as base64 `data:` URIs — they are read via the Django storage API and never loaded through WeasyPrint's URL fetcher. This means assets work correctly regardless of whether remote URL fetching is enabled, and also work with remote storage backends such as S3.
There are various [helper functions](./helpers.md#report-assets) available to assist with embedding assets into templates.
@ -128,6 +128,25 @@ As an example, consider a label template for a StockItem. A user may wish to def
To restrict the label accordingly, we could set the *filters* value to `part__IPN=IPN123`.
## Printing Labels
Labels are printed directly from the web interface, from the pages where the target items are displayed. To print labels against one or more items:
1. Select the items to print - either from a table (using the row checkboxes), or by viewing the detail page of a single item
2. Select the *Print* action, and choose the *Print Label* option
3. Select the desired label template - only *enabled* templates which match the selected model type (and pass any template filters) are available for selection
4. Select the *printer* (plugin) to use for printing the labels
### Label Printing Plugins
The actual printing of labels is handled by a [label printing plugin](../plugins/mixins/label.md). InvenTree provides a number of built-in printing plugins:
- The default [InvenTree Label Printer](../plugins/builtin/inventree_label.md) plugin generates a PDF file, which is then made available for download.
- The [Label Sheet](../plugins/builtin/inventree_label_sheet.md) plugin arranges multiple labels onto a single sheet for printing.
- The [Label Machine](../plugins/builtin/inventree_label_machine.md) plugin sends the label to an external [label printer machine](../plugins/machines/label_printer.md).
Custom label printing plugins (e.g. for driving a specific hardware printer) can be installed to extend this list - refer to the [label mixin documentation](../plugins/mixins/label.md) for further information.
## Built-In Templates
The InvenTree installation provides a number of simple *default* templates which can be used as a starting point for creating custom labels. These built-in templates can be disabled if they are not required.
InvenTree supports a customizable reporting ecosystem, allowing the user to develop document templates that meet their particular needs.
Report templates are used to generate formal PDF documents - such as order reports, packing lists, or test reports - rendered against a particular database item (or list of items).
PDF files are generated from custom HTML template files which are written by the user.
Like all InvenTree templates, report templates are written using a mixture of HTML / CSS and the django template language, and are rendered to a PDF file using the WeasyPrint engine:
Templates can be used to generate *reports* or *labels* which can be used in a variety of situations to format data in a friendly format for printing, distribution, conformance and testing.
- Refer to the [template overview](./index.md) for information on creating and managing templates.
- Refer to the [template rendering documentation](./weasyprint.md) for information on the WeasyPrint engine and the django template language.
- Refer to the [context variables documentation](./context_variables.md) for the variables available when rendering a template.
In addition to providing the ability for end-users to provide their own reporting templates, some report types offer "built-in" report templates ready for use.
## Report Options
### WeasyPrint Templates
In addition to the [options common to all templates](./index.md#creating-templates), each report template provides the following options:
InvenTree report templates utilize the powerful [WeasyPrint](https://weasyprint.org/) PDF generation engine.
### Page Size
!!! info "WeasyPrint"
WeasyPrint is an extremely powerful and flexible reporting library. Refer to the [WeasyPrint docs](https://doc.courtbouillon.org/weasyprint/stable/) for further information.
The page size (e.g. `A4` or `Letter`) used when rendering the report to a PDF file. When a new report template is created, this value defaults to the [default page size](./index.md#default-page-size) specified in the global settings.
### Stylesheets
### Landscape
Templates are rendered using standard HTML / CSS - if you are familiar with web page layout, you're ready to go!
If enabled, the report is rendered in landscape orientation, rather than the default portrait orientation.
### Template Language
### Merge
Uploaded report template files are passed through the [django template rendering framework]({% include "django.html" %}/topics/templates/), and as such accept the same variable template strings as any other django template file. Different variables are passed to the report template (based on the context of the report) and can be used to customize the contents of the generated PDF.
If enabled, a single report document is generated for all selected items, rather than a separate document for each item. Refer to the [merging reports](#merging-reports) section below for further information.
### Variables
!!! info "Context Variables"
The `page_size`, `landscape` and `merge` values are also made available to the template as [context variables](./context_variables.md#report-context).
Each report template is provided a set of *context variables* which can be used when rendering the template.
## Generating Reports
For example, rendering the name of a part (which is available in the particular template context as `part`) is as follows:
Reports are generated directly from the web interface, from the pages where the target items are displayed. To generate a report against one or more items:
```html
{% raw %}
1. Select the items to print - either from a table (using the row checkboxes), or by viewing the detail page of a single item
2. Select the *Print* action, and choose the *Print Report* option
3. Select the desired report template - only *enabled* templates which match the selected model type (and pass any [template filters](./index.md#template-filters)) are available for selection
4. The report is generated by the server, and the resulting PDF file is made available for download
<!-- Template variables use {{ double_curly_braces }} -->
<h2>Part: {{ part.name }}</h3>
<p><i>
Description:<br>
{{ part.description }}
</p></i>
{% endraw %}
```
!!! info "Enable Reports"
Report generation must be [enabled in the global settings](./index.md#enable-reports) before reports can be generated.
## Merging Reports
When rendering reports for multiple items, the default behaviour is that each item is rendered as a separate report. The chosen templeate is rendered multiple times, once for each item selected, and expects a single item in the context variable.
When rendering reports for multiple items, the default behaviour is that each item is rendered as a separate report. The chosen template is rendered multiple times, once for each item selected, and expects a single item in the context variable.
However, it is possible to merge multiple items into a single report document. This is achieved by enabling the `merge` attribute of the report template: