mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Improvements for global settings
- Name and description are defined in models.py - Lookup functions for name / description / units / default - Shortcut template for rending settings - More unit testing
This commit is contained in:
parent
5e63ccc9f6
commit
10758a9626
@ -32,7 +32,7 @@ class CommonConfig(AppConfig):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Default instance name
|
# Default instance name
|
||||||
instance_name = 'InvenTree Server'
|
instance_name = InvenTreeSetting.get_default_value('INVENTREE_INSTANCE')
|
||||||
|
|
||||||
# Use the old name if it exists
|
# Use the old name if it exists
|
||||||
if InvenTreeSetting.objects.filter(key='InstanceName').exists():
|
if InvenTreeSetting.objects.filter(key='InstanceName').exists():
|
||||||
@ -59,12 +59,12 @@ class CommonConfig(AppConfig):
|
|||||||
|
|
||||||
from .models import InvenTreeSetting
|
from .models import InvenTreeSetting
|
||||||
|
|
||||||
for key in InvenTreeSetting.DEFAULT_VALUES.keys():
|
for key in InvenTreeSetting.GLOBAL_SETTINGS.keys():
|
||||||
try:
|
try:
|
||||||
settings = InvenTreeSetting.objects.filter(key__iexact=key)
|
settings = InvenTreeSetting.objects.filter(key__iexact=key)
|
||||||
|
|
||||||
if settings.count() == 0:
|
if settings.count() == 0:
|
||||||
value = InvenTreeSetting.DEFAULT_VALUES[key]
|
value = InvenTreeSetting.get_default_value(key)
|
||||||
|
|
||||||
print(f"Creating default setting for {key} -> '{value}'")
|
print(f"Creating default setting for {key} -> '{value}'")
|
||||||
|
|
||||||
|
@ -27,34 +27,144 @@ class InvenTreeSetting(models.Model):
|
|||||||
even if that key does not exist.
|
even if that key does not exist.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Dict of default values for various internal settings
|
"""
|
||||||
DEFAULT_VALUES = {
|
Dict of all global settings values:
|
||||||
# Global inventree settings
|
|
||||||
'INVENTREE_INSTANCE': 'InvenTree Server',
|
|
||||||
|
|
||||||
# Part settings
|
The key of each item is the name of the value as it appears in the database.
|
||||||
'PART_IPN_REGEX': '',
|
|
||||||
'PART_COPY_BOM': True,
|
|
||||||
'PART_COPY_PARAMETERS': True,
|
|
||||||
'PART_COPY_TESTS': True,
|
|
||||||
|
|
||||||
# Stock settings
|
Each global setting has the following parameters:
|
||||||
|
|
||||||
|
- name: Translatable string name of the setting (required)
|
||||||
|
- description: Translatable string description of the setting (required)
|
||||||
|
- default: Default value (optional)
|
||||||
|
- units: Units of the particular setting (optional)
|
||||||
|
- validator: Validation function for the setting (optional)
|
||||||
|
|
||||||
# Build Order settings
|
The keys must be upper-case
|
||||||
'BUILDORDER_REFERENCE_PREFIX': 'BO',
|
"""
|
||||||
'BUILDORDER_REFERENCE_REGEX': '',
|
|
||||||
|
|
||||||
# Purchase Order Settings
|
GLOBAL_SETTINGS = {
|
||||||
'PURCHASEORDER_REFERENCE_PREFIX': 'PO',
|
|
||||||
|
|
||||||
# Sales Order Settings
|
'INVENTREE_INSTANCE': {
|
||||||
'SALESORDER_REFERENCE_PREFIX': 'SO',
|
'name': _('InvenTree Instance Name'),
|
||||||
|
'default': 'InvenTree server',
|
||||||
|
'description': _('String descriptor for the server instance'),
|
||||||
|
},
|
||||||
|
|
||||||
|
'PART_IPN_REGEX': {
|
||||||
|
'name': _('IPN Regex'),
|
||||||
|
'description': _('Regular expression pattern for matching Part IPN')
|
||||||
|
},
|
||||||
|
|
||||||
|
'PART_COPY_BOM': {
|
||||||
|
'name': _('Copy Part BOM Data'),
|
||||||
|
'description': _('Copy BOM data by default when duplicating a part'),
|
||||||
|
'default': True,
|
||||||
|
},
|
||||||
|
|
||||||
|
'PART_COPY_PARAMETERS': {
|
||||||
|
'name': _('Copy Part Parameter Data'),
|
||||||
|
'description': _('Copy parameter data by default when duplicating a part'),
|
||||||
|
'default': True,
|
||||||
|
},
|
||||||
|
|
||||||
|
'PART_COPY_TESTS': {
|
||||||
|
'name': _('Copy Part Test Data'),
|
||||||
|
'description': _('Copy test data by default when duplicating a part'),
|
||||||
|
'default': True,
|
||||||
|
},
|
||||||
|
|
||||||
|
'BUILDORDER_REFERENCE_PREFIX': {
|
||||||
|
'name': _('Build Order Reference Prefix'),
|
||||||
|
'description': _('Prefix value for build order reference'),
|
||||||
|
'default': 'BO',
|
||||||
|
},
|
||||||
|
|
||||||
|
'BUILDORDER_REFERENCE_REGEX': {
|
||||||
|
'name': _('Build Order Reference Regex'),
|
||||||
|
'description': _('Regular expression pattern for matching build order reference')
|
||||||
|
},
|
||||||
|
|
||||||
|
'SALESORDER_REFERENCE_PREFIX': {
|
||||||
|
'name': _('Sales Order Reference Prefix'),
|
||||||
|
'description': _('Prefix value for sales order reference'),
|
||||||
|
},
|
||||||
|
|
||||||
|
'PURCHASEORDER_REFERENCE_PREFIX': {
|
||||||
|
'name': _('Purchase Order Reference Prefix'),
|
||||||
|
'description': _('Prefix value for purchase order reference'),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "InvenTree Setting"
|
verbose_name = "InvenTree Setting"
|
||||||
verbose_name_plural = "InvenTree Settings"
|
verbose_name_plural = "InvenTree Settings"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_setting_name(cls, key):
|
||||||
|
"""
|
||||||
|
Return the name of a particular setting.
|
||||||
|
|
||||||
|
If it does not exist, return an empty string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
key = str(key).strip().upper()
|
||||||
|
|
||||||
|
if key in cls.GLOBAL_SETTINGS:
|
||||||
|
setting = cls.GLOBAL_SETTINGS[key]
|
||||||
|
return setting.get('name', '')
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_setting_description(cls, key):
|
||||||
|
"""
|
||||||
|
Return the description for a particular setting.
|
||||||
|
|
||||||
|
If it does not exist, return an empty string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
key = str(key).strip().upper()
|
||||||
|
|
||||||
|
if key in cls.GLOBAL_SETTINGS:
|
||||||
|
setting = cls.GLOBAL_SETTINGS[key]
|
||||||
|
return setting.get('description', '')
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_setting_units(cls, key):
|
||||||
|
"""
|
||||||
|
Return the units for a particular setting.
|
||||||
|
|
||||||
|
If it does not exist, return an empty string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
key = str(key).strip().upper()
|
||||||
|
|
||||||
|
if key in cls.GLOBAL_SETTINGS:
|
||||||
|
setting = cls.GLOBAL_SETTINGS[key]
|
||||||
|
return setting.get('units', '')
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_default_value(cls, key):
|
||||||
|
"""
|
||||||
|
Return the default value for a particular setting.
|
||||||
|
|
||||||
|
If it does not exist, return an empty string
|
||||||
|
"""
|
||||||
|
|
||||||
|
key = str(key).strip().upper()
|
||||||
|
|
||||||
|
if key in cls.GLOBAL_SETTINGS:
|
||||||
|
setting = cls.GLOBAL_SETTINGS[key]
|
||||||
|
return setting.get('default', '')
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_setting(cls, key, backup_value=None):
|
def get_setting(cls, key, backup_value=None):
|
||||||
"""
|
"""
|
||||||
@ -64,7 +174,7 @@ class InvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
# If no backup value is specified, atttempt to retrieve a "default" value
|
# If no backup value is specified, atttempt to retrieve a "default" value
|
||||||
if backup_value is None:
|
if backup_value is None:
|
||||||
backup_value = InvenTreeSetting.DEFAULT_VALUES.get(key, None)
|
backup_value = cls.get_default_value(key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
settings = InvenTreeSetting.objects.filter(key__iexact=key)
|
settings = InvenTreeSetting.objects.filter(key__iexact=key)
|
||||||
|
@ -35,14 +35,37 @@ class SettingsTest(TestCase):
|
|||||||
|
|
||||||
self.client.login(username='username', password='password')
|
self.client.login(username='username', password='password')
|
||||||
|
|
||||||
|
def test_required_values(self):
|
||||||
|
"""
|
||||||
|
- Ensure that every global setting has a name.
|
||||||
|
- Ensure that every global setting has a description.
|
||||||
|
"""
|
||||||
|
|
||||||
|
for key in InvenTreeSetting.GLOBAL_SETTINGS.keys():
|
||||||
|
|
||||||
|
setting = InvenTreeSetting.GLOBAL_SETTINGS[key]
|
||||||
|
|
||||||
|
name = setting.get('name', None)
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
raise ValueError(f'Missing GLOBAL_SETTING name for {key}')
|
||||||
|
|
||||||
|
description = setting.get('description', None)
|
||||||
|
|
||||||
|
if description is None:
|
||||||
|
raise ValueError(f'Missing GLOBAL_SETTING description for {key}')
|
||||||
|
|
||||||
|
if not key == key.upper():
|
||||||
|
raise ValueError(f"GLOBAL_SETTINGS key '{key}' is not uppercase")
|
||||||
|
|
||||||
def test_defaults(self):
|
def test_defaults(self):
|
||||||
"""
|
"""
|
||||||
Populate the settings with default values
|
Populate the settings with default values
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for key in InvenTreeSetting.DEFAULT_VALUES.keys():
|
for key in InvenTreeSetting.GLOBAL_SETTINGS.keys():
|
||||||
|
|
||||||
value = InvenTreeSetting.DEFAULT_VALUES[key]
|
value = InvenTreeSetting.get_default_value(key)
|
||||||
|
|
||||||
InvenTreeSetting.set_setting(key, value, self.user)
|
InvenTreeSetting.set_setting(key, value, self.user)
|
||||||
|
|
||||||
|
@ -87,7 +87,34 @@ def inventree_docs_url(*args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
@register.simple_tag()
|
@register.simple_tag()
|
||||||
def inventree_setting(key, *args, **kwargs):
|
def settings_name(key, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns the name of a GLOBAL_SETTINGS object
|
||||||
|
"""
|
||||||
|
|
||||||
|
return InvenTreeSetting.get_setting_name(key)
|
||||||
|
|
||||||
|
@register.simple_tag()
|
||||||
|
def settings_description(key, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns the description of a GLOBAL_SETTINGS object
|
||||||
|
"""
|
||||||
|
|
||||||
|
return InvenTreeSetting.get_setting_description(key)
|
||||||
|
|
||||||
|
@register.simple_tag()
|
||||||
|
def settings_units(key, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Return the units of a GLOBAL_SETTINGS object
|
||||||
|
"""
|
||||||
|
|
||||||
|
return InvenTreeSetting.get_setting_units(key)
|
||||||
|
|
||||||
|
@register.simple_tag()
|
||||||
|
def settings_value(key, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns the value of a GLOBAL_SETTINGS object
|
||||||
|
"""
|
||||||
return InvenTreeSetting.get_setting(key, backup_value=kwargs.get('backup', None))
|
return InvenTreeSetting.get_setting(key, backup_value=kwargs.get('backup', None))
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,17 +15,8 @@
|
|||||||
<table class='table table-striped table-condensed'>
|
<table class='table table-striped table-condensed'>
|
||||||
<thead></thead>
|
<thead></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
{% include "InvenTree/settings/setting.html" with key="BUILDORDER_REFERENCE_PREFIX" %}
|
||||||
<th>{% trans "Reference Prefix" %}</th>
|
{% include "InvenTree/settings/setting.html" with key="BUILDORDER_REFERENCE_REGEX" %}
|
||||||
<th>{% inventree_setting 'BUILDORDER_REFERENCE_PREFIX' backup='BO' %}</th>
|
|
||||||
<td>{% trans "Prefix for Build Order reference" %}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Reference Regex" %}</th>
|
|
||||||
<th>{% inventree_setting 'BUILDORDER_REFERENCE_REGEX' %}</th>
|
|
||||||
<td>{% trans "Regex validator for Build Order reference" %}</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -11,6 +11,16 @@
|
|||||||
|
|
||||||
{% block settings %}
|
{% block settings %}
|
||||||
|
|
||||||
|
<table class='table table-striped table-condensed'>
|
||||||
|
<thead></thead>
|
||||||
|
<tbody>
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="PART_IPN_REGEX" %}
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="PART_COPY_BOM" %}
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="PART_COPY_PARAMETERS" %}
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="PART_COPY_TESTS" %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<h4>{% trans "Part Parameter Templates" %}</h4>
|
<h4>{% trans "Part Parameter Templates" %}</h4>
|
||||||
|
|
||||||
<div id='param-buttons'>
|
<div id='param-buttons'>
|
||||||
@ -53,7 +63,7 @@
|
|||||||
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
|
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
|
||||||
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
|
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
|
||||||
|
|
||||||
var html = "<div class='btn-group' role='group'>" + bEdit + bDel + "</div>";
|
var html = "<div class='btn-group float-right' role='group'>" + bEdit + bDel + "</div>";
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,10 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block settings %}
|
{% block settings %}
|
||||||
|
<table class='table table-striped table-condensed'>
|
||||||
|
<thead></thead>
|
||||||
|
<tbody>
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="PURCHASEORDER_REFERENCE_PREFIX" %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
{% endblock %}
|
{% endblock %}
|
15
InvenTree/templates/InvenTree/settings/setting.html
Normal file
15
InvenTree/templates/InvenTree/settings/setting.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{% load inventree_extras %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><b>{% settings_name key %}</b></td>
|
||||||
|
<td><b>{% settings_value key %}</b>{% settings_units key %}</td>
|
||||||
|
<td>{% settings_description key %}</td>
|
||||||
|
<td>
|
||||||
|
<div class='btn-group float-right'>
|
||||||
|
<button class='btn btn-default btn-glyph btn-edit-setting' setting='{{ key }}' title='{% trans "Edit setting" %}'>
|
||||||
|
<span class='fas fa-edit icon-green'></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
@ -10,4 +10,12 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block settings %}
|
{% block settings %}
|
||||||
|
|
||||||
|
<table class='table table-striped table-condensed'>
|
||||||
|
<thead></thead>
|
||||||
|
<tbody>
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="SALESORDER_REFERENCE_PREFIX" %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -42,7 +42,7 @@ function loadBuildTable(table, options) {
|
|||||||
switchable: false,
|
switchable: false,
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
|
|
||||||
var prefix = "{% inventree_setting 'BUILDORDER_REFERENCE_PREFIX' %}";
|
var prefix = "{% settings_value 'BUILDORDER_REFERENCE_PREFIX' %}";
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
value = `${prefix}${value}`;
|
value = `${prefix}${value}`;
|
||||||
|
@ -139,7 +139,7 @@ function loadPurchaseOrderTable(table, options) {
|
|||||||
title: '{% trans "Purchase Order" %}',
|
title: '{% trans "Purchase Order" %}',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
|
|
||||||
var prefix = "{% inventree_setting 'PURCHASEORDER_REFERENCE_PREFIX' %}";
|
var prefix = "{% settings_value 'PURCHASEORDER_REFERENCE_PREFIX' %}";
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
value = `${prefix}${value}`;
|
value = `${prefix}${value}`;
|
||||||
@ -221,7 +221,7 @@ function loadSalesOrderTable(table, options) {
|
|||||||
title: '{% trans "Sales Order" %}',
|
title: '{% trans "Sales Order" %}',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
|
|
||||||
var prefix = "{% inventree_setting 'SALESORDER_REFERENCE_PREFIX' %}";
|
var prefix = "{% settings_value 'SALESORDER_REFERENCE_PREFIX' %}";
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
value = `${prefix}${value}`;
|
value = `${prefix}${value}`;
|
||||||
|
Loading…
Reference in New Issue
Block a user