diff --git a/addons/gamification/data/goal_base.xml b/addons/gamification/data/goal_base.xml
index 0437dee031c..c12763025f6 100644
--- a/addons/gamification/data/goal_base.xml
+++ b/addons/gamification/data/goal_base.xml
@@ -164,7 +164,7 @@
once
personal
never
- [('groups_id', 'in', ref('base.group_user'))]
+
inprogress
other
@@ -174,7 +174,7 @@
once
personal
never
- [('groups_id', 'in', ref('base.user_root'))]
+
inprogress
other
diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py
index 081127d6bf0..a0c4b638ae3 100644
--- a/addons/gamification/models/challenge.py
+++ b/addons/gamification/models/challenge.py
@@ -21,14 +21,13 @@
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
-from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
+from openerp.tools import ustr, DEFAULT_SERVER_DATE_FORMAT as DF
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from datetime import date, datetime, timedelta
import calendar
import logging
-import functools
_logger = logging.getLogger(__name__)
# display top 3 in ranking, could be db variable
@@ -117,12 +116,6 @@ class gamification_challenge(osv.Model):
except ValueError:
return False
- def _get_challenger_users(self, cr, uid, domain, context=None):
- ref = functools.partial(self.pool['ir.model.data'].xmlid_to_res_id, cr, uid)
- user_domain = eval(domain, {'ref': ref})
- return self.pool['res.users'].search(cr, uid, user_domain, context=context)
-
-
_order = 'end_date, start_date, name, id'
_columns = {
'name': fields.char('Challenge Name', required=True, translate=True),
@@ -218,7 +211,6 @@ class gamification_challenge(osv.Model):
def create(self, cr, uid, vals, context=None):
"""Overwrite the create method to add the user of groups"""
- # add users when change the group auto-subscription
if vals.get('user_domain'):
user_ids = self._get_challenger_users(cr, uid, vals.get('user_domain'), context=context)
@@ -240,14 +232,18 @@ class gamification_challenge(osv.Model):
if isinstance(ids, (int,long)):
ids = [ids]
- if vals.get('state') == 'inprogress':
- for challenge in self.browse(cr, uid, ids, context=context):
- user_ids = self._get_challenger_users(cr, uid, challenge.user_domain, context=context)
- write_op = [(4, user_id) for user_id in user_ids]
- self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
- self.message_subscribe_users(cr, uid, [challenge.id], user_ids, context=context)
+ if vals.get('user_domain'):
+ user_ids = self._get_challenger_users(cr, uid, vals.get('user_domain'), context=context)
- self.generate_goals_from_challenge(cr, uid, ids, context=context)
+ if not vals.get('user_ids'):
+ vals['user_ids'] = []
+ vals['user_ids'] += [(4, user_id) for user_id in user_ids]
+
+ write_res = super(gamification_challenge, self).write(cr, uid, ids, vals, context=context)
+
+ if vals.get('state') == 'inprogress':
+ self._recompute_challenge_users(cr, uid, ids, context=context)
+ self._generate_goals_from_challenge(cr, uid, ids, context=context)
elif vals.get('state') == 'done':
self.check_challenge_reward(cr, uid, ids, force=True, context=context)
@@ -256,9 +252,6 @@ class gamification_challenge(osv.Model):
# resetting progress
if self.pool.get('gamification.goal').search(cr, uid, [('challenge_id', 'in', ids), ('state', '=', 'inprogress')], context=context):
raise osv.except_osv("Error", "You can not reset a challenge with unfinished goals.")
-
- write_res = super(gamification_challenge, self).write(cr, uid, ids, vals, context=context)
-
return write_res
@@ -314,18 +307,10 @@ class gamification_challenge(osv.Model):
# update every running goal already generated linked to selected challenges
goal_obj.update(cr, uid, goal_ids, context=context)
+ self._recompute_challenge_users(cr, uid, ids, context=context)
+ self._generate_goals_from_challenge(cr, uid, ids, context=context)
+
for challenge in self.browse(cr, uid, ids, context=context):
- # in case of new users matching the domain
- old_user_ids = [user.id for user in challenge.user_ids]
- new_user_ids = self._get_challenger_users(cr, uid, challenge.user_domain, context=context)
- to_remove_ids = list(set(old_user_ids) - set(new_user_ids))
- to_add_ids = list(set(new_user_ids) - set(old_user_ids))
-
- write_op = [(3, user_id) for user_id in to_remove_ids]
- write_op += [(4, user_id) for user_id in to_add_ids]
- self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
-
- self.generate_goals_from_challenge(cr, uid, [challenge.id], context=context)
# goals closed but still opened at the last report date
closed_goals_to_report = goal_obj.search(cr, uid, [
@@ -345,11 +330,37 @@ class gamification_challenge(osv.Model):
return True
def quick_update(self, cr, uid, challenge_id, context=None):
- """Update all the goals of a challenge, no generation of new goals"""
+ """Update all the goals of a specific challenge, no generation of new goals"""
goal_ids = self.pool.get('gamification.goal').search(cr, uid, [('challenge_id', '=', challenge_id)], context=context)
self.pool.get('gamification.goal').update(cr, uid, goal_ids, context=context)
return True
+ def _get_challenger_users(self, cr, uid, domain, context=None):
+ user_domain = eval(ustr(domain))
+ return self.pool['res.users'].search(cr, uid, user_domain, context=context)
+
+ def _recompute_challenge_users(self, cr, uid, challenge_ids, context=None):
+ """Recompute the domain to add new users and remove the one no longer matching the domain"""
+ for challenge in self.browse(cr, uid, challenge_ids, context=context):
+ if challenge.user_domain:
+
+ old_user_ids = [user.id for user in challenge.user_ids]
+ new_user_ids = self._get_challenger_users(cr, uid, challenge.user_domain, context=context)
+ to_remove_ids = list(set(old_user_ids) - set(new_user_ids))
+ to_add_ids = list(set(new_user_ids) - set(old_user_ids))
+
+ write_op = [(3, user_id) for user_id in to_remove_ids]
+ write_op += [(4, user_id) for user_id in to_add_ids]
+ if write_op:
+ self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
+
+ if to_remove_ids:
+ self.message_unsubscribe_users(cr, uid, [challenge.id], to_remove_ids, context=None)
+ if to_add_ids:
+ self.message_subscribe_users(cr, uid, [challenge.id], to_add_ids, context=context)
+
+ return True
+
def action_check(self, cr, uid, ids, context=None):
"""Check a challenge
@@ -370,6 +381,10 @@ class gamification_challenge(osv.Model):
##### Automatic actions #####
def generate_goals_from_challenge(self, cr, uid, ids, context=None):
+ _logger.warning("Deprecated, use private method _generate_goals_from_challenge(...) instead.")
+ return self._generate_goals_from_challenge(cr, uid, ids, context=context)
+
+ def _generate_goals_from_challenge(self, cr, uid, ids, context=None):
"""Generate the goals for each line and user.
If goals already exist for this line and user, the line is skipped. This
@@ -388,44 +403,49 @@ class gamification_challenge(osv.Model):
end_date = challenge.end_date
for line in challenge.line_ids:
- # FIXME: allow to restrict to a subset of users
- for user in challenge.user_ids:
- domain = [('line_id', '=', line.id), ('user_id', '=', user.id)]
- if start_date:
- domain.append(('start_date', '=', start_date))
+ # there is potentially a lot of users
+ # detect the ones with no goal linked to this line
+ date_clause = ""
+ query_params = [line.id]
+ if start_date:
+ date_clause += "AND g.start_date = %s"
+ query_params.append(start_date)
+ if end_date:
+ date_clause += "AND g.end_date = %s"
+ query_params.append(end_date)
+
+ query = """SELECT u.id AS user_id
+ FROM res_users u
+ LEFT JOIN gamification_goal g
+ ON (u.id = g.user_id)
+ WHERE line_id = %s
+ {date_clause}
+ """.format(date_clause=date_clause)
- # goal already existing for this line ?
- if len(goal_obj.search(cr, uid, domain, context=context)) > 0:
+ cr.execute(query, query_params)
+ user_with_goal_ids = cr.dictfetchall()
+ user_without_goal_ids = list(set([user.id for user in challenge.user_ids]) - set([user['user_id'] for user in user_with_goal_ids]))
- # resume canceled goals
- domain.append(('state', '=', 'canceled'))
- canceled_goal_ids = goal_obj.search(cr, uid, domain, context=context)
- if canceled_goal_ids:
- goal_obj.write(cr, uid, canceled_goal_ids, {'state': 'inprogress'}, context=context)
- to_update.extend(canceled_goal_ids)
+ values = {
+ 'definition_id': line.definition_id.id,
+ 'line_id': line.id,
+ 'target_goal': line.target_goal,
+ 'state': 'inprogress',
+ }
- # skip to next user
- continue
+ if start_date:
+ values['start_date'] = start_date
+ if end_date:
+ values['end_date'] = end_date
- values = {
- 'definition_id': line.definition_id.id,
- 'line_id': line.id,
- 'user_id': user.id,
- 'target_goal': line.target_goal,
- 'state': 'inprogress',
- }
+ if challenge.remind_update_delay:
+ values['remind_update_delay'] = challenge.remind_update_delay
- if start_date:
- values['start_date'] = start_date
- if end_date:
- values['end_date'] = end_date
-
- if challenge.remind_update_delay:
- values['remind_update_delay'] = challenge.remind_update_delay
-
- new_goal_id = goal_obj.create(cr, uid, values, context=context)
- to_update.append(new_goal_id)
+ for user_id in user_without_goal_ids:
+ values.update({'user_id': user_id})
+ goal_id = goal_obj.create(cr, uid, values, context=context)
+ to_update.append(goal_id)
goal_obj.update(cr, uid, to_update, context=context)
@@ -638,7 +658,7 @@ class gamification_challenge(osv.Model):
message = "%s has joined the challenge" % user.name
self.message_post(cr, SUPERUSER_ID, challenge_ids, body=message, context=context)
self.write(cr, SUPERUSER_ID, challenge_ids, {'invited_user_ids': [(3, user_id)], 'user_ids': [(4, user_id)]}, context=context)
- return self.generate_goals_from_challenge(cr, SUPERUSER_ID, challenge_ids, context=context)
+ return self._generate_goals_from_challenge(cr, SUPERUSER_ID, challenge_ids, context=context)
# TODO in trunk, remove unused parameter user_id
def discard_challenge(self, cr, uid, challenge_ids, context=None, user_id=None):
diff --git a/addons/gamification/models/res_users.py b/addons/gamification/models/res_users.py
index 330311ba05e..67020520467 100644
--- a/addons/gamification/models/res_users.py
+++ b/addons/gamification/models/res_users.py
@@ -19,7 +19,6 @@
#
##############################################################################
-from openerp import SUPERUSER_ID
from openerp.osv import osv
from challenge import MAX_VISIBILITY_RANKING
diff --git a/addons/gamification/views/challenge.xml b/addons/gamification/views/challenge.xml
index 75dcd4a7959..87dea680222 100644
--- a/addons/gamification/views/challenge.xml
+++ b/addons/gamification/views/challenge.xml
@@ -48,6 +48,7 @@
+
diff --git a/addons/gamification_sale_crm/sale_crm_goals.xml b/addons/gamification_sale_crm/sale_crm_goals.xml
index fbc1c952bb8..13bf49767dc 100644
--- a/addons/gamification_sale_crm/sale_crm_goals.xml
+++ b/addons/gamification_sale_crm/sale_crm_goals.xml
@@ -130,7 +130,7 @@
Monthly Sales Targets
monthly
ranking
- [('groups_id', 'in', ref('base.group_sale_salesman'))]
+
weekly
@@ -138,7 +138,7 @@
Lead Acquisition
monthly
ranking
- [('groups_id', 'in', ref('base.group_sale_salesman'))]
+ "
weekly
diff --git a/addons/website_forum/data/badges_answer.xml b/addons/website_forum/data/badges_answer.xml
index 4e92600663d..d4e9ead5f89 100644
--- a/addons/website_forum/data/badges_answer.xml
+++ b/addons/website_forum/data/badges_answer.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/addons/website_forum/data/badges_moderation.xml b/addons/website_forum/data/badges_moderation.xml
index d99508bba51..2ebb0f23cd1 100644
--- a/addons/website_forum/data/badges_moderation.xml
+++ b/addons/website_forum/data/badges_moderation.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/addons/website_forum/data/badges_participation.xml b/addons/website_forum/data/badges_participation.xml
index cf1f79185e1..8c922f09b33 100644
--- a/addons/website_forum/data/badges_participation.xml
+++ b/addons/website_forum/data/badges_participation.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/addons/website_forum/data/badges_question.xml b/addons/website_forum/data/badges_question.xml
index ab05d8bcf7a..f0d403a3455 100644
--- a/addons/website_forum/data/badges_question.xml
+++ b/addons/website_forum/data/badges_question.xml
@@ -1,6 +1,6 @@
-
+