From 79206a10e32cb16cc3e8087d8c7ecbe93ff168cb Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 27 Feb 2013 17:56:00 +0100 Subject: [PATCH] [IMP] gamification: corrections with feedbacks and usage of templates bzr revid: mat@openerp.com-20130227165600-0majyllrmy452hwb --- addons/gamification/goal.py | 99 +++++++++++++------ addons/gamification/report/reminder.xml | 23 ----- .../gamification/report/report_progress.xml | 81 --------------- .../templates/group_progress.mako | 38 +++++++ .../templates/personal_progress.mako | 31 ++++++ addons/gamification/templates/reminder.mako | 16 +++ addons/gamification/view/goal.xml | 14 +-- addons/gamification/view/plan.xml | 4 +- 8 files changed, 166 insertions(+), 140 deletions(-) delete mode 100644 addons/gamification/report/reminder.xml delete mode 100644 addons/gamification/report/report_progress.xml create mode 100644 addons/gamification/templates/group_progress.mako create mode 100644 addons/gamification/templates/personal_progress.mako create mode 100644 addons/gamification/templates/reminder.mako diff --git a/addons/gamification/goal.py b/addons/gamification/goal.py index 2b120eeaedf..75b5b4e7019 100644 --- a/addons/gamification/goal.py +++ b/addons/gamification/goal.py @@ -22,11 +22,50 @@ from openerp.osv import fields, osv from openerp.tools.safe_eval import safe_eval -from mako.template import Template as MakoTemplate - from datetime import date, datetime, timedelta +from mako.template import Template as MakoTemplate +from urllib import urlencode, quote as quote + import calendar import itertools +import logging +import os.path + +_logger = logging.getLogger(__name__) + +GAMIFICATION_PATH = os.path.dirname(os.path.abspath(__file__)) + +try: + # We use a jinja2 sandboxed environment to render mako templates. + # Note that the rendering does not cover all the mako syntax, in particular + # arbitrary Python statements are not accepted, and not all expressions are + # allowed: only "public" attributes (not starting with '_') of objects may + # be accessed. + # This is done on purpose: it prevents incidental or malicious execution of + # Python code that may break the security of the server. + from jinja2.sandbox import SandboxedEnvironment + from jinja2 import FileSystemLoader + mako_template_env = SandboxedEnvironment( + loader=FileSystemLoader(os.path.join(GAMIFICATION_PATH,'templates/')), + block_start_string="<%", + block_end_string="%>", + variable_start_string="${", + variable_end_string="}", + comment_start_string="<%doc>", + comment_end_string="", + line_statement_prefix="%", + line_comment_prefix="##", + trim_blocks=True, # do not output newline after blocks + autoescape=True, # XML/HTML automatic escaping + ) + mako_template_env.globals.update({ + 'str': str, + 'quote': quote, + 'urlencode': urlencode, + }) +except ImportError: + _logger.warning("jinja2 not available, templating features will not work!") + def start_end_date_for_period(period): @@ -221,12 +260,13 @@ class gamification_goal(osv.Model): if goal.remind_update_delay and goal.last_update: delta_max = timedelta(days=goal.remind_update_delay) last_update = datetime.strptime(goal.last_update,'%Y-%m-%d').date() - if date.today() - last_update > delta_max: + if date.today() - last_update > delta_max and goal.state == 'inprogress': towrite['state'] = 'inprogress_update' # generate a remind report - template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'gamification', 'email_template_goal_reminder')[1] - self.pool.get('email.template').send_mail(cr, uid, template_id, goal.id, context=context) + body_html = mako_template_env.get_template('reminder.mako').render({'object':goal}) + self.pool.get('mail.thread').message_post(cr, goal.user_id.id, False, body=body_html, context=context) + #self.pool.get('email.template').send_mail(cr, uid, template_id, goal.id, context=context) else: # count or sum obj = self.pool.get(goal.type_id.model_id.model) @@ -280,7 +320,9 @@ class gamification_goal(osv.Model): def write(self, cr, uid, ids, vals, context=None): """Overwrite the write method to update the last_update field to today""" for goal in self.browse(cr, uid, ids, vals): - vals['last_update'] = fields.date.today() + # TODO if current in vals + #vals['last_update'] = fields.date.today() + pass write_res = super(gamification_goal, self).write(cr, uid, ids, vals, context=context) return write_res @@ -553,10 +595,9 @@ class gamification_goal_plan(osv.Model): template_context = dict(context) if plan.visibility_mode == 'board': # generate a shared report - template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'gamification', 'email_template_gamification_leaderboard')[1] + template_id = self.pool.get('ir.model.data').get_object(cr, uid, 'gamification', 'email_template_gamification_leaderboard') - # unsorted list of planline - template_context['planlines'] = [] + planlines_boards = [] for planline in plan.planline_ids: (start_date, end_date) = start_end_date_for_period(plan.period) @@ -567,12 +608,12 @@ class gamification_goal_plan(osv.Model): ] if start_date: domain.append(('start_date', '=', start_date.isoformat())) - - goal_ids = goal_obj.search(cr, uid, domain, context=context) - planlines_stats = [] + + board_goals = [] + goal_ids = goal_obj.search(cr, uid, domain, context=context) for goal in goal_obj.browse(cr, uid, goal_ids, context=context): - planlines_stats.append({ + board_goals.append({ 'user': goal.user_id, 'current':goal.current, 'target_goal':goal.target_goal, @@ -580,23 +621,30 @@ class gamification_goal_plan(osv.Model): }) # most complete first, current if same percentage (eg: if several 100%) - sorted_planline_goals = enumerate(sorted(planlines_stats, key=lambda k: (k['completeness'], k['current']), reverse=True)) - template_context['planlines'].append({'goal_type':planline.type_id.name, 'list':sorted_planline_goals}) + sorted_board = enumerate(sorted(board_goals, key=lambda k: (k['completeness'], k['current']), reverse=True)) + planlines_boards.append({'goal_type':planline.type_id.name, 'board_goals':sorted_board}) - self.pool.get('email.template').send_mail(cr, uid, template_id, plan.id, context=template_context) + body_html = mako_template_env.get_template('group_progress.mako').render({'object':plan, 'planlines_boards':planlines_boards}) + self.pool.get('mail.thread').message_post(cr, [user.id for user in plan.user_ids], False, body=body_html, context=context) + #self.pool.get('email.template').send_mail(cr, uid, template_id, plan.id, context=template_context) else: # generate individual reports template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'gamification', 'email_template_gamification_individual')[1] for user in plan.user_ids: - goal_ids = self.get_current_related_user_goals(cr, uid, plan.id, user.id, context) + goal_ids = self.get_current_related_goals(cr, uid, plan.id, user.id, context=context) if len(goal_ids) == 0: continue - template_context['goals'] = goal_obj.browse(cr, uid, goal_ids, context=context) - template_context['user'] = user - self.pool.get('email.template').send_mail(cr, uid, template_id, plan.id, context=template_context) + variables = { + 'object':plan, + 'user':user, + 'goals':goal_obj.browse(cr, uid, goal_ids, context=context) + } + body_html = mako_template_env.get_template('personal_progress.mako').render(variables) + self.pool.get('mail.thread').message_post(cr, user.id, False, body=body_html, context=context) + #self.pool.get('email.template').send_mail(cr, uid, template_id, plan.id, context=template_context) return True @@ -616,19 +664,14 @@ class gamification_goal_plan(osv.Model): for planline in plan.planline_ids: domain = [('planline_id', '=', planline.id), - ('user_id', '=', user_id)] + ('user_id', '=', user_id), + ('state','in',('inprogress','inprogress_update','reached'))] if start_date: domain.append(('start_date', '=', start_date.isoformat())) goal_ids = goal_obj.search(cr, uid, domain, context=context) - related_goal_ids.append(goal_ids[0]) - if len(goal_ids) == 0: - # this goal has been deleted - raise osv.except_osv('Warning!','Planline {0} has no goal present for user {1} at date {2}'.format(planline.id, user.id, start_date)) - else: # more than one goal ? - raise osv.except_osv('Warning!', 'Duplicate goals for planline {0}, user {1}, date {2}'.format(planline.id, user.id, start_date)) - related_goal_ids.extend(goal_ids) + related_goal_ids.extend(goal_ids) return related_goal_ids diff --git a/addons/gamification/report/reminder.xml b/addons/gamification/report/reminder.xml deleted file mode 100644 index 918e2773bc5..00000000000 --- a/addons/gamification/report/reminder.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Goal Update Reminder - Send by Email - noreply@localhost - Goal Update Reminder - ${object.user_id.alias_id.name_get()[0][1]} - - - -

