diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 8c43a623a0..692c3b53b8 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -8,6 +8,7 @@ import decimal import os import logging +import re from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError @@ -555,7 +556,9 @@ class Part(MPTTModel): @property def full_name(self): - """ Format a 'full name' for this Part. + """ Format a 'full name' for this Part based on the format PART_NAME_FORMAT defined in part.settings file + + As a failsafe option, the following is done - IPN (if not null) - Part name @@ -564,17 +567,45 @@ class Part(MPTTModel): Elements are joined by the | character """ - elements = [] + full_name = part_settings.PART_NAME_FORMAT + field_parser_regex_pattern = re.compile('{.*?}') + field_regex_pattern = re.compile('(?<=part\\.)[A-z]*') - if self.IPN: - elements.append(self.IPN) + try: - elements.append(self.name) + for field_parser in field_parser_regex_pattern.findall(part_settings.PART_NAME_FORMAT): - if self.revision: - elements.append(self.revision) + # Each parser should contain a single field + field_name = field_regex_pattern.findall(field_parser)[0] + field_value = getattr(self, field_name) - return ' | '.join(elements) + if field_value: + # replace the part.$field with field's value and remove the braces + parsed_value = field_parser.replace(f'part.{field_name}', field_value)[1:-1] + full_name = full_name.replace(field_parser, parsed_value) + + else: + # remove the field parser in full name + full_name = full_name.replace(field_parser, '') + + return full_name + + except AttributeError as attr_err: + + logger.warning(f"exception while trying to create full name for part {self.name}", attr_err) + + # Fallback to default format + elements = [] + + if self.IPN: + elements.append(self.IPN) + + elements.append(self.name) + + if self.revision: + elements.append(self.revision) + + return ' | '.join(elements) def set_category(self, category): diff --git a/InvenTree/part/settings.py b/InvenTree/part/settings.py index e345a9d88d..c1d2f4c7e6 100644 --- a/InvenTree/part/settings.py +++ b/InvenTree/part/settings.py @@ -62,3 +62,13 @@ def part_trackable_default(): """ return InvenTreeSetting.get_setting('PART_TRACKABLE') + + +# CONSTANTS + +# Every brace pair is a field parser within which a field name of part has to be defined in the format part.$field_name +# When full name is constructed, It would be replaced by its value from the database and if the value is None, +# the entire field_parser i.e {.*} would be replaced with ''. +# Other characters inside and between the brace pairs would be copied as is. +PART_NAME_FORMAT = '{part.IPN | }{part.name}{ | part.revision}' + diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index aba3c46330..db8d435b96 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -876,23 +876,7 @@ function loadPartTable(table, url, options={}) { switchable: false, formatter: function(value, row) { - var name = ''; - - if (row.IPN) { - name += row.IPN; - name += ' | '; - } - - name += value; - - if (row.revision) { - name += ' | '; - name += row.revision; - } - - if (row.is_template) { - name = '' + name + ''; - } + var name = row.full_name; var display = imageHoverIcon(row.thumbnail) + renderLink(name, '/part/' + row.pk + '/');