From 886b1f1d726524c4a09d5a7a30cb527db3a58502 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 10 Jan 2022 17:24:53 +1100 Subject: [PATCH] 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 --- InvenTree/build/models.py | 5 ---- InvenTree/company/models.py | 27 ------------------- InvenTree/order/models.py | 18 ------------- InvenTree/part/models.py | 6 +---- InvenTree/plugin/events.py | 53 +++++++++++++++++++++++++++++++++++++ InvenTree/stock/models.py | 30 --------------------- 6 files changed, 54 insertions(+), 85 deletions(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index fb506d5ec9..b2a7e1de16 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -1067,11 +1067,6 @@ def after_save_build(sender, instance: Build, created: bool, **kwargs): # Run checks on required parts 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): """ diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 3c90ef6e2d..815c840dac 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -271,15 +271,6 @@ class Company(models.Model): 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): """ A Contact represents a person who works at a particular company. A Company may have zero or more associated Contact objects. @@ -399,15 +390,6 @@ class ManufacturerPart(models.Model): 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): """ A ManufacturerPartParameter represents a key:value parameter for a MnaufacturerPart. @@ -708,15 +690,6 @@ class SupplierPart(models.Model): 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): """ Represents a quantity price break for a SupplierPart. - Suppliers can offer discounts at larger quantities diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 5fad9ea692..d437de1685 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -470,15 +470,6 @@ class PurchaseOrder(Order): 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): """ A SalesOrder represents a list of goods shipped outwards to a customer. @@ -772,15 +763,6 @@ class SalesOrder(Order): 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): """ Model for storing file attachments against a PurchaseOrder object diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 76aa160804..124140b5bd 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -280,8 +280,6 @@ def before_delete_part_category(sender, instance, using, **kwargs): child.parent = instance.parent child.save() - trigger_event('category.deleted') - def rename_part_image(instance, filename): """ Function for renaming a part image file @@ -2186,10 +2184,8 @@ def after_save_part(sender, instance: Part, created, **kwargs): """ if created: - trigger_event('part.created', part_id=instance.pk) + pass else: - trigger_event('part.saved', part_id=instance.pk) - # Check part stock only if we are *updating* the part (not creating it) # Run this check in the background diff --git a/InvenTree/plugin/events.py b/InvenTree/plugin/events.py index 1020c5ac4d..3c7211f95b 100644 --- a/InvenTree/plugin/events.py +++ b/InvenTree/plugin/events.py @@ -9,6 +9,8 @@ import logging from django.conf import settings 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 @@ -87,3 +89,54 @@ def process_event(plugin_slug, event, *args, **kwargs): plugin = plugin_registry.plugins[plugin_slug] 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, + ) diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index b2d09c3de8..f4d2471519 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -135,20 +135,6 @@ def before_delete_stock_location(sender, instance, using, **kwargs): child.parent = instance.parent 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): """ @@ -1801,8 +1787,6 @@ def before_delete_stock_item(sender, instance, using, **kwargs): child.parent = instance.parent child.save() - trigger_event('stockitem.deleted') - @receiver(post_delete, sender=StockItem, dispatch_uid='stock_item_post_delete_log') 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 """ - 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 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, 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)