diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py
index ecb4c495d94..d3297a048d3 100644
--- a/addons/gamification/models/challenge.py
+++ b/addons/gamification/models/challenge.py
@@ -240,6 +240,11 @@ class gamification_challenge(osv.Model):
write_res = super(gamification_challenge, self).write(cr, uid, ids, vals, context=context)
+ if vals.get('report_message_frequency', 'never') != 'never':
+ # _recompute_challenge_users do not set users for challenges with no reports, subscribing them now
+ for challenge in self.browse(cr, uid, ids, context=context):
+ self.message_subscribe(cr, uid, [challenge.id], [user.partner_id.id for user in challenge.user_ids], 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)
@@ -264,6 +269,9 @@ class gamification_challenge(osv.Model):
- Create the missing goals (eg: modified the challenge to add lines)
- Update every running challenge
"""
+ if context is None:
+ context = {}
+
# start scheduled challenges
planned_challenge_ids = self.search(cr, uid, [
('state', '=', 'draft'),
@@ -281,6 +289,9 @@ class gamification_challenge(osv.Model):
if not ids:
ids = self.search(cr, uid, [('state', '=', 'inprogress')], context=context)
+ # in cron mode, will do intermediate commits
+ # TODO in trunk: replace by parameter
+ context.update({'commit_gamification': True})
return self._update_all(cr, uid, ids, context=context)
def _update_all(self, cr, uid, ids, context=None):
@@ -355,10 +366,12 @@ class gamification_challenge(osv.Model):
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)
+ # TODO for trunk: use proper parameter
+ if challenge.report_message_frequency != 'never':
+ if to_remove_ids:
+ self.message_unsubscribe_users(cr, uid, [challenge.id], to_remove_ids, context=context)
+ if to_add_ids:
+ self.message_subscribe_users(cr, uid, [challenge.id], to_add_ids, context=context)
return True
@@ -393,9 +406,9 @@ class gamification_challenge(osv.Model):
:param list(int) ids: the list of challenge concerned"""
goal_obj = self.pool.get('gamification.goal')
- to_update = []
for challenge in self.browse(cr, uid, ids, context=context):
(start_date, end_date) = start_end_date_for_period(challenge.period)
+ to_update = []
# if no periodicity, use challenge dates
if not start_date and challenge.start_date:
@@ -698,34 +711,35 @@ class gamification_challenge(osv.Model):
rewarded_users = []
challenge_ended = end_date == yesterday.strftime(DF) or force
if challenge.reward_id and challenge_ended or challenge.reward_realtime:
- for user in challenge.user_ids:
- reached_goal_ids = self.pool.get('gamification.goal').search(cr, uid, [
- ('challenge_id', '=', challenge.id),
- ('user_id', '=', user.id),
- ('start_date', '=', start_date),
- ('end_date', '=', end_date),
- ('state', '=', 'reached')
- ], context=context)
- if len(reached_goal_ids) == len(challenge.line_ids):
+ # not using start_date as intemportal goals have a start date but no end_date
+ reached_goals = self.pool.get('gamification.goal').read_group(cr, uid, [
+ ('challenge_id', '=', challenge.id),
+ ('end_date', '=', end_date),
+ ('state', '=', 'reached')
+ ], fields=['user_id'], groupby=['user_id'], context=context)
+ for reach_goals_user in reached_goals:
+ if reach_goals_user['user_id_count'] == len(challenge.line_ids):
# the user has succeeded every assigned goal
+ user_id = reach_goals_user['user_id'][0]
if challenge.reward_realtime:
badges = self.pool['gamification.badge.user'].search(cr, uid, [
('challenge_id', '=', challenge.id),
('badge_id', '=', challenge.reward_id.id),
- ('user_id', '=', user.id),
+ ('user_id', '=', user_id),
], count=True, context=context)
if badges > 0:
# has already recieved the badge for this challenge
continue
- self.reward_user(cr, uid, user.id, challenge.reward_id.id, challenge.id, context=context)
- rewarded_users.append(user)
+ self.reward_user(cr, uid, user_id, challenge.reward_id.id, challenge.id, context=context)
+ rewarded_users.append(user_id)
if challenge_ended:
# open chatter message
message_body = _("The challenge %s is finished." % challenge.name)
if rewarded_users:
- message_body += _("
Reward (badge %s) for every succeeding user was sent to %s." % (challenge.reward_id.name, ", ".join([user.name for user in rewarded_users])))
+ user_names = self.pool['res.users'].name_get(cr, uid, rewarded_users, context=context)
+ message_body += _("
Reward (badge %s) for every succeeding user was sent to %s." % (challenge.reward_id.name, ", ".join([name for (user_id, name) in user_names])))
else:
message_body += _("
Nobody has succeeded to reach every goal, no badge is rewared for this challenge.")
diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py
index af9a763236d..b4a47a0d07a 100644
--- a/addons/gamification/models/goal.py
+++ b/addons/gamification/models/goal.py
@@ -138,7 +138,6 @@ class gamification_goal(osv.Model):
_name = 'gamification.goal'
_description = 'Gamification goal instance'
- _inherit = 'mail.thread'
def _get_completion(self, cr, uid, ids, field_name, arg, context=None):
"""Return the percentage of completeness of the goal, between 0 and 100"""
@@ -226,8 +225,7 @@ class gamification_goal(osv.Model):
temp_obj = self.pool.get('email.template')
template_id = self.pool['ir.model.data'].get_object(cr, uid, 'gamification', 'email_template_goal_reminder', context)
body_html = temp_obj.render_template(cr, uid, template_id.body_html, 'gamification.goal', goal.id, context=context)
-
- self.message_post(cr, uid, goal.id, body=body_html, partner_ids=[goal.user_id.partner_id.id], context=context, subtype='mail.mt_comment')
+ self.pool['mail.thread'].message_post(cr, uid, 0, body=body_html, partner_ids=[goal.user_id.partner_id.id], context=context, subtype='mail.mt_comment')
return {'to_update': True}
return {}
@@ -241,9 +239,9 @@ class gamification_goal(osv.Model):
the target value being reached, the goal is set as failed."""
if context is None:
context = {}
+ commit = context.get('commit_gamification', False)
goals_by_definition = {}
- goals_to_write = {}
all_goals = {}
for goal in self.browse(cr, uid, ids, context=context):
if goal.state in ('draft', 'canceled'):
@@ -251,10 +249,10 @@ class gamification_goal(osv.Model):
continue
goals_by_definition.setdefault(goal.definition_id, []).append(goal)
- goals_to_write[goal.id] = {}
all_goals[goal.id] = goal
for definition, goals in goals_by_definition.items():
+ goals_to_write = dict((goal.id, {}) for goal in goals)
if definition.computation_mode == 'manually':
for goal in goals:
goals_to_write[goal.id].update(self._check_remind_delay(cr, uid, goal, context))
@@ -345,22 +343,24 @@ class gamification_goal(osv.Model):
if new_value != goal.current:
goals_to_write[goal.id]['current'] = new_value
- for goal_id, value in goals_to_write.items():
- if not value:
- continue
- goal = all_goals[goal_id]
+ for goal_id, value in goals_to_write.items():
+ if not value:
+ continue
+ goal = all_goals[goal_id]
- # check goal target reached
- if (goal.definition_condition == 'higher' and value.get('current', goal.current) >= goal.target_goal) \
- or (goal.definition_condition == 'lower' and value.get('current', goal.current) <= goal.target_goal):
- value['state'] = 'reached'
+ # check goal target reached
+ if (goal.definition_condition == 'higher' and value.get('current', goal.current) >= goal.target_goal) \
+ or (goal.definition_condition == 'lower' and value.get('current', goal.current) <= goal.target_goal):
+ value['state'] = 'reached'
- # check goal failure
- elif goal.end_date and fields.date.today() > goal.end_date:
- value['state'] = 'failed'
- value['closed'] = True
- if value:
- self.write(cr, uid, [goal.id], value, context=context)
+ # check goal failure
+ elif goal.end_date and fields.date.today() > goal.end_date:
+ value['state'] = 'failed'
+ value['closed'] = True
+ if value:
+ self.write(cr, uid, [goal.id], value, context=context)
+ if commit:
+ cr.commit()
return True
def action_start(self, cr, uid, ids, context=None):
diff --git a/addons/gamification/views/goal.xml b/addons/gamification/views/goal.xml
index 528d5db0511..884467404ce 100644
--- a/addons/gamification/views/goal.xml
+++ b/addons/gamification/views/goal.xml
@@ -86,10 +86,6 @@
-