mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-02 13:28:49 +00:00
Added admin view, improved validation of part related relationship
This commit is contained in:
parent
34e4409e7f
commit
0b26d68d0f
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user