Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Data importer #6911

Merged
merged 234 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
234 commits
Select commit Hold shift + click to select a range
41aad9a
Adds new model for DataImportSession
SchrodingersGat Mar 21, 2024
b12a053
Add file extension validation
SchrodingersGat Mar 21, 2024
c4ce8d6
Switch to new 'importer' app
SchrodingersGat Mar 22, 2024
55593c7
Refactoring to help prevent circular imports
SchrodingersGat Mar 22, 2024
52b5302
Add serializer registry
SchrodingersGat Mar 22, 2024
05f8dcb
Cleanup migration file
SchrodingersGat Mar 22, 2024
ed21dcf
Refactor code into registry.py
SchrodingersGat Mar 22, 2024
46371c4
Add validation for the uploaded file
SchrodingersGat Mar 22, 2024
b0fc755
Refactoring
SchrodingersGat Mar 22, 2024
fa7d15f
Adds property to retrieve matching serializer class
SchrodingersGat Mar 22, 2024
f0eba71
Update helper functions
SchrodingersGat Mar 22, 2024
fec8c1f
Add hook to auto-assign columns on initial creation
SchrodingersGat Mar 22, 2024
7264c89
Rename field
SchrodingersGat Mar 22, 2024
97f91cd
Enforce initial status value
SchrodingersGat Mar 22, 2024
db54d30
Add model for individual rows in the data import
SchrodingersGat Mar 22, 2024
5b251dc
Add DataImportRow model
SchrodingersGat Mar 24, 2024
58a1c72
Extract data rows as dict
SchrodingersGat Mar 24, 2024
d4e4611
Update fields
SchrodingersGat Mar 25, 2024
35dd0e9
Auto-map column names
SchrodingersGat Mar 25, 2024
002b77c
Add API endpoint for DataImportSession
SchrodingersGat Mar 25, 2024
7e70f76
Offload data import operation
SchrodingersGat Mar 25, 2024
4025901
Refactor data import code
SchrodingersGat Mar 25, 2024
4863f20
Update models
SchrodingersGat Mar 25, 2024
657500b
Move field mapping to a new model type
SchrodingersGat Mar 25, 2024
122e2d3
Save "valid" status for each data row
SchrodingersGat Mar 25, 2024
6d43109
Include session defaults when validating row data
SchrodingersGat Mar 25, 2024
c6e5e74
Update content_excludes
SchrodingersGat Mar 25, 2024
2642ff9
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Mar 25, 2024
e688eb2
Remove port from ALLOWED_HOST entries
SchrodingersGat Mar 25, 2024
fc4832d
Skip table events for importer models
SchrodingersGat Mar 25, 2024
0f30ae8
Bug fixes
SchrodingersGat Mar 25, 2024
e1587a9
Serializer updates
SchrodingersGat Mar 25, 2024
3117417
Add more endpoints
SchrodingersGat Mar 25, 2024
ddb23a1
further updates:
SchrodingersGat Mar 25, 2024
a2ece15
Expose "available fields" to the DataImportSession serializer
SchrodingersGat Mar 25, 2024
8baf848
Add detail endpoints
SchrodingersGat Mar 25, 2024
2a797a0
Clear existing column mappings
SchrodingersGat Mar 25, 2024
fa0b1db
Add endpoint for accepting column mappings
SchrodingersGat Mar 25, 2024
4bc70bc
Add API endpoint exposing available importer serializers
SchrodingersGat Mar 25, 2024
37297a3
Add simple playground area for testing data importer
SchrodingersGat Mar 25, 2024
9b66bb1
Adds simple form to start new import session
SchrodingersGat Mar 25, 2024
1fa7a4a
data_file is *not* read_only
SchrodingersGat Mar 25, 2024
156def3
Add check for file type
SchrodingersGat Mar 25, 2024
33f4ba7
Remove debug statements
SchrodingersGat Mar 25, 2024
1695ff3
Refactor column mapping
SchrodingersGat Mar 26, 2024
3897a38
Fix uniqueness requirements on mapping table
SchrodingersGat Mar 26, 2024
0eefb14
Admin updates
SchrodingersGat Mar 26, 2024
6cace47
API endpoint updates
SchrodingersGat Mar 26, 2024
e25eaa7
Update importer drawer
SchrodingersGat Mar 26, 2024
ee8113f
Merge branch 'master' into data-importer
SchrodingersGat Mar 26, 2024
7a01567
Add widget for selecting data columns
SchrodingersGat Mar 26, 2024
94afb8a
UI tweaks
SchrodingersGat Mar 26, 2024
6d80a4c
Delete import session when closing modal
SchrodingersGat Mar 26, 2024
60a0d09
Allow empty string value
SchrodingersGat Mar 26, 2024
b4a6ce2
Complete column mapping
SchrodingersGat Mar 26, 2024
910cd9d
Adds ability to remove rows
SchrodingersGat Mar 26, 2024
020df74
Adjust drawer specs
SchrodingersGat Mar 26, 2024
258fcf3
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Mar 27, 2024
cf00e55
Add column 'description' to serializer
SchrodingersGat Mar 27, 2024
f376788
Add option to hide labels in API form field
SchrodingersGat Mar 27, 2024
d933d36
Update column heading
SchrodingersGat Mar 27, 2024
fcf8c2d
Merge branch 'master' into data-importer
SchrodingersGat Mar 27, 2024
8555692
Fix frontend linting errors
SchrodingersGat Mar 27, 2024
e6d9109
Revert drawer position
SchrodingersGat Mar 27, 2024
f458a83
Merge branch 'master' into data-importer
SchrodingersGat Apr 2, 2024
f9cbb37
Return correct type
SchrodingersGat Apr 2, 2024
77c3092
Fix shadowing
SchrodingersGat Apr 2, 2024
9838157
Fix f-string
SchrodingersGat Apr 2, 2024
6376eee
simplify frontend code
SchrodingersGat Apr 2, 2024
e348482
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Apr 3, 2024
14728af
Move importer app
SchrodingersGat Apr 3, 2024
a984b4f
Merge branch 'master' into data-importer
SchrodingersGat Apr 3, 2024
2f6df7e
Merge branch 'master' into data-importer
SchrodingersGat Apr 5, 2024
f774f41
Update API version
SchrodingersGat Apr 5, 2024
5ecc43e
Reintroduce export formats
SchrodingersGat Apr 5, 2024
5205ce3
Add new models to RuleSet
SchrodingersGat Apr 5, 2024
f04623b
typescript cleanup
SchrodingersGat Apr 5, 2024
c8e4612
Typescript cleanup
SchrodingersGat Apr 5, 2024
b9af9cc
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Apr 6, 2024
b529d9f
Merge branch 'master' into data-importer
SchrodingersGat Apr 7, 2024
3eb525d
Improvement for Switch / boolean field
SchrodingersGat Apr 7, 2024
c270edc
Display original row data on popover
SchrodingersGat Apr 7, 2024
57a3531
Only display mapped columns
SchrodingersGat Apr 7, 2024
be3cfe7
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Apr 8, 2024
1070e66
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Apr 10, 2024
b7444c4
Merge branch 'master' into data-importer
SchrodingersGat Apr 13, 2024
7d5b770
Add DataExportMixin class
SchrodingersGat Apr 14, 2024
7ac563f
Create new file: importer.mixins.py
SchrodingersGat Apr 14, 2024
cc413c8
Add new mixin to existing views which support data export
SchrodingersGat Apr 14, 2024
52492e3
Better error handling
SchrodingersGat Apr 14, 2024
6210c5a
Cleanup:
SchrodingersGat Apr 14, 2024
5a4aeef
Replace table with InvenTreeTable
SchrodingersGat Apr 14, 2024
b4605c3
Make 'pathstring' fields read-only
SchrodingersGat Apr 14, 2024
79b6711
Expose list of valid importer types to the API
SchrodingersGat Apr 14, 2024
81a9b14
Exclude read-only fields
SchrodingersGat Apr 14, 2024
22b644a
Cleanup
SchrodingersGat Apr 14, 2024
99d5ebb
Updates for session model
SchrodingersGat Apr 14, 2024
910ff74
Adds new custom hook for controlling data import session
SchrodingersGat Apr 14, 2024
c006d82
Refactor column mapping widget
SchrodingersGat Apr 14, 2024
1ab1524
Refactor ImportDataSelector
SchrodingersGat Apr 14, 2024
c6fd5d7
Working on ImportDataSelector component
SchrodingersGat Apr 14, 2024
be93aa4
Adds method for editing fields in import table
SchrodingersGat Apr 15, 2024
bed02f7
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Apr 15, 2024
b18d2bd
Adds background task for removing old import sessions
SchrodingersGat Apr 15, 2024
989b2b9
Merge branch 'master' into data-importer
SchrodingersGat Apr 17, 2024
dfe5cf6
Fix api_version.py
SchrodingersGat Apr 17, 2024
7e327a6
Update src/frontend/src/components/importer/ImportDataSelector.tsx
SchrodingersGat Apr 17, 2024
2b8d95a
Merge branch 'master' into data-importer
SchrodingersGat Apr 29, 2024
52f75ec
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat May 7, 2024
9fbd1b8
Merge branch 'master' into data-importer
SchrodingersGat May 24, 2024
7554cc5
Merge branch 'master' into data-importer
SchrodingersGat May 27, 2024
bd3d4cd
Merge branch 'master' into data-importer
SchrodingersGat May 28, 2024
a1cb5db
Merge branch 'master' into data-importer
SchrodingersGat May 28, 2024
933a15d
Update model verbose names
SchrodingersGat May 28, 2024
5a60d26
Merge branch 'master' into data-importer
SchrodingersGat Jun 4, 2024
447ad7d
Merge branch 'master' into data-importer
SchrodingersGat Jun 8, 2024
7d3d190
Rename mixin class
SchrodingersGat Jun 8, 2024
16f4ca0
Add serializer mixin classes
SchrodingersGat Jun 8, 2024
ce14ce1
@register_importer requires specific mixin
SchrodingersGat Jun 8, 2024
5444fa3
Check subclass for export
SchrodingersGat Jun 8, 2024
5abd0b2
Fix typos
SchrodingersGat Jun 8, 2024
9f35f98
Refactor export serializer
SchrodingersGat Jun 8, 2024
a6b9416
Add shim class to process an individual row before exporting it
SchrodingersGat Jun 8, 2024
fca090f
Add mixin to existing serializers
SchrodingersGat Jun 8, 2024
0e94089
Add export functionality for company serializers
SchrodingersGat Jun 8, 2024
9295d05
Adds placeholder for custom admin class
SchrodingersGat Jun 8, 2024
8b8dd79
Merge branch 'master' into data-importer
SchrodingersGat Jun 9, 2024
1e5c7b2
Merge branch 'master' into data-importer
SchrodingersGat Jun 10, 2024
b4ea551
Merge branch 'master' into data-importer
SchrodingersGat Jun 10, 2024
6952f5d
Merge branch 'master' into data-importer
SchrodingersGat Jun 10, 2024
c8e1e96
Update mantine styling
SchrodingersGat Jun 10, 2024
ed210be
spacing -> gap
SchrodingersGat Jun 10, 2024
c950c8f
Add functionality to pre-process form data before upload
SchrodingersGat Jun 10, 2024
a731388
Merge branch 'master' into data-importer
SchrodingersGat Jun 11, 2024
d45cc4b
Merge branch 'master' into data-importer
SchrodingersGat Jun 15, 2024
18acaf0
Remove old references to download_queryset
SchrodingersGat Jun 20, 2024
8af20ba
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 20, 2024
0077f29
Improvements for data import drawer:
SchrodingersGat Jun 20, 2024
cfce2c6
Further improvements
SchrodingersGat Jun 20, 2024
1a00326
Fix column selection input
SchrodingersGat Jun 20, 2024
60e728a
Formatting improvements
SchrodingersGat Jun 20, 2024
edd49a0
Use a <Stepper> component for better progress display
SchrodingersGat Jun 20, 2024
792cab6
Cleanup text
SchrodingersGat Jun 20, 2024
0fec1c7
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 22, 2024
f051973
Add export-only fields to BuildItem queryset
SchrodingersGat Jun 22, 2024
c42fd0e
Expand "export" fields for BuildItem dataset
SchrodingersGat Jun 22, 2024
922ed09
Skip backup and static steps in CI
SchrodingersGat Jun 22, 2024
cda3b99
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 22, 2024
66249da
Remove hard-coded paths
SchrodingersGat Jun 22, 2024
a1e1a42
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 23, 2024
81b6ca5
Merge branch 'master' into data-importer
SchrodingersGat Jun 24, 2024
be50489
Fix for "accept_mapping" method
SchrodingersGat Jun 24, 2024
138e121
Present required fields first on import session
SchrodingersGat Jun 24, 2024
2256b7c
Add "get_importable_fields" method
SchrodingersGat Jun 24, 2024
b65f207
Add method for commiting imported row to database
SchrodingersGat Jun 24, 2024
bc81237
Cleanup
SchrodingersGat Jun 24, 2024
6e636e2
Save "complete" state after row import
SchrodingersGat Jun 24, 2024
2b43e65
Allow prevention of column caching
SchrodingersGat Jun 24, 2024
0de5312
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 26, 2024
4762f54
Merge branch 'data-importer' of github.com:SchrodingersGat/InvenTree …
SchrodingersGat Jun 26, 2024
ff49474
Remove debug statement
SchrodingersGat Jun 26, 2024
4b63260
Add basic admin table for import sessions
SchrodingersGat Jun 26, 2024
089a288
Fix for table filter functions
SchrodingersGat Jun 26, 2024
65dc3c7
Add filters for import session table
SchrodingersGat Jun 26, 2024
95d9c5f
Remove debug message
SchrodingersGat Jun 26, 2024
0f17464
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 26, 2024
e204fe0
fix for <FilterItem />
SchrodingersGat Jun 26, 2024
0082600
Create new import session from admin page
SchrodingersGat Jun 26, 2024
41b7fcd
Cleanup playground
SchrodingersGat Jun 26, 2024
501e93c
Re-open an existing import session
SchrodingersGat Jun 26, 2024
5358f6a
Memoize cell value
SchrodingersGat Jun 26, 2024
c40b3f3
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 26, 2024
743e91e
Update <ImportDataSelector>
SchrodingersGat Jun 28, 2024
d8050e2
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 29, 2024
f90d802
Enable download of build line data
SchrodingersGat Jun 29, 2024
0588de4
Add extra detail fields
SchrodingersGat Jun 29, 2024
ddccc0d
Register data importers for the stock app
SchrodingersGat Jun 30, 2024
f48b931
Enable download of stock item tracking data
SchrodingersGat Jun 30, 2024
0055c9a
Register importerrs for "company" app
SchrodingersGat Jun 30, 2024
843dbda
Register importers for the "order" app
SchrodingersGat Jun 30, 2024
5163ae4
Add extra fields to purchase order line item serializer
SchrodingersGat Jun 30, 2024
57382fe
Update verbose names for order models
SchrodingersGat Jun 30, 2024
82abfe5
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jun 30, 2024
3a43efd
Cleanup import data table rendering
SchrodingersGat Jun 30, 2024
5106ae7
Pass session information through to cell renderer
SchrodingersGat Jun 30, 2024
fecd7f3
add separate 'field_overrides' field
SchrodingersGat Jun 30, 2024
de6b57f
Expose 'field_overrides' to API
SchrodingersGat Jun 30, 2024
07c611a
Refactor import field selection
SchrodingersGat Jun 30, 2024
1392805
Use override data if provided
SchrodingersGat Jun 30, 2024
5afed6f
Fix data extraction
SchrodingersGat Jun 30, 2024
cd5302c
Fix fields.pop
SchrodingersGat Jun 30, 2024
25d09af
Update import data rendering
SchrodingersGat Jun 30, 2024
7f5e036
Handle missing / empty column names when importing data
SchrodingersGat Jun 30, 2024
a8aafbb
Bug fixin'
SchrodingersGat Jun 30, 2024
72314e2
Update hook
SchrodingersGat Jun 30, 2024
ff48181
Adds button to upload data straight to table
SchrodingersGat Jun 30, 2024
c7bede5
Merge branch 'master' into data-importer
SchrodingersGat Jul 2, 2024
4e2008b
Cache "available_fields"
SchrodingersGat Jul 2, 2024
7801ed7
Fix calculation of completed_row_count
SchrodingersGat Jul 3, 2024
7fca114
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jul 3, 2024
216aac3
Import individual rows from import session
SchrodingersGat Jul 3, 2024
a808869
Allow import of multiple simultaneous records
SchrodingersGat Jul 3, 2024
d8e4a1d
Improve extraction of metadata
SchrodingersGat Jul 3, 2024
363a8ab
Implement suspended rendering of model instances
SchrodingersGat Jul 3, 2024
12c9c01
Cleanup
SchrodingersGat Jul 3, 2024
ae40e4a
Implement more columns for StockTable
SchrodingersGat Jul 3, 2024
6812601
Allow stock filtering by packaging field
SchrodingersGat Jul 3, 2024
6e84814
Fix "stock_value" column
SchrodingersGat Jul 3, 2024
87af1fb
Improve metadata extraction
SchrodingersGat Jul 4, 2024
cfa169f
Increase maximum number of importable rows
SchrodingersGat Jul 4, 2024
f82c74a
Force data import to run on background worker
SchrodingersGat Jul 4, 2024
325ab90
Add export-only fields to StockItemSerializer class
SchrodingersGat Jul 4, 2024
5346936
Data conversion when performing initial import
SchrodingersGat Jul 4, 2024
debf688
Various tweaks
SchrodingersGat Jul 4, 2024
c6f6f5f
Fix order of operations for data import
SchrodingersGat Jul 4, 2024
133b31b
Rename component
SchrodingersGat Jul 4, 2024
fa50c0e
Allow import/export of more model types
SchrodingersGat Jul 4, 2024
f9b13b6
Fix verbose name
SchrodingersGat Jul 4, 2024
394f56c
Import rows as a bulk db operation
SchrodingersGat Jul 4, 2024
ed0ec99
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jul 4, 2024
39963c6
Enable download for PartCategoryTemplateTable
SchrodingersGat Jul 5, 2024
17f7cc3
Update stock item export
SchrodingersGat Jul 5, 2024
1b8adae
Updates for unit tests
SchrodingersGat Jul 5, 2024
5ef7a56
Remove xls format for now
SchrodingersGat Jul 5, 2024
e4dab42
Merge remote-tracking branch 'origin/master' into data-importer
SchrodingersGat Jul 5, 2024
3713fb9
More unit test updates
SchrodingersGat Jul 5, 2024
c6342dd
Future proof migration
SchrodingersGat Jul 5, 2024
319e5bc
Updates
SchrodingersGat Jul 5, 2024
d8126ff
unit tests
SchrodingersGat Jul 5, 2024
732ec5b
Unit test fix
SchrodingersGat Jul 5, 2024
43f7dd6
Remove 'field_overrides'
SchrodingersGat Jul 5, 2024
10dd6cd
Remove 'xls' as download option from frontend
SchrodingersGat Jul 5, 2024
64b6460
Add simple unit test for data import
SchrodingersGat Jul 5, 2024
c462eb7
PUI tweaks
SchrodingersGat Jul 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,4 @@ runs:
- name: Run invoke update
if: ${{ inputs.update == 'true' }}
shell: bash
run: invoke update --uv
run: invoke update --uv --skip-backup --skip-static
36 changes: 0 additions & 36 deletions src/backend/InvenTree/InvenTree/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,42 +383,6 @@ class ListCreateDestroyAPIView(BulkDeleteMixin, ListCreateAPI):
...


