mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	Simplify event triggering
- add generic receivers for database actions - exclude django_q tables, otherwise we get an infinite loop! Ref: https://stackoverflow.com/questions/17507784/consolidating-multiple-post-save-signals-with-one-receiver/32230933#32230933
This commit is contained in:
		| @@ -1067,11 +1067,6 @@ def after_save_build(sender, instance: Build, created: bool, **kwargs): | |||||||
|         # Run checks on required parts |         # Run checks on required parts | ||||||
|         InvenTree.tasks.offload_task('build.tasks.check_build_stock', instance) |         InvenTree.tasks.offload_task('build.tasks.check_build_stock', instance) | ||||||
|  |  | ||||||
|         trigger_event('build.created', build_id=instance.pk) |  | ||||||
|  |  | ||||||
|     else: |  | ||||||
|         trigger_event('build.saved', build_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class BuildOrderAttachment(InvenTreeAttachment): | class BuildOrderAttachment(InvenTreeAttachment): | ||||||
|     """ |     """ | ||||||
|   | |||||||
| @@ -271,15 +271,6 @@ class Company(models.Model): | |||||||
|         return self.purchase_orders.filter(status__in=PurchaseOrderStatus.FAILED) |         return self.purchase_orders.filter(status__in=PurchaseOrderStatus.FAILED) | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=Company, dispatch_uid='company_post_save_log') |  | ||||||
| def after_save_company(sender, instance: Company, created: bool, **kwargs): |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('company.created', company_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('company.saved', company_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Contact(models.Model): | class Contact(models.Model): | ||||||
|     """ A Contact represents a person who works at a particular company. |     """ A Contact represents a person who works at a particular company. | ||||||
|     A Company may have zero or more associated Contact objects. |     A Company may have zero or more associated Contact objects. | ||||||
| @@ -399,15 +390,6 @@ class ManufacturerPart(models.Model): | |||||||
|         return s |         return s | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=ManufacturerPart, dispatch_uid='manufacturerpart_post_save_log') |  | ||||||
| def after_save_manufacturer_part(sender, instance: ManufacturerPart, created: bool, **kwargs): |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('manufacturerpart.created', manufacturer_part_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('manufacturerpart.saved', manufacturer_part_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ManufacturerPartParameter(models.Model): | class ManufacturerPartParameter(models.Model): | ||||||
|     """ |     """ | ||||||
|     A ManufacturerPartParameter represents a key:value parameter for a MnaufacturerPart. |     A ManufacturerPartParameter represents a key:value parameter for a MnaufacturerPart. | ||||||
| @@ -708,15 +690,6 @@ class SupplierPart(models.Model): | |||||||
|         return s |         return s | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=SupplierPart, dispatch_uid='supplierpart_post_save_log') |  | ||||||
| def after_save_supplier_part(sender, instance: SupplierPart, created: bool, **kwargs): |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('supplierpart.created', supplier_part_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('supplierpart.saved', supplier_part_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPriceBreak(common.models.PriceBreak): | class SupplierPriceBreak(common.models.PriceBreak): | ||||||
|     """ Represents a quantity price break for a SupplierPart. |     """ Represents a quantity price break for a SupplierPart. | ||||||
|     - Suppliers can offer discounts at larger quantities |     - Suppliers can offer discounts at larger quantities | ||||||
|   | |||||||
| @@ -470,15 +470,6 @@ class PurchaseOrder(Order): | |||||||
|             self.complete_order()  # This will save the model |             self.complete_order()  # This will save the model | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=PurchaseOrder, dispatch_uid='po_post_save_log') |  | ||||||
| def after_save_po(sender, instance: PurchaseOrder, created: bool, **kwargs): |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('purchaseorder.created', order_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('purchasesorder.saved', order_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrder(Order): | class SalesOrder(Order): | ||||||
|     """ |     """ | ||||||
|     A SalesOrder represents a list of goods shipped outwards to a customer. |     A SalesOrder represents a list of goods shipped outwards to a customer. | ||||||
| @@ -772,15 +763,6 @@ class SalesOrder(Order): | |||||||
|         return self.pending_shipments().count() |         return self.pending_shipments().count() | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=SalesOrder, dispatch_uid='so_post_save_log') |  | ||||||
| def after_save_so(sender, instance: SalesOrder, created: bool, **kwargs): |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('salesorder.created', order_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('salesorder.saved', order_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderAttachment(InvenTreeAttachment): | class PurchaseOrderAttachment(InvenTreeAttachment): | ||||||
|     """ |     """ | ||||||
|     Model for storing file attachments against a PurchaseOrder object |     Model for storing file attachments against a PurchaseOrder object | ||||||
|   | |||||||
| @@ -280,8 +280,6 @@ def before_delete_part_category(sender, instance, using, **kwargs): | |||||||
|         child.parent = instance.parent |         child.parent = instance.parent | ||||||
|         child.save() |         child.save() | ||||||
|  |  | ||||||
|     trigger_event('category.deleted') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def rename_part_image(instance, filename): | def rename_part_image(instance, filename): | ||||||
|     """ Function for renaming a part image file |     """ Function for renaming a part image file | ||||||
| @@ -2186,10 +2184,8 @@ def after_save_part(sender, instance: Part, created, **kwargs): | |||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     if created: |     if created: | ||||||
|         trigger_event('part.created', part_id=instance.pk) |         pass | ||||||
|     else: |     else: | ||||||
|         trigger_event('part.saved', part_id=instance.pk) |  | ||||||
|  |  | ||||||
|         # Check part stock only if we are *updating* the part (not creating it) |         # Check part stock only if we are *updating* the part (not creating it) | ||||||
|  |  | ||||||
|         # Run this check in the background |         # Run this check in the background | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ import logging | |||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.db import transaction | from django.db import transaction | ||||||
|  | from django.db.models.signals import post_save, post_delete | ||||||
|  | from django.dispatch.dispatcher import receiver | ||||||
|  |  | ||||||
| from common.models import InvenTreeSetting | from common.models import InvenTreeSetting | ||||||
|  |  | ||||||
| @@ -87,3 +89,54 @@ def process_event(plugin_slug, event, *args, **kwargs): | |||||||
|     plugin = plugin_registry.plugins[plugin_slug] |     plugin = plugin_registry.plugins[plugin_slug] | ||||||
|  |  | ||||||
|     plugin.process_event(event, *args, **kwargs) |     plugin.process_event(event, *args, **kwargs) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | Register some default event triggers on model signals | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | @receiver(post_save) | ||||||
|  | def after_save(sender, instance, created, **kwargs): | ||||||
|  |     """ | ||||||
|  |     Trigger an event whenever a database entry is saved | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     table = sender.objects.model._meta.db_table | ||||||
|  |  | ||||||
|  |     if table.startswith('django_q'): | ||||||
|  |         # Ignore django_q tables, to avoid recursion | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |     if created: | ||||||
|  |         trigger_event( | ||||||
|  |             'instance.created', | ||||||
|  |             id=instance.id, | ||||||
|  |             model=sender.__name__, | ||||||
|  |             table=table, | ||||||
|  |         ) | ||||||
|  |     else: | ||||||
|  |         trigger_event( | ||||||
|  |             'instance.saved', | ||||||
|  |             id=instance.id, | ||||||
|  |             model=sender.__name__, | ||||||
|  |             table=table, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @receiver(post_delete) | ||||||
|  | def after_delete(sender, instance, **kwargs): | ||||||
|  |     """ | ||||||
|  |     Trigger an event whenever a database entry is deleted | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     table = sender.objects.model._meta.db_table | ||||||
|  |  | ||||||
|  |     if table.startswith('django_q'): | ||||||
|  |         # Ignore django_q tables, to avoid recursion | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |     trigger_event( | ||||||
|  |         'instance.deleted', | ||||||
|  |         model=sender.__name__, | ||||||
|  |         table=table, | ||||||
|  |     ) | ||||||
|   | |||||||
| @@ -135,20 +135,6 @@ def before_delete_stock_location(sender, instance, using, **kwargs): | |||||||
|         child.parent = instance.parent |         child.parent = instance.parent | ||||||
|         child.save() |         child.save() | ||||||
|  |  | ||||||
|     trigger_event('location.deleted') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=StockLocation, dispatch_uid='stock_location_post_save_log') |  | ||||||
| def after_save_stock_location(sender, instance: StockLocation, created, **kwargs): |  | ||||||
|     """ |  | ||||||
|     Hook function to be executed after StockLocation object is saved/updated |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('stocklocation.created', location_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('stocklocation.saved', location_id=instance.pk) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class StockItemManager(TreeManager): | class StockItemManager(TreeManager): | ||||||
|     """ |     """ | ||||||
| @@ -1801,8 +1787,6 @@ def before_delete_stock_item(sender, instance, using, **kwargs): | |||||||
|         child.parent = instance.parent |         child.parent = instance.parent | ||||||
|         child.save() |         child.save() | ||||||
|  |  | ||||||
|     trigger_event('stockitem.deleted') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_delete, sender=StockItem, dispatch_uid='stock_item_post_delete_log') | @receiver(post_delete, sender=StockItem, dispatch_uid='stock_item_post_delete_log') | ||||||
| def after_delete_stock_item(sender, instance: StockItem, **kwargs): | def after_delete_stock_item(sender, instance: StockItem, **kwargs): | ||||||
| @@ -1820,11 +1804,6 @@ def after_save_stock_item(sender, instance: StockItem, created, **kwargs): | |||||||
|     Hook function to be executed after StockItem object is saved/updated |     Hook function to be executed after StockItem object is saved/updated | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('stockitem.created', item_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('stockitem.saved', item_id=instance.pk) |  | ||||||
|  |  | ||||||
|     # Run this check in the background |     # Run this check in the background | ||||||
|     InvenTree.tasks.offload_task('part.tasks.notify_low_stock_if_required', instance.part) |     InvenTree.tasks.offload_task('part.tasks.notify_low_stock_if_required', instance.part) | ||||||
|  |  | ||||||
| @@ -2018,12 +1997,3 @@ class StockItemTestResult(models.Model): | |||||||
|         auto_now_add=True, |         auto_now_add=True, | ||||||
|         editable=False |         editable=False | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(post_save, sender=StockItemTestResult, dispatch_uid='stock_item_test_result_post_save_log') |  | ||||||
| def after_save_test_result(sender, instance: StockItemTestResult, created: bool, **kwargs): |  | ||||||
|  |  | ||||||
|     if created: |  | ||||||
|         trigger_event('stockitemtestresult.created', test_id=instance.pk) |  | ||||||
|     else: |  | ||||||
|         trigger_event('stockitemtestresult.saved', test_id=instance.pk) |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user