Thibault Delavallée (OpenERP) has proposed merging
lp:~openerp-dev/openobject-server/trunk-needaction-review-vmt-tde into
lp:openobject-server.
Requested reviews:
OpenERP Core Team (openerp)
For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-needaction-review-vmt-tde/+merge/102464
Changes for the
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-need_action-tde/+merge/97207
review (the proposed branch was already merged, before the review was taken
into account), following the
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-needaction-review-vmt/+merge/102064
branch.
--
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-needaction-review-vmt-tde/+merge/102464
Your team OpenERP R&D Team is subscribed to branch
lp:~openerp-dev/openobject-server/trunk-needaction-review-vmt-tde.
=== modified file 'doc/api/need_action_specs.rst'
--- doc/api/need_action_specs.rst 2012-04-03 15:49:41 +0000
+++ doc/api/need_action_specs.rst 2012-04-18 09:11:36 +0000
@@ -1,14 +1,14 @@
Need action mechanism
=====================
-ir.needaction mixin class
-++++++++++++++++++++++++++
+ir.needaction_mixin mixin class
++++++++++++++++++++++++++++++++
This revision adds a mixin class for objects using the need action feature.
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 list of users asked to perform an action.
-This class wraps a class (ir.needaction_users) 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 class wraps a class (ir.needaction_users) that behaves like a many2many field. However, no field is added to the model inheriting from ir.needaction_mixin. 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.
@@ -30,12 +30,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:
+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 ``ir.needaction_mixin``, you override the ``get_needaction_user_ids`` method:
::
[...]
- _inherit = [base.needaction]
+ _inherit = [`ir.needaction_mixin]
[...]
def get_needaction_user_ids(self, cr, uid, ids, context=None):
result = dict.fromkeys(ids)
=== modified file 'openerp/addons/base/ir/ir_needaction.py'
--- openerp/addons/base/ir/ir_needaction.py 2012-04-03 16:41:27 +0000
+++ openerp/addons/base/ir/ir_needaction.py 2012-04-18 09:11:36 +0000
@@ -24,17 +24,18 @@
from osv import osv, fields
from tools.translate import _
-class ir_needaction_users(osv.osv):
+class ir_needaction_users_rel(osv.osv):
'''
- ir_needaction_users holds data related to the needaction
- mechanism inside OpenERP. A needaction is characterized by:
+ ir_needaction_users_rel holds data related to the needaction
+ mechanism inside OpenERP. A row in this model is characterized by:
- 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 the action
- '''
+ This model can be seen as a many2many, linking (res_model, res_id) to
+ users (those whose attention is required on the record).'''
- _name = 'ir.needaction_users'
+ _name = 'ir.ir_needaction_users_rel'
_description = 'Needaction relationship table'
_rec_name = 'id'
_order = 'id desc'
@@ -49,15 +50,11 @@
def _get_users(self, cr, uid, res_ids, res_model, context=None):
"""Given res_ids of res_model, get user_ids present in table"""
- if context is None:
- context = {}
- needact_ids = self.search(cr, uid, [('res_model', '=', res_model), ('res_id', 'in', res_ids)], context=context)
- return map(itemgetter('res_id'), self.read(cr, uid, needact_ids, context=context))
+ rel_ids = self.search(cr, uid, [('res_model', '=', res_model), ('res_id', 'in', res_ids)], context=context)
+ return list(set(map(itemgetter('user_id'), self.read(cr, uid, rel_ids, ['user_id'], context=context))))
def create_users(self, cr, uid, res_ids, res_model, user_ids, context=None):
"""Given res_ids of res_model, add user_ids to the relationship table"""
- if context is None:
- context = {}
for res_id in res_ids:
for user_id in user_ids:
self.create(cr, uid, {'res_model': res_model, 'res_id': res_id, 'user_id': user_id}, context=context)
@@ -65,8 +62,6 @@
def unlink_users(self, cr, uid, res_ids, res_model, context=None):
"""Given res_ids of res_model, delete all entries in the relationship table"""
- if context is None:
- context = {}
to_del_ids = self.search(cr, uid, [('res_model', '=', res_model), ('res_id', 'in', res_ids)], context=context)
return self.unlink(cr, uid, to_del_ids, context=context)
@@ -74,7 +69,7 @@
"""Given res_ids of res_model, update their entries in the relationship table to user_ids"""
# read current records
cur_users = self._get_users(cr, uid, res_ids, res_model, context=context)
- if len(cur_users) == len(user_ids) and all([cur_user in user_ids for cur_user in cur_users]):
+ if len(cur_users) == len(user_ids) and all(cur_user in user_ids for cur_user in cur_users):
return True
# unlink old records
self.unlink_users(cr, uid, res_ids, res_model, context=context)
@@ -94,11 +89,11 @@
This class wraps a class (ir.needaction_users) 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
+ inheriting from this mixin class. This class handles 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
+ 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,
@@ -118,7 +113,7 @@
are given as references, a list of tuples (model_name, record_id)
'''
_name = 'ir.needaction_mixin'
- _description = 'Need action of users on records API'
+ _description = '"Need action" mixin'
#------------------------------------------------------
# Addon API
@@ -131,68 +126,56 @@
return dict.fromkeys(ids, [])
def create(self, cr, uid, values, context=None):
- if context is None:
- context = {}
- needact_table_obj = self.pool.get('ir.needaction_users')
+ rel_obj = self.pool.get('ir.needaction_users')
# perform create
obj_id = super(ir_needaction_mixin, self).create(cr, uid, values, context=context)
# link user_ids
needaction_user_ids = self.get_needaction_user_ids(cr, uid, [obj_id], context=context)
- needact_table_obj.create_users(cr, uid, [obj_id], self._name, needaction_user_ids[obj_id], context=context)
+ rel_obj.create_users(cr, uid, [obj_id], self._name, needaction_user_ids[obj_id], context=context)
return obj_id
def write(self, cr, uid, ids, values, context=None):
- if context is None:
- context = {}
- needact_table_obj = self.pool.get('ir.needaction_users')
+ rel_obj = self.pool.get('ir.needaction_users')
# perform write
write_res = super(ir_needaction_mixin, 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:
- needact_table_obj.update_users(cr, uid, [id], self._name, needaction_user_ids[id], context=context)
+ rel_obj.update_users(cr, uid, [id], self._name, needaction_user_ids[id], context=context)
return write_res
def unlink(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
# unlink user_ids
- needact_table_obj = self.pool.get('ir.needaction_users')
- needact_table_obj.unlink_users(cr, uid, ids, self._name, context=context)
+ rel_obj = self.pool.get('ir.needaction_users')
+ rel_obj.unlink_users(cr, uid, ids, self._name, context=context)
# perform unlink
return super(ir_needaction_mixin, self).unlink(cr, uid, ids, context=context)
#------------------------------------------------------
- # Need action API
+ # "Need action" API
#------------------------------------------------------
def needaction_get_record_ids(self, cr, uid, user_id, limit=80, context=None):
"""Given the current model and a user_id
- get the number of actions it has to perform"""
- if context is None:
- context = {}
- needact_table_obj = self.pool.get('ir.needaction_users')
- needact_table_ids = needact_table_obj.search(cr, uid, [('res_model', '=', self._name), ('user_id', '=', user_id)], limit=limit, context=context)
- return map(itemgetter('res_id'), needact_table_obj.read(cr, uid, needact_table_ids, context=context))
+ return the record ids that require the user to perform an
+ action"""
+ rel_obj = self.pool.get('ir.needaction_users')
+ rel_ids = rel_obj.search(cr, uid, [('res_model', '=', self._name), ('user_id', '=', user_id)], limit=limit, context=context)
+ return map(itemgetter('res_id'), rel_obj.read(cr, uid, rel_ids, ['res_id'], context=context))
def needaction_get_action_count(self, cr, uid, user_id, limit=80, context=None):
"""Given the current model and a user_id
get the number of actions it has to perform"""
- if context is None:
- context = {}
- needact_table_obj = self.pool.get('ir.needaction_users')
- return needact_table_obj.search(cr, uid, [('res_model', '=', self._name), ('user_id', '=', user_id)], limit=limit, count=True, context=context)
+ rel_obj = self.pool.get('ir.needaction_users')
+ return rel_obj.search(cr, uid, [('res_model', '=', self._name), ('user_id', '=', user_id)], limit=limit, count=True, context=context)
def needaction_get_record_references(self, cr, uid, user_id, offset=None, limit=None, order=None, context=None):
"""For a given user_id, 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 method is trans-model."""
- if context is None:
- context = {}
- needact_table_obj = self.pool.get('ir.needaction_users')
- needact_table_ids = needact_table_obj.search(cr, uid, [('user_id', '=', user_id)], offset=offset, limit=limit, order=order, context=context)
- needact_records = needact_table_obj.read(cr, uid, needact_table_ids, context=context)
- return map(itemgetter('res_model', 'id'), needact_records)
+ rel_obj = self.pool.get('ir.needaction_users')
+ rel_ids = rel_obj.search(cr, uid, [('user_id', '=', user_id)], offset=offset, limit=limit, order=order, context=context)
+ return map(itemgetter('res_model', 'res_id'), rel_obj.read(cr, uid, rel_ids, ['res_model', 'res_id'], context=context))
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== modified file 'openerp/addons/base/ir/ir_ui_menu.py'
--- openerp/addons/base/ir/ir_ui_menu.py 2012-04-06 08:17:26 +0000
+++ openerp/addons/base/ir/ir_ui_menu.py 2012-04-18 09:11:36 +0000
@@ -258,19 +258,17 @@
def _get_needaction(self, cr, uid, ids, field_names, args, context=None):
if context is None:
context = {}
- res = dict.fromkeys(ids)
+ res = {}
for menu in self.browse(cr, uid, ids, context=context):
res[menu.id] = {}
if menu.action and menu.action.type == 'ir.actions.act_window' and menu.action.res_model:
- menu_needaction_res = self.pool.get(menu.action.res_model).get_needaction_info(cr, uid, uid, domain=menu.action.domain, context=context)
+ menu_needaction_res = self.pool.get(menu.action.res_model)._get_needaction_info(cr, uid, uid, domain=menu.action.domain, context=context)
# TODO: find the addon that causes a bug on runbot, not on local
if not isinstance(menu_needaction_res[1], (int, long)): menu_needaction_res[1] = 0
else:
- menu_needaction_res = [False, 0, ()]
+ menu_needaction_res = [False, 0]
res[menu.id]['needaction_enabled'] = menu_needaction_res[0]
res[menu.id]['needaction_counter'] = menu_needaction_res[1]
- # not used currently, therefore set to a void list
- res[menu.id]['needaction_record_ids'] = []
return res
_columns = {
=== modified file 'openerp/addons/base/security/ir.model.access.csv'
--- openerp/addons/base/security/ir.model.access.csv 2012-04-04 13:33:28 +0000
+++ openerp/addons/base/security/ir.model.access.csv 2012-04-18 09:11:36 +0000
@@ -121,6 +121,6 @@
"access_ir_mail_server_all","ir_mail_server","model_ir_mail_server",,1,0,0,0
"access_ir_actions_todo_category","ir_actions_todo_category","model_ir_actions_todo_category","group_system",1,1,1,1
"access_ir_actions_client","ir_actions_client all","model_ir_actions_client",,1,0,0,0
-"access_ir_needaction_users","ir_needaction_users","model_ir_needaction_users",,1,1,1,1
+"access_ir_needaction_users_rel","ir_needaction_users_rel","model_ir_needaction_users_rel",,1,1,1,1
"access_ir_needaction_mixin","ir_needaction_mixin","model_ir_needaction_mixin",,1,1,1,1
=== modified file 'openerp/osv/orm.py'
--- openerp/osv/orm.py 2012-04-10 13:48:13 +0000
+++ openerp/osv/orm.py 2012-04-18 09:11:36 +0000
@@ -4866,7 +4866,7 @@
get_xml_id = get_external_id
_get_xml_ids = _get_external_ids
- def get_needaction_info(self, cr, uid, user_id, limit=None, order=None, domain=False, context=None):
+ def _get_needaction_info(self, cr, uid, user_id, limit=None, order=None, domain=False, context=None):
"""Base method for needaction mechanism
- see ir.needaction for actual implementation
- if the model uses the need action mechanism
@@ -4883,16 +4883,18 @@
:return: [uses_needaction=True/False, needaction_uid_ctr=%d]
"""
if hasattr(self, 'needaction_get_record_ids'):
+ # Arbitrary limit, but still much lower thant infinity, to avoid
+ # getting too much data.
ids = self.needaction_get_record_ids(cr, uid, user_id, limit=8192, context=context)
if not ids:
- return [True, 0, []]
+ return [True, 0]
if domain:
new_domain = eval(domain, locals_dict={'uid': user_id}) + [('id', 'in', ids)]
else:
new_domain = [('id', 'in', ids)]
- return [True, self.search(cr, uid, new_domain, limit=limit, order=order, count=True, context=context), ids]
+ return [True, self.search(cr, uid, new_domain, limit=limit, order=order, count=True, context=context)]
else:
- return [False, 0, []]
+ return [False, 0]
# Transience
def is_transient(self):
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp