2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-01 21:16:46 +00:00

Added admin view, improved validation of part related relationship

This commit is contained in:
eeintech 2020-10-16 15:29:58 -05:00
parent 34e4409e7f
commit 0b26d68d0f
6 changed files with 66 additions and 10 deletions

View File

@ -9,7 +9,7 @@ from import_export.fields import Field
import import_export.widgets as widgets import import_export.widgets as widgets
from .models import PartCategory, Part from .models import PartCategory, Part
from .models import PartAttachment, PartStar from .models import PartAttachment, PartStar, PartRelated
from .models import BomItem from .models import BomItem
from .models import PartParameterTemplate, PartParameter from .models import PartParameterTemplate, PartParameter
from .models import PartTestTemplate from .models import PartTestTemplate
@ -121,6 +121,11 @@ class PartCategoryAdmin(ImportExportModelAdmin):
search_fields = ('name', 'description') search_fields = ('name', 'description')
class PartRelatedAdmin(admin.ModelAdmin):
''' Class to manage PartRelated objects '''
pass
class PartAttachmentAdmin(admin.ModelAdmin): class PartAttachmentAdmin(admin.ModelAdmin):
list_display = ('part', 'attachment', 'comment') list_display = ('part', 'attachment', 'comment')
@ -279,6 +284,7 @@ class PartSellPriceBreakAdmin(admin.ModelAdmin):
admin.site.register(Part, PartAdmin) admin.site.register(Part, PartAdmin)
admin.site.register(PartCategory, PartCategoryAdmin) admin.site.register(PartCategory, PartCategoryAdmin)
admin.site.register(PartRelated, PartRelatedAdmin)
admin.site.register(PartAttachment, PartAttachmentAdmin) admin.site.register(PartAttachment, PartAttachmentAdmin)
admin.site.register(PartStar, PartStarAdmin) admin.site.register(PartStar, PartStarAdmin)
admin.site.register(BomItem, BomItemAdmin) admin.site.register(BomItem, BomItemAdmin)

View File

@ -1754,16 +1754,18 @@ class BomItem(models.Model):
class PartRelated(models.Model): class PartRelated(models.Model):
""" Store and handle related parts (eg. mating connector, crimps, etc.) """ """ Store and handle related parts (eg. mating connector, crimps, etc.) """
part_1 = models.ForeignKey(Part, related_name='related_parts_1', on_delete=models.DO_NOTHING) part_1 = models.ForeignKey(Part, related_name='related_parts_1',
on_delete=models.DO_NOTHING)
part_2 = models.ForeignKey(Part, related_name='related_parts_2', on_delete=models.DO_NOTHING, part_2 = models.ForeignKey(Part, related_name='related_parts_2',
help_text=_('Choose Related Part')) on_delete=models.DO_NOTHING,
help_text=_('Select Related Part'))
def __str__(self): def __str__(self):
return f'{self.part_1} <-> {self.part_2}' return f'{self.part_1} <--> {self.part_2}'
def create_relationship(self, part_1, part_2): def validate(self, part_1, part_2):
''' Create relationship between two parts ''' ''' Validate that the two parts relationship is unique '''
validate = True validate = True
@ -1771,15 +1773,35 @@ class PartRelated(models.Model):
related_parts = PartRelated.objects.all() related_parts = PartRelated.objects.all()
# Check if part exist and there are not the same part # Check if part exist and there are not the same part
if (part_1 in parts and part_2 in parts) and (part_1 is not part_2): if (part_1 in parts and part_2 in parts) and (part_1.pk != part_2.pk):
# Check if relation exists already # Check if relation exists already
for relation in related_parts: for relation in related_parts:
if (part_1 == relation.part_1 and part_2 == relation.part_2) \ if (part_1 == relation.part_1 and part_2 == relation.part_2) \
or (part_1 == relation.part_2 and part_2 == relation.part_1): or (part_1 == relation.part_2 and part_2 == relation.part_1):
validate = False validate = False
break
else: else:
validate = False validate = False
return validate
def clean(self):
''' Overwrite clean method to check that relation is unique '''
validate = self.validate(self.part_1, self.part_2)
if not validate:
error_message = _('Error creating relationship: check that '
'the part is not related to itself '
'and that the relationship is unique')
raise ValidationError(error_message)
def create_relationship(self, part_1, part_2):
''' Create relationship between two parts '''
validate = self.validate(part_1, part_2)
if validate: if validate:
# Add relationship # Add relationship
self.part_1 = part_1 self.part_1 = part_1

View File

@ -11,10 +11,12 @@
<div id='button-bar'> <div id='button-bar'>
<div class='button-toolbar container-fluid' style='float: left;'> <div class='button-toolbar container-fluid' style='float: left;'>
{% if roles.part.change %}
<button class='btn btn-primary' type='button' id='add-related-part' title='{% trans "Add Related" %}'>{% trans "Add Related" %}</button> <button class='btn btn-primary' type='button' id='add-related-part' title='{% trans "Add Related" %}'>{% trans "Add Related" %}</button>
<div class='filter-list' id='filter-list-related'> <div class='filter-list' id='filter-list-related'>
<!-- An empty div in which the filter list will be constructed --> <!-- An empty div in which the filter list will be constructed -->
</div> </div>
{% endif %}
</div> </div>
</div> </div>

View File

@ -201,6 +201,29 @@ class PartTests(PartViewTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
class PartRelatedTests(PartViewTestCase):
def test_valid_create(self):
""" test creation of an attachment for a valid part """
response = self.client.get(reverse('part-related-create'), {'part': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200)
# TODO - Create a new attachment using this view
def test_invalid_create(self):
""" test creation of an attachment for an invalid part """
# TODO
pass
def test_edit(self):
""" test editing an attachment """
# TODO
pass
class PartAttachmentTests(PartViewTestCase): class PartAttachmentTests(PartViewTestCase):
def test_valid_create(self): def test_valid_create(self):

View File

@ -113,10 +113,12 @@ class PartRelatedCreate(AjaxCreateView):
# Get existing related parts # Get existing related parts
related_parts = [related_part[1].pk for related_part in parent_part.get_related_parts()] related_parts = [related_part[1].pk for related_part in parent_part.get_related_parts()]
# Build updated choice list excluding parts already related to parent part # Build updated choice list excluding
# - parts already related to parent part
# - the parent part itself
updated_choices = [] updated_choices = []
for choice in form.fields["part_2"].choices: for choice in form.fields["part_2"].choices:
if choice[0] not in related_parts: if (choice[0] not in related_parts) and (choice[0] != parent_part.pk):
updated_choices.append(choice) updated_choices.append(choice)
# Update choices for related part # Update choices for related part

View File

@ -57,6 +57,7 @@ class RuleSet(models.Model):
'part_parttesttemplate', 'part_parttesttemplate',
'part_partparametertemplate', 'part_partparametertemplate',
'part_partparameter', 'part_partparameter',
'part_partrelated',
], ],
'stock': [ 'stock': [
'stock_stockitem', 'stock_stockitem',