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="%doc>",
+ 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}.
-
-
-
- | Goal |
- Target |
- Current |
- Completeness |
-
- % for goal in ctx['goals']:
-
- | ${goal.type_id.name} |
- ${goal.target_goal} |
- ${goal.current} |
- ${goal.completeness} % |
-
- % endfor
-
-
-
- ]]>
-
-
-
-
- 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']}
-
- | # |
- User |
- Completeness |
- Current |
- % for idx, goal in planline['list']:
- = 100:
- style="font-weight:bold;""
- % endif
- >
- | ${idx+1} |
- ${goal.user.name} |
- ${goal.completeness}% |
- ${goal.current}/${goal.target_goal} |
-
- % endfor
-
- % 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']}
+
+
+ | # |
+ User |
+ Completeness |
+ Current |
+
+ % for idx, goal in planline['board_goals']:
+ = 100:
+ style="font-weight:bold;"
+ % endif
+ >
+ | ${idx+1} |
+ ${goal.user.name} |
+ ${goal.completeness}% |
+ ${goal.current}/${goal.target_goal} |
+
+ % endfor
+
+ % 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}.
+
+
+
+ | Goal |
+ Target |
+ Current |
+ Completeness |
+
+ % for goal in goals:
+
+ | ${goal.type_id.name} |
+ ${goal.target_goal} |
+ ${goal.current} |
+ ${goal.completeness} % |
+
+ % endfor
+
+
\ 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 @@