class APIDownloadMixin:
"""Mixin for enabling a LIST endpoint to be downloaded a file.

To download the data, add the ?export=<fmt> to the query string.

The implementing class must provided a download_queryset method,
e.g.

def download_queryset(self, queryset, export_format):
dataset = StockItemResource().export(queryset=queryset)

filedata = dataset.export(export_format)

filename = 'InvenTree_Stocktake_{date}.{fmt}'.format(
date=datetime.now().strftime("%d-%b-%Y"),
fmt=export_format
)

return DownloadFile(filedata, filename)
"""

def get(self, request, *args, **kwargs):
"""Generic handler for a download request."""
export_format = request.query_params.get('export', None)

if export_format and export_format in ['csv', 'tsv', 'xls', 'xlsx']:
queryset = self.filter_queryset(self.get_queryset())
return self.download_queryset(queryset, export_format)
# Default to the parent class implementation
return super().get(request, *args, **kwargs)

def download_queryset(self, queryset, export_format):
"""This function must be implemented to provide a downloadFile request."""
raise NotImplementedError('download_queryset method not implemented!')


class APISearchViewSerializer(serializers.Serializer):
"""Serializer for the APISearchView."""

Expand Down
5 changes: 4 additions & 1 deletion src/backend/InvenTree/InvenTree/api_version.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""InvenTree API version information."""

# InvenTree API version
INVENTREE_API_VERSION = 210
INVENTREE_API_VERSION = 211

"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""

INVENTREE_API_TEXT = """
v211 - 2024-06-26 : https://github.com/inventree/InvenTree/pull/6911
- Adds API endpoints for managing data import and export

