Merge lp:~openerp-dev/openobject-addons/saas-4-gamification-fixes-mat into lp:~openerp/openobject-addons/saas-4

Proposed by Martin Trigaux (OpenERP)
Status: Merged
Merged at revision: 9362
Proposed branch: lp:~openerp-dev/openobject-addons/saas-4-gamification-fixes-mat
Merge into: lp:~openerp/openobject-addons/saas-4
Diff against target: 360 lines (+98/-79)
9 files modified
gamification/data/goal_base.xml (+2/-2)
gamification/models/challenge.py (+89/-70)
gamification/models/res_users.py (+0/-1)
gamification/views/challenge.xml (+1/-0)
gamification_sale_crm/sale_crm_goals.xml (+2/-2)
website_forum/data/badges_answer.xml (+1/-1)
website_forum/data/badges_moderation.xml (+1/-1)
website_forum/data/badges_participation.xml (+1/-1)
website_forum/data/badges_question.xml (+1/-1)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/saas-4-gamification-fixes-mat
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+216452@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'gamification/data/goal_base.xml'
--- gamification/data/goal_base.xml 2014-04-16 15:10:26 +0000
+++ gamification/data/goal_base.xml 2014-04-22 07:53:23 +0000
@@ -164,7 +164,7 @@
164 <field name="period">once</field>164 <field name="period">once</field>
165 <field name="visibility_mode">personal</field>165 <field name="visibility_mode">personal</field>
166 <field name="report_message_frequency">never</field>166 <field name="report_message_frequency">never</field>
167 <field name="user_domain">[('groups_id', 'in', ref('base.group_user'))]</field>167 <field name="user_domain" eval="[('groups_id', '=', ref('base.group_user'))]" />
168 <field name="state">inprogress</field>168 <field name="state">inprogress</field>
169 <field name="category">other</field>169 <field name="category">other</field>
170 </record>170 </record>
@@ -174,7 +174,7 @@
174 <field name="period">once</field>174 <field name="period">once</field>
175 <field name="visibility_mode">personal</field>175 <field name="visibility_mode">personal</field>
176 <field name="report_message_frequency">never</field>176 <field name="report_message_frequency">never</field>
177 <field name="user_domain">[('groups_id', 'in', ref('base.user_root'))]</field>177 <field name="user_domain" eval="[('groups_id', '=', ref('base.group_erp_manager'))]" />
178 <field name="state">inprogress</field>178 <field name="state">inprogress</field>
179 <field name="category">other</field>179 <field name="category">other</field>
180 </record>180 </record>
181181
=== modified file 'gamification/models/challenge.py'
--- gamification/models/challenge.py 2014-04-18 09:05:20 +0000
+++ gamification/models/challenge.py 2014-04-22 07:53:23 +0000
@@ -21,14 +21,13 @@
2121
22from openerp import SUPERUSER_ID22from openerp import SUPERUSER_ID
23from openerp.osv import fields, osv23from openerp.osv import fields, osv
24from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF24from openerp.tools import ustr, DEFAULT_SERVER_DATE_FORMAT as DF
25from openerp.tools.safe_eval import safe_eval as eval25from openerp.tools.safe_eval import safe_eval as eval
26from openerp.tools.translate import _26from openerp.tools.translate import _
2727
28from datetime import date, datetime, timedelta28from datetime import date, datetime, timedelta
29import calendar29import calendar
30import logging30import logging
31import functools
32_logger = logging.getLogger(__name__)31_logger = logging.getLogger(__name__)
3332
34# display top 3 in ranking, could be db variable33# display top 3 in ranking, could be db variable
@@ -117,12 +116,6 @@
117 except ValueError:116 except ValueError:
118 return False117 return False
119118
120 def _get_challenger_users(self, cr, uid, domain, context=None):
121 ref = functools.partial(self.pool['ir.model.data'].xmlid_to_res_id, cr, uid)
122 user_domain = eval(domain, {'ref': ref})
123 return self.pool['res.users'].search(cr, uid, user_domain, context=context)
124
125
126 _order = 'end_date, start_date, name, id'119 _order = 'end_date, start_date, name, id'
127 _columns = {120 _columns = {
128 'name': fields.char('Challenge Name', required=True, translate=True),121 'name': fields.char('Challenge Name', required=True, translate=True),
@@ -218,7 +211,6 @@
218 def create(self, cr, uid, vals, context=None):211 def create(self, cr, uid, vals, context=None):
219 """Overwrite the create method to add the user of groups"""212 """Overwrite the create method to add the user of groups"""
220213
221 # add users when change the group auto-subscription
222 if vals.get('user_domain'):214 if vals.get('user_domain'):
223 user_ids = self._get_challenger_users(cr, uid, vals.get('user_domain'), context=context)215 user_ids = self._get_challenger_users(cr, uid, vals.get('user_domain'), context=context)
224216
@@ -240,14 +232,18 @@
240 if isinstance(ids, (int,long)):232 if isinstance(ids, (int,long)):
241 ids = [ids]233 ids = [ids]
242234
235 if vals.get('user_domain'):
236 user_ids = self._get_challenger_users(cr, uid, vals.get('user_domain'), context=context)
237
238 if not vals.get('user_ids'):
239 vals['user_ids'] = []
240 vals['user_ids'] += [(4, user_id) for user_id in user_ids]
241
242 write_res = super(gamification_challenge, self).write(cr, uid, ids, vals, context=context)
243
243 if vals.get('state') == 'inprogress':244 if vals.get('state') == 'inprogress':
244 for challenge in self.browse(cr, uid, ids, context=context):245 self._recompute_challenge_users(cr, uid, ids, context=context)
245 user_ids = self._get_challenger_users(cr, uid, challenge.user_domain, context=context)246 self._generate_goals_from_challenge(cr, uid, ids, context=context)
246 write_op = [(4, user_id) for user_id in user_ids]
247 self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
248 self.message_subscribe_users(cr, uid, [challenge.id], user_ids, context=context)
249
250 self.generate_goals_from_challenge(cr, uid, ids, context=context)
251247
252 elif vals.get('state') == 'done':248 elif vals.get('state') == 'done':
253 self.check_challenge_reward(cr, uid, ids, force=True, context=context)249 self.check_challenge_reward(cr, uid, ids, force=True, context=context)
@@ -256,9 +252,6 @@
256 # resetting progress252 # resetting progress
257 if self.pool.get('gamification.goal').search(cr, uid, [('challenge_id', 'in', ids), ('state', '=', 'inprogress')], context=context):253 if self.pool.get('gamification.goal').search(cr, uid, [('challenge_id', 'in', ids), ('state', '=', 'inprogress')], context=context):
258 raise osv.except_osv("Error", "You can not reset a challenge with unfinished goals.")254 raise osv.except_osv("Error", "You can not reset a challenge with unfinished goals.")
259
260 write_res = super(gamification_challenge, self).write(cr, uid, ids, vals, context=context)
261
262255
263 return write_res256 return write_res
264257
@@ -314,18 +307,10 @@
314 # update every running goal already generated linked to selected challenges307 # update every running goal already generated linked to selected challenges
315 goal_obj.update(cr, uid, goal_ids, context=context)308 goal_obj.update(cr, uid, goal_ids, context=context)
316309
310 self._recompute_challenge_users(cr, uid, ids, context=context)
311 self._generate_goals_from_challenge(cr, uid, ids, context=context)
312
317 for challenge in self.browse(cr, uid, ids, context=context):313 for challenge in self.browse(cr, uid, ids, context=context):
318 # in case of new users matching the domain
319 old_user_ids = [user.id for user in challenge.user_ids]
320 new_user_ids = self._get_challenger_users(cr, uid, challenge.user_domain, context=context)
321 to_remove_ids = list(set(old_user_ids) - set(new_user_ids))
322 to_add_ids = list(set(new_user_ids) - set(old_user_ids))
323
324 write_op = [(3, user_id) for user_id in to_remove_ids]
325 write_op += [(4, user_id) for user_id in to_add_ids]
326 self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
327
328 self.generate_goals_from_challenge(cr, uid, [challenge.id], context=context)
329314
330 # goals closed but still opened at the last report date315 # goals closed but still opened at the last report date
331 closed_goals_to_report = goal_obj.search(cr, uid, [316 closed_goals_to_report = goal_obj.search(cr, uid, [
@@ -345,11 +330,36 @@
345 return True330 return True
346331
347 def quick_update(self, cr, uid, challenge_id, context=None):332 def quick_update(self, cr, uid, challenge_id, context=None):
348 """Update all the goals of a challenge, no generation of new goals"""333 """Update all the goals of a specific challenge, no generation of new goals"""
349 goal_ids = self.pool.get('gamification.goal').search(cr, uid, [('challenge_id', '=', challenge_id)], context=context)334 goal_ids = self.pool.get('gamification.goal').search(cr, uid, [('challenge_id', '=', challenge_id)], context=context)
350 self.pool.get('gamification.goal').update(cr, uid, goal_ids, context=context)335 self.pool.get('gamification.goal').update(cr, uid, goal_ids, context=context)
351 return True336 return True
352337
338 def _get_challenger_users(self, cr, uid, domain, context=None):
339 user_domain = eval(ustr(domain))
340 return self.pool['res.users'].search(cr, uid, user_domain, context=context)
341
342 def _recompute_challenge_users(self, cr, uid, challenge_ids, context=None):
343 """Recompute the domain to add new users and remove the one no longer matching the domain"""
344 for challenge in self.browse(cr, uid, challenge_ids, context=context):
345 if challenge.user_domain:
346
347 old_user_ids = [user.id for user in challenge.user_ids]
348 new_user_ids = self._get_challenger_users(cr, uid, challenge.user_domain, context=context)
349 to_remove_ids = list(set(old_user_ids) - set(new_user_ids))
350 to_add_ids = list(set(new_user_ids) - set(old_user_ids))
351
352 write_op = [(3, user_id) for user_id in to_remove_ids]
353 write_op += [(4, user_id) for user_id in to_add_ids]
354 self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
355
356 if to_remove_ids:
357 self.message_unsubscribe_users(cr, uid, [challenge.id], to_remove_ids, context=None)
358 if to_add_ids:
359 self.message_subscribe_users(cr, uid, [challenge.id], new_user_ids, context=context)
360
361 return True
362
353363
354 def action_check(self, cr, uid, ids, context=None):364 def action_check(self, cr, uid, ids, context=None):
355 """Check a challenge365 """Check a challenge
@@ -370,6 +380,10 @@
370 ##### Automatic actions #####380 ##### Automatic actions #####
371381
372 def generate_goals_from_challenge(self, cr, uid, ids, context=None):382 def generate_goals_from_challenge(self, cr, uid, ids, context=None):
383 _logger.warning("Deprecated, use private method _generate_goals_from_challenge(...) instead.")
384 return self._generate_goals_from_challenge(cr, uid, ids, context=context)
385
386 def _generate_goals_from_challenge(self, cr, uid, ids, context=None):
373 """Generate the goals for each line and user.387 """Generate the goals for each line and user.
374388
375 If goals already exist for this line and user, the line is skipped. This389 If goals already exist for this line and user, the line is skipped. This
@@ -388,44 +402,49 @@
388 end_date = challenge.end_date402 end_date = challenge.end_date
389403
390 for line in challenge.line_ids:404 for line in challenge.line_ids:
391 # FIXME: allow to restrict to a subset of users405
392 for user in challenge.user_ids:406 # there is potentially a lot of users
393407 # detect the ones with no goal linked to this line
394 domain = [('line_id', '=', line.id), ('user_id', '=', user.id)]408 date_clause = ""
395 if start_date:409 query_params = [line.id]
396 domain.append(('start_date', '=', start_date))410 if start_date:
397411 date_clause += "AND g.start_date = %s"
398 # goal already existing for this line ?412 query_params.append(start_date)
399 if len(goal_obj.search(cr, uid, domain, context=context)) > 0:413 if end_date:
400414 date_clause += "AND g.end_date = %s"
401 # resume canceled goals415 query_params.append(end_date)
402 domain.append(('state', '=', 'canceled'))416
403 canceled_goal_ids = goal_obj.search(cr, uid, domain, context=context)417 query = """SELECT u.id AS user_id
404 if canceled_goal_ids:418 FROM res_users u
405 goal_obj.write(cr, uid, canceled_goal_ids, {'state': 'inprogress'}, context=context)419 LEFT JOIN gamification_goal g
406 to_update.extend(canceled_goal_ids)420 ON (u.id = g.user_id)
407421 WHERE line_id = %s
408 # skip to next user422 {date_clause}
409 continue423 """.format(date_clause=date_clause)
410424
411 values = {425 cr.execute(query, query_params)
412 'definition_id': line.definition_id.id,426 user_with_goal_ids = cr.dictfetchall()
413 'line_id': line.id,427 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]))
414 'user_id': user.id,428
415 'target_goal': line.target_goal,429 values = {
416 'state': 'inprogress',430 'definition_id': line.definition_id.id,
417 }431 'line_id': line.id,
418432 'target_goal': line.target_goal,
419 if start_date:433 'state': 'inprogress',
420 values['start_date'] = start_date434 }
421 if end_date:435
422 values['end_date'] = end_date436 if start_date:
423437 values['start_date'] = start_date
424 if challenge.remind_update_delay:438 if end_date:
425 values['remind_update_delay'] = challenge.remind_update_delay439 values['end_date'] = end_date
426440
427 new_goal_id = goal_obj.create(cr, uid, values, context=context)441 if challenge.remind_update_delay:
428 to_update.append(new_goal_id)442 values['remind_update_delay'] = challenge.remind_update_delay
443
444 for user_id in user_without_goal_ids:
445 values.update({'user_id': user_id})
446 goal_id = goal_obj.create(cr, uid, values, context=context)
447 to_update.append(goal_id)
429448
430 goal_obj.update(cr, uid, to_update, context=context)449 goal_obj.update(cr, uid, to_update, context=context)
431450
@@ -638,7 +657,7 @@
638 message = "%s has joined the challenge" % user.name657 message = "%s has joined the challenge" % user.name
639 self.message_post(cr, SUPERUSER_ID, challenge_ids, body=message, context=context)658 self.message_post(cr, SUPERUSER_ID, challenge_ids, body=message, context=context)
640 self.write(cr, SUPERUSER_ID, challenge_ids, {'invited_user_ids': [(3, user_id)], 'user_ids': [(4, user_id)]}, context=context)659 self.write(cr, SUPERUSER_ID, challenge_ids, {'invited_user_ids': [(3, user_id)], 'user_ids': [(4, user_id)]}, context=context)
641 return self.generate_goals_from_challenge(cr, SUPERUSER_ID, challenge_ids, context=context)660 return self._generate_goals_from_challenge(cr, SUPERUSER_ID, challenge_ids, context=context)
642661
643 # TODO in trunk, remove unused parameter user_id662 # TODO in trunk, remove unused parameter user_id
644 def discard_challenge(self, cr, uid, challenge_ids, context=None, user_id=None):663 def discard_challenge(self, cr, uid, challenge_ids, context=None, user_id=None):
645664
=== modified file 'gamification/models/res_users.py'
--- gamification/models/res_users.py 2014-04-16 15:10:26 +0000
+++ gamification/models/res_users.py 2014-04-22 07:53:23 +0000
@@ -19,7 +19,6 @@
19#19#
20##############################################################################20##############################################################################
2121
22from openerp import SUPERUSER_ID
23from openerp.osv import osv22from openerp.osv import osv
24from challenge import MAX_VISIBILITY_RANKING23from challenge import MAX_VISIBILITY_RANKING
2524
2625
=== modified file 'gamification/views/challenge.xml'
--- gamification/views/challenge.xml 2014-04-16 15:22:08 +0000
+++ gamification/views/challenge.xml 2014-04-22 07:53:23 +0000
@@ -48,6 +48,7 @@
48 <label for="user_domain" class="oe_edit_only" string="Assign Challenge To"/>48 <label for="user_domain" class="oe_edit_only" string="Assign Challenge To"/>
49 <div>49 <div>
50 <field name="user_domain" widget="char_domain" options="{'model': 'res.users'}" />50 <field name="user_domain" widget="char_domain" options="{'model': 'res.users'}" />
51 <field name="user_ids" groups="base.group_no_one" widget="many2many_tags" />
51 </div>52 </div>
52 </div>53 </div>
5354
5455
=== modified file 'gamification_sale_crm/sale_crm_goals.xml'
--- gamification_sale_crm/sale_crm_goals.xml 2014-04-16 15:34:28 +0000
+++ gamification_sale_crm/sale_crm_goals.xml 2014-04-22 07:53:23 +0000
@@ -130,7 +130,7 @@
130 <field name="name">Monthly Sales Targets</field>130 <field name="name">Monthly Sales Targets</field>
131 <field name="period">monthly</field>131 <field name="period">monthly</field>
132 <field name="visibility_mode">ranking</field>132 <field name="visibility_mode">ranking</field>
133 <field name="user_domain">[('groups_id', 'in', ref('base.group_sale_salesman'))]</field>133 <field name="user_domain" eval="[('groups_id', 'in', ref('base.group_sale_salesman'))]" />
134 <field name="report_message_frequency">weekly</field>134 <field name="report_message_frequency">weekly</field>
135 </record>135 </record>
136136
@@ -138,7 +138,7 @@
138 <field name="name">Lead Acquisition</field>138 <field name="name">Lead Acquisition</field>
139 <field name="period">monthly</field>139 <field name="period">monthly</field>
140 <field name="visibility_mode">ranking</field>140 <field name="visibility_mode">ranking</field>
141 <field name="user_domain">[('groups_id', 'in', ref('base.group_sale_salesman'))]</field>141 <field name="user_domain" eval="[('groups_id', 'in', ref('base.group_sale_salesman'))]" />"
142 <field name="report_message_frequency">weekly</field>142 <field name="report_message_frequency">weekly</field>
143 </record>143 </record>
144144
145145
=== modified file 'website_forum/data/badges_answer.xml'
--- website_forum/data/badges_answer.xml 2014-04-16 15:10:26 +0000
+++ website_forum/data/badges_answer.xml 2014-04-22 07:53:23 +0000
@@ -1,6 +1,6 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<openerp>2<openerp>
3 <data>3 <data noupdate="1">
44
5 <!-- QUALITY (VOTES) -->5 <!-- QUALITY (VOTES) -->
6 <!-- Teacher: at least 3 upvotes -->6 <!-- Teacher: at least 3 upvotes -->
77
=== modified file 'website_forum/data/badges_moderation.xml'
--- website_forum/data/badges_moderation.xml 2014-04-16 15:14:10 +0000
+++ website_forum/data/badges_moderation.xml 2014-04-22 07:53:23 +0000
@@ -1,6 +1,6 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<openerp>2<openerp>
3 <data>3 <data noupdate="1">
44
5 <!-- Cleanup: answer or question edition -->5 <!-- Cleanup: answer or question edition -->
6 <!-- Not rollback feature in forum -->6 <!-- Not rollback feature in forum -->
77
=== modified file 'website_forum/data/badges_participation.xml'
--- website_forum/data/badges_participation.xml 2014-04-16 15:22:08 +0000
+++ website_forum/data/badges_participation.xml 2014-04-22 07:53:23 +0000
@@ -1,6 +1,6 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<openerp>2<openerp>
3 <data>3 <data noupdate="1">
44
5 <!-- Biography: complet your profile -->5 <!-- Biography: complet your profile -->
6 <record id="badge_p_1" model="gamification.badge">6 <record id="badge_p_1" model="gamification.badge">
77
=== modified file 'website_forum/data/badges_question.xml'
--- website_forum/data/badges_question.xml 2014-04-16 15:14:10 +0000
+++ website_forum/data/badges_question.xml 2014-04-22 07:53:23 +0000
@@ -1,6 +1,6 @@
1<!-- <?xml version="1.0" encoding="utf-8"?> -->1<!-- <?xml version="1.0" encoding="utf-8"?> -->
2<openerp>2<openerp>
3 <data>3 <data noupdate="1">
44
5 <!-- POPULARITY (VIEWS) -->5 <!-- POPULARITY (VIEWS) -->
6 <!-- Popular: 150 views -->6 <!-- Popular: 150 views -->

Subscribers

People subscribed via source and target branches