mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-17 12:35:46 +00:00
Notification on new orders (#3145)
* Trigger a notification when a new SalesOrder is created - Notify the "responsible" owners (excluding the creator) - Add unit test for new notification * Adds notification when a new PurchaseOrder is created * Add notification when a new build order is created - Includes unit tests * Refactor order notification code - Adds a "exclude users" option for sending notifications * Fixes for notification refactoring * make notification a helper * reduce statements togehter * make reuse easier * Add docs * Make context variables clearer * fix assertation * Fix set notation Co-authored-by: Matthias <code@mjmair.com>
This commit is contained in:
@ -30,7 +30,8 @@ import InvenTree.ready
|
||||
from common.settings import currency_code_default
|
||||
from company.models import Company, SupplierPart
|
||||
from InvenTree.fields import InvenTreeModelMoneyField, RoundingDecimalField
|
||||
from InvenTree.helpers import decimal2string, getSetting, increment
|
||||
from InvenTree.helpers import (decimal2string, getSetting, increment,
|
||||
notify_responsible)
|
||||
from InvenTree.models import InvenTreeAttachment, ReferenceIndexingMixin
|
||||
from InvenTree.status_codes import (PurchaseOrderStatus, SalesOrderStatus,
|
||||
StockHistoryCode, StockStatus)
|
||||
@ -574,6 +575,17 @@ class PurchaseOrder(Order):
|
||||
self.complete_order() # This will save the model
|
||||
|
||||
|
||||
@receiver(post_save, sender=PurchaseOrder, dispatch_uid='purchase_order_post_save')
|
||||
def after_save_purchase_order(sender, instance: PurchaseOrder, created: bool, **kwargs):
|
||||
"""Callback function to be executed after a PurchaseOrder is saved."""
|
||||
if not InvenTree.ready.canAppAccessDatabase(allow_test=True) or InvenTree.ready.isImportingData():
|
||||
return
|
||||
|
||||
if created:
|
||||
# Notify the responsible users that the purchase order has been created
|
||||
notify_responsible(instance, sender, exclude=instance.created_by)
|
||||
|
||||
|
||||
class SalesOrder(Order):
|
||||
"""A SalesOrder represents a list of goods shipped outwards to a customer.
|
||||
|
||||
@ -839,29 +851,29 @@ class SalesOrder(Order):
|
||||
return self.pending_shipments().count()
|
||||
|
||||
|
||||
@receiver(post_save, sender=SalesOrder, dispatch_uid='build_post_save_log')
|
||||
@receiver(post_save, sender=SalesOrder, dispatch_uid='sales_order_post_save')
|
||||
def after_save_sales_order(sender, instance: SalesOrder, created: bool, **kwargs):
|
||||
"""Callback function to be executed after a SalesOrder instance is saved.
|
||||
"""Callback function to be executed after a SalesOrder is saved.
|
||||
|
||||
- If the SALESORDER_DEFAULT_SHIPMENT setting is enabled, create a default shipment
|
||||
- Ignore if the database is not ready for access
|
||||
- Ignore if data import is active
|
||||
"""
|
||||
|
||||
if not InvenTree.ready.canAppAccessDatabase(allow_test=True):
|
||||
if not InvenTree.ready.canAppAccessDatabase(allow_test=True) or InvenTree.ready.isImportingData():
|
||||
return
|
||||
|
||||
if InvenTree.ready.isImportingData():
|
||||
return
|
||||
|
||||
if created and getSetting('SALESORDER_DEFAULT_SHIPMENT'):
|
||||
if created:
|
||||
# A new SalesOrder has just been created
|
||||
|
||||
# Create default shipment
|
||||
SalesOrderShipment.objects.create(
|
||||
order=instance,
|
||||
reference='1',
|
||||
)
|
||||
if getSetting('SALESORDER_DEFAULT_SHIPMENT'):
|
||||
# Create default shipment
|
||||
SalesOrderShipment.objects.create(
|
||||
order=instance,
|
||||
reference='1',
|
||||
)
|
||||
|
||||
# Notify the responsible users that the sales order has been created
|
||||
notify_responsible(instance, sender, exclude=instance.created_by)
|
||||
|
||||
|
||||
class PurchaseOrderAttachment(InvenTreeAttachment):
|
||||
|
@ -260,3 +260,27 @@ class SalesOrderTest(TestCase):
|
||||
)
|
||||
|
||||
self.assertEqual(len(messages), 2)
|
||||
|
||||
def test_new_so_notification(self):
|
||||
"""Test that a notification is sent when a new SalesOrder is created.
|
||||
|
||||
- The responsible user should receive a notification
|
||||
- The creating user should *not* receive a notification
|
||||
"""
|
||||
|
||||
SalesOrder.objects.create(
|
||||
customer=self.customer,
|
||||
reference='1234567',
|
||||
created_by=get_user_model().objects.get(pk=3),
|
||||
responsible=Owner.create(obj=Group.objects.get(pk=3))
|
||||
)
|
||||
|
||||
messages = NotificationMessage.objects.filter(
|
||||
category='order.new_salesorder',
|
||||
)
|
||||
|
||||
# A notification should have been generated for user 4 (who is a member of group 3)
|
||||
self.assertTrue(messages.filter(user__pk=4).exists())
|
||||
|
||||
# However *no* notification should have been generated for the creating user
|
||||
self.assertFalse(messages.filter(user__pk=3).exists())
|
||||
|
@ -9,7 +9,7 @@ from django.test import TestCase
|
||||
|
||||
import common.models
|
||||
import order.tasks
|
||||
from company.models import SupplierPart
|
||||
from company.models import Company, SupplierPart
|
||||
from InvenTree.status_codes import PurchaseOrderStatus
|
||||
from part.models import Part
|
||||
from stock.models import StockLocation
|
||||
@ -237,3 +237,29 @@ class OrderTest(TestCase):
|
||||
|
||||
self.assertEqual(msg.target_object_id, 1)
|
||||
self.assertEqual(msg.name, 'Overdue Purchase Order')
|
||||
|
||||
def test_new_po_notification(self):
|
||||
"""Test that a notification is sent when a new PurchaseOrder is created
|
||||
|
||||
- The responsible user(s) should receive a notification
|
||||
- The creating user should *not* receive a notification
|
||||
"""
|
||||
|
||||
PurchaseOrder.objects.create(
|
||||
supplier=Company.objects.get(pk=1),
|
||||
reference='XYZABC',
|
||||
created_by=get_user_model().objects.get(pk=3),
|
||||
responsible=Owner.create(obj=get_user_model().objects.get(pk=4)),
|
||||
)
|
||||
|
||||
messages = common.models.NotificationMessage.objects.filter(
|
||||
category='order.new_purchaseorder',
|
||||
)
|
||||
|
||||
self.assertEqual(messages.count(), 1)
|
||||
|
||||
# A notification should have been generated for user 4 (who is a member of group 3)
|
||||
self.assertTrue(messages.filter(user__pk=4).exists())
|
||||
|
||||
# However *no* notification should have been generated for the creating user
|
||||
self.assertFalse(messages.filter(user__pk=3).exists())
|
||||
|
Reference in New Issue
Block a user