2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 04:25:42 +00:00

Merge branch 'inventree:master' into matmair/issue2788

This commit is contained in:
Matthias Mair
2022-04-23 21:29:52 +02:00
committed by GitHub
24 changed files with 10504 additions and 316 deletions

View File

@ -282,6 +282,7 @@ INSTALLED_APPS = [
MIDDLEWARE = CONFIG.get('middleware', [
'django.middleware.security.SecurityMiddleware',
'x_forwarded_for.middleware.XForwardedForMiddleware',
'user_sessions.middleware.SessionMiddleware', # db user sessions
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
@ -545,11 +546,19 @@ if "sqlite" in db_engine:
# Provide OPTIONS dict back to the database configuration dict
db_config['OPTIONS'] = db_options
# Set testing options for the database
db_config['TEST'] = {
'CHARSET': 'utf8',
}
# Set collation option for mysql test database
if 'mysql' in db_engine:
db_config['TEST']['COLLATION'] = 'utf8_general_ci'
DATABASES = {
'default': db_config
}
_cache_config = CONFIG.get("cache", {})
_cache_host = _cache_config.get("host", os.getenv("INVENTREE_CACHE_HOST"))
_cache_port = _cache_config.get(
@ -662,6 +671,7 @@ LANGUAGE_CODE = CONFIG.get('language', 'en-us')
# If a new language translation is supported, it must be added here
LANGUAGES = [
('cs', _('Czech')),
('de', _('German')),
('el', _('Greek')),
('en', _('English')),

View File

@ -1,4 +1,4 @@
/*! jQuery UI - v1.12.1 - 2021-07-18
/*! jQuery UI - v1.13.0 - 2021-10-07
* http://jqueryui.com
* Includes: widget.js, position.js, disable-selection.js, keycode.js, unique-id.js, widgets/resizable.js, widgets/autocomplete.js, widgets/menu.js, widgets/mouse.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */
@ -17,11 +17,11 @@
$.ui = $.ui || {};
var version = $.ui.version = "1.12.1";
var version = $.ui.version = "1.13.1";
/*!
* jQuery UI Widget 1.12.1
* jQuery UI Widget 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -744,7 +744,7 @@ var widget = $.widget;
/*!
* jQuery UI Position 1.12.1
* jQuery UI Position 1.13.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -1232,7 +1232,7 @@ var position = $.ui.position;
/*!
* jQuery UI Disable Selection 1.12.1
* jQuery UI Disable Selection 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -1268,7 +1268,7 @@ var disableSelection = $.fn.extend( {
/*!
* jQuery UI Keycode 1.12.1
* jQuery UI Keycode 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -1303,7 +1303,7 @@ var keycode = $.ui.keyCode = {
/*!
* jQuery UI Unique ID 1.12.1
* jQuery UI Unique ID 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -1347,7 +1347,7 @@ var uniqueId = $.fn.extend( {
var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
/*!
* jQuery UI Mouse 1.12.1
* jQuery UI Mouse 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -1368,7 +1368,7 @@ $( document ).on( "mouseup", function() {
} );
var widgetsMouse = $.widget( "ui.mouse", {
version: "1.12.1",
version: "1.13.0",
options: {
cancel: "input, textarea, button, select, option",
distance: 1,
@ -1592,7 +1592,7 @@ var plugin = $.ui.plugin = {
/*!
* jQuery UI Resizable 1.12.1
* jQuery UI Resizable 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -1612,7 +1612,7 @@ var plugin = $.ui.plugin = {
$.widget( "ui.resizable", $.ui.mouse, {
version: "1.12.1",
version: "1.13.0",
widgetEventPrefix: "resize",
options: {
alsoResize: false,
@ -2806,7 +2806,7 @@ var safeActiveElement = $.ui.safeActiveElement = function( document ) {
/*!
* jQuery UI Menu 1.12.1
* jQuery UI Menu 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -2826,7 +2826,7 @@ var safeActiveElement = $.ui.safeActiveElement = function( document ) {
var widgetsMenu = $.widget( "ui.menu", {
version: "1.12.1",
version: "1.13.0",
defaultElement: "<ul>",
delay: 300,
options: {
@ -3461,7 +3461,7 @@ var widgetsMenu = $.widget( "ui.menu", {
/*!
* jQuery UI Autocomplete 1.12.1
* jQuery UI Autocomplete 1.13.0
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
@ -3481,7 +3481,7 @@ var widgetsMenu = $.widget( "ui.menu", {
$.widget( "ui.autocomplete", {
version: "1.12.1",
version: "1.13.0",
defaultElement: "<input>",
options: {
appendTo: null,

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
"name": "jquery-ui",
"title": "jQuery UI",
"description": "A curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library.",
"version": "1.12.1",
"version": "1.13.0",
"homepage": "http://jqueryui.com",
"author": {
"name": "jQuery Foundation and other contributors",

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -777,7 +777,8 @@ class Part(MPTTModel):
# User can decide whether duplicate IPN (Internal Part Number) values are allowed
allow_duplicate_ipn = common.models.InvenTreeSetting.get_setting('PART_ALLOW_DUPLICATE_IPN')
if self.IPN is not None and not allow_duplicate_ipn:
# Raise an error if an IPN is set, and it is a duplicate
if self.IPN and not allow_duplicate_ipn:
parts = Part.objects.filter(IPN__iexact=self.IPN)
parts = parts.exclude(pk=self.pk)
@ -798,6 +799,10 @@ class Part(MPTTModel):
super().clean()
# Strip IPN field
if type(self.IPN) is str:
self.IPN = self.IPN.strip()
if self.trackable:
for part in self.get_used_in().all():

View File

@ -349,6 +349,26 @@ class PartSettingsTest(TestCase):
part = Part(name='Hello', description='A thing', IPN='IPN123', revision='C')
part.full_clean()
# Any duplicate IPN should raise an error
Part.objects.create(name='xyz', revision='1', description='A part', IPN='UNIQUE')
# Case insensitive, so variations on spelling should throw an error
for ipn in ['UNiquE', 'uniQuE', 'unique']:
with self.assertRaises(ValidationError):
Part.objects.create(name='xyz', revision='2', description='A part', IPN=ipn)
with self.assertRaises(ValidationError):
Part.objects.create(name='zyx', description='A part', IPN='UNIQUE')
# However, *blank* / empty IPN values should be allowed, even if duplicates are not
# Note that leading / trailling whitespace characters are trimmed, too
Part.objects.create(name='abc', revision='1', description='A part', IPN=None)
Part.objects.create(name='abc', revision='2', description='A part', IPN='')
Part.objects.create(name='abc', revision='3', description='A part', IPN=None)
Part.objects.create(name='abc', revision='4', description='A part', IPN=' ')
Part.objects.create(name='abc', revision='5', description='A part', IPN=' ')
Part.objects.create(name='abc', revision='6', description='A part', IPN=' ')
class PartSubscriptionTests(TestCase):

View File

@ -94,6 +94,14 @@ class IntegrationPluginBase(MixinBase, plugin_base.InvenTreePluginBase):
"""
return getattr(self, 'is_package', False)
@property
def is_sample(self):
"""
Is this plugin part of the samples?
"""
path = str(self.package_path)
return path.startswith('plugin/samples/')
# region properties
@property
def slug(self):

View File

@ -453,10 +453,12 @@ class StockItem(MPTTModel):
super().clean()
if self.serial is not None and type(self.serial) is str:
# Strip serial number field
if type(self.serial) is str:
self.serial = self.serial.strip()
if self.batch is not None and type(self.batch) is str:
# Strip batch code field
if type(self.batch) is str:
self.batch = self.batch.strip()
try:

View File

@ -77,6 +77,12 @@
{% endfor %}
{% endif %}
{% if plugin.is_sample %}
<a class='sidebar-selector' id='select-plugin-{{plugin_key}}' data-bs-parent="#sidebar">
<span class='badge bg-info rounded-pill'>{% trans "code sample" %}</span>
</a>
{% endif %}
{% if plugin.website %}
<a href="{{ plugin.website }}"><span class="fas fa-globe"></span></a>
{% endif %}