diff --git a/addons/gamification/data/badge.xml b/addons/gamification/data/badge.xml index 35686b0ec4d..5588d327f82 100644 --- a/addons/gamification/data/badge.xml +++ b/addons/gamification/data/badge.xml @@ -616,6 +616,242 @@ c3eZ58/32vV1fV1f19f1dX1dX9fX9XV9XV/X1/V1fb0a1/8He8q//0YPCp0AAAAASUVORK5CYII= + + Hidden + You have found the hidden badge + nobody + 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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== + + + + Brilliant With your brilliant ideas, you are an inspiration to others. @@ -892,8 +1128,8 @@ Received Badge Congratulation, you have received the badge ${object.badge_id.name} ! - % if ctx["user_from"] - This badge was granted by ${ctx["user_from"]}. + % if object.user_from_id + This badge was granted by ${object.user_from_id.name}. % endif

diff --git a/addons/gamification/doc/gamification_plan_howto.rst b/addons/gamification/doc/gamification_plan_howto.rst deleted file mode 100644 index b0e8d1603b8..00000000000 --- a/addons/gamification/doc/gamification_plan_howto.rst +++ /dev/null @@ -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 : - -:: - - - Number of items - count - ... - - -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. - -:: - - - ... - - - - -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``. - -:: - - - ... - [('shopper_id', '=', user.id), ('list_id.state', '=', 'confirmed')] - - -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``. - -:: - - - ... - groceries.action_groceries_list_form - user.groceries_list.id - - - -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. - -:: - - - Discover the Groceries Module - once - progressbar - never - - - - -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. - -:: - - - - 3 - - \ No newline at end of file diff --git a/addons/gamification/doc/goal.rst b/addons/gamification/doc/goal.rst deleted file mode 100644 index f82cb7b4cbb..00000000000 --- a/addons/gamification/doc/goal.rst +++ /dev/null @@ -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. diff --git a/addons/gamification/doc/goal_type.rst b/addons/gamification/doc/goal_type.rst deleted file mode 100644 index 4da960b3371..00000000000 --- a/addons/gamification/doc/goal_type.rst +++ /dev/null @@ -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`` \ No newline at end of file diff --git a/addons/gamification/doc/index.rst b/addons/gamification/doc/index.rst deleted file mode 100644 index 85d4ffe2048..00000000000 --- a/addons/gamification/doc/index.rst +++ /dev/null @@ -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 - \ No newline at end of file diff --git a/addons/gamification/models/badge.py b/addons/gamification/models/badge.py index b1380627e39..2b997384467 100644 --- a/addons/gamification/models/badge.py +++ b/addons/gamification/models/badge.py @@ -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 \ No newline at end of file diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py index 7cbd784b9bf..83ec0fd5beb 100644 --- a/addons/gamification/models/challenge.py +++ b/addons/gamification/models/challenge.py @@ -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): diff --git a/addons/gamification/static/src/js/gamification.js b/addons/gamification/static/src/js/gamification.js index cf5b2228b08..22cfd5f3ab5 100644 --- a/addons/gamification/static/src/js/gamification.js +++ b/addons/gamification/static/src/js/gamification.js @@ -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); } - } + }, }); }; diff --git a/addons/gamification/views/badge.xml b/addons/gamification/views/badge.xml index 33c0e21ea7a..0b37e62051d 100644 --- a/addons/gamification/views/badge.xml +++ b/addons/gamification/views/badge.xml @@ -56,7 +56,7 @@ -
+
Security rules to define who is allowed to manually grant badges. Not enforced for administrator.
diff --git a/addons/gamification/wizard/grant_badge.py b/addons/gamification/wizard/grant_badge.py index e100b2dce29..1b80c490ef3 100644 --- a/addons/gamification/wizard/grant_badge.py +++ b/addons/gamification/wizard/grant_badge.py @@ -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 diff --git a/addons/hr_gamification/models/gamification.py b/addons/hr_gamification/models/gamification.py index 27c1834bc39..f07ed9c95c4 100644 --- a/addons/hr_gamification/models/gamification.py +++ b/addons/hr_gamification/models/gamification.py @@ -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 = {} diff --git a/addons/hr_gamification/wizard/grant_badge.py b/addons/hr_gamification/wizard/grant_badge.py index 967324b7b87..22e72e84e27 100644 --- a/addons/hr_gamification/wizard/grant_badge.py +++ b/addons/hr_gamification/wizard/grant_badge.py @@ -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 \ No newline at end of file