Hello ${object.user_id.name}

- -

You have not updated your progress for the goal ${object.type_id.name} (currently reached at ${object.completeness}%) for at least ${object.remind_update_delay}. Do not forget to do it.

- -

If you have not changed your score yet, you can use the button "The current value is up to date" to indicate so.

- - ]]>
-
- -
-
diff --git a/addons/gamification/report/report_progress.xml b/addons/gamification/report/report_progress.xml deleted file mode 100644 index 08e37df1dec..00000000000 --- a/addons/gamification/report/report_progress.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - Individual Goal Report - Send by Email - noreply@localhost - Individual report - ${object.name} - ${object.report_message_group_id.alias_id.name_get()[0][1]} - - - -

Individual report - ${object.name}

- -

Hello, bellow are the latest results for the plan ${object.name} for ${ctx['user'].name}.

- - - - - - - - - % for goal in ctx['goals']: - - - - - - - % endfor -
GoalTargetCurrentCompleteness
${goal.type_id.name}${goal.target_goal}${goal.current}${goal.completeness} %
- - - ]]>
-
- - - - Leaderboard Goal Report - Send by Email - noreply@localhost - ${object.name} group report - ${object.report_message_group_id.alias_id.name_get()[0][1]} - - - -

Group report - ${object.name}

- -

