From 82840b05902ed9982f213d91f0049309161b195d Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 10 Mar 2022 15:01:20 +1100 Subject: [PATCH] Adds custom delete routine for PartCategory model --- InvenTree/part/models.py | 52 ++++++++++++++++++++++----------------- InvenTree/stock/models.py | 2 +- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index fc09dcd042..d9788f5fd9 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -20,7 +20,7 @@ from django.db.models.functions import Coalesce from django.core.validators import MinValueValidator from django.contrib.auth.models import User -from django.db.models.signals import pre_delete, post_save +from django.db.models.signals import post_save from django.dispatch import receiver from jinja2 import Template @@ -76,6 +76,35 @@ class PartCategory(InvenTreeTree): default_keywords: Default keywords for parts created in this category """ + def delete(self, *args, **kwargs): + """ + Custom model deletion routine, which updates any child categories or parts. + This must be handled within a transaction.atomic(), otherwise the tree structure is damaged + """ + + with transaction.atomic(): + + parent = self.parent + tree_id = self.tree_id + + # Update each part in this category to point to the parent category + for part in self.parts.all(): + part.category = self.parent + part.save() + + # Update each child category + for child in self.children.all(): + child.parent = self.parent + child.save() + + super().delete(*args, **kwargs) + + if parent is not None: + # Partially rebuild the tree (cheaper than a complete rebuild) + PartCategory.objects.partial_rebuild(tree_id) + else: + PartCategory.objects.rebuild() + default_location = TreeForeignKey( 'stock.StockLocation', related_name="default_categories", null=True, blank=True, @@ -260,27 +289,6 @@ class PartCategory(InvenTreeTree): ).delete() -@receiver(pre_delete, sender=PartCategory, dispatch_uid='partcategory_delete_log') -def before_delete_part_category(sender, instance, using, **kwargs): - """ Receives before_delete signal for PartCategory object - - Before deleting, update child Part and PartCategory objects: - - - For each child category, set the parent to the parent of *this* category - - For each part, set the 'category' to the parent of *this* category - """ - - # Update each part in this category to point to the parent category - for part in instance.parts.all(): - part.category = instance.parent - part.save() - - # Update each child category - for child in instance.children.all(): - child.parent = instance.parent - child.save() - - def rename_part_image(instance, filename): """ Function for renaming a part image file diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 1fa0dd1f5b..171ee7e0a3 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -65,7 +65,7 @@ class StockLocation(InvenTreeTree): parent = self.parent tree_id = self.tree_id - # Update each part in the stock location + # Update each stock item in the stock location for item in self.stock_items.all(): item.location = self.parent item.save()