v210 - 2024-06-26 : https://github.com/inventree/InvenTree/pull/7518
- Adds translateable text to User API fields

Expand Down
2 changes: 1 addition & 1 deletion src/backend/InvenTree/InvenTree/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def __init__(self, *args, **kwargs):

# check for two password fields
if not get_global_setting('LOGIN_SIGNUP_PWD_TWICE'):
self.fields.pop('password2')
self.fields.pop('password2', None)

# reorder fields
set_form_field_order(
Expand Down
4 changes: 2 additions & 2 deletions src/backend/InvenTree/InvenTree/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,8 @@ def MakeBarcode(cls_name, object_pk: int, object_data=None, **kwargs):


def GetExportFormats():
"""Return a list of allowable file formats for exporting data."""
return ['csv', 'tsv', 'xls', 'xlsx', 'json', 'yaml']
"""Return a list of allowable file formats for importing or exporting tabular data."""
return ['csv', 'xlsx', 'tsv', 'json']


def DownloadFile(
Expand Down
2 changes: 1 addition & 1 deletion src/backend/InvenTree/InvenTree/helpers_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def render_currency(


def getModelsWithMixin(mixin_class) -> list:
"""Return a list of models that inherit from the given mixin class.
"""Return a list of database models that inherit from the given mixin class.

Args:
mixin_class: The mixin class to search for
Expand Down
49 changes: 37 additions & 12 deletions src/backend/InvenTree/InvenTree/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ def override_value(self, field_name: str, field_key: str, field_value, model_val
- field_value: The value of the field (if available)
- model_value: The equivalent value of the model (if available)
"""
if model_value and not field_value:
if field_value is None and model_value is not None:
return model_value

if field_value and not model_value:
if model_value is None and field_value is not None:
return field_value

# Callable values will be evaluated later
Expand All @@ -160,6 +160,8 @@ def get_serializer_info(self, serializer):
"""Override get_serializer_info so that we can add 'default' values to any fields whose Meta.model specifies a default value."""
self.serializer = serializer

request = getattr(self, 'request', None)

serializer_info = super().get_serializer_info(serializer)

# Look for any dynamic fields which were not available when the serializer was instantiated
Expand All @@ -169,12 +171,19 @@ def get_serializer_info(self, serializer):
# Already know about this one
continue

if hasattr(serializer, field_name):
field = getattr(serializer, field_name)
if field := getattr(serializer, field_name, None):
serializer_info[field_name] = self.get_field_info(field)

model_class = None

# Extract read_only_fields and write_only_fields from the Meta class (if available)
if meta := getattr(serializer, 'Meta', None):
read_only_fields = getattr(meta, 'read_only_fields', [])
write_only_fields = getattr(meta, 'write_only_fields', [])
else:
read_only_fields = []
write_only_fields = []

# Attributes to copy extra attributes from the model to the field (if they don't exist)
# Note that the attributes may be named differently on the underlying model!
extra_attributes = {
Expand All @@ -188,16 +197,20 @@ def get_serializer_info(self, serializer):

model_fields = model_meta.get_field_info(model_class)

model_default_func = getattr(model_class, 'api_defaults', None)

if model_default_func:
model_default_values = model_class.api_defaults(self.request)
if model_default_func := getattr(model_class, 'api_defaults', None):
model_default_values = model_default_func(request=request) or {}
else:
model_default_values = {}

# Iterate through simple fields
for name, field in model_fields.fields.items():
if name in serializer_info.keys():
if name in read_only_fields:
serializer_info[name]['read_only'] = True

if name in write_only_fields:
serializer_info[name]['write_only'] = True

if field.has_default():
default = field.default

Expand Down Expand Up @@ -231,6 +244,12 @@ def get_serializer_info(self, serializer):
# Ignore reverse relations
continue

if name in read_only_fields:
serializer_info[name]['read_only'] = True

if name in write_only_fields:
serializer_info[name]['write_only'] = True

# Extract and provide the "limit_choices_to" filters
# This is used to automatically filter AJAX requests
serializer_info[name]['filters'] = (
Expand Down Expand Up @@ -261,7 +280,8 @@ def get_serializer_info(self, serializer):

if instance is None and model_class is not None:
# Attempt to find the instance based on kwargs lookup
kwargs = getattr(self.view, 'kwargs', None)
view = getattr(self, 'view', None)
kwargs = getattr(view, 'kwargs', None) if view else None

if kwargs:
pk = None
Expand Down Expand Up @@ -318,8 +338,10 @@ def get_field_info(self, field):

# Force non-nullable fields to read as "required"
# (even if there is a default value!)
if not field.allow_null and not (
hasattr(field, 'allow_blank') and field.allow_blank
if (
'required' not in field_info
and not field.allow_null
and not (hasattr(field, 'allow_blank') and field.allow_blank)
):
field_info['required'] = True

Expand All @@ -346,8 +368,11 @@ def get_field_info(self, field):
field_info['api_url'] = '/api/user/'
elif field_info['model'] == 'contenttype':
field_info['api_url'] = '/api/contenttype/'
else:
elif hasattr(model, 'get_api_url'):
field_info['api_url'] = model.get_api_url()
else:
logger.warning("'get_api_url' method not defined for %s", model)
field_info['api_url'] = getattr(model, 'api_url', None)

# Handle custom 'primary key' field
field_info['pk_field'] = getattr(field, 'pk_field', 'pk') or 'pk'
Expand Down
3 changes: 3 additions & 0 deletions src/backend/InvenTree/InvenTree/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ class DataImportMixin(object):
Models which implement this mixin should provide information on the fields available for import
"""

# TODO: This mixin should be removed after https://github.com/inventree/InvenTree/pull/6911 is implemented
# TODO: This approach to data import functionality is *outdated*

# Define a map of fields available for import
IMPORT_FIELDS = {}

Expand Down
2 changes: 1 addition & 1 deletion src/backend/InvenTree/InvenTree/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ def skip_create_fields(self):

remote_image = serializers.URLField(
required=False,
allow_blank=False,
allow_blank=True,
write_only=True,
label=_('Remote Image'),
help_text=_('URL of remote image file'),
Expand Down
1 change: 1 addition & 0 deletions src/backend/InvenTree/InvenTree/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
'stock.apps.StockConfig',
'users.apps.UsersConfig',
'machine.apps.MachineConfig',
'importer.apps.ImporterConfig',
'web',
'generic',
'InvenTree.apps.InvenTreeConfig', # InvenTree app runs last
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ function exportFormatOptions() {
value: 'tsv',
display_name: 'TSV',
},
{
value: 'xls',
display_name: 'XLS',
},
{
value: 'xlsx',
display_name: 'XLSX',
Expand Down
4 changes: 2 additions & 2 deletions src/backend/InvenTree/InvenTree/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ def offload_task(
_func(*args, **kwargs)
except Exception as exc:
log_error('InvenTree.offload_task')
raise_warning(f"WARNING: '{taskname}' not started due to {str(exc)}")
return False
raise_warning(f"WARNING: '{taskname}' failed due to {str(exc)}")
raise exc

# Finally, task either completed successfully or was offloaded
return True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,10 @@ def get_user_color_theme(user):
"""Get current user color theme."""
from common.models import ColorTheme

if not user.is_authenticated:
try:
if not user.is_authenticated:
return 'default'
except Exception:
return 'default'

try:
Expand Down
4 changes: 2 additions & 2 deletions src/backend/InvenTree/InvenTree/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,12 @@ def download_file(
# Extract filename
disposition = response.headers['Content-Disposition']

result = re.search(r'attachment; filename="([\w.]+)"', disposition)
result = re.search(r'attachment; filename="([\w\d\-.]+)"', disposition)

fn = result.groups()[0]

if expected_fn is not None:
self.assertEqual(expected_fn, fn)
self.assertRegex(fn, expected_fn)

if decode:
# Decode data and return as StringIO file object
Expand Down
22 changes: 12 additions & 10 deletions src/backend/InvenTree/InvenTree/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import build.api
import common.api
import company.api
import importer.api
import machine.api
import order.api
import part.api
Expand Down Expand Up @@ -80,11 +81,19 @@

apipatterns = [
# Global search
path('search/', APISearchView.as_view(), name='api-search'),
path('settings/', include(common.api.settings_api_urls)),
path('part/', include(part.api.part_api_urls)),
path('admin/', include(common.api.admin_api_urls)),
path('bom/', include(part.api.bom_api_urls)),
path('build/', include(build.api.build_api_urls)),
path('company/', include(company.api.company_api_urls)),
path('importer/', include(importer.api.importer_api_urls)),
path('label/', include(report.api.label_api_urls)),
path('machine/', include(machine.api.machine_api_urls)),
path('order/', include(order.api.order_api_urls)),
path('part/', include(part.api.part_api_urls)),
path('report/', include(report.api.report_api_urls)),
path('search/', APISearchView.as_view(), name='api-search'),
path('settings/', include(common.api.settings_api_urls)),
path('stock/', include(stock.api.stock_api_urls)),
path(
'generate/',
include([
Expand All @@ -100,14 +109,7 @@
),
]),
),
path('stock/', include(stock.api.stock_api_urls)),
path('build/', include(build.api.build_api_urls)),
path('order/', include(order.api.order_api_urls)),
path('label/', include(report.api.label_api_urls)),
path('report/', include(report.api.report_api_urls)),
path('machine/', include(machine.api.machine_api_urls)),
path('user/', include(users.api.user_urls)),
path('admin/', include(common.api.admin_api_urls)),
path('web/', include(web_api_urls)),
# Plugin endpoints
path('', include(plugin.api.plugin_api_urls)),
Expand Down
Loading
Loading