Hello, - - Bellow are the latest results for the plan ${object.name} for the group ${object.report_message_group_id.name}

- - % for planline in ctx['planlines']: -

${planline['goal_type']}

- - - - - - % for idx, goal in planline['list']: - = 100: - style="font-weight:bold;"" - % endif - > - - - - - - % endfor -
#UserCompletenessCurrent
${idx+1}${goal.user.name}${goal.completeness}%${goal.current}/${goal.target_goal}
- % endfor - - - ]]>
-
-
-
diff --git a/addons/gamification/templates/group_progress.mako b/addons/gamification/templates/group_progress.mako new file mode 100644 index 00000000000..b0b6e7d6243 --- /dev/null +++ b/addons/gamification/templates/group_progress.mako @@ -0,0 +1,38 @@ + + + + + + +
+ % if object.report_header + ${object.report_header} + % endif +
+ + Below are the latest results for the plan ${object.name} for the group ${object.report_message_group_id.name}.

+ !${planlines_boards}! + % for planline in planlines_boards: +

${planline['goal_type']}

+ + + + + + + + % for idx, goal in planline['board_goals']: + = 100: + style="font-weight:bold;" + % endif + > + + + + + + % endfor +
#UserCompletenessCurrent
${idx+1}${goal.user.name}${goal.completeness}%${goal.current}/${goal.target_goal}
+ % endfor + \ No newline at end of file diff --git a/addons/gamification/templates/personal_progress.mako b/addons/gamification/templates/personal_progress.mako new file mode 100644 index 00000000000..a7325760b56 --- /dev/null +++ b/addons/gamification/templates/personal_progress.mako @@ -0,0 +1,31 @@ + + + + + + +
+ % if object.report_header + ${object.report_header} + % endif +
+ +

Below are the latest results for the plan ${object.name} for ${user.name}.

+ + + + + + + + + % for goal in goals: + + + + + + + % endfor +
GoalTargetCurrentCompleteness
${goal.type_id.name}${goal.target_goal}${goal.current}${goal.completeness} %
+ \ No newline at end of file diff --git a/addons/gamification/templates/reminder.mako b/addons/gamification/templates/reminder.mako new file mode 100644 index 00000000000..9e161dcef0e --- /dev/null +++ b/addons/gamification/templates/reminder.mako @@ -0,0 +1,16 @@ + + + + + + +
+ % if object.report_header + ${object.report_header} + % endif +
+ +

You have not updated your progress for the goal ${object.type_id.name} (currently reached at ${object.completeness}%) for at least ${object.remind_update_delay}. Do not forget to do it.

+ +

If you have not changed your score yet, you can use the button "The current value is up to date" to indicate so.

+ \ No newline at end of file diff --git a/addons/gamification/view/goal.xml b/addons/gamification/view/goal.xml index a15e53a074e..c497270eff0 100644 --- a/addons/gamification/view/goal.xml +++ b/addons/gamification/view/goal.xml @@ -41,16 +41,13 @@
-
-
@@ -69,9 +66,14 @@ - + - +
diff --git a/addons/gamification/view/plan.xml b/addons/gamification/view/plan.xml index 265deaaecd8..fbf4dc4a3e3 100644 --- a/addons/gamification/view/plan.xml +++ b/addons/gamification/view/plan.xml @@ -47,8 +47,8 @@