[REF] gamification: add user_from_id on badge, remove outdated-doc, remove useless message_post call

bzr revid: mat@openerp.com-20131223155404-h4in4ocr8jakq3ff
This commit is contained in:
Martin Trigaux 2013-12-23 16:54:04 +01:00
parent aec8f50b20
commit c0eef31160
12 changed files with 292 additions and 251 deletions

View File

@ -616,6 +616,242 @@
c3eZ58/32vV1fV1f19f1dX1dX9fX9XV9XV/X1/V1fb0a1/8He8q//0YPCp0AAAAASUVORK5CYII=</field>
</record>
<record id="badge_hidden" model="gamification.badge">
<field name="name">Hidden</field>
<field name="description">You have found the hidden badge</field>
<field name="rule_auth">nobody</field>
<field name="image">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
oZLwTwSrpfvBrHNcSUesOjyfJLWUiLcDPe1haF///Zh9t1HQUWnFS9BX3I8e/xzHFh2TVUtN+Lbz
vXeNyl1Q937yIlQiWMLFMViuueWucSU84WK7R7jWAjcAr06aDOj4AOv7+ugevpnD+mYMu9hyYaOF
iWGEGAnPEVn4LqcmxzAKk8wXqQAPA89QO5jsuqlinaPKOF+zHqGqeIQKESsRLOGFHZebfOq6rjZH
uNqd7xOOeN0NbAWG1rWjOgZuIJvcixUZohjqQ2sbrW2MJppvGgOtTNrVEpXiPIPlQ5w9f5r5hQmc
UO4c8BjwLMulgFyhynmEyhWpHLW1q7IIlQiWcHX9Y3iEy+u6XPFq8whX3PnzVzgCNggwkDToHryR
waGdHK7uaIqGSRglenKPUZl9hEPnl9zfrgCPAA+xXBzPrVdWdMTIFaqsR6TyLC+kuweUJfQTwRKu
oZ+8ritMLQnVdV5tjoC5n7jz6QTWABud8HFzbwzKoR6i8U529LcxG7uJaNsI58p9KKrYNg0/22hh
olTNPSllclPkAOfm57HSJ8hmZykUcxRLRco2aWr5UsdZruRpeZxUyRP25Txila9bm6rUrU+JUIlg
CddRuJTHdYXrnFf9x3VdEeeziVrJm80sp1BEN3VAJrqFdV0xThk30hk1wEximQnaI7Bg92FrN31V
o7DRujazjYsUzdROyHbBg6vadzbGc79uM/KE7DyZkqZLzZEqwTBjZLMLRAunmEnlmSsDy4vgM9TS
D445guO9zcgrUgWPULkCVagTKa+bkrBPBEtYBfEyLuK8vO6r/uP+ecT5++4a2Q5gOzBKrWLqBYRN
xZo2g5F2E6J9nGEn6zpM+tqTPFJ8yfMertPMcUv0ANmyJlvRpIo2qaJNoVTilsgTnM9ajGcsZvMX
TckoA2eAk44wTXuExVswseIJ5Yp1QlXwfLzhXn3IJyIlgiU0oA/rxStUJ2BRj2DFnE+9eLkCZnrW
yFyn5mbkez9uvtgLXchb9giKKyZZj2NKsZxW4Doib4hWL1DecK9UJ1Tur0uef7fq+X+JSIlgCT4W
L/cT8giYG0J6xapeuCKev296RMzwfFV1X72uj4uEWF6h8N7zqD3CVC9Q9SLlFar678uev29dZE1K
REoESwhI/xp1ImZ6RMwrZOG6UNHrukIe4fJ+6kXsYoKl60TKFZIXEimvWFU8604Vz59XX8BBiUiJ
YAlN4r4uJmKuEzPqhOlS319MtLybApdyU7pOYNzvq3XCVf/VrnNOlxInESkRLKEFRKw+nPSKWb2w
1f/auIjDulg4eLFQ0Ou67Iv8nr7ER8RJBEsQnjcm1AsIm6pzbJdCv4CIvdD3iDgJIljC9R4vVzKO
9FX+mSAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAI
giAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIghBg/j+I/UnoNLmiuQAAAABJRU5ErkJggg==</field>
<field name="active" eval="False" />
</record>
<record id="badge_idea" model="gamification.badge">
<field name="name">Brilliant</field>
<field name="description">With your brilliant ideas, you are an inspiration to others.</field>
@ -892,8 +1128,8 @@
<field name="name">Received Badge</field>
<field name="body_html"><![CDATA[
<p>Congratulation, you have received the badge <strong>${object.badge_id.name}</strong> !
% if ctx["user_from"]
This badge was granted by <strong>${ctx["user_from"]}</strong>.
% if object.user_from_id
This badge was granted by <strong>${object.user_from_id.name}</strong>.
% endif
</p>

View File

@ -1,107 +0,0 @@
How to create new challenge for my addon
========================================
Running example
+++++++++++++++
A module to create and manage groceries lists has been developped. To motivate users to use it, a challenge (gamification.goal.plan) is developped. This how to will explain the creation of a dedicated module and the XML file for the required data.
Module
++++++
The challenge for my addon will consist of an auto-installed module containing only the definition of goals. Goal type are quite technical to create and should not be seen or modified through the web interface. By default, goal types can only be modified by "Gamification Manager". After installing the hr_gamification module, HR Officers will be able to see goal types but not modying it.
If our groceries module is called ``groceries``, the addons structure will be consisted of three addons :
::
addons/
...
gamification/
groceries/
groceries_gamification/
__openerp__.py
groceries_goals.xml
The ``__openerp__.py`` file containing the following information :
::
{
...
'depends': ['gamification','groceries'],
'data': ['groceries_goals.xml'],
'auto_install': True,
}
Goal type definition
+++++++++++++++++++++
For our groceries module, we would like to evaluate the total number of items written on lists during a month. The evaluated value being a number of line in the database, the goal type computation mode will be ``count``. The XML data file will contain the following information :
::
<record model="gamification.goal.type" id="type_groceries_nbr_items">
<field name="name">Number of items</field>
<field name="computation_mode">count</field>
...
</record>
To be able to compute the number of lines, the model containing groceries is required. To be able to refine the computation on a time period, a reference date field should be mention. This field date must be a field of the selected model. In our example, we will use the ``gorceries_item`` model and the ``shopping_day`` field.
::
<record model="gamification.goal.type" id="type_groceries_nbr_items">
...
<field name="model_id" eval="ref('groceries.model_groceries_item')" />
<field name="field_date_id" eval="ref('groceries.field_groceries_item_shopping_day')" />
</record>
As we do not want to count every recorded item, we will use a domain to restrict the selection on the user (display the count only for the items the users has bought) and the state (only the items whose list is confirmed are included). The user restriction is made with the keyword ``user`` in the domain and should correspond to a many2one field with the relation ``res.users``. During the evaluation, it is replaced by the user of the linked goal. As we need the user ID of, we user ``user.id``.
::
<record model="gamification.goal.type" id="type_groceries_nbr_items">
...
<field name="domain">[('shopper_id', '=', user.id), ('list_id.state', '=', 'confirmed')]</field>
</record>
An action can also be defined to help users to quickly reach the screen where they will be able to modify their current value. This is done by adding the XML ID of the ir.action we want to call. In our example, we would like to open the grocery list form view owned by the user.
If we do not specify a res_id to the action, only the list of records can be displayed. The restriction is done with the field ``res_id_field`` containing the field name from the user profile containing the required id. The parsing mechanism is the same as for the domain of a goal, using the keyword 'user' that wil lbe replaced by the current user. In our example, we assume the res.users model has been extended with a many2one field ``groceries_list`` to the model ``groceries.list``.
::
<record model="gamification.goal.type" id="type_groceries_nbr_items">
...
<field name="action_id">groceries.action_groceries_list_form</field>
<field name="res_id_field">user.groceries_list.id</field>
</record>
Plan definition
++++++++++++++++
Once all the goal types are defined, a challenge (or goal plan) can be created. In our example, we would like to create a plan "Discover the Groceries Module" with simple tasks applied to every new user in the group ``groceries.shoppers_group``. This goal plan should only be applied once by user and with no ending period, no dates or peridocity is then selected. The goal will be started manually but specifying a value to ``start_date`` can make it start automatically.
::
<record model="gamification.goal.plan" id="plan_groceries_discover">
<field name="name">Discover the Groceries Module</field>
<field name="period">once</field>
<field name="visibility_mode">progressbar</field>
<field name="report_message_frequency">never</field>
<field name="planline_ids" eval="[(4, ref('planline_groceries_discover1'))]"/>
<field name="autojoin_group_id" eval="ref('groceries.shoppers_group')" />
</record>
To add goal types to a plan, planlines must be created. The value to reach is defined for a planline, this will be the ``target_goal`` for each goal generated.
::
<record model="gamification.goal.planline" id="planline_groceries_discover1">
<field name="type_id" eval="ref('type_groceries_nbr_items')" />
<field name="target_goal">3</field>
<field name="plan_id" eval="ref('plan_groceries_discover')" />
</record>

View File

@ -1,44 +0,0 @@
.. _gamification_goal:
gamification.goal
=================
Models
++++++
``gamification.goal`` for the generated goals from plans
Fields
++++++
- ``type_id`` : The related gamification.goal.type object.
- ``user_id`` : The user responsible for the goal. Goal type domain filtering on the user id will use that value.
- ``planline_id`` : if the goal is generated from a plan, the planline used to generate this goal
- ``plan_id`` : if the goal is generated from a plan, related link from planline_id.plan_id
- ``start_date`` : the starting date for goal evaluation. If a goal is evaluated using a date field (eg: creation date of an invoice), this field will be used in the domain. Without starting date, every past recorded data will be considered in the goal type computation.
- ``end_date`` : the end date for goal evaluation, similar to start_date. When an end_date is passed, the goal update method will change to status to reached or failed depending of the current value.
- ``target_goal`` : the numerical value to reach (higher or lower depending of goal type) to reach a goal
- ``current`` : current computed value of the goal
- ``completeness`` : percentage of completion of a goal
- ``state`` :
- ``draft`` : goal not active and displayed in user's goal list. Only present for manual creation of goal as plans generate goals in progress.
- ``inprogress`` : a goal is started and is not closed yet
- ``inprogress_update`` : in case of manual goal, a number of day can be specified. If the last manual update from the user is older than this number of days, a reminder will be sent and the state changed to this.
- ``reached`` : the goal is succeeded
- ``failed`` : the goal is failed
- ``canceled`` : state if the goal plan is canceled
- ``remind_update_delay`` : the number of day before an inprogress goal is set to inprogress_update and a reminder is sent.
- ``last_update`` : the date of the last modification of this goal
- ``computation_mode`` : related field from the linked goal type
- ``type_description`` : related field from the linked goal type
- ``type_suffix`` : related field from the linked goal type
- ``type_condition`` : related field from the linked goal type
- ``type_display`` : related field from the linked goal type
Methods
+++++++
- ``update`` :
Compute the current value of goal and change states accordingly and send reminder if needed.
- ``get_action`` :
Returns the action description specified for the goal modification. If an action XML ID is specified in the goal type definition it will be used. If a goal is manual, the action is a simple wizard to input a new value.

View File

@ -1,42 +0,0 @@
.. _gamification_goal_type:
gamification.goal.type
======================
Models
++++++
``gamification.goal.type`` for the shared behaviour of goals
Fields
++++++
- ``name`` : The name of the goal type.
- ``description`` : Explain briefly in non-technical terms what the goal evaluates
- ``computation_mode`` : How is computed the current value for each individual goal
- ``manually`` : the user will set the value itself, no computation
- ``count`` : the result is the number of lines returned by a search (eg: number of phone calls)
- ``sum`` : the total of the value of a chosen field for each record returned by the search (eg: total amount of all invoices)
- ``python`` : for complex computation, will execute a chosen method
- ``display_mode`` : How is represented the current value of a goal
- ``progress`` : numerical value (eg: an amount)
- ``checkbox`` : boolean value with only two state: todo and done (eg: select a timezone)
- ``suffix`` : text suffix added to the result
- ``full_suffix`` : function field combining the monetary and suffix field (eg: €/month, $ expected)
- ``model_id`` : the model to evaluate for count and sum goals (eg: Invoices)
- ``field_id`` : for sum goals only, the field of model_id that will be evaluated through the computation
- ``field_date_id`` : the date to evaluate to restrict the search on a time interval for count and sum goals (eg: validation date)
- ``domain`` : Additional restrictions in the form of a domain. To restric the search to a user, use the keyword 'user', can be chained. Eg: ``[('state', '=', 'done'), ('user_id', '=', user.id)]`` or ``[('company_id', '=', user.company_id.id)]``
- ``compute_code`` : for python goals only, the method of type gamification.goal.type to execute (eg: self.my_method(cr, uid))
- ``condition`` : when is the goal considered as reacher
- ``higher`` : when the current value is higher or equal than the target
- ``lower`` : when the current value is smaller or equal than the target
- ``sequence`` : to order list of goals in a challenger
- ``action_id`` : the XML id to of an ir.actions.act_window to execute when the user clicks on a goal on the home page
- ``res_id_field`` : the res_id used by the action, using user as for the domain (eg: user.company_id.id)
Methods
+++++++
Add new methods inheriting from this class to add goal type with python computation mode. Look at the example in ``gamification/goal_type_data.py``

View File

@ -1,24 +0,0 @@
Gamification module documentation
=================================
The Gamification module holds all the module and logic related to goals, plans and badges. The computation is mainly done in this module, other modules inherating from it should only add data and tests.
Goals
-----
A **Goal** is an objective applied to an user with a numerical target to reach. It can have a starting and end date. Users usually do not create goals but relies on goal plans.
A **Goal Type** is a generic objective that can be applied to any structure stored in the database and use numerical value. The creation of goal types is quite technical and should rarely be done. Once a generic goal is created, it can be associated to several goal plans with different numerical targets.
A **Goal Plan** (also called Challenge in the interface) is a a set of goal types with a target value to reach applied to a group of users. It can be periodic to create and evaluate easily the performances of a team.
Badges
------
A **Badge** is a symbolic token granted to a user as a sign of reward. It can be offered by a user to another freely or with some required conditions (selected users, max. number of time per month, etc.).
.. toctree::
:maxdepth: 1
goal_type
goal
gamification_plan_howto

View File

@ -44,6 +44,7 @@ class gamification_badge_user(osv.Model):
_columns = {
'user_id': fields.many2one('res.users', string="User", required=True),
'user_from_id': fields.many2one('res.users', string="User From"),
'badge_id': fields.many2one('gamification.badge', string='Badge', required=True),
'comment': fields.text('Comment'),
'badge_name': fields.related('badge_id', 'name', type="char", string="Badge Name"),
@ -52,14 +53,13 @@ class gamification_badge_user(osv.Model):
}
def _send_badge(self, cr, uid, ids, user_from=False, context=None):
def _send_badge(self, cr, uid, ids, context=None):
"""Send a notification to a user for receiving a badge
Does not verify constrains on badge granting.
The users are added to the owner_ids (create badge_user if needed)
The stats counters are incremented
:param ids: list(int) of badge users that will receive the badge
:param user_from: optional id of the res.users object that has sent the badge
"""
res = True
temp_obj = self.pool.get('email.template')
@ -68,7 +68,6 @@ class gamification_badge_user(osv.Model):
ctx = context.copy()
for badge_user in self.browse(cr, uid, ids, context=context):
ctx.update({'user_from': user_obj.browse(cr, uid, user_from).name})
body_html = temp_obj.render_template(cr, uid, template_id.body_html, 'gamification.badge.user', badge_user.id, context=ctx)
res = user_obj.message_post(cr, uid, badge_user.user_id.id, body=body_html, context=context)
@ -180,6 +179,7 @@ class gamification_badge(osv.Model):
'owner_ids': fields.one2many('gamification.badge.user', 'badge_id',
string='Owners', help='The list of instances of this badge granted to users'),
'active': fields.boolean('Active'),
'unique_owner_ids': fields.function(_get_owners_info,
string='Unique Owners',
help="The list of unique users having received this badge.",
@ -213,6 +213,7 @@ class gamification_badge(osv.Model):
_defaults = {
'rule_auth': 'everyone',
'active': True,
}
def check_granting(self, cr, uid, badge_id, context=None):
@ -265,3 +266,17 @@ class gamification_badge(osv.Model):
# badge.rule_auth == 'everyone' -> no check
return CAN_GRANT
def check_progress(self, cr, uid, context=None):
try:
model, res_id = template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'gamification', 'badge_hidden')
except ValueError:
return True
badge_user_obj = self.pool.get('gamification.badge.user')
if not badge_user_obj.search(cr, uid, [('user_id', '=', uid), ('badge_id', '=', res_id)], context=context):
values = {
'user_id': uid,
'badge_id': res_id,
}
badge_user_obj.create(cr, SUPERUSER_ID, values, context=context)
return True

View File

@ -626,7 +626,7 @@ class gamification_challenge(osv.Model):
continue
ctx.update({'challenge_lines': goals})
template_id = self.pool['ir.model.data'].get_object(cr, uid, 'gamification', 'email_template_goal_progress_perso', context)
template_id = self.pool.get('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=ctx)
# send message only to users, not on the challenge
self.message_post(cr, uid, 0,
@ -642,7 +642,6 @@ class gamification_challenge(osv.Model):
return self.write(cr, uid, challenge.id, {'last_report_date': fields.date.today()}, context=context)
##### Challenges #####
def accept_challenge(self, cr, uid, challenge_ids, context=None, user_id=None):
"""The user accept the suggested challenge"""
user_id = user_id or uid
@ -788,7 +787,7 @@ class gamification_challenge(osv.Model):
"""
badge_user_obj = self.pool.get('gamification.badge.user')
user_badge_id = badge_user_obj.create(cr, uid, {'user_id': user_id, 'badge_id': badge_id}, context=context)
return badge_user_obj._send_badge(cr, uid, [user_badge_id], user_from=None, context=context)
return badge_user_obj._send_badge(cr, uid, [user_badge_id], context=context)
class gamification_challenge_line(osv.Model):

View File

@ -57,14 +57,6 @@ openerp.gamification = function(instance) {
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_replace: function(target,template) {
var self = this;
target.html(QWeb.render(template,{'widget': self}));
},
get_goal_todo_info: function() {
var self = this;
var challenges = new instance.web.Model('res.users').call('get_serialised_gamification_summary', []).then(function(result) {
@ -72,7 +64,6 @@ openerp.gamification = function(instance) {
self.$el.find(".oe_gamification_challenge_list").hide();
} else {
_.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);
@ -122,12 +113,38 @@ openerp.gamification = function(instance) {
instance.mail.Widget.include({
start: function() {
this._super();
var self = this;
var sidebar = new instance.gamification.Sidebar(self);
var sidebar = new instance.gamification.Sidebar(this);
sidebar.appendTo($('.oe_mail_wall_aside'));
}
});
instance.web_kanban.KanbanView.include({
start: function() {
this._super();
$(document).off('keydown.klistener');
},
events: {
'click': function(event) {
var self = this;
if (this.ViewManager.dataset.model === 'gamification.badge') {
this.kkeys = [];
$(document).off('keydown.klistener');
$(document).on('keydown.klistener', function(event) {
if ("37,38,39,40,65,66".indexOf(event.keyCode) < 0) {
$(document).off('keydown.klistener');
} else {
self.kkeys.push(event.keyCode);
if (self.kkeys.toString().indexOf("38,38,40,40,37,39,37,39,66,65") >= 0) {
new instance.web.Model('gamification.badge').call('check_progress', []);
$(document).off('keydown.klistener');
}
}
});
}
}
}
});
instance.web_kanban.KanbanRecord.include({
// open related goals when clicking on challenge kanban view
on_card_clicked: function() {
@ -136,7 +153,7 @@ openerp.gamification = function(instance) {
} else {
this._super.apply(this, arguments);
}
}
},
});
};

View File

@ -56,7 +56,7 @@
<field name="description" nolabel="1" placeholder="Badge Description" />
</group>
<group string="Granting">
<div class="oe_grey">
<div class="oe_grey" colspan="4">
Security rules to define who is allowed to manually grant badges. Not enforced for administrator.
</div>
<field name="rule_auth" widget="radio" />

View File

@ -46,10 +46,11 @@ class grant_badge_wizard(osv.TransientModel):
#create the badge
values = {
'user_id': wiz.user_id.id,
'user_from_id': uid,
'badge_id': wiz.badge_id.id,
'comment': wiz.comment,
}
badge_user = badge_user_obj.create(cr, uid, values, context=context)
result = badge_obj._send_badge(cr, uid, badge_user, user_from=uid, context=context)
result = badge_obj._send_badge(cr, uid, badge_user, context=context)
return result

View File

@ -49,17 +49,6 @@ class gamification_badge(osv.Model):
_name = 'gamification.badge'
_inherit = ['gamification.badge']
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
"""Overwrite the message_post method to send the badge to the employee"""
# badge_user included in the send_badge method and 'badge_id' in the wizard view
if 'badge_user' in context and 'badge_id' in context:
# badge = self.browse(cr, uid, context['badge_id'], context=context)
badge_user = context['badge_user']
if badge_user.employee_id:
return self.pool.get('hr.employee').message_post(cr, SUPERUSER_ID,
badge_user.employee_id.id, context=context, **kwargs)
return super(gamification_badge, self).message_post(cr, uid, thread_id, context=context, **kwargs)
def get_granted_employees(self, cr, uid, badge_ids, context=None):
if context is None:
context = {}

View File

@ -49,11 +49,12 @@ class hr_grant_badge_wizard(osv.TransientModel):
values = {
'user_id': wiz.user_id.id,
'user_from_id': uid,
'badge_id': wiz.badge_id.id,
'employee_id': wiz.employee_id.id,
'comment': wiz.comment,
}
badge_user = badge_user_obj.create(cr, uid, values, context=context)
result = badge_user_obj._send_badge(cr, uid, [badge_user], user_from=uid, context=context)
result = badge_user_obj._send_badge(cr, uid, [badge_user], context=context)
return result