From 94051b9812f444add364621a117cd74ec68ad2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 13 Mar 2012 13:23:51 +0100 Subject: [PATCH 01/11] [ADD] base_needaction file, holding the base.needaction mixin class. bzr revid: tde@openerp.com-20120313122351-fw8e4gk3zuhaqr18 --- openerp/addons/base/base_needaction.py | 67 ++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 openerp/addons/base/base_needaction.py diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py new file mode 100644 index 00000000000..b9dd9c65826 --- /dev/null +++ b/openerp/addons/base/base_needaction.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2009-Today OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## + +from osv import osv, fields +from tools.translate import _ + +class base_needaction(osv.osv): + '''Mixin class for object implementing the need action mechanism. + + Need action mechanism can be used by objects that have to be able to + signal that an action is required on a particular record. If in the + business logic an action must be performed by somebody, for instance + validation by a manager, this mechanism allows to set a field with + the user_id of the user requested to perform the action. + + Technically, this class adds a need_action_user_id field; when + set to false, no action is required; when an user_id is set, + this user has an action to perform. This field is a function field. + Setting an user_id is done through redefining the get_needaction_user_id method. + Therefore by redefining only one method, you can specify + the cases in which an action will be required on a particular record. + + This mechanism is used for instance to display the number of pending actions + in menus, such as Leads (12). + ''' + _name = 'base.needaction' + _description = 'Need action mechanism' + + def get_needaction_user_id(self, cr, uid, ids, name, arg, context=None): + if context is None: + context = {} + result = {} + for id in ids: + result[id] = False + return result + + ''' Wrapper: in 6.1 the reference to a method is given to a function + field, not the function name. Inheritance is therefore not directly + possible.''' + def get_needaction_user_id_wrapper(self, cr, uid, ids, name, arg, context=None): + return self.get_needaction_user_id(cr, uid, ids, name, arg, context=context) + + _columns = { + 'need_action_user_id': fields.function(get_needaction_user_id_wrapper, + type='many2one', relation='res.users', store=True, + select=1, string='User'), + } + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 059cc5bef3a4eb60768be9f9a750a468b87d57a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 13 Mar 2012 13:29:39 +0100 Subject: [PATCH 02/11] [ADD] Added documentation for merge proposal, related to the need_action mixin class. bzr revid: tde@openerp.com-20120313122939-239ae3ftask1rrmb --- doc/api/need_action_specs.rst | 8 ++++++++ doc/index.rst.inc | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 doc/api/need_action_specs.rst diff --git a/doc/api/need_action_specs.rst b/doc/api/need_action_specs.rst new file mode 100644 index 00000000000..5d5d94cf903 --- /dev/null +++ b/doc/api/need_action_specs.rst @@ -0,0 +1,8 @@ +Need action mixin class +======================= + +This revision adds a mixin class for object implementing the need action mechanism. Need action mechanism can be used by objects that have to be able to signal that an action is required on a particular record. If in the business logic an action must be performed by somebody, for instance validation by a manager, this mechanism allows to set a field with the user_id of the user requested to perform the action. + +Technically, this class adds a need_action_user_id field; when set to false, no action is required; when an user_id is set, this user has an action to perform. This field is a function field. Setting an user_id is done through redefining the get_needaction_user_id method. Therefore by redefining only one method, you can specify the cases in which an action will be required on a particular record. + +This mechanism is used for instance to display the number of pending actions in menus, such as Leads (12). diff --git a/doc/index.rst.inc b/doc/index.rst.inc index 05c4a53640b..f6c4f6dbf20 100644 --- a/doc/index.rst.inc +++ b/doc/index.rst.inc @@ -6,3 +6,11 @@ OpenERP Server :maxdepth: 1 test-framework + +New feature merges +++++++++++++++++++ + +.. toctree:: + :maxdepth: 1 + + api/need_action_specs From dbd4f6dfcee98442b41fe53d10f303cc73daadd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 13 Mar 2012 16:53:39 +0100 Subject: [PATCH 03/11] [FIX] Added base_needaction import bzr revid: tde@openerp.com-20120313155339-eqifoe0celu5n43b --- openerp/addons/base/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openerp/addons/base/__init__.py b/openerp/addons/base/__init__.py index 16a61521fb4..af551e60c1e 100644 --- a/openerp/addons/base/__init__.py +++ b/openerp/addons/base/__init__.py @@ -25,6 +25,7 @@ import res import publisher_warranty import report import test +import base_needaction # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 5ef1483f933d18fe5af55ed2ff6bda9872a7b15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 13 Mar 2012 16:54:25 +0100 Subject: [PATCH 04/11] [IMP] base.needaction: clened code bzr revid: tde@openerp.com-20120313155425-vkmzmobas76re0x4 --- openerp/addons/base/base_needaction.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index b9dd9c65826..eb953125cd4 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -45,11 +45,7 @@ class base_needaction(osv.osv): _description = 'Need action mechanism' def get_needaction_user_id(self, cr, uid, ids, name, arg, context=None): - if context is None: - context = {} - result = {} - for id in ids: - result[id] = False + result = dict.fromkeys[ids, False] return result ''' Wrapper: in 6.1 the reference to a method is given to a function From bf3d2cd284a2f2f7309bc14ff2945c03c237af40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 14 Mar 2012 15:26:05 +0100 Subject: [PATCH 05/11] [REF] Refactored base_needaction class. bzr revid: tde@openerp.com-20120314142605-hhii6p976zrdwmw3 --- openerp/addons/base/base_needaction.py | 108 ++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 11 deletions(-) diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index eb953125cd4..20f32c947c2 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -22,6 +22,29 @@ from osv import osv, fields from tools.translate import _ +class base_needaction_users_rel(osv.osv): + ''' + base_needaction_users_rel holds the data related to the needaction + mechanism inside OpenERP. A needaction is characterized by: + - res_model: model of the followed objects + - res_id: ID of resource + - user_id: foreign key to the res.users table, to the user that + has to perform an action + ''' + + _name = 'base.needaction_users_rel' + _rec_name = 'id' + _order = 'res_model asc' + _columns = { + 'res_model': fields.char('Related Document Model', size=128, + select=1, required=True), + 'res_id': fields.integer('Related Document ID', + select=1, required=True), + 'user_id': fields.many2one('res.users', string='Related User ID', + ondelete='cascade', select=1, required=True), + } + + class base_needaction(osv.osv): '''Mixin class for object implementing the need action mechanism. @@ -44,20 +67,83 @@ class base_needaction(osv.osv): _name = 'base.needaction' _description = 'Need action mechanism' - def get_needaction_user_id(self, cr, uid, ids, name, arg, context=None): - result = dict.fromkeys[ids, False] - return result + #------------------------------------------------------ + # base_needaction_users_rel API + #------------------------------------------------------ + + def needaction_create(self, cr, uid, ids, user_ids, context=None): + if context is None: + context = {} + needact_rel_obj = self.pool.get('base.needaction_users_rel') + for id in ids: + for user_id in user_ids: + needact_rel_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context) + return True + + def needaction_unlink_users(self, cr, uid, ids, context=None): + if context is None: + context = {} + needact_rel_obj = self.pool.get('base.needaction_users_rel') + to_del_ids = needact_rel_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) + return needact_rel_obj.unlink(cr, uid, to_del_ids, context=context) + + def needaction_write_users(self, cr, uid, ids, user_ids, context=None): + if context is None: + context = {} + # unlink old records + self.needaction_unlink_users(cr, uid, ids, context=context) + # link new records + for res_id in ids: + self.needaction_create(cr, uid, ids, user_ids, context=context) + return True + + #------------------------------------------------------ + # Addon API + #------------------------------------------------------ - ''' Wrapper: in 6.1 the reference to a method is given to a function - field, not the function name. Inheritance is therefore not directly - possible.''' - def get_needaction_user_id_wrapper(self, cr, uid, ids, name, arg, context=None): - return self.get_needaction_user_id(cr, uid, ids, name, arg, context=context) + def get_needaction_user_ids(self, cr, uid, ids, context=None): + needact_rel_obj = self.pool.get('base.needaction_users_rel') + needact_rel_ids = needact_rel_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) + needact_rel_objs = needact_rel_obj.read(cr, uid, needact_rel_ids, ['user_id'], context=context) + return [needact_rel_obj['user_id'][0] for needact_rel_obj in needact_rel_objs] + + def set_needaction_user_ids(self, cr, uid, ids, context=None): + result = dict.fromkeys(ids, []) + return result + + def write(self, cr, uid, ids, values, context=None): + if context is None: + context = {} + # get and update needaction_user_ids + needaction_user_ids = self.set_needaction_user_ids(cr, uid, ids, context=context) + for id in ids: + self.needaction_write_users(cr, uid, [id], needaction_user_ids[id], context=context) + # perform write + return super(base_needaction, self).write(cr, uid, ids, values, context=context) _columns = { - 'need_action_user_id': fields.function(get_needaction_user_id_wrapper, - type='many2one', relation='res.users', store=True, - select=1, string='User'), } + + + #------------------------------------------------------ + # General API + #------------------------------------------------------ + + def get_user_needaction_ids(self, cr, uid, user_id, offset=0, limit=None, order=None, count=False, context=None): + if context is None: + context = {} + needact_rel_obj = self.pool.get('base.needaction_users_rel') + search_res = needact_rel_obj.search(cr, uid, [('user_id', '=', user_id)], offset=offset, limit=limit, order=order, count=count, context=context) + return search_res + + def get_record_references(self, cr, uid, user_id, offset=0, limit=None, order=None, context=None): + if context is None: + context = {} + needact_rel_obj = self.pool.get('base.needaction_users_rel') + search_res = self.get_user_needaction_ids(cr, uid, user_id, offset=offset, limit=limit, order=order, context=context) + needact_objs = needact_rel_obj.browse(cr, uid, search_res, context=context) + record_references = [(needact_obj.res_model, needact_obj.res_id) for needact_obj in needact_objs] + return record_references + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 0aa3125ce77db964cebd45bd2f7ab740cbabbdd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 14 Mar 2012 18:14:46 +0100 Subject: [PATCH 06/11] [IMP] Cleaned code bzr revid: tde@openerp.com-20120314171446-75rf519voc4hwuw7 --- openerp/addons/base/base_needaction.py | 57 +++++++++++++++----------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index 20f32c947c2..68f8d27b017 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -67,11 +67,14 @@ class base_needaction(osv.osv): _name = 'base.needaction' _description = 'Need action mechanism' + _columns = { + } + #------------------------------------------------------ - # base_needaction_users_rel API + # need action relationship management #------------------------------------------------------ - def needaction_create(self, cr, uid, ids, user_ids, context=None): + def _link_users(self, cr, uid, ids, user_ids, context=None): if context is None: context = {} needact_rel_obj = self.pool.get('base.needaction_users_rel') @@ -80,68 +83,76 @@ class base_needaction(osv.osv): needact_rel_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context) return True - def needaction_unlink_users(self, cr, uid, ids, context=None): + def _unlink_users(self, cr, uid, ids, context=None): if context is None: context = {} needact_rel_obj = self.pool.get('base.needaction_users_rel') to_del_ids = needact_rel_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) return needact_rel_obj.unlink(cr, uid, to_del_ids, context=context) - def needaction_write_users(self, cr, uid, ids, user_ids, context=None): + def _update_users(self, cr, uid, ids, user_ids, context=None): if context is None: context = {} # unlink old records - self.needaction_unlink_users(cr, uid, ids, context=context) + self._unlink_users(cr, uid, ids, context=context) # link new records for res_id in ids: - self.needaction_create(cr, uid, ids, user_ids, context=context) + self._link_users(cr, uid, ids, user_ids, context=context) return True #------------------------------------------------------ # Addon API #------------------------------------------------------ - - def get_needaction_user_ids(self, cr, uid, ids, context=None): - needact_rel_obj = self.pool.get('base.needaction_users_rel') - needact_rel_ids = needact_rel_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) - needact_rel_objs = needact_rel_obj.read(cr, uid, needact_rel_ids, ['user_id'], context=context) - return [needact_rel_obj['user_id'][0] for needact_rel_obj in needact_rel_objs] - def set_needaction_user_ids(self, cr, uid, ids, context=None): + def get_needaction_user_ids(self, cr, uid, ids, context=None): result = dict.fromkeys(ids, []) return result + def create(self, cr, uid, values, context=None): + if context is None: + context = {} + # perform create + obj_id = super(base_needaction, self).create(cr, uid, ids, values, context=context) + # link user_ids + needaction_user_ids = self.get_needaction_user_ids(cr, uid, [obj_id], context=context) + self._update_users(cr, uid, [id], needaction_user_ids[obj_id], context=context) + return obj_id + def write(self, cr, uid, ids, values, context=None): if context is None: context = {} - # get and update needaction_user_ids - needaction_user_ids = self.set_needaction_user_ids(cr, uid, ids, context=context) + # get and update user_ids + needaction_user_ids = self.get_needaction_user_ids(cr, uid, ids, context=context) for id in ids: - self.needaction_write_users(cr, uid, [id], needaction_user_ids[id], context=context) + self._update_users(cr, uid, [id], needaction_user_ids[id], context=context) # perform write return super(base_needaction, self).write(cr, uid, ids, values, context=context) - - _columns = { - } + def unlink(self, cr, uids, ids, context=None): + if context is None: + context = {} + # unlink user_ids + self._unlink_users(cr, uid, ids, context=context) + # perform unlink + return super(base_needaction, self).unlink(cr, uid, ids, values, context=context) #------------------------------------------------------ # General API #------------------------------------------------------ - def get_user_needaction_ids(self, cr, uid, user_id, offset=0, limit=None, order=None, count=False, context=None): + def needaction_get_user_needaction_ids(self, cr, uid, user_id, offset=0, limit=None, order=None, count=False, context=None): if context is None: context = {} needact_rel_obj = self.pool.get('base.needaction_users_rel') search_res = needact_rel_obj.search(cr, uid, [('user_id', '=', user_id)], offset=offset, limit=limit, order=order, count=count, context=context) return search_res - def get_record_references(self, cr, uid, user_id, offset=0, limit=None, order=None, context=None): + def needaction_get_record_references(self, cr, uid, user_id, offset=0, limit=None, order=None, context=None): if context is None: context = {} needact_rel_obj = self.pool.get('base.needaction_users_rel') - search_res = self.get_user_needaction_ids(cr, uid, user_id, offset=offset, limit=limit, order=order, context=context) - needact_objs = needact_rel_obj.browse(cr, uid, search_res, context=context) + needact_obj_ids = self.get_user_needaction_ids(cr, uid, user_id, offset=offset, limit=limit, order=order, context=context) + needact_objs = needact_rel_obj.browse(cr, uid, needact_obj_ids, context=context) record_references = [(needact_obj.res_model, needact_obj.res_id) for needact_obj in needact_objs] return record_references From 8d627fc8a646f9e6b1a6677fc110a7b634b61c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 14 Mar 2012 18:59:35 +0100 Subject: [PATCH 07/11] [FIX] bugs in unlink bzr revid: tde@openerp.com-20120314175935-aylkpt8ejcxqmu82 --- openerp/addons/base/base_needaction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index 68f8d27b017..6df6d077a6b 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -128,13 +128,13 @@ class base_needaction(osv.osv): # perform write return super(base_needaction, self).write(cr, uid, ids, values, context=context) - def unlink(self, cr, uids, ids, context=None): + def unlink(self, cr, uid, ids, context=None): if context is None: context = {} # unlink user_ids self._unlink_users(cr, uid, ids, context=context) # perform unlink - return super(base_needaction, self).unlink(cr, uid, ids, values, context=context) + return super(base_needaction, self).unlink(cr, uid, ids, context=context) #------------------------------------------------------ # General API From 67d5a3f42593479d5ddbbf5e402e2299e94aa55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 15 Mar 2012 10:08:29 +0100 Subject: [PATCH 08/11] [FIX] Check of need_action_user_ids is now done after updating the object, not before bzr revid: tde@openerp.com-20120315090829-1be3yba7yhcw8qxu --- openerp/addons/base/base_needaction.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index 6df6d077a6b..8d9724e70d1 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -121,12 +121,13 @@ class base_needaction(osv.osv): def write(self, cr, uid, ids, values, context=None): if context is None: context = {} + # perform write + write_res = super(base_needaction, self).write(cr, uid, ids, values, context=context) # get and update user_ids needaction_user_ids = self.get_needaction_user_ids(cr, uid, ids, context=context) for id in ids: self._update_users(cr, uid, [id], needaction_user_ids[id], context=context) - # perform write - return super(base_needaction, self).write(cr, uid, ids, values, context=context) + return write_res def unlink(self, cr, uid, ids, context=None): if context is None: From 0f32742ff054fb7fce0bc4aa2e0ef60799b701f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 15 Mar 2012 10:12:57 +0100 Subject: [PATCH 09/11] [FIX] Fixed bug in object create bzr revid: tde@openerp.com-20120315091257-7h04fdhmjr9gczzy --- openerp/addons/base/base_needaction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index 8d9724e70d1..2deeec64492 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -112,10 +112,10 @@ class base_needaction(osv.osv): if context is None: context = {} # perform create - obj_id = super(base_needaction, self).create(cr, uid, ids, values, context=context) + obj_id = super(base_needaction, self).create(cr, uid, values, context=context) # link user_ids needaction_user_ids = self.get_needaction_user_ids(cr, uid, [obj_id], context=context) - self._update_users(cr, uid, [id], needaction_user_ids[obj_id], context=context) + self._update_users(cr, uid, [obj_id], needaction_user_ids[obj_id], context=context) return obj_id def write(self, cr, uid, ids, values, context=None): From 632c5e3036b39fdee58b442aff72e7a50baa7496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 15 Mar 2012 10:52:03 +0100 Subject: [PATCH 10/11] [DOC] Updated code and server documentation. bzr revid: tde@openerp.com-20120315095203-8g7drwdz9axjexwj --- doc/api/need_action_specs.rst | 28 +++++++++++++-- openerp/addons/base/base_needaction.py | 47 ++++++++++++++++---------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/doc/api/need_action_specs.rst b/doc/api/need_action_specs.rst index 5d5d94cf903..d33536a347d 100644 --- a/doc/api/need_action_specs.rst +++ b/doc/api/need_action_specs.rst @@ -1,8 +1,32 @@ Need action mixin class ======================= -This revision adds a mixin class for object implementing the need action mechanism. Need action mechanism can be used by objects that have to be able to signal that an action is required on a particular record. If in the business logic an action must be performed by somebody, for instance validation by a manager, this mechanism allows to set a field with the user_id of the user requested to perform the action. +This revision adds a mixin class for objects using the need action feature. Need action mechanism can be used by objects that have to be able to signal that an action is required on a particular record. If in the business logic an action must be performed by somebody, for instance validation by a manager, this mechanism allows to set a field with the user_id of the user requested to perform the action. -Technically, this class adds a need_action_user_id field; when set to false, no action is required; when an user_id is set, this user has an action to perform. This field is a function field. Setting an user_id is done through redefining the get_needaction_user_id method. Therefore by redefining only one method, you can specify the cases in which an action will be required on a particular record. +This class wraps a table (base.needaction_users_rel) that behaves like a many2many field. However, no field is added to the model inheriting from base.needaction. The mixin class manages the low-level considerations of updating relationships. Every change made on the record calls a method that updates the relationships. + +Objects using the need_action feature should override the ``get_needaction_user_ids`` method. This methods returns a dictionary whose keys are record ids, and values a list of user ids, like in a many2many relationship. Therefore by defining only one method, you can specify if an action is required by defining the users that have to do it, in every possible situation. + +This class also offers several global services,: + - ``needaction_get_user_record_references``: for a given uid, get all the records that asks this user to perform an action. Records are given as references, a list of tuples (model_name, record_id). This mechanism is used for instance to display the number of pending actions in menus, such as Leads (12). + +Addon implementation example +++++++++++++++++++++++++++++ + +In your ``foo`` module, you want to specify that when it is in state ``confirmed``, it has to be validated by a manager, given by the field ``manager_id``. After making ``foo`` inheriting from ``base.needaction``, you override the ``get_needaction_user_ids`` method: + +:: + + [...] + _inherit = [base.needaction] + [...] + def get_needaction_user_ids(self, cr, uid, ids, context=None): + # set the list void by default + result = dict.fromkeys(ids, []) + for foo_obj in self.browse(cr, uid, ids, context=context): + # if foo_obj is confirmed: manager is required to perform an action + if foo_obj.state == 'confirmed': + result[foo_obj.id] = [foo_obj.manager_id] + return result diff --git a/openerp/addons/base/base_needaction.py b/openerp/addons/base/base_needaction.py index 2deeec64492..62a36162e89 100644 --- a/openerp/addons/base/base_needaction.py +++ b/openerp/addons/base/base_needaction.py @@ -24,12 +24,12 @@ from tools.translate import _ class base_needaction_users_rel(osv.osv): ''' - base_needaction_users_rel holds the data related to the needaction + base_needaction_users_rel holds data related to the needaction mechanism inside OpenERP. A needaction is characterized by: - - res_model: model of the followed objects - - res_id: ID of resource + - res_model: model of the record requiring an action + - res_id: ID of the record requiring an action - user_id: foreign key to the res.users table, to the user that - has to perform an action + has to perform the action ''' _name = 'base.needaction_users_rel' @@ -46,23 +46,33 @@ class base_needaction_users_rel(osv.osv): class base_needaction(osv.osv): - '''Mixin class for object implementing the need action mechanism. + '''Mixin class for objects using the need action feature. - Need action mechanism can be used by objects that have to be able to + Need action feature can be used by objects willing to be able to signal that an action is required on a particular record. If in the business logic an action must be performed by somebody, for instance - validation by a manager, this mechanism allows to set a field with - the user_id of the user requested to perform the action. + validation by a manager, this mechanism allows to set a list of + users asked ot perform an action. - Technically, this class adds a need_action_user_id field; when - set to false, no action is required; when an user_id is set, - this user has an action to perform. This field is a function field. - Setting an user_id is done through redefining the get_needaction_user_id method. - Therefore by redefining only one method, you can specify - the cases in which an action will be required on a particular record. + This class wraps a table (base.needaction_users_rel) that behaves + like a many2many field. However, no field is added to the model + inheriting from base.needaction. The mixin class manages the low-level + considerations of updating relationships. Every change made on the + record calls a method that updates the relationships. - This mechanism is used for instance to display the number of pending actions - in menus, such as Leads (12). + Objects using the need_action feature should override the + ``get_needaction_user_ids`` method. This methods returns a dictionary + whose keys are record ids, and values a list of user ids, like + in a many2many relationship. Therefore by defining only one method, + you can specify if an action is required by defining the users + that have to do it, in every possible situation. + + This class also offers several global services,: + - ``needaction_get_user_record_references``: for a given uid, get all + the records that asks this user to perform an action. Records + are given as references, a list of tuples (model_name, record_id). + This mechanism is used for instance to display the number of pending + actions in menus, such as Leads (12). ''' _name = 'base.needaction' _description = 'Need action mechanism' @@ -148,7 +158,10 @@ class base_needaction(osv.osv): search_res = needact_rel_obj.search(cr, uid, [('user_id', '=', user_id)], offset=offset, limit=limit, order=order, count=count, context=context) return search_res - def needaction_get_record_references(self, cr, uid, user_id, offset=0, limit=None, order=None, context=None): + def needaction_get_user_record_references(self, cr, uid, user_id, offset=0, limit=None, order=None, context=None): + '''for a given uid, get all the records that asks this user to + perform an action. Records are given as references, a list of + tuples (model_name, record_id).''' if context is None: context = {} needact_rel_obj = self.pool.get('base.needaction_users_rel') From 6808cd7e5321d73e47fa2e75c8d50da061fc7389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 15 Mar 2012 11:05:42 +0100 Subject: [PATCH 11/11] [ADD] Added a menu entry in Settings/Users, along with a tree view definition. bzr revid: tde@openerp.com-20120315100542-xhlvb43lda9d3a0m --- doc/api/need_action_specs.rst | 2 ++ openerp/addons/base/__openerp__.py | 1 + openerp/addons/base/base_needaction_view.xml | 29 ++++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 openerp/addons/base/base_needaction_view.xml diff --git a/doc/api/need_action_specs.rst b/doc/api/need_action_specs.rst index d33536a347d..5cffe05be2c 100644 --- a/doc/api/need_action_specs.rst +++ b/doc/api/need_action_specs.rst @@ -12,6 +12,8 @@ This class also offers several global services,: This mechanism is used for instance to display the number of pending actions in menus, such as Leads (12). +A menu in Settings/Users has been added to allows having a quick look to need_action_user_ids. + Addon implementation example ++++++++++++++++++++++++++++ diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py index 802a0510e28..67920c7239a 100644 --- a/openerp/addons/base/__openerp__.py +++ b/openerp/addons/base/__openerp__.py @@ -40,6 +40,7 @@ ], 'update_xml': [ 'base_update.xml', + 'base_needaction_view.xml', 'ir/wizard/wizard_menu_view.xml', 'ir/ir.xml', 'ir/ir_config_parameter_view.xml', diff --git a/openerp/addons/base/base_needaction_view.xml b/openerp/addons/base/base_needaction_view.xml new file mode 100644 index 00000000000..84f7612cac9 --- /dev/null +++ b/openerp/addons/base/base_needaction_view.xml @@ -0,0 +1,29 @@ + + + + + + base.needaction_users_rel.tree + base.needaction_users_rel + tree + 10 + + + + + + + + + + + Need action relationships + base.needaction_users_rel + form + tree,form + + + + + +