diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index b42d54cbe9..63a4d23ce2 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -45,6 +45,62 @@ def rename_attachment(instance, filename): return os.path.join(instance.getSubdir(), filename) +class DataImportMixin(object): + """ + Model mixin class which provides support for 'data import' functionality. + + Models which implement this mixin should provide information on the fields available for import + """ + + # Define a map of fields avaialble for import + IMPORT_FIELDS = {} + + @classmethod + def get_import_fields(cls): + """ + Return all available import fields + + Where information on a particular field is not explicitly provided, + introspect the base model to (attempt to) find that information. + + """ + fields = cls.IMPORT_FIELDS + + for name, field in fields.items(): + + # Attempt to extract base field information from the model + base_field = None + + for f in cls._meta.fields: + if f.name == name: + base_field = f + break + + if base_field: + if 'label' not in field: + field['label'] = base_field.verbose_name + + if 'help_text' not in field: + field['help_text'] = base_field.help_text + + fields[name] = field + + return fields + + @classmethod + def get_required_import_fields(cls): + """ Return all *required* import fields """ + fields = {} + + for name, field in cls.get_import_fields().items(): + required = field.get('required', False) + + if required: + fields[name] = field + + return fields + + class ReferenceIndexingMixin(models.Model): """ A mixin for keeping track of numerical copies of the "reference" field. diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index b312937e30..e45fd1a783 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -46,7 +46,7 @@ from common.models import InvenTreeSetting from InvenTree import helpers from InvenTree import validators -from InvenTree.models import InvenTreeTree, InvenTreeAttachment +from InvenTree.models import InvenTreeTree, InvenTreeAttachment, DataImportMixin from InvenTree.fields import InvenTreeURLField from InvenTree.helpers import decimal2string, normalize, decimal2money import InvenTree.tasks @@ -2550,7 +2550,7 @@ class PartCategoryParameterTemplate(models.Model): help_text=_('Default Parameter Value')) -class BomItem(models.Model): +class BomItem(models.Model, DataImportMixin): """ A BomItem links a part to its component items. A part can have a BOM (bill of materials) which defines which parts are required (and in what quantity) to make it. @@ -2568,6 +2568,35 @@ class BomItem(models.Model): allow_variants: Stock for part variants can be substituted for this BomItem """ + # Fields available for bulk import + IMPORT_FIELDS = { + 'quantity': { + 'required': True + }, + 'optional': {}, + 'reference': {}, + 'overage': {}, + 'note': {}, + 'inherited': {}, + 'allow_variants': {}, + 'part': { + 'label': _('Part'), + 'help_text': _('Part ID or part name'), + }, + 'part_id': { + 'label': _('Part ID'), + 'help_text': _('Unique part ID value') + }, + 'part_name': { + 'label': _('Part Name'), + 'help_text': _('Part name'), + }, + 'part_ipn': { + 'label': _('Part IPN'), + 'help_text': _('Part IPN value'), + } + } + @staticmethod def get_api_url(): return reverse('api-bom-list')