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
|
||||
|
||||
# Default instance name
|
||||
instance_name = 'InvenTree Server'
|
||||
instance_name = InvenTreeSetting.get_default_value('INVENTREE_INSTANCE')
|
||||
|
||||
# Use the old name if it exists
|
||||
if InvenTreeSetting.objects.filter(key='InstanceName').exists():
|
||||
@ -59,12 +59,12 @@ class CommonConfig(AppConfig):
|
||||
|
||||
from .models import InvenTreeSetting
|
||||
|
||||
for key in InvenTreeSetting.DEFAULT_VALUES.keys():
|
||||
for key in InvenTreeSetting.GLOBAL_SETTINGS.keys():
|
||||
try:
|
||||
settings = InvenTreeSetting.objects.filter(key__iexact=key)
|
||||
|
||||
if settings.count() == 0:
|
||||
value = InvenTreeSetting.DEFAULT_VALUES[key]
|
||||
value = InvenTreeSetting.get_default_value(key)
|
||||
|
||||
print(f"Creating default setting for {key} -> '{value}'")
|
||||
|
||||
|
@ -27,34 +27,144 @@ class InvenTreeSetting(models.Model):
|
||||
even if that key does not exist.
|
||||
"""
|
||||
|
||||
# Dict of default values for various internal settings
|
||||
DEFAULT_VALUES = {
|
||||
# Global inventree settings
|
||||
'INVENTREE_INSTANCE': 'InvenTree Server',
|
||||
"""
|
||||
Dict of all global settings values:
|
||||
|
||||
# Part settings
|
||||
'PART_IPN_REGEX': '',
|
||||
'PART_COPY_BOM': True,
|
||||
'PART_COPY_PARAMETERS': True,
|
||||
'PART_COPY_TESTS': True,
|
||||
The key of each item is the name of the value as it appears in the database.
|
||||
|
||||
# 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
|
||||
'BUILDORDER_REFERENCE_PREFIX': 'BO',
|
||||
'BUILDORDER_REFERENCE_REGEX': '',
|
||||
The keys must be upper-case
|
||||
"""
|
||||
|
||||
# Purchase Order Settings
|
||||
'PURCHASEORDER_REFERENCE_PREFIX': 'PO',
|
||||
GLOBAL_SETTINGS = {
|
||||
|
||||
# Sales Order Settings
|
||||
'SALESORDER_REFERENCE_PREFIX': 'SO',
|
||||
'INVENTREE_INSTANCE': {
|
||||
'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:
|
||||
verbose_name = "InvenTree Setting"
|
||||
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
|
||||
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 backup_value is None:
|
||||
backup_value = InvenTreeSetting.DEFAULT_VALUES.get(key, None)
|
||||
backup_value = cls.get_default_value(key)
|
||||
|
||||
try:
|
||||
settings = InvenTreeSetting.objects.filter(key__iexact=key)
|
||||
|
@ -35,14 +35,37 @@ class SettingsTest(TestCase):
|
||||
|
||||
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):
|
||||
"""
|
||||
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)
|
||||
|
||||
|
@ -87,7 +87,34 @@ def inventree_docs_url(*args, **kwargs):
|
||||
|
||||
|
||||
@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))
|
||||
|
||||
|
||||
|
@ -15,17 +15,8 @@
|
||||
<table class='table table-striped table-condensed'>
|
||||
<thead></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{% trans "Reference Prefix" %}</th>
|
||||
<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>
|
||||
{% include "InvenTree/settings/setting.html" with key="BUILDORDER_REFERENCE_PREFIX" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="BUILDORDER_REFERENCE_REGEX" %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -11,6 +11,16 @@
|
||||
|
||||
{% 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>
|
||||
|
||||
<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 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;
|
||||
}
|
||||
|
@ -10,4 +10,10 @@
|
||||
{% endblock %}
|
||||
|
||||
{% 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 %}
|
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 %}
|
||||
|
||||
{% 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 %}
|
@ -42,7 +42,7 @@ function loadBuildTable(table, options) {
|
||||
switchable: false,
|
||||
formatter: function(value, row, index, field) {
|
||||
|
||||
var prefix = "{% inventree_setting 'BUILDORDER_REFERENCE_PREFIX' %}";
|
||||
var prefix = "{% settings_value 'BUILDORDER_REFERENCE_PREFIX' %}";
|
||||
|
||||
if (prefix) {
|
||||
value = `${prefix}${value}`;
|
||||
|
@ -139,7 +139,7 @@ function loadPurchaseOrderTable(table, options) {
|
||||
title: '{% trans "Purchase Order" %}',
|
||||
formatter: function(value, row, index, field) {
|
||||
|
||||
var prefix = "{% inventree_setting 'PURCHASEORDER_REFERENCE_PREFIX' %}";
|
||||
var prefix = "{% settings_value 'PURCHASEORDER_REFERENCE_PREFIX' %}";
|
||||
|
||||
if (prefix) {
|
||||
value = `${prefix}${value}`;
|
||||
@ -221,7 +221,7 @@ function loadSalesOrderTable(table, options) {
|
||||
title: '{% trans "Sales Order" %}',
|
||||
formatter: function(value, row, index, field) {
|
||||
|
||||
var prefix = "{% inventree_setting 'SALESORDER_REFERENCE_PREFIX' %}";
|
||||
var prefix = "{% settings_value 'SALESORDER_REFERENCE_PREFIX' %}";
|
||||
|
||||
if (prefix) {
|
||||
value = `${prefix}${value}`;
|
||||
|
Loading…
Reference in New Issue
Block a user