[FIX] gamification send report at right frequency
bzr revid: mat@openerp.com-20130304112712-5qt8x9mikoqyg59o
This commit is contained in:
parent
12c30843eb
commit
e7ba23a4f7
|
@ -282,6 +282,6 @@ class gamification_goal(osv.Model):
|
|||
|
||||
if goal.planline_id and goal.planline_id.plan_id.report_message_frequency == 'onchange':
|
||||
plan_obj = self.pool.get('gamification.goal.plan')
|
||||
plan_obj.report_progress(cr, uid, [goal.planline_id.plan_id.id], users=[goal.user_id], context=context)
|
||||
plan_obj.report_progress(cr, uid, goal.planline_id.plan_id, users=[goal.user_id], context=context)
|
||||
return super(gamification_goal, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
|
|
@ -69,6 +69,26 @@ class gamification_goal_plan(osv.Model):
|
|||
_description = 'Gamification goal plan'
|
||||
_inherit = 'mail.thread'
|
||||
|
||||
def _get_next_report_date(self, cr, uid, ids, field_name, arg, context=None):
|
||||
"""Return the next report date based on the last report date and report
|
||||
period. Return a string in isoformat."""
|
||||
res = {}
|
||||
for plan in self.browse(cr, uid, ids, context):
|
||||
last = datetime.strptime(plan.last_report_date,'%Y-%m-%d').date()
|
||||
if plan.report_message_frequency == 'daily':
|
||||
next = last + timedelta(days=1)
|
||||
elif plan.report_message_frequency == 'weekly':
|
||||
next = last + timedelta(days=7)
|
||||
elif plan.report_message_frequency == 'monthly':
|
||||
month_range = calendar.monthrange(last.year, last.month)
|
||||
next = last.replace(day=month_range[1]) + timedelta(days=1)
|
||||
elif plan.report_message_frequency == 'yearly':
|
||||
next = last.replace(year=last.year + 1)
|
||||
else: # frequency == 'once':
|
||||
next = False
|
||||
res[plan.id] = next.isoformat()
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Plan Name', required=True, translate=True),
|
||||
'user_ids' : fields.many2many('res.users',
|
||||
|
@ -121,7 +141,11 @@ class gamification_goal_plan(osv.Model):
|
|||
help='Group that will receive a copy of the report in addition to the user'),
|
||||
'report_header' : fields.text('Report Header'),
|
||||
'remind_update_delay' : fields.integer('Remind delay',
|
||||
help="The number of days after which the user assigned to a manual goal will be reminded. Never reminded if no value or zero is specified.")
|
||||
help="The number of days after which the user assigned to a manual goal will be reminded. Never reminded if no value or zero is specified."),
|
||||
'last_report_date': fields.date('Last Report Date'),
|
||||
'next_report_date': fields.function(_get_next_report_date,
|
||||
type='date',
|
||||
string='Next Report Date'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -129,6 +153,7 @@ class gamification_goal_plan(osv.Model):
|
|||
'state': 'draft',
|
||||
'visibility_mode' : 'progressbar',
|
||||
'report_message_frequency' : 'onchange',
|
||||
'last_report_date' : fields.date.today
|
||||
}
|
||||
|
||||
def _check_nonzero_planline(self, cr, uid, ids, context=None):
|
||||
|
@ -167,25 +192,44 @@ class gamification_goal_plan(osv.Model):
|
|||
Create the goals for planlines not linked to goals (eg: modified the
|
||||
plan to add planlines)
|
||||
:param list(int) ids: the ids of the plans to update, if False will
|
||||
update only goals in progress."""
|
||||
update only plans in progress."""
|
||||
if not context: context = {}
|
||||
if not ids:
|
||||
ids = self.search(cr, uid, [('state', '=', 'inprogress')])
|
||||
|
||||
self.generate_goals_from_plan(cr, uid, ids, context=context)
|
||||
|
||||
# update goals
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
# we use yesterday to update the goals that just ended
|
||||
yesterday = date.today() - timedelta(days=1)
|
||||
goal_ids = goal_obj.search(cr, uid, [
|
||||
'&',
|
||||
('state', 'in', ('inprogress','inprogress_update', 'reached')),
|
||||
'|',
|
||||
('end_date', '>=', fields.date.today()),
|
||||
('end_date', '>=', yesterday.isoformat()),
|
||||
('end_date', '=', False)
|
||||
], context=context)
|
||||
goal_obj.update(cr, uid, goal_ids, context=context)
|
||||
|
||||
self.report_progress(cr, uid, ids, context=context)
|
||||
for plan in self.browse(cr, uid, ids, context=context):
|
||||
# goals closed but still opened at the last report date
|
||||
closed_goals_to_report = []
|
||||
for planline in plan.planline_ids:
|
||||
closed_goals_to_report.extend( goal_obj.search(cr, uid, [
|
||||
('planline_id','=',planline.id),
|
||||
('start_date', '>=', plan.last_report_date),
|
||||
('end_date', '<=', plan.last_report_date)
|
||||
]) )
|
||||
|
||||
if len(closed_goals_to_report) > 0:
|
||||
# some goals need a final report
|
||||
self.report_progress(cr, uid, plan, subset_goal_ids=closed_goals_to_report, context=context)
|
||||
self.write(cr, uid, plan.id, {'last_report_date':fields.date.today}, context=context)
|
||||
|
||||
if fields.date.today() == plan.next_report_date:
|
||||
self.report_progress(cr, uid, plan, context=context)
|
||||
self.write(cr, uid, plan.id, {'last_report_date':fields.date.today}, context=context)
|
||||
|
||||
|
||||
def action_start(self, cr, uid, ids, context=None):
|
||||
"""Start a draft goal plan
|
||||
|
@ -199,7 +243,7 @@ class gamification_goal_plan(osv.Model):
|
|||
|
||||
Create goals that haven't been created yet (eg: if added users of planlines)
|
||||
Recompute the current value for each goal related"""
|
||||
return self._update_all(cr, uid, ids, context=context)
|
||||
return self._update_all(cr, uid, ids=ids, context=context)
|
||||
|
||||
|
||||
def action_close(self, cr, uid, ids, context=None):
|
||||
|
@ -254,6 +298,12 @@ class gamification_goal_plan(osv.Model):
|
|||
res['domain'] = [('id','in', related_goal_ids)]
|
||||
return res
|
||||
|
||||
def action_report_progress(self, cr, uid, ids, context=None):
|
||||
"""Manual report of a goal, does not influence automatic report frequency"""
|
||||
for plan in self.browse(cr, uid, ids, context):
|
||||
self.report_progress(cr, uid, plan, context=context)
|
||||
return True
|
||||
|
||||
def generate_goals_from_plan(self, cr, uid, ids, context=None):
|
||||
"""Generate the list of goals linked to a plan.
|
||||
|
||||
|
@ -324,55 +374,112 @@ class gamification_goal_plan(osv.Model):
|
|||
return True
|
||||
|
||||
|
||||
def report_progress(self, cr, uid, ids, context=None, users=False):
|
||||
def report_progress(self, cr, uid, plan, context=None, users=False, subset_goal_ids=False):
|
||||
"""Post report about the progress of the goals
|
||||
|
||||
:param list(int) ids: the list of plan ids that need to be reported
|
||||
:param plan: the plan object that need to be reported
|
||||
:param list(res.users) users: the list of users that are concerned by
|
||||
the report. If False, will send the report to every user concerned
|
||||
(goal users and group that recieves a copy). Only used for plan with
|
||||
a visibility mode set to 'personal'."""
|
||||
a visibility mode set to 'personal'.
|
||||
:param list(int) goal_ids: the list of goal ids linked to the plan for
|
||||
the report. If not specified, use the goals for the current plan
|
||||
period. This parameter can be used to produce report for previous plan
|
||||
periods."""
|
||||
|
||||
context = context or {}
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
template_env = TemplateHelper()
|
||||
|
||||
for plan in self.browse(cr, uid, ids, context=context):
|
||||
(start_date, end_date) = start_end_date_for_period(plan.period)
|
||||
|
||||
if plan.visibility_mode == 'board':
|
||||
# generate a shared report
|
||||
planlines_boards = []
|
||||
if plan.visibility_mode == 'board':
|
||||
# generate a shared report
|
||||
planlines_boards = []
|
||||
|
||||
for planline in plan.planline_ids:
|
||||
|
||||
domain = [
|
||||
('planline_id', '=', planline.id),
|
||||
('state', 'in', ('inprogress', 'inprogress_update',
|
||||
'reached', 'failed')),
|
||||
]
|
||||
|
||||
if subset_goal_ids:
|
||||
goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
common_goal_ids = [goal.id 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.isoformat()))
|
||||
if end_date:
|
||||
domain.append(('end_date', '=', end_date.isoformat()))
|
||||
common_goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
|
||||
board_goals = []
|
||||
for goal in goal_obj.browse(cr, uid, common_goal_ids, context=context):
|
||||
board_goals.append({
|
||||
'user': goal.user_id,
|
||||
'current':goal.current,
|
||||
'target_goal':goal.target_goal,
|
||||
'completeness':goal.completeness,
|
||||
})
|
||||
|
||||
# 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))
|
||||
planlines_boards.append({'goal_type':planline.type_id.name, 'board_goals':sorted_board})
|
||||
|
||||
body_html = template_env.get_template('group_progress.mako').render({'object':plan, 'planlines_boards':planlines_boards})
|
||||
|
||||
self.message_post(cr, uid, plan.id,
|
||||
body=body_html,
|
||||
partner_ids=[(6, 0, [user.partner_id.id for user in plan.user_ids])],
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
if plan.report_message_group_id:
|
||||
self.pool.get('mail.group').message_post(cr, uid, plan.report_message_group_id.id,
|
||||
body=body_html,
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
|
||||
else:
|
||||
# generate individual reports
|
||||
for user in users or plan.user_ids:
|
||||
related_goal_ids = []
|
||||
for planline in plan.planline_ids:
|
||||
|
||||
(start_date, end_date) = start_end_date_for_period(plan.period)
|
||||
domain = [
|
||||
('planline_id', '=', planline.id),
|
||||
('user_id', '=', user.id),
|
||||
('state', 'in', ('inprogress', 'inprogress_update',
|
||||
'reached', 'failed')),
|
||||
]
|
||||
if start_date:
|
||||
domain.append(('start_date', '=', start_date.isoformat()))
|
||||
|
||||
if subset_goal_ids:
|
||||
goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
related_goal_ids.extend( [goal.id for goal in goal_ids if goal in subset_goal_ids] )
|
||||
|
||||
board_goals = []
|
||||
goal_ids = goal_obj.search(cr, uid, domain, context=context)
|
||||
for goal in goal_obj.browse(cr, uid, goal_ids, context=context):
|
||||
board_goals.append({
|
||||
'user': goal.user_id,
|
||||
'current':goal.current,
|
||||
'target_goal':goal.target_goal,
|
||||
'completeness':goal.completeness,
|
||||
})
|
||||
else:
|
||||
# if no subset goals, use the dates for restriction
|
||||
if start_date:
|
||||
domain.append(('start_date', '=', start_date.isoformat()))
|
||||
if end_date:
|
||||
domain.append(('end_date', '=', end_date.isoformat()))
|
||||
|
||||
# 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))
|
||||
planlines_boards.append({'goal_type':planline.type_id.name, 'board_goals':sorted_board})
|
||||
related_goal_ids.extend( goal_obj.search(cr, uid, domain, context=context) )
|
||||
|
||||
body_html = template_env.get_template('group_progress.mako').render({'object':plan, 'planlines_boards':planlines_boards})
|
||||
if len(related_goal_ids) == 0:
|
||||
continue
|
||||
|
||||
variables = {
|
||||
'object':plan,
|
||||
'user':user,
|
||||
'goals':goal_obj.browse(cr, uid, related_goal_ids, context=context)
|
||||
}
|
||||
body_html = template_env.get_template('personal_progress.mako').render(variables)
|
||||
|
||||
self.message_post(cr, uid, plan.id,
|
||||
body=body_html,
|
||||
partner_ids=[(6, 0, [user.partner_id.id for user in plan.user_ids])],
|
||||
partner_ids=[(6, 0, [user.partner_id.id])],
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
if plan.report_message_group_id:
|
||||
|
@ -380,60 +487,8 @@ class gamification_goal_plan(osv.Model):
|
|||
body=body_html,
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
|
||||
else:
|
||||
# generate individual reports
|
||||
for user in users or plan.user_ids:
|
||||
goal_ids = self.get_current_related_goals(cr, uid, plan.id, user.id, context=context)
|
||||
if len(goal_ids) == 0:
|
||||
continue
|
||||
|
||||
variables = {
|
||||
'object':plan,
|
||||
'user':user,
|
||||
'goals':goal_obj.browse(cr, uid, goal_ids, context=context)
|
||||
}
|
||||
body_html = template_env.get_template('personal_progress.mako').render(variables)
|
||||
|
||||
self.message_post(cr, uid, plan.id,
|
||||
body=body_html,
|
||||
partner_ids=[(6, 0, [user.partner_id.id])],
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
if plan.report_message_group_id:
|
||||
self.pool.get('mail.group').message_post(cr, uid, plan.report_message_group_id.id,
|
||||
body=body_html,
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
return True
|
||||
|
||||
|
||||
def get_current_related_goals(self, cr, uid, plan_id, user_id, context=None):
|
||||
"""Get the ids of goals linked to a plan for the current instance
|
||||
|
||||
If several goals are linked to the same planline and user, only the
|
||||
latest instance of the plan is checked (eg: if the plan is monthly,
|
||||
return the goals started the 1st of this month).
|
||||
"""
|
||||
|
||||
plan = self.browse(cr, uid, plan_id, context=context)
|
||||
(start_date, end_date) = start_end_date_for_period(plan.period)
|
||||
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
related_goal_ids = []
|
||||
|
||||
for planline in plan.planline_ids:
|
||||
domain = [('planline_id', '=', planline.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.extend(goal_ids)
|
||||
|
||||
return related_goal_ids
|
||||
|
||||
|
||||
class gamification_goal_planline(osv.Model):
|
||||
"""Gamification goal planline
|
||||
|
@ -477,4 +532,4 @@ class gamification_goal_planline(osv.Model):
|
|||
store={
|
||||
'gamification.goal.type': (_get_planline_types, ['sequence'], 10),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<button string="Close Plan" type="object" name="action_close" states="inprogress" class="oe_highlight"/>
|
||||
<button string="Reset to Draft" type="object" name="action_cancel" states="inprogress"/>
|
||||
<button string="Reset Completion" type="object" name="action_reset" states="done"/>
|
||||
<button string="Report Progress" type="object" name="report_progress" states="inprogress,done" groups="base.group_no_one"/>
|
||||
<button string="Report Progress" type="object" name="action_report_progress" states="inprogress,done" groups="base.group_no_one"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet>
|
||||
|
|
Loading…
Reference in New Issue