[REF] gamification: cleaning methods and reports
bzr revid: mat@openerp.com-20131220144521-wyu1gx8bcitu6nk4
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<field name="name">Set your Timezone</field>
|
||||
<field name="description">Configure your profile and specify your timezone</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">checkbox</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('base.model_res_users')" />
|
||||
<field name="domain">[('id','=',user.id),('partner_id.tz', '!=', False)]</field>
|
||||
<field name="action_id" eval="ref('base.action_res_users_my')" />
|
||||
@@ -18,7 +18,7 @@
|
||||
<field name="name">Set your Company Data</field>
|
||||
<field name="description">Write some information about your company (specify at least a name)</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">checkbox</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('base.model_res_company')" />
|
||||
<field name="domain">[('user_ids', 'in', [user.id]), ('name', '=', 'Your Company')]</field>
|
||||
<field name="condition">lower</field>
|
||||
@@ -29,7 +29,7 @@
|
||||
<record model="gamification.goal.definition" id="definition_base_company_logo">
|
||||
<field name="name">Set your Company Logo</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">checkbox</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('base.model_res_company')" />
|
||||
<field name="domain">[('user_ids', 'in', user.id),('logo', '!=', False)]</field>
|
||||
<field name="action_id" eval="ref('base.action_res_company_form')" />
|
||||
@@ -50,7 +50,7 @@
|
||||
<record model="gamification.goal.definition" id="definition_base_invite">
|
||||
<field name="name">Invite new Users</field>
|
||||
<field name="description">Create at least another user</field>
|
||||
<field name="display_mode">checkbox</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="model_id" eval="ref('base.model_res_users')" />
|
||||
<field name="domain">[('id', '!=', user.id)]</field>
|
||||
@@ -146,24 +146,24 @@
|
||||
<th>Current</th>
|
||||
<th>Completeness</th>
|
||||
</tr>
|
||||
% for goal in ctx["goals"]:
|
||||
% for line in ctx["challenge_lines"]:
|
||||
<tr
|
||||
% if goal.completeness >= 100:
|
||||
% if line['completeness'] >= 100:
|
||||
style="font-weight:bold;"
|
||||
% endif
|
||||
>
|
||||
<td>${goal.definition_id.name}</td>
|
||||
<td>${goal.target_goal}
|
||||
% if goal.definition_suffix:
|
||||
${goal.definition_suffix}
|
||||
<td>${line['name']}</td>
|
||||
<td>${line['target']}
|
||||
% if line['suffix']:
|
||||
${line['suffix']}
|
||||
% endif
|
||||
</td>
|
||||
<td>${goal.current}
|
||||
% if goal.definition_suffix:
|
||||
${goal.definition_suffix}
|
||||
<td>${line['current']}
|
||||
% if line['suffix']:
|
||||
${line['suffix']}
|
||||
% endif
|
||||
</td>
|
||||
<td>${goal.completeness} %</td>
|
||||
<td>${line['completeness']} %</td>
|
||||
</tr>
|
||||
% endfor
|
||||
</table>]]></field>
|
||||
@@ -177,10 +177,10 @@
|
||||
</header>
|
||||
<p class="oe_grey">${object.report_header or ''}</p>
|
||||
|
||||
% for line in ctx['lines_boards']:
|
||||
% for line in ctx["challenge_lines"]:
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<th colspan="4">${line.goal_definition.name}</th>
|
||||
<th colspan="4">${line['name']}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
@@ -188,23 +188,21 @@
|
||||
<th>Completeness</th>
|
||||
<th>Current</th>
|
||||
</tr>
|
||||
% for idx, goal in line.board_goals:
|
||||
% if idx < 3 or goal.user_id.id == user.id:
|
||||
<tr
|
||||
% if goal.completeness >= 100:
|
||||
style="font-weight:bold;"
|
||||
% endif
|
||||
>
|
||||
<td>${idx+1}</td>
|
||||
<td>${goal.user_id.name}</td>
|
||||
<td>${goal.completeness}%</td>
|
||||
<td>${goal.current}/${goal.target_goal}
|
||||
% if goal.definition_suffix:
|
||||
${goal.definition_suffix}
|
||||
% endif
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% for goal in line['goals']:
|
||||
<tr
|
||||
% if goal.completeness >= 100:
|
||||
style="font-weight:bold;"
|
||||
% endif
|
||||
>
|
||||
<td>${goal['rank']}</td>
|
||||
<td>${goal['name']}</td>
|
||||
<td>${goal['completeness']}%</td>
|
||||
<td>${goal['current']}/${line['target']}
|
||||
% if line['suffix']:
|
||||
${line['suffix']}
|
||||
% endif
|
||||
</td>
|
||||
</tr>
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
|
||||
@@ -19,17 +19,18 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
|
||||
from openerp.tools.translate import _
|
||||
|
||||
# from templates import TemplateHelper
|
||||
|
||||
from datetime import date, datetime, timedelta
|
||||
import calendar
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# display top 3 in ranking, could be db variable
|
||||
MAX_VISIBILITY_RANKING = 3
|
||||
|
||||
def start_end_date_for_period(period, default_start_date=False, default_end_date=False):
|
||||
"""Return the start and end date for a goal period based on today
|
||||
@@ -107,7 +108,7 @@ class gamification_challenge(osv.Model):
|
||||
('other', 'Settings / Gamification Tools'),
|
||||
]
|
||||
|
||||
_sort = 'end_date, start_date, name, id'
|
||||
_order = 'end_date, start_date, name, id'
|
||||
_columns = {
|
||||
'name': fields.char('Challenge Name', required=True, translate=True),
|
||||
'description': fields.text('Description', translate=True),
|
||||
@@ -444,89 +445,137 @@ class gamification_challenge(osv.Model):
|
||||
|
||||
##### JS utilities #####
|
||||
|
||||
def get_board_goal_info(self, cr, uid, challenge, subset_goal_ids=False, context=None):
|
||||
"""Get the list of latest goals for a challenge, sorted by user ranking for each line"""
|
||||
def _get_serialized_challenge_lines(self, cr, uid, challenge, user_id=False, restrict_goal_ids=False, restrict_top=False, context=None):
|
||||
"""Return a serialised version of the goals information
|
||||
|
||||
:challenge: browse record of challenge to compute
|
||||
:user_id: res.users id of the user retrieving progress (False if no distinction, only for ranking challenges)
|
||||
:restrict_goal_ids: <list(int)> compute only the results for this subset if gamification.goal ids, if False retrieve every goal of current running challenge
|
||||
:restrict_top: <int> for challenge lines where visibility_mode == 'ranking', retrieve only these bests results and itself, if False retrieve all
|
||||
restrict_goal_ids has priority over restrict_top
|
||||
|
||||
format list
|
||||
# if visibility_mode == 'ranking'
|
||||
{
|
||||
'name': <gamification.goal.description name>,
|
||||
'description': <gamification.goal.description description>,
|
||||
'condition': <reach condition {lower,higher}>,
|
||||
'computation_mode': <target computation {manually,count,sum,python}>,
|
||||
'monetary': <{True,False}>,
|
||||
'suffix': <value suffix>,
|
||||
'action': <{True,False}>,
|
||||
'display_mode': <{progress,boolean}>,
|
||||
'target': <challenge line target>,
|
||||
'own_goal_id': <gamification.goal id where user_id == uid>,
|
||||
'goals': [
|
||||
{
|
||||
'id': <gamification.goal id>,
|
||||
'rank': <user ranking>,
|
||||
'user_id': <res.users id>,
|
||||
'name': <res.users name>,
|
||||
'state': <gamification.goal state {draft,inprogress,inprogress_update,reached,failed,canceled}>,
|
||||
'completeness': <percentage>,
|
||||
'current': <current value>,
|
||||
}
|
||||
]
|
||||
},
|
||||
# if visibility_mode == 'personal'
|
||||
{
|
||||
'id': <gamification.goal id>,
|
||||
'name': <gamification.goal.description name>,
|
||||
'description': <gamification.goal.description description>,
|
||||
'condition': <reach condition {lower,higher}>,
|
||||
'computation_mode': <target computation {manually,count,sum,python}>,
|
||||
'monetary': <{True,False}>,
|
||||
'suffix': <value suffix>,
|
||||
'action': <{True,False}>,
|
||||
'display_mode': <{progress,boolean}>,
|
||||
'target': <challenge line target>,
|
||||
'state': <gamification.goal state {draft,inprogress,inprogress_update,reached,failed,canceled}>,
|
||||
'completeness': <percentage>,
|
||||
'current': <current value>,
|
||||
}
|
||||
"""
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
lines_boards = []
|
||||
(start_date, end_date) = start_end_date_for_period(challenge.period)
|
||||
|
||||
res_lines = []
|
||||
for line in challenge.line_ids:
|
||||
|
||||
line_data = {
|
||||
'name': line.definition_id.name,
|
||||
'description': line.definition_id.description,
|
||||
'condition': line.definition_id.condition,
|
||||
'computation_mode': line.definition_id.computation_mode,
|
||||
'monetary': line.definition_id.monetary,
|
||||
'suffix': line.definition_id.suffix,
|
||||
'action': True if line.definition_id.action_id else False,
|
||||
'display_mode': line.definition_id.display_mode,
|
||||
'target': line.target_goal,
|
||||
}
|
||||
domain = [
|
||||
('line_id', '=', line.id),
|
||||
('state', 'in', ('inprogress', 'inprogress_update',
|
||||
'reached', 'failed')),
|
||||
('state', '!=', 'draft'),
|
||||
]
|
||||
|
||||
if subset_goal_ids:
|
||||
goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
common_goal_ids = [goal for goal in goal_ids if goal in subset_goal_ids]
|
||||
if restrict_goal_ids:
|
||||
domain.append(('ids', 'in', restrict_goal_ids))
|
||||
else:
|
||||
# if no subset goals, use the dates for restriction
|
||||
if start_date:
|
||||
domain.append(('start_date', '=', start_date))
|
||||
if end_date:
|
||||
domain.append(('end_date', '=', end_date))
|
||||
common_goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
|
||||
board_goals = [goal for goal in goal_obj.browse(cr, uid, common_goal_ids, context=context)]
|
||||
|
||||
if len(board_goals) == 0:
|
||||
# line has no generated goals
|
||||
continue
|
||||
|
||||
# most complete first, current if same percentage (eg: if several 100%)
|
||||
sorted_board = enumerate(sorted(board_goals, key=lambda k: (k.completeness, k.current), reverse=True))
|
||||
lines_boards.append({'goal_definition': line.definition_id, 'board_goals': sorted_board, 'target_goal': line.target_goal})
|
||||
return lines_boards
|
||||
|
||||
def get_indivual_goal_info(self, cr, uid, user_id, challenge, subset_goal_ids=False, context=None):
|
||||
"""Get the list of latest goals of a user for a challenge"""
|
||||
domain = [
|
||||
('challenge_id', '=', challenge.id),
|
||||
('user_id', '=', user_id),
|
||||
('state', 'in', ('inprogress', 'inprogress_update',
|
||||
'reached', 'failed')),
|
||||
]
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
(start_date, end_date) = start_end_date_for_period(challenge.period)
|
||||
|
||||
if subset_goal_ids:
|
||||
# use the domain for safety, don't want irrelevant report if wrong argument
|
||||
goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
related_goal_ids = [goal for goal in goal_ids if goal in subset_goal_ids]
|
||||
else:
|
||||
# if no subset goals, use the dates for restriction
|
||||
if start_date:
|
||||
domain.append(('start_date', '=', start_date))
|
||||
if end_date:
|
||||
domain.append(('end_date', '=', end_date))
|
||||
related_goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
|
||||
if len(related_goal_ids) == 0:
|
||||
return False
|
||||
|
||||
goals = []
|
||||
all_done = True
|
||||
for goal in goal_obj.browse(cr, uid, related_goal_ids, context=context):
|
||||
if goal.end_date:
|
||||
if goal.end_date < fields.date.today():
|
||||
# do not include goals of previous challenge run
|
||||
continue
|
||||
else:
|
||||
all_done = False
|
||||
if challenge.visibility_mode == 'personal':
|
||||
if not user_id:
|
||||
raise osv.except_osv(_('Error!'),_("Retrieving progress for personal challenge without user information"))
|
||||
domain.append(('user_id', '=', user_id))
|
||||
sorting = goal_obj._order
|
||||
limit = 1
|
||||
# initialise in case search returns no results
|
||||
line_data.update({
|
||||
'id': 0,
|
||||
'current': 0,
|
||||
'completeness': 0,
|
||||
'state': 'draft',
|
||||
})
|
||||
else:
|
||||
if goal.state == 'inprogress' or goal.state == 'inprogress_update':
|
||||
all_done = False
|
||||
line_data.update({
|
||||
'own_goal_id': False,
|
||||
'goals': [],
|
||||
})
|
||||
sorting = "completeness desc, current desc"
|
||||
limit = False
|
||||
|
||||
goals.append(goal)
|
||||
goal_ids = goal_obj.search(cr, uid, domain, order=sorting, limit=limit, context=context)
|
||||
ranking = 0
|
||||
for goal in goal_obj.browse(cr, uid, goal_ids, context=context):
|
||||
if challenge.visibility_mode == 'personal':
|
||||
# limit=1 so only one result
|
||||
line_data.update({
|
||||
'id': goal.id,
|
||||
'current': goal.current,
|
||||
'completeness': goal.completeness,
|
||||
'state': goal.state,
|
||||
})
|
||||
else:
|
||||
ranking += 1
|
||||
if user_id and goal.user_id.id == user_id:
|
||||
line_data['own_goal_id'] = goal.id
|
||||
elif restrict_top and ranking > restrict_top:
|
||||
# not own goal, over top, skipping
|
||||
continue
|
||||
|
||||
if all_done:
|
||||
# skip challenges where all goal are done or failed
|
||||
return False
|
||||
else:
|
||||
return goals
|
||||
line_data['goals'].append({
|
||||
'id': goal.id,
|
||||
'user_id': goal.user_id.id,
|
||||
'name': goal.user_id.name,
|
||||
'rank': ranking,
|
||||
'current': goal.current,
|
||||
'completeness': goal.completeness,
|
||||
'state': goal.state,
|
||||
})
|
||||
res_lines.append(line_data)
|
||||
return res_lines
|
||||
|
||||
##### Reporting #####
|
||||
|
||||
@@ -550,11 +599,11 @@ class gamification_challenge(osv.Model):
|
||||
temp_obj = self.pool.get('email.template')
|
||||
ctx = context.copy()
|
||||
if challenge.visibility_mode == 'ranking':
|
||||
lines_boards = self.get_board_goal_info(cr, uid, challenge, subset_goal_ids, context)
|
||||
lines_boards = self._get_serialized_challenge_lines(cr, uid, challenge, user_id=False, restrict_goal_ids=subset_goal_ids, restrict_top=False, context=context)
|
||||
|
||||
ctx.update({'lines_boards': lines_boards})
|
||||
template_id = self.pool['ir.model.data'].get_object(cr, uid, 'gamification', 'email_template_goal_progress_group', context)
|
||||
body_html = temp_obj.render_template(cr, uid, template_id.body_html, 'gamification.challenge', challenge.id, context=context)
|
||||
ctx.update({'challenge_lines': lines_boards})
|
||||
template_id = self.pool.get('ir.model.data').get_object(cr, uid, 'gamification', 'email_template_goal_progress_group', context)
|
||||
body_html = temp_obj.render_template(cr, uid, template_id.body_html, 'gamification.challenge', challenge.id, context=ctx)
|
||||
|
||||
# body_html = template_env.get_template('group_progress.mako').render({'object': challenge, 'lines_boards': lines_boards, 'uid': uid})
|
||||
|
||||
@@ -572,14 +621,14 @@ class gamification_challenge(osv.Model):
|
||||
else:
|
||||
# generate individual reports
|
||||
for user in users or challenge.user_ids:
|
||||
goals = self.get_indivual_goal_info(cr, uid, user.id, challenge, subset_goal_ids, context=context)
|
||||
goals = self._get_serialized_challenge_lines(cr, uid, challenge, user.id, restrict_goal_ids=subset_goal_ids, context=context)
|
||||
if not goals:
|
||||
continue
|
||||
|
||||
ctx.update({'goals': goals})
|
||||
ctx.update({'challenge_lines': goals})
|
||||
template_id = self.pool['ir.model.data'].get_object(cr, uid, 'gamification', 'email_template_goal_progress_perso', context)
|
||||
body_html = temp_obj.render_template(cr, user.id, template_id.body_html, 'gamification.challenge', challenge.id, context=context)
|
||||
# send message only to users
|
||||
body_html = temp_obj.render_template(cr, user.id, template_id.body_html, 'gamification.challenge', challenge.id, context=ctx)
|
||||
# send message only to users, not on the challenge
|
||||
self.message_post(cr, uid, 0,
|
||||
body=body_html,
|
||||
partner_ids=[(4, user.partner_id.id)],
|
||||
@@ -600,7 +649,7 @@ class gamification_challenge(osv.Model):
|
||||
user = self.pool.get('res.users').browse(cr, uid, user_id, context=context)
|
||||
message = "%s has joined the challenge" % user.name
|
||||
self.message_post(cr, uid, challenge_ids, body=message, context=context)
|
||||
self.write(cr, uid, challenge_ids, {'invited_user_ids': [(3, user_id)], 'user_ids': [(4, user_id)]}, 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, uid, challenge_ids, context=context)
|
||||
|
||||
def discard_challenge(self, cr, uid, challenge_ids, context=None, user_id=None):
|
||||
@@ -608,7 +657,7 @@ class gamification_challenge(osv.Model):
|
||||
user_id = user_id or uid
|
||||
user = self.pool.get('res.users').browse(cr, uid, user_id, context=context)
|
||||
message = "%s has refused the challenge" % user.name
|
||||
self.message_post(cr, uid, challenge_ids, body=message, context=context)
|
||||
self.message_post(cr, SUPERUSER_ID, challenge_ids, body=message, context=context)
|
||||
return self.write(cr, uid, challenge_ids, {'invited_user_ids': (3, user_id)}, context=context)
|
||||
|
||||
def reply_challenge_wizard(self, cr, uid, challenge_id, context=None):
|
||||
@@ -710,7 +759,7 @@ class gamification_challenge(osv.Model):
|
||||
for goal in goal_obj.browse(cr, uid, goal_ids, context=context):
|
||||
if goal.state != 'reached':
|
||||
all_reached = False
|
||||
if goal.definition_condition == 'higher':
|
||||
if goal.condition == 'higher':
|
||||
# can be over 100
|
||||
total_completness += 100.0 * goal.current / goal.target_goal
|
||||
elif goal.state == 'reached':
|
||||
@@ -761,7 +810,7 @@ class gamification_challenge_line(osv.Model):
|
||||
goal_definition = goal_definition.browse(cr, uid, definition_id, context=context)
|
||||
ret = {
|
||||
'value': {
|
||||
'definition_condition': goal_definition.condition,
|
||||
'condition': goal_definition.condition,
|
||||
'definition_full_suffix': goal_definition.full_suffix
|
||||
}
|
||||
}
|
||||
@@ -781,7 +830,7 @@ class gamification_challenge_line(osv.Model):
|
||||
required=True),
|
||||
'sequence': fields.integer('Sequence',
|
||||
help='Sequence number for ordering'),
|
||||
'definition_condition': fields.related('definition_id', 'condition', type="selection",
|
||||
'condition': fields.related('definition_id', 'condition', type="selection",
|
||||
readonly=True, string="Condition", selection=[('lower', '<='), ('higher', '>=')]),
|
||||
'definition_suffix': fields.related('definition_id', 'suffix', type="char", readonly=True, string="Unit"),
|
||||
'definition_monetary': fields.related('definition_id', 'monetary', type="boolean", readonly=True, string="Monetary"),
|
||||
|
||||
@@ -76,6 +76,7 @@ class gamification_goal_definition(osv.Model):
|
||||
'display_mode': fields.selection([
|
||||
('progress', 'Progressive (using numerical values)'),
|
||||
('checkbox', 'Checkbox (done or not-done)'),
|
||||
('boolean', 'Exclusive (done or not-done)'),
|
||||
],
|
||||
string="Displayed as", required=True),
|
||||
'model_id': fields.many2one('ir.model',
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import osv
|
||||
|
||||
from challenge import MAX_VISIBILITY_RANKING
|
||||
|
||||
class res_users_gamification_group(osv.Model):
|
||||
""" Update of res.users class
|
||||
@@ -58,14 +58,23 @@ class res_users_gamification_group(osv.Model):
|
||||
challenge_obj.write(cr, uid, challenge_ids, {'user_ids': [(4, write_res)]}, context=context)
|
||||
return write_res
|
||||
|
||||
def get_goals_todo_info(self, cr, uid, context=None):
|
||||
"""Return the list of goals assigned to the user, grouped by challenge
|
||||
# def get_goals_todo_info(self, cr, uid, context=None):
|
||||
|
||||
This method intends to return processable data in javascript in the
|
||||
goal_list_to_do template. The output format is not constant as the
|
||||
required information is different between individual and board goal
|
||||
definitions
|
||||
:return: list of dictionnaries for each goal to display
|
||||
def get_serialised_gamification_summary(self, cr, uid, context=None):
|
||||
return self._serialised_goals_summary(cr, uid, user_id=uid, context=context)
|
||||
|
||||
def _serialised_goals_summary(self, cr, uid, user_id, context=None):
|
||||
"""Return a serialised list of goals assigned to the user, grouped by challenge
|
||||
|
||||
[
|
||||
{
|
||||
'id': <gamification.challenge id>,
|
||||
'name': <gamification.challenge name>,
|
||||
'visibility_mode': <visibility {ranking,personal}>,
|
||||
'currency': <res.currency id>,
|
||||
'lines': [(see gamification_challenge._get_serialized_challenge_lines() format)]
|
||||
},
|
||||
]
|
||||
"""
|
||||
all_goals_info = []
|
||||
challenge_obj = self.pool.get('gamification.challenge')
|
||||
@@ -74,78 +83,14 @@ class res_users_gamification_group(osv.Model):
|
||||
challenge_ids = challenge_obj.search(cr, uid, [('user_ids', 'in', uid), ('state', '=', 'inprogress')], context=context)
|
||||
for challenge in challenge_obj.browse(cr, uid, challenge_ids, context=context):
|
||||
# serialize goals info to be able to use it in javascript
|
||||
serialized_goals_info = {
|
||||
all_goals_info.append({
|
||||
'id': challenge.id,
|
||||
'name': challenge.name,
|
||||
'visibility_mode': challenge.visibility_mode,
|
||||
'currency': user.company_id.currency_id.id
|
||||
}
|
||||
'currency': user.company_id.currency_id.id,
|
||||
'lines': challenge_obj._get_serialized_challenge_lines(cr, uid, challenge, user_id, restrict_top=MAX_VISIBILITY_RANKING, context=context),
|
||||
})
|
||||
|
||||
if challenge.visibility_mode == 'ranking':
|
||||
# board report should be grouped by line for all users
|
||||
goals_info = challenge_obj.get_board_goal_info(cr, uid, challenge, subset_goal_ids=False, context=context)
|
||||
|
||||
if not goals_info:
|
||||
# challenge with no valid lines
|
||||
continue
|
||||
|
||||
serialized_goals_info['lines'] = []
|
||||
for line_board in goals_info:
|
||||
vals = {'definition_name': line_board['goal_definition'].name,
|
||||
'definition_description': line_board['goal_definition'].description,
|
||||
'definition_condition': line_board['goal_definition'].condition,
|
||||
'computation_mode': line_board['goal_definition'].computation_mode,
|
||||
'definition_monetary': line_board['goal_definition'].monetary,
|
||||
'definition_suffix': line_board['goal_definition'].suffix,
|
||||
'definition_action': True if line_board['goal_definition'].action_id else False,
|
||||
'definition_display': line_board['goal_definition'].display_mode,
|
||||
'target_goal': line_board['target_goal'],
|
||||
'goals': []}
|
||||
for goal in line_board['board_goals']:
|
||||
# Keep only the Top 3 and the current user
|
||||
if goal[0] > 2 and goal[1].user_id.id != uid:
|
||||
continue
|
||||
|
||||
vals['goals'].append({
|
||||
'rank': goal[0] + 1,
|
||||
'id': goal[1].id,
|
||||
'user_id': goal[1].user_id.id,
|
||||
'user_name': goal[1].user_id.name,
|
||||
'state': goal[1].state,
|
||||
'completeness': goal[1].completeness,
|
||||
'current': goal[1].current,
|
||||
'target_goal': goal[1].target_goal,
|
||||
})
|
||||
if uid == goal[1].user_id.id:
|
||||
vals['own_goal_id'] = goal[1].id
|
||||
serialized_goals_info['lines'].append(vals)
|
||||
|
||||
else:
|
||||
# individual report are simply a list of goal
|
||||
goals_info = challenge_obj.get_indivual_goal_info(cr, uid, uid, challenge, subset_goal_ids=False, context=context)
|
||||
|
||||
if not goals_info:
|
||||
continue
|
||||
|
||||
serialized_goals_info['goals'] = []
|
||||
for goal in goals_info:
|
||||
serialized_goals_info['goals'].append({
|
||||
'id': goal.id,
|
||||
'definition_name': goal.definition_id.name,
|
||||
'definition_description': goal.definition_description,
|
||||
'definition_condition': goal.definition_id.condition,
|
||||
'definition_monetary': goal.definition_id.monetary,
|
||||
'definition_suffix': goal.definition_id.suffix,
|
||||
'definition_action': True if goal.definition_id.action_id else False,
|
||||
'definition_display': goal.definition_id.display_mode,
|
||||
'state': goal.state,
|
||||
'completeness': goal.completeness,
|
||||
'computation_mode': goal.computation_mode,
|
||||
'current': goal.current,
|
||||
'target_goal': goal.target_goal,
|
||||
})
|
||||
|
||||
all_goals_info.append(serialized_goals_info)
|
||||
return all_goals_info
|
||||
|
||||
def get_challenge_suggestions(self, cr, uid, context=None):
|
||||
@@ -171,7 +116,9 @@ class res_groups_gamification_group(osv.Model):
|
||||
_name = 'res.groups'
|
||||
_inherit = 'res.groups'
|
||||
|
||||
# No need to overwrite create as very unlikely to be the value in the autojoin_group_id field
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
"""Overwrite to autosubscribe users if add users to a group marked as autojoin, these will be added to the challenge"""
|
||||
write_res = super(res_groups_gamification_group, self).write(cr, uid, ids, vals, context=context)
|
||||
if vals.get('users'):
|
||||
# form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
width: 280px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside > .oe_gamification_goal {
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_gamification_challenge_list {
|
||||
background-color: #EDEDF6;
|
||||
}
|
||||
.openerp .oe_mail_wall_aside .oe_gamification_suggestion {
|
||||
@@ -188,7 +188,7 @@
|
||||
width: 24px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal .oe_update_plan.oe_e,
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal .oe_update_challenge.oe_e,
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal .oe_goal_action.oe_e {
|
||||
visibility: hidden;
|
||||
font-size: 25px;
|
||||
@@ -196,7 +196,7 @@
|
||||
/*margin-right: 15px;*/
|
||||
position: relative;
|
||||
}
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal div:hover > .oe_update_plan,
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal div:hover > .oe_update_challenge,
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal div:hover > .oe_goal_action,
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside .oe_goal th:hover > .oe_goal_action {
|
||||
visibility: visible;
|
||||
|
||||
@@ -2,12 +2,12 @@ openerp.gamification = function(instance) {
|
||||
var QWeb = instance.web.qweb;
|
||||
|
||||
instance.gamification.Sidebar = instance.web.Widget.extend({
|
||||
template: 'gamification.user_wall_sidebar',
|
||||
template: 'gamification.UserWallSidebar',
|
||||
init: function (parent, action) {
|
||||
var self = this;
|
||||
this._super(parent, action);
|
||||
this.deferred = $.Deferred();
|
||||
this.res_user = new instance.web.DataSetSearch(this, 'res.users');
|
||||
// this.res_user = new instance.web.DataSetSearch(this, 'res.users');
|
||||
this.goals_info = {};
|
||||
this.challenge_suggestions = {};
|
||||
},
|
||||
@@ -51,54 +51,53 @@ openerp.gamification = function(instance) {
|
||||
});
|
||||
}
|
||||
},
|
||||
renderElement: function() {
|
||||
start: function() {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
self.get_goal_todo_info();
|
||||
self.get_challenge_suggestions();
|
||||
},
|
||||
render_template: function(target,template) {
|
||||
var self = this;
|
||||
target.append(QWeb.render(template,{'widget': self}));
|
||||
},
|
||||
// render_template: function(target,template) {
|
||||
// var self = this;
|
||||
// target.append(QWeb.render(template,{'widget': self}));
|
||||
// },
|
||||
render_template_replace: function(target,template) {
|
||||
var self = this;
|
||||
target.html(QWeb.render(template,{'widget': self}));
|
||||
},
|
||||
get_goal_todo_info: function() {
|
||||
var self = this;
|
||||
var goals_info = this.res_user.call('get_goals_todo_info', {}).then(function(res) {
|
||||
self.goals_info['info'] = res;
|
||||
});
|
||||
$.when(goals_info).done(function() {
|
||||
if(self.goals_info.info.length > 0){
|
||||
self.render_template_replace(self.$el.filter(".oe_gamification_goal"),'gamification.goal_list_to_do');
|
||||
self.render_money_fields(self.goals_info.info[0].currency);
|
||||
self.render_user_avatars();
|
||||
var challenges = new instance.web.Model('res.users').call('get_serialised_gamification_summary', []).then(function(result) {
|
||||
if (result.length === 0) {
|
||||
self.$el.find(".oe_gamification_challenge_list").hide();
|
||||
} else {
|
||||
self.$el.filter(".oe_gamification_goal").hide();
|
||||
_.each(result, function(item){
|
||||
console.log(item);
|
||||
var $item = $(QWeb.render("gamification.ChallengeSummary", {challenge: item}));
|
||||
self.render_money_fields($item);
|
||||
self.render_user_avatars($item);
|
||||
self.$el.find('.oe_gamification_challenge_list').append($item);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
get_challenge_suggestions: function() {
|
||||
var self = this;
|
||||
var challenge_suggestions = this.res_user.call('get_challenge_suggestions', {}).then(function(res) {
|
||||
self.challenge_suggestions['info'] = res;
|
||||
});
|
||||
$.when(challenge_suggestions).done(function() {
|
||||
if(self.challenge_suggestions.info.length > 0){
|
||||
self.render_template_replace(self.$el.filter(".oe_gamification_suggestion"),'gamification.challenge_suggestions');
|
||||
var challenge_suggestions = new instance.web.Model('res.users').call('get_challenge_suggestions', []).then(function(result) {
|
||||
if (result.length === 0) {
|
||||
self.$el.find(".oe_gamification_suggestion").hide();
|
||||
} else {
|
||||
self.$el.filter(".oe_gamification_suggestion").hide();
|
||||
var $item = $(QWeb.render("gamification.ChallengeSuggestion", {challenges: result}));
|
||||
self.$el.find('.oe_gamification_suggestion').append($item);
|
||||
}
|
||||
});
|
||||
},
|
||||
render_money_fields: function(currency_id) {
|
||||
render_money_fields: function(item) {
|
||||
var self = this;
|
||||
|
||||
self.dfm = new instance.web.form.DefaultFieldManager(self);
|
||||
// Generate a FieldMonetary for each .oe_goal_field_monetary
|
||||
self.$(".oe_goal_field_monetary").each(function() {
|
||||
item.find(".oe_goal_field_monetary").each(function() {
|
||||
var currency_id = parseInt( $(this).attr('data-id'), 10);
|
||||
money_field = new instance.web.form.FieldMonetary(self.dfm, {
|
||||
attrs: {
|
||||
modifiers: '{"readonly": true}'
|
||||
@@ -110,9 +109,9 @@ openerp.gamification = function(instance) {
|
||||
money_field.replace($(this));
|
||||
});
|
||||
},
|
||||
render_user_avatars: function() {
|
||||
render_user_avatars: function(item) {
|
||||
var self = this;
|
||||
self.$(".oe_user_avatar").each(function() {
|
||||
item.find(".oe_user_avatar").each(function() {
|
||||
var user_id = parseInt( $(this).attr('data-id'), 10);
|
||||
var url = instance.session.url('/web/binary/image', {model: 'res.users', field: 'image_small', id: user_id});
|
||||
$(this).attr("src", url);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<templates>
|
||||
<t t-name="gamification.user_wall_sidebar" class="oe_gamification_user_wall_sidebar">
|
||||
<div class="oe_gamification_suggestion"><em>No challenge suggestions</em></div>
|
||||
<div class="oe_gamification_goal"><em>Your goal list is empty</em></div>
|
||||
<t t-name="gamification.UserWallSidebar" class="oe_gamification_user_wall_sidebar">
|
||||
<div>
|
||||
<div class="oe_gamification_suggestion"></div>
|
||||
<div class="oe_gamification_challenge_list"></div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="gamification.goal_list_to_do">
|
||||
<div t-foreach="widget.goals_info.info" t-as="challenge" class="oe_goal">
|
||||
<t t-name="gamification.ChallengeSummary">
|
||||
<div class="oe_goal">
|
||||
<div>
|
||||
<a class="oe_update_challenge oe_e" rol="button" t-attf-id="{challenge.id}">e</a>
|
||||
<h4><t t-esc="challenge.name" /></h4>
|
||||
@@ -12,29 +14,29 @@
|
||||
|
||||
<t t-if="challenge.visibility_mode == 'personal'">
|
||||
<div class="oe_table oe_goals_list">
|
||||
<div t-foreach="challenge.goals" t-as="goal" t-attf-class="oe_row oe_goal_outer_box #{goal.state == 'reached' ? 'oe_goal_reached' : ''} #{goal.definition_display != 'progress' ? 'oe_no_progress' : ''}">
|
||||
<t t-if="goal.definition_display == 'progress'">
|
||||
<div t-foreach="challenge.lines" t-as="line" t-attf-class="oe_row oe_goal_outer_box #{line.state == 'reached' ? 'oe_goal_reached' : ''} #{line.display_mode != 'progress' ? 'oe_no_progress' : ''}">
|
||||
<t t-if="line.display_mode == 'progress'">
|
||||
<div class="oe_goal_progress_background"></div>
|
||||
<div class="oe_goal_progress" t-attf-style="#{goal.definition_display == 'progress' ? 'width: '+goal.completeness+'%;' : 'width:0;'}"></div>
|
||||
<div class="oe_cell oe_goal_current"><t t-esc="goal.current" /></div>
|
||||
<div class="oe_goal_progress" t-attf-style="#{line.display_mode == 'progress' ? 'width: '+line.completeness+'%;' : 'width:0;'}"></div>
|
||||
<div class="oe_cell oe_goal_current"><t t-esc="line.current" /></div>
|
||||
</t>
|
||||
<div class="oe_cell">
|
||||
<t t-if="goal.computation_mode != 'manually' and !goal.definition_action">
|
||||
<span t-att-title="goal.definition_description"><t t-esc="goal.definition_name" /></span>
|
||||
<t t-if="line.computation_mode != 'manually' and !line.action">
|
||||
<span t-att-title="line.description"><t t-esc="line.name" /></span>
|
||||
</t>
|
||||
<t t-if="goal.definition_action or goal.computation_mode == 'manually'">
|
||||
<span t-att-title="goal.definition_description"><a class="oe_goal_action" t-att-id="goal.id"><t t-esc="goal.definition_name" /></a></span>
|
||||
<t t-if="line.action or line.computation_mode == 'manually'">
|
||||
<span t-att-title="line.description"><a class="oe_goal_action" t-att-id="line.id"><t t-esc="line.name" /></a></span>
|
||||
</t>
|
||||
<t t-if="goal.definition_display == 'progress'"><br/>
|
||||
<t t-if="line.display_mode == 'progress'"><br/>
|
||||
<div class="oe_grey">
|
||||
<t t-if="goal.definition_condition == 'higher'">
|
||||
<t t-if="line.definition_condition == 'higher'">
|
||||
Target:
|
||||
</t>
|
||||
<t t-if="goal.definition_condition == 'lower'">
|
||||
<t t-if="line.definition_condition == 'lower'">
|
||||
Target: <=
|
||||
</t>
|
||||
<span t-attf-class="#{goal.definition_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.target_goal"/></span>
|
||||
<t t-if="goal.definition_suffix"><t t-esc="goal.definition_suffix"/></t>
|
||||
<span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="line.target"/></span>
|
||||
<t t-if="line.suffix"><t t-esc="line.suffix"/></t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
@@ -45,8 +47,8 @@
|
||||
<t t-if="challenge.visibility_mode == 'ranking'">
|
||||
<div t-foreach="challenge.lines" t-as="line" class="oe_goals_list oe_table">
|
||||
<div class="oe_row">
|
||||
<div class="oe_cell oe_thead" colspan="3" t-attf-title="#{line.definition_description ? line.definition_description : ''}">
|
||||
<strong><t t-esc="line.definition_name"/></strong>
|
||||
<div class="oe_cell oe_thead" colspan="3" t-attf-title="#{line.description ? line.description : ''}">
|
||||
<strong><t t-esc="line.name"/></strong>
|
||||
<br/>
|
||||
<div class="oe_grey">
|
||||
<t t-if="line.definition_condition == 'higher'">
|
||||
@@ -55,39 +57,39 @@
|
||||
<t t-if="line.definition_condition == 'lower'">
|
||||
Target: <=
|
||||
</t>
|
||||
<span t-attf-class="#{line.definition_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="line.target_goal" /></span><t t-if="line.definition_suffix"> <t t-esc="line.definition_suffix"/></t>
|
||||
<span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="line.target" /></span><t t-if="line.suffix"> <t t-esc="line.suffix"/></t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div t-foreach="line.goals" t-as="goal" t-attf-class="#{goal.id == line.own_goal_id ? 'oe_bold' : ''}">
|
||||
<div t-attf-class="oe_row oe_goal_outer_box #{goal.state == 'reached' ? 'oe_goal_reached' : ''} #{line.definition_display != 'progress' ? 'oe_no_progress' : ''}">
|
||||
<t t-if="line.definition_display == 'progress'">
|
||||
<div t-attf-class="oe_row oe_goal_outer_box #{goal.state == 'reached' ? 'oe_goal_reached' : ''} #{line.display_mode != 'progress' ? 'oe_no_progress' : ''}">
|
||||
<t t-if="line.display_mode == 'progress'">
|
||||
<div class="oe_goal_progress_background"></div>
|
||||
<div class="oe_goal_progress" t-attf-style="#{line.definition_display == 'progress' ? 'width: '+goal.completeness+'%;' : 'width:0;'}"></div>
|
||||
<div class="oe_goal_progress" t-attf-style="#{line.display_mode == 'progress' ? 'width: '+goal.completeness+'%;' : 'width:0;'}"></div>
|
||||
</t>
|
||||
|
||||
<div class="oe_cell col0"><t t-esc="goal.rank" /></div>
|
||||
<div class="oe_cell col1"><img class="oe_user_avatar" t-attf-alt="#{goal.user_name}" t-attf-data-id="#{goal.user_id}"/></div>
|
||||
<div class="oe_cell col1"><img class="oe_user_avatar" t-attf-alt="#{goal.name}" t-attf-data-id="#{goal.user_id}"/></div>
|
||||
<div class="oe_cell col2">
|
||||
<t t-if="line.definition_display == 'progress'">
|
||||
<t t-if="line.display_mode == 'progress'">
|
||||
<!-- progress, action on current value -->
|
||||
<t t-esc="goal.user_name"/><br/>
|
||||
<t t-if="goal.id != line.own_goal_id or (line.computation_mode != 'manually' and !line.definition_action)">
|
||||
<span t-attf-class="#{line.definition_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.current" /></span><t t-if="line.definition_suffix"> <t t-esc="line.definition_suffix"/></t>
|
||||
<t t-esc="goal.name"/><br/>
|
||||
<t t-if="goal.id != line.own_goal_id or (line.computation_mode != 'manually' and !line.action)">
|
||||
<span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="goal.current" /></span><t t-if="line.suffix"> <t t-esc="line.suffix"/></t>
|
||||
</t>
|
||||
<t t-if="goal.id == line.own_goal_id and (line.definition_action or line.computation_mode == 'manually')">
|
||||
<t t-if="goal.id == line.own_goal_id and (line.action or line.computation_mode == 'manually')">
|
||||
<a class="oe_goal_action" t-att-id="line.own_goal_id">
|
||||
<span t-attf-class="#{line.definition_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="goal.current" /></span><t t-if="line.definition_suffix"> <t t-esc="line.definition_suffix"/></t>
|
||||
<span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="goal.current" /></span><t t-if="line.suffix"> <t t-esc="line.suffix"/></t>
|
||||
</a>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="line.definition_display != 'progress'">
|
||||
<t t-if="line.display_mode != 'progress'">
|
||||
<!-- not progress, action on user name -->
|
||||
<t t-if="goal.id != line.own_goal_id or (line.computation_mode != 'manually' and !line.definition_action)">
|
||||
<t t-esc="goal.user_name"/>
|
||||
<t t-if="goal.id != line.own_goal_id or (line.computation_mode != 'manually' and !line.action)">
|
||||
<t t-esc="goal.name"/>
|
||||
</t>
|
||||
<t t-if="goal.id == line.own_goal_id and (line.definition_action or line.computation_mode == 'manually')">
|
||||
<a class="oe_goal_action" t-att-id="line.own_goal_id"><t t-esc="goal.user_name"/></a>
|
||||
<t t-if="goal.id == line.own_goal_id and (line.action or line.computation_mode == 'manually')">
|
||||
<a class="oe_goal_action" t-att-id="line.own_goal_id"><t t-esc="goal.name"/></a>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
@@ -98,10 +100,10 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="gamification.challenge_suggestions">
|
||||
<t t-name="gamification.ChallengeSuggestion">
|
||||
<div class="oe_goal">
|
||||
<h4>Invited Challenges</h4>
|
||||
<ul t-foreach="widget.challenge_suggestions.info" t-as="challenge" class="oe_goals_list">
|
||||
<ul t-foreach="challenges" t-as="challenge" class="oe_goals_list">
|
||||
<li>
|
||||
<strong><a class="oe_challenge_reply" t-attf-title="#{challenge.description.value ? challenge.description.value : ''}" t-attf-id="{challenge.id}" title="more details..."><t t-esc="challenge.name"/></a></strong>
|
||||
</li>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text_css">${css}</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Congratulation, you have received the badge <strong>${badge_user.badge_id.name}</strong> !
|
||||
% if user_from
|
||||
This badge was granted by <strong>${user_from.name}</strong>.
|
||||
% endif
|
||||
</p>
|
||||
|
||||
% if badge_user.comment
|
||||
<p><em>${badge_user.comment}</em></p>
|
||||
% endif
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text_css">${css}</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<strong>${object.name}</strong>
|
||||
</header>
|
||||
<p class="oe_grey">${object.report_header or ''}</p>
|
||||
<% block body %><% endblock %>
|
||||
|
||||
</body>
|
||||
@@ -1,38 +0,0 @@
|
||||
<% extends 'base.mako' %>
|
||||
|
||||
<% block body %>
|
||||
% for line in lines_boards:
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<th colspan="4">${line.goal_definition.name}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Person</th>
|
||||
<th>Completeness</th>
|
||||
<th>Current</th>
|
||||
</tr>
|
||||
% for idx, goal in line.board_goals:
|
||||
% if idx < 3 or goal.user_id.id == uid:
|
||||
<tr
|
||||
% if goal.completeness >= 100:
|
||||
style="font-weight:bold;"
|
||||
% endif
|
||||
>
|
||||
<td>${idx+1}</td>
|
||||
<td>${goal.user_id.name}</td>
|
||||
<td>${goal.completeness}%</td>
|
||||
<td>${goal.current}/${goal.target_goal}
|
||||
% if goal.definition_suffix:
|
||||
${goal.definition_suffix}
|
||||
% endif
|
||||
</td>
|
||||
</tr>
|
||||
% endif
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
<br/><br/>
|
||||
|
||||
% endfor
|
||||
<% endblock %>
|
||||
@@ -1,31 +0,0 @@
|
||||
<% extends 'base.mako' %>
|
||||
|
||||
<% block body %><table width="100%" border="1">
|
||||
<tr>
|
||||
<th>Goal</th>
|
||||
<th>Target</th>
|
||||
<th>Current</th>
|
||||
<th>Completeness</th>
|
||||
</tr>
|
||||
% for goal in goals:
|
||||
<tr
|
||||
% if goal.completeness >= 100:
|
||||
style="font-weight:bold;"
|
||||
% endif
|
||||
>
|
||||
<td>${goal.definition_id.name}</td>
|
||||
<td>${goal.target_goal}
|
||||
% if goal.definition_suffix:
|
||||
${goal.definition_suffix}
|
||||
% endif
|
||||
</td>
|
||||
<td>${goal.current}
|
||||
% if goal.definition_suffix:
|
||||
${goal.definition_suffix}
|
||||
% endif
|
||||
</td>
|
||||
<td>${goal.completeness} %</td>
|
||||
</tr>
|
||||
% endfor
|
||||
</table>
|
||||
<% endblock %>
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text_css">${css}</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<strong>Reminder ${object.name}</strong>
|
||||
</header>
|
||||
|
||||
<p class="oe_grey">${object.report_header or ''}</p>
|
||||
|
||||
<p>You have not updated your progress for the goal ${object.definition_id.name} (currently reached at ${object.completeness}%) for at least ${object.remind_update_delay} days. Do not forget to do it.</p>
|
||||
|
||||
<p>If you have not changed your score yet, you can use the button "The current value is up to date" to indicate so.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -76,7 +76,7 @@
|
||||
<tree string="Line List" version="7.0" editable="bottom" >
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="definition_id" on_change="on_change_definition_id(definition_id)" />
|
||||
<field name="definition_condition"/>
|
||||
<field name="condition"/>
|
||||
<field name="target_goal"/>
|
||||
<field name="definition_full_suffix"/>
|
||||
</tree>
|
||||
@@ -101,6 +101,9 @@
|
||||
<field name="invited_user_ids" widget="many2many_tags" />
|
||||
</group>
|
||||
<group string="Notification Messages">
|
||||
<div class="oe_grey">
|
||||
<p>Depending on the Diasplay mode, reports will be individual or shared.</p>
|
||||
</div>
|
||||
<field name="report_message_frequency" />
|
||||
<field name="report_header" placeholder="e.g. The following message contains the current progress of the sale team..." attrs="{'invisible': [('report_message_frequency','=','never')]}" />
|
||||
<field name="report_message_group_id" attrs="{'invisible': [('report_message_frequency','=','never')]}" />
|
||||
@@ -247,7 +250,7 @@
|
||||
<tree string="Challenge Lines" version="7.0" editable="bottom" >
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="definition_id"/>
|
||||
<field name="definition_condition"/>
|
||||
<field name="condition"/>
|
||||
<field name="target_goal"/>
|
||||
<field name="definition_full_suffix"/>
|
||||
</tree>
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
</div>
|
||||
<field name="user_id" />
|
||||
<div class="oe_goal_state_block">
|
||||
<t t-if="record.definition_display.raw_value == 'checkbox'">
|
||||
<t t-if="record.definition_display.raw_value == 'boolean'">
|
||||
<div class="oe_goal_state oe_e">
|
||||
<t t-if="record.state.raw_value=='reached'"><span class="oe_green" title="Goal Reached">W</span></t>
|
||||
<t t-if="record.state.raw_value=='inprogress' || record.state.raw_value=='inprogress_update'"><span title="Goal in Progress">N</span></t>
|
||||
|
||||
Reference in New Issue
Block a user