diff --git a/InvenTree/part/admin.py b/InvenTree/part/admin.py index eb0c32e751..e7e3b4b675 100644 --- a/InvenTree/part/admin.py +++ b/InvenTree/part/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import PartCategory, Part +from .models import PartCategory, Part, PartParameter, PartParameterTemplate class PartAdmin(admin.ModelAdmin): @@ -12,5 +12,17 @@ class PartCategoryAdmin(admin.ModelAdmin): list_display = ('name', 'path', 'description') + +class ParameterTemplateAdmin(admin.ModelAdmin): + list_display = ('name', 'units', 'category') + + +class ParameterAdmin(admin.ModelAdmin): + list_display = ('part', 'template', 'value') + + admin.site.register(Part, PartAdmin) admin.site.register(PartCategory, PartCategoryAdmin) + +admin.site.register(PartParameter, ParameterAdmin) +admin.site.register(PartParameterTemplate, ParameterTemplateAdmin) \ No newline at end of file diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 6780aad57c..776b12d60e 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals from django.db import models from django.db.models import Sum -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, ValidationError from InvenTree.models import InvenTreeTree @@ -75,7 +75,67 @@ class Part(models.Model): projects.append(pp.project) return projects + +class PartParameterTemplate(models.Model): + """ A PartParameterTemplate pre-defines a parameter field, + ready to be copied for use with a given Part. + A PartParameterTemplate can be optionally associated with a PartCategory + """ + + category = models.ForeignKey(PartCategory, on_delete=models.CASCADE, blank=True, null=True) + + name = models.CharField(max_length=20) + description = models.CharField(max_length=100, blank=True) + units = models.CharField(max_length=10, blank=True) + + default_value = models.CharField(max_length=50, blank=True) + default_min = models.CharField(max_length=50, blank=True) + default_max = models.CharField(max_length=50, blank=True) + + def __str__(self): + return "{name} ({units})".format( + name=self.name, + units=self.units) + + class Meta: + verbose_name = "Parameter Template" + verbose_name_plural = "Parameter Templates" + +class PartParameter(models.Model): + """ PartParameter is associated with a single part + """ + + part = models.ForeignKey(Part, on_delete=models.CASCADE) + + template = models.ForeignKey(PartParameterTemplate) + + # Value data + value = models.CharField(max_length=50, blank=True) + min_value = models.CharField(max_length=50, blank=True) + max_value = models.CharField(max_length=50, blank=True) + + # Prevent multiple parameters of the same template + # from being added to the same part + def save(self, *args, **kwargs): + params = PartParameter.objects.filter(part=self.part, template=self.template) + if len(params) > 0: + raise ValidationError("Parameter '{param}' already exists for {part}".format( + param=self.template.name, + part=self.part.name)) + + super(PartParameter, self).save(*args, **kwargs) + + def __str__(self): + return "{name} : {val}{units}".format( + name=self.template.name, + val=self.value, + units=self.template.units) + + class Meta: + verbose_name = "Part Parameter" + verbose_name_plural = "Part Parameters" + class PartRevision(models.Model): """ A PartRevision represents a change-notification to a Part