2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-05 13:10:57 +00:00

Delete part via API (#3135)

* Updates for the PartRelated model

- Deleting a part also deletes the relationships
- Add unique_together requirement
- Bug fixes
- Added unit tests

* Adds JS function to delete a part instance

* Remove legacy delete view

* JS linting
This commit is contained in:
Oliver
2022-06-06 11:42:22 +10:00
committed by GitHub
parent f38386b13c
commit fe8f111a63
8 changed files with 151 additions and 143 deletions

View File

@ -2037,27 +2037,20 @@ class Part(MetadataMixin, MPTTModel):
return filtered_parts
def get_related_parts(self):
"""Return list of tuples for all related parts.
Includes:
- first value is PartRelated object
- second value is matching Part object
"""
related_parts = []
"""Return a set of all related parts for this part"""
related_parts = set()
related_parts_1 = self.related_parts_1.filter(part_1__id=self.pk)
related_parts_2 = self.related_parts_2.filter(part_2__id=self.pk)
related_parts.append()
for related_part in related_parts_1:
# Add to related parts list
related_parts.append(related_part.part_2)
related_parts.add(related_part.part_2)
for related_part in related_parts_2:
# Add to related parts list
related_parts.append(related_part.part_1)
related_parts.add(related_part.part_1)
return related_parts
@ -2829,44 +2822,35 @@ class BomItemSubstitute(models.Model):
class PartRelated(models.Model):
"""Store and handle related parts (eg. mating connector, crimps, etc.)."""
class Meta:
"""Metaclass defines extra model properties"""
unique_together = ('part_1', 'part_2')
part_1 = models.ForeignKey(Part, related_name='related_parts_1',
verbose_name=_('Part 1'), on_delete=models.DO_NOTHING)
verbose_name=_('Part 1'), on_delete=models.CASCADE)
part_2 = models.ForeignKey(Part, related_name='related_parts_2',
on_delete=models.DO_NOTHING,
on_delete=models.CASCADE,
verbose_name=_('Part 2'), help_text=_('Select Related Part'))
def __str__(self):
"""Return a string representation of this Part-Part relationship"""
return f'{self.part_1} <--> {self.part_2}'
def validate(self, part_1, part_2):
"""Validate that the two parts relationship is unique."""
validate = True
parts = Part.objects.all()
related_parts = PartRelated.objects.all()
# Check if part exist and there are not the same part
if (part_1 in parts and part_2 in parts) and (part_1.pk != part_2.pk):
# Check if relation exists already
for relation in related_parts:
if (part_1 == relation.part_1 and part_2 == relation.part_2) \
or (part_1 == relation.part_2 and part_2 == relation.part_1):
validate = False
break
else:
validate = False
return validate
def save(self, *args, **kwargs):
"""Enforce a 'clean' operation when saving a PartRelated instance"""
self.clean()
self.validate_unique()
super().save(*args, **kwargs)
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')
super().clean()
raise ValidationError(error_message)
if self.part_1 == self.part_2:
raise ValidationError(_("Part relationship cannot be created between a part and itself"))
# Check for inverse relationship
if PartRelated.objects.filter(part_1=self.part_2, part_2=self.part_1).exists():
raise ValidationError(_("Duplicate relationship already exists"))