details:   https://code.tryton.org/tryton/commit/0e3f9c26b751
branch:    default
user:      Cédric Krier <[email protected]>
date:      Wed Mar 11 10:01:51 2026 +0100
description:
        Add notify_user to ModelStorage

        Closes #14667
diffstat:

 trytond/CHANGELOG                          |   1 +
 trytond/doc/ref/models.rst                 |   5 +++++
 trytond/doc/ref/transaction.rst            |   2 ++
 trytond/trytond/model/modelstorage.py      |  20 ++++++++++++++++++++
 trytond/trytond/res/notification.py        |   2 +-
 trytond/trytond/tests/test_modelstorage.py |  24 ++++++++++++++++++++++++
 trytond/trytond/transaction.py             |  18 ++++++++++++++++++
 7 files changed, 71 insertions(+), 1 deletions(-)

diffs (181 lines):

diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/CHANGELOG
--- a/trytond/CHANGELOG Wed Mar 11 10:01:22 2026 +0100
+++ b/trytond/CHANGELOG Wed Mar 11 10:01:51 2026 +0100
@@ -1,3 +1,4 @@
+* Add notify_user to ModelStorage
 * Check button states when testing access
 * Remove the files of Binary fields from the Filestore
 * Add delete and delete_many to Filestore
diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/doc/ref/models.rst
--- a/trytond/doc/ref/models.rst        Wed Mar 11 10:01:22 2026 +0100
+++ b/trytond/doc/ref/models.rst        Wed Mar 11 10:01:51 2026 +0100
@@ -356,6 +356,11 @@
 
    Log event for records.
 
+
+.. classmethod:: ModelStorage.notify_user(records, icon, label[, description[, 
user[, \**extra]]])
+
+   Notify user about records.
+
 .. classmethod:: ModelStorage.preprocess_values(cls, mode, values)
 
    Returns a copy of ``values`` to be used for :meth:`~ModelStorage.create` and
diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/doc/ref/transaction.rst
--- a/trytond/doc/ref/transaction.rst   Wed Mar 11 10:01:22 2026 +0100
+++ b/trytond/doc/ref/transaction.rst   Wed Mar 11 10:01:51 2026 +0100
@@ -54,6 +54,8 @@
 
 .. attribute:: Transaction.log_records
 
+.. attribute:: Transaction.user_notifications
+
 .. attribute:: Transaction.check_warnings
 
     The dictionary of warnings already checked with user and warning
diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/trytond/model/modelstorage.py
--- a/trytond/trytond/model/modelstorage.py     Wed Mar 11 10:01:22 2026 +0100
+++ b/trytond/trytond/model/modelstorage.py     Wed Mar 11 10:01:51 2026 +0100
@@ -5,6 +5,7 @@
 import csv
 import datetime
 import decimal
+import json
 import math
 import random
 import time
@@ -245,6 +246,25 @@
                             resource=record, event=event, target=target,
                             user=user, **extra))
 
+    @dualmethod
+    def notify_user(
+            cls, records, icon, label, description=None, user=None, **extra):
+        pool = Pool()
+        Notification = pool.get('res.notification')
+        for transaction, sub_records in groupby(
+                records, lambda r: r._transaction):
+            with Transaction().set_current_transaction(transaction):
+                if user is None:
+                    user = transaction.user
+                transaction.user_notifications.append(Notification(
+                        user=user,
+                        icon=icon,
+                        label=label,
+                        description=description,
+                        model=cls.__name__,
+                        records=json.dumps([r.id for r in records]),
+                        **extra))
+
     @classmethod
     def preprocess_values(cls, mode, values):
         assert mode in {'create', 'write'}
diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/trytond/res/notification.py
--- a/trytond/trytond/res/notification.py       Wed Mar 11 10:01:22 2026 +0100
+++ b/trytond/trytond/res/notification.py       Wed Mar 11 10:01:51 2026 +0100
@@ -54,7 +54,7 @@
     @classmethod
     def __setup__(cls):
         super().__setup__()
-
+        cls._order = [('id', 'DESC')]
         cls.__rpc__.update({
                 'get': RPC(),
                 'get_count': RPC(),
diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/trytond/tests/test_modelstorage.py
--- a/trytond/trytond/tests/test_modelstorage.py        Wed Mar 11 10:01:22 
2026 +0100
+++ b/trytond/trytond/tests/test_modelstorage.py        Wed Mar 11 10:01:51 
2026 +0100
@@ -743,6 +743,30 @@
 
         Model.delete([record])
 
+    @with_transaction()
+    def test_notify_user(self):
+        "Test notify user"
+        pool = Pool()
+        Model = pool.get('test.modelstorage')
+        Notification = pool.get('res.notification')
+        transaction = Transaction()
+
+        record = Model(name="Foo")
+        record.save()
+
+        record.notify_user(
+            'tryton-notification',
+            "Test notification",
+            "Long description")
+        transaction._store_user_notifications()
+
+        notification, = Notification.search([])
+
+        self.assertEqual(notification.user.id, transaction.user)
+        self.assertEqual(notification.icon, 'tryton-notification')
+        self.assertEqual(notification.label, "Test notification")
+        self.assertEqual(notification.description, "Long description")
+
 
 class EvalEnvironmentTestCase(TestCase):
     "Test EvalEnvironment"
diff -r db7cbffa9536 -r 0e3f9c26b751 trytond/trytond/transaction.py
--- a/trytond/trytond/transaction.py    Wed Mar 11 10:01:22 2026 +0100
+++ b/trytond/trytond/transaction.py    Wed Mar 11 10:01:51 2026 +0100
@@ -130,6 +130,7 @@
             instance.delete_records = None
             instance.trigger_records = None
             instance.log_records = None
+            instance.user_notifications = None
             instance.check_warnings = None
             instance.timestamp = None
             instance.started_at = None
@@ -198,6 +199,7 @@
             self.delete_records = defaultdict(set)
             self.trigger_records = defaultdict(set)
             self.log_records = []
+            self.user_notifications = []
             self.check_warnings = defaultdict(set)
             self.timestamp = {}
             self.counter = 0
@@ -265,6 +267,7 @@
                     self.delete_records = None
                     self.trigger_records = None
                     self.log_records = None
+                    self.user_notifications = None
                     self.timestamp = None
                     self._datamanagers = []
 
@@ -340,6 +343,19 @@
         if self.log_records:
             self.log_records.clear()
 
+    def _store_user_notifications(self):
+        from trytond.pool import Pool
+        if self.user_notifications:
+            pool = Pool()
+            Notification = pool.get('res.notification')
+            with without_check_access():
+                Notification.save(self.user_notifications)
+        self._clear_user_notifications()
+
+    def _clear_user_notifications(self):
+        if self.user_notifications:
+            self.user_notifications.clear()
+
     def _remove_warnings(self):
         from trytond.pool import Pool
         if self.check_warnings:
@@ -358,6 +374,7 @@
         from trytond.cache import Cache
         try:
             self._store_log_records()
+            self._store_user_notifications()
             self._remove_warnings()
             if self._datamanagers:
                 for datamanager in self._datamanagers:
@@ -391,6 +408,7 @@
             datamanager.tpc_abort(self)
         Cache.rollback(self)
         self._clear_log_records()
+        self._clear_user_notifications()
         self._clear_warnings()
         if self.connection:
             self.connection.rollback()

Reply via email to