[IMP] adding features

bzr revid: mat@openerp.com-20130415140401-qzg3f0lz2i9b6kki
This commit is contained in:
Martin Trigaux 2013-04-15 16:04:01 +02:00
parent c005944f7b
commit 7b8b0ed467
6 changed files with 192 additions and 65 deletions

View File

@ -193,6 +193,8 @@ class gamification_badge(osv.Model):
string="Automatic Rule",
help="Can this badge be automatically rewarded",
required=True),
'challenge_ids': fields.one2many('gamification.goal.plan', 'reward_id',
string="Granted upon completion of"),
'compute_code': fields.char('Compute Code',
help="The name of the python method that will be executed to verify if a user can receive this badge."),

View File

@ -7,6 +7,7 @@
<field name="name">Goals</field>
<field name="res_model">gamification.goal</field>
<field name="view_mode">tree,form,kanban</field>
<field name="context">{'search_default_group_by_user': True, 'search_default_group_by_type': True}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a goal.

View File

@ -20,6 +20,7 @@
##############################################################################
from openerp.osv import fields, osv
from openerp.tools.translate import _
from templates import TemplateHelper
@ -104,6 +105,7 @@ class gamification_goal_plan(osv.Model):
_columns = {
'name': fields.char('Plan Name', required=True, translate=True),
'description': fields.text('Description', translate=True),
'state': fields.selection([
('draft', 'Draft'),
('inprogress', 'In Progress'),
@ -113,22 +115,47 @@ class gamification_goal_plan(osv.Model):
required=True),
'manager_id': fields.many2one('res.users',
string='Responsible', help="The user responsible for the plan."),
'start_date': fields.date('Planned Start Date', help="The day a new plan will be automatically started. The start and end dates for goals are still defined by the periodicity (eg: weekly goals run from Monday to Sunday)."),
'start_date': fields.date('Planned Start Date',
help="The day a new plan will be automatically started. If no periodicity is set, will use this date as the goal start date."),
'end_date': fields.date('Planned End Date',
help="The day a new plan will be automatically closed. If no periodicity is set, will use this date as the goal end date."),
'user_ids': fields.many2many('res.users',
'user_ids': fields.many2many('res.users', 'user_ids',
string='Users',
help="List of users to which the goal will be set"),
'autojoin_group_id': fields.many2one('res.groups',
string='Auto-subscription Group',
help='Group of users whose members will automatically be added to the users'),
'planline_ids': fields.one2many('gamification.goal.planline',
'plan_id',
'subscription_action': fields.selection([
('automatic', 'The user is subscribed automatically'),
('approve', 'The user has to approve the challenge'),
],
string="Subscription approval",
help="What happens when the user is added to a challenge (manually or automatically) ?",
required=True),
'proposed_user_ids': fields.many2many('res.users', 'proposed_user_ids',
string="Propose to users"),
'proposed_mail_group_ids': fields.many2many('mail.group', 'proposed_mail_group_ids',
string="Propose to mail groups"),
'proposed_later_user_ids': fields.many2many('res.users', 'proposed_later_user_ids',
string='Users to Remind',
help="List of users that have asked to decide later if they approve the challenge"),
'proposed_refused_user_ids': fields.many2many('res.users', 'refused_approval_user_ids',
string='Discard Request Users',
help="List of users that have discared the approval request"),
'propose_after_login': fields.integer("Propose challenge after login", help="Number of minutes"),
'planline_ids': fields.one2many('gamification.goal.planline', 'plan_id',
string='Planline',
help="list of goals that will be set",
help="List of goals that will be set",
required=True),
'planline_count': fields.function(_planline_count, type='integer', string="Planlines"),
'reward_id': fields.many2one('gamification.badge', string="Reward upon completion"),
'reward_bests': fields.integer('Number of Best Perforers Rewared'),
'reward_failure': fields.boolean('Grant if not succeed'),
'period': fields.selection([
('once', 'Non recurring'),
('daily', 'Daily'),
@ -145,11 +172,11 @@ class gamification_goal_plan(osv.Model):
],
string="Display Mode", required=True),
'report_message_frequency': fields.selection([
('never','Never'),
('onchange','On change'),
('daily','Daily'),
('weekly','Weekly'),
('monthly','Monthly'),
('never', 'Never'),
('onchange', 'On change'),
('daily', 'Daily'),
('weekly', 'Weekly'),
('monthly', 'Monthly'),
('yearly', 'Yearly')
],
string="Report Frequency", required=True),
@ -165,10 +192,10 @@ class gamification_goal_plan(osv.Model):
string='Next Report Date'),
'category': fields.selection([
('hr', 'Human Ressources / Appraisals'),
('other', 'Other'),
('hr', 'Human Ressources / Engagement'),
('other', 'Settings / Gamification Tools'),
],
string="Appears in", help="Only HR plans can be accessed by managers", required=True)
string="Appears in", help="Define the visibility of the challenge through menus", required=True),
}
_defaults = {
@ -180,8 +207,12 @@ class gamification_goal_plan(osv.Model):
'start_date': fields.date.today,
'manager_id': lambda s, cr, uid, c: uid,
'category': 'hr',
'subscription_action': 'automatic',
'reward_failure': False,
}
_sort = 'end_date start_date name'
def write(self, cr, uid, ids, vals, context=None):
"""Overwrite the write method to add the user of groups"""
context = context or {}
@ -196,8 +227,23 @@ class gamification_goal_plan(osv.Model):
if new_group:
self.plan_subscribe_users(cr, uid, ids, [user.id for user in new_group.users], context=context)
if 'proposed_user_ids' in vals:
for plan in self.browse(cr, uid, ids, context=context):
if plan.subscription_action == 'approve':
puser_ids = [puser.id for puser in plan.proposed_user_ids]
ruser_ids = [ruser.id for ruser in plan.proposed_refused_user_ids if ruser.id in puser_ids]
if len(ruser_ids) > 0:
raise osv.except_osv(_('Error!'), _('Can not propose a challenge to an user that has refused it'))
auser_ids = [auser.id for auser in plan.proposed_later_user_ids if auser.id in puser_ids]
if len(auser_ids) > 0:
raise osv.except_osv(_('Error!'), _('Can not propose a challenge to an user that has cast aside it'))
user_ids = [user.id for user in plan.user_ids if user.id in puser_ids]
if len(user_ids) > 0:
raise osv.except_osv(_('Error!'), _('Can not propose a challenge to an user already assigned to it'))
return write_res
##### Update #####
def _cron_update(self, cr, uid, context=None, ids=False):
"""Daily cron check.
@ -215,6 +261,12 @@ class gamification_goal_plan(osv.Model):
('start_date', '<=', fields.date.today())])
self.action_start(cr, uid, planned_plan_ids, context=context)
# close planned plans
planned_plan_ids = self.search(cr, uid, [
('state', '=', 'inprogress'),
('end_date', '>=', fields.date.today())])
self.action_close(cr, uid, planned_plan_ids, context=context)
if not ids:
ids = self.search(cr, uid, [('state', '=', 'inprogress')])
@ -273,10 +325,12 @@ class gamification_goal_plan(osv.Model):
self.pool.get('gamification.goal').update(cr, uid, goal_ids, context=context)
return True
##### User actions #####
def action_start(self, cr, uid, ids, context=None):
"""Start a draft goal plan
Change the state of the plan to in progress and genereate related goals
Change the state of the plan to in progress and generate related goals
"""
# subscribe users if autojoin group
for plan in self.browse(cr, uid, ids, context=context):
@ -327,6 +381,8 @@ class gamification_goal_plan(osv.Model):
self.report_progress(cr, uid, plan, context=context)
return True
##### Automatic actions #####
def generate_goals_from_plan(self, cr, uid, ids, context=None):
"""Generate the list of goals linked to a plan.
@ -337,6 +393,12 @@ class gamification_goal_plan(osv.Model):
for plan in self.browse(cr, uid, ids, context):
(start_date, end_date) = start_end_date_for_period(plan.period)
# if no periodicity, use plan dates
if not start_date and plan.start_date:
start_date = plan.start_date
if not end_date and plan.end_date:
end_date = plan.end_date
for planline in plan.planline_ids:
for user in plan.user_ids:
@ -391,9 +453,11 @@ class gamification_goal_plan(osv.Model):
# remove duplicates
unified_subscription = list(set(subscription))
self.write(cr, uid, ids, {'user_ids': [(4, user) for user in unified_subscription]}, context=context)
self.write(cr, uid, [plan.id], {'user_ids': [(4, user) for user in unified_subscription]}, context=context)
return True
##### JS utilities #####
def get_board_goal_info(self, cr, uid, plan, subset_goal_ids=False, context=None):
"""Get the list of latest goals for a plan, sorted by user ranking for each planline"""
@ -478,6 +542,8 @@ class gamification_goal_plan(osv.Model):
else:
return values
##### Reporting #####
def report_progress(self, cr, uid, plan, context=None, users=False, subset_goal_ids=False):
"""Post report about the progress of the goals
@ -537,6 +603,30 @@ class gamification_goal_plan(osv.Model):
subtype='mail.mt_comment')
return True
##### Suggestions #####
def accept_challenge(self, cr, uid, plan_id, user_id=None, context=None):
"""The user accept the suggested challenge"""
context = context or {}
user_id = user_id or uid
self.write(cr, uid, [plan_id], {'proposed_user_ids': (3, user_id), 'user_id': (4, user_id)}, context=context)
return self.generate_goals_from_plan(cr, uid, [plan_id], context=context)
def discard_challenge(self, cr, uid, plan_id, user_id=None, context=None):
"""The user discard the suggested challenge"""
context = context or {}
user_id = user_id or uid
return self.write(cr, uid, [plan_id], {'proposed_user_ids': (3, user_id), 'proposed_refused_user_ids': (4, user_id)}, context=context)
def postpone_challenge(self, cr, uid, plan_id, user_id=None, context=None):
"""The user ask to be reminded later for the suggested challenge"""
context = context or {}
user_id = user_id or uid
return self.write(cr, uid, [plan_id], {'proposed_user_ids': (3, user_id), 'proposed_later_user_ids': (4, user_id)}, context=context)
def get_suggestions_info(self, cr, uid, context=None):
pass
class gamification_goal_planline(osv.Model):
"""Gamification goal planline

View File

@ -3,23 +3,24 @@
<data>
<record id="goal_plan_list_action" model="ir.actions.act_window">
<field name="name">Goal Plans</field>
<field name="name">Challenges</field>
<field name="res_model">gamification.goal.plan</field>
<field name="view_mode">kanban,tree,form</field>
<field name="context">{'search_default_inprogress':True, 'default_inprogress':True}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a goal plan.
Click to create a challenge.
</p>
<p>
Assign a list of goals to chosen users to evaluate them.
The plan can use a period (weekly, monthly...) for automatic creation of goals.
The challenge can use a period (weekly, monthly...) for automatic creation of goals.
The goals are created for the specified users or member of the group.
</p>
</field>
</record>
<record id="goal_plan_list_view" model="ir.ui.view">
<field name="name">Goal Plans List</field>
<field name="name">Challenges List</field>
<field name="model">gamification.goal.plan</field>
<field name="arch" type="xml">
<tree string="Goal types" colors="blue:state == 'draft';grey:state == 'done'">
@ -38,14 +39,14 @@
<field name="context">{'search_default_group_by_type': True, 'search_default_inprogress': True, 'search_default_plan_id': active_id, 'default_plan_id': active_id}</field>
<field name="help" type="html">
<p>
There is no goals associated to this plan matching your search.
Make sure that your plan is active and associated to at least one user.
There is no goals associated to this challenge matching your search.
Make sure that your challenge is active and assigned to at least one user.
</p>
</field>
</record>
<record id="goal_plan_form_view" model="ir.ui.view">
<field name="name">Goal Plan Form</field>
<field name="name">Challenge Form</field>
<field name="model">gamification.goal.plan</field>
<field name="arch" type="xml">
<form string="Goal types" version="7.0">
@ -83,38 +84,51 @@
<group>
<field name="manager_id"/>
<field name="start_date" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="end_date" attrs="{'readonly':[('state','!=','draft')]}"/>
</group>
</group>
<notebook>
<page string="Goals">
<field name="planline_ids" nolabel="1" colspan="4">
<tree string="Planline List" version="7.0" editable="bottom" >
<field name="type_id"/>
<field name="type_condition"/>
<field name="target_goal"/>
<field name="type_full_suffix"/>
</tree>
</field>
</page>
<page string="Advanced Options">
<group string="Subscribe Users Automatically">
<field name="autojoin_group_id" />
</group>
<group string="Notification Messages">
<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')]}" />
</group>
<group string="Reminders for Manual Goals">
<label for="remind_update_delay" />
<div>
<field name="remind_update_delay" class="oe_inline"/> days
</div>
</group>
<group string="Category" groups="base.group_no_one">
<field name="category" widget="radio" />
</group>
</page>
<page string="Goals">
<field name="planline_ids" nolabel="1" colspan="4">
<tree string="Planline List" version="7.0" editable="bottom" >
<field name="type_id"/>
<field name="type_condition"/>
<field name="target_goal"/>
<field name="type_full_suffix"/>
</tree>
</field>
</page>
<page string="Reward">
<group>
<field name="reward_id"/>
<field name="reward_bests" attrs="{'invisible': [('reward_id','=', False)]}" />
<field name="reward_failure" attrs="{'invisible': [('reward_id','=', False)]}" />
</group>
</page>
<page string="Advanced Options">
<group string="Subscribe Users Automatically">
<field name="autojoin_group_id" />
<field name="subscription_action" />
<field name="proposed_user_ids" attrs="{'invisible':[('subscription_action','=','automatic')]}" widget="many2many_tags" />
<field name="proposed_mail_group_ids" attrs="{'invisible':[('subscription_action','=','automatic')]}" widget="many2many_tags" />
<field name="proposed_later_user_ids" attrs="{'invisible':[('subscription_action','=','automatic')]}" widget="many2many_tags" />
<field name="proposed_refused_user_ids" attrs="{'invisible':[('subscription_action','=','automatic')]}" widget="many2many_tags" />
</group>
<group string="Notification Messages">
<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')]}" />
</group>
<group string="Reminders for Manual Goals">
<label for="remind_update_delay" />
<div>
<field name="remind_update_delay" class="oe_inline"/> days
</div>
</group>
<group string="Category" groups="base.group_no_one">
<field name="category" widget="radio" />
</group>
</page>
</notebook>
@ -128,7 +142,7 @@
</record>
<record model="ir.ui.view" id="view_goal_plan_kanban">
<field name="name">Goal Plan Kanban</field>
<field name="name">Challenge Kanban</field>
<field name="model">gamification.goal.plan</field>
<field name="arch" type="xml">
<kanban version="7.0" class="oe_background_grey">
@ -141,7 +155,7 @@
<div class="oe_dropdown_toggle oe_dropdown_kanban">
<span class="oe_e">í</span>
<ul class="oe_dropdown_menu">
<li><a type="edit">Configure Goal Plan</a></li>
<li><a type="edit">Configure Challenge</a></li>
</ul>
</div>
<div class="oe_kanban_content">
@ -180,13 +194,13 @@
<record id="goal_plan_search_view" model="ir.ui.view">
<field name="name">Goal Plan Search</field>
<field name="name">Challenge Search</field>
<field name="model">gamification.goal.plan</field>
<field name="arch" type="xml">
<search string="Search Goal Plans">
<filter name="draft_inprogress" string="Non-closed Plans"
domain="[('state', 'in', ('inprogress', 'draft'))]"/>
<filter name="hr_plans" string="HR Plans"
<search string="Search Challenges">
<filter name="inprogress" string="Running Challenges"
domain="[('state', '=', 'inprogress')]"/>
<filter name="hr_plans" string="HR Challenges"
domain="[('category', '=', 'hr')]"/>
<field name="name"/>
<group expand="0" string="Group By...">

View File

@ -41,12 +41,11 @@
<tr>
<th colspan="4" t-attf-title="#{planline.type_description ? planline.type_description : ''}">
<t t-esc="planline.type_name"/>
(Goal: <span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="planline.target_goal" /></span><t t-if="planline.type_unit"> <t t-esc="planline.type_unit"/></t>)
(Goal: max <span t-attf-class="#{planline.type_monetary ? 'oe_goal_field_monetary' : ''}"><t t-esc="planline.target_goal" /></span><t t-if="planline.type_unit"> <t t-esc="planline.type_unit"/></t>)
<t t-if="planline.type_computation_mode == 'manually' or planline.type_action">
<a class="oe_goal_action" t-att-id="planline.own_goal_id">modify</a>
</t>
</th>
<th></th><th></th>
</tr>
<tr>
<th>#</th>

View File

@ -413,27 +413,48 @@
<field name="act_window_id" ref="action_hr_evaluation_interview_tree"/>
</record>
<record id="goals_menu_groupby_act" model="ir.actions.act_window">
<record id="goals_menu_groupby_action" model="ir.actions.act_window">
<field name="res_model">gamification.goal</field>
<field name="view_type">form</field>
<field name="name">Goals History</field>
<field name="view_mode">tree,kanban</field>
<field name="context">{'search_default_group_by_user': True, 'search_default_group_by_type': True}</field>
<field name="domain">[('plan_id.category', '=', 'hr')]</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a goal.
</p>
<p>
A goal is defined by a user and a goal type.
Goals can be created automatically by using goal plans.
</p>
</field>
</record>
<record id="goal_plan_list_action2" model="ir.actions.act_window">
<field name="name">Goal Plans</field>
<field name="domain">[('category', '=', 'hr')]</field>
<field name="inherit_id" ref="gamification.goal_plan_list_action"/>
<field name="name">Challenges</field>
<field name="res_model">gamification.goal.plan</field>
<field name="view_mode">kanban,form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="domain">[('category', '=', 'hr')]</field>
<field name="context">{'search_default_inprogress':True, 'default_inprogress':True}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a challenge.
</p>
<p>
Assign a list of goals to chosen users to evaluate them.
The challenge can use a period (weekly, monthly...) for automatic creation of goals.
The goals are created for the specified users or member of the group.
</p>
</field>
</record>
<menuitem name="Interview Requests" parent="menu_eval_hr" id="menu_open_hr_evaluation_interview_requests"
action="action_hr_evaluation_interview_tree"/>
<menuitem id="gamification_plan_menu_hr" parent="menu_eval_hr" action="goal_plan_list_action2" groups="base.group_hr_user"/>
<menuitem id="gamification_goal_menu_hr" parent="menu_eval_hr" action="goals_menu_groupby_act" groups="base.group_hr_user"/>
<menuitem id="gamification_goal_menu_hr" parent="menu_eval_hr" action="goals_menu_groupby_action" groups="base.group_hr_user"/>
<!-- Email Compose message Action-->
<act_window