diff --git a/addons/gamification/goal.py b/addons/gamification/goal.py index 6ee819a9610..9f9df9b9d41 100644 --- a/addons/gamification/goal.py +++ b/addons/gamification/goal.py @@ -41,49 +41,46 @@ class gamification_goal_type(osv.Model): _description = 'Gamification goal type' _columns = { - 'name': fields.char('Type Name', required=True, translate=True), - 'description': fields.text('Description'), - 'monetary': fields.boolean('Use Currency', help="The target and current value used is monetary"), - 'unit': fields.char('Unit', + 'name': fields.char('Goal Type Name', required=True, translate=True), + 'description': fields.text('Goal Description'), + 'monetary': fields.boolean('Monetary Value', help="The target and current value are defined in the company currency."), + 'unit': fields.char('Suffix', help="The unit of the target and current values", translate=True), 'computation_mode': fields.selection([ - ('sum', 'Sum'), - ('count', 'Count'), - ('manually', 'Manually') + ('manually', 'Recorded manually'), + ('count', 'Automatic: number of records'), + ('sum', 'Automatic: sum on a field'), ], - string="Mode of Computation", - help="""How is computed the goal value :\n -- 'Sum' for the total of the values if the 'Evaluated field'\n -- 'Count' for the number of entries\n -- 'Manually' for user defined values""", + string="Computation Mode", required=True), 'model_id': fields.many2one('ir.model', string='Model', help='The model object for the field to evaluate'), 'field_id': fields.many2one('ir.model.fields', - string='Evaluated Field', + string='Field to Sum', help='The field containing the value to evaluate'), 'field_date_id': fields.many2one('ir.model.fields', - string='Evaluated Date Field', + string='Date Field', help='The date to use for the time period evaluated'), - 'domain': fields.char("Domain", + 'domain': fields.char("Filter Domain", help="Technical filters rules to apply", required=True), # how to apply it ? 'condition': fields.selection([ - ('lower', '<='), - ('higher', '>=') + ('higher', 'The higher the better'), + ('lower', 'The lower the better') ], - string='Validation Condition', + string='Goal Performance', help='A goal is considered as completed when the current value is compared to the value to reach', required=True), 'sequence': fields.integer('Sequence', help='Sequence number for ordering', required=True), - 'action_id': fields.char("Action", - help="The action xml id that will be called to update the goal value."), - 'res_id_field': fields.char("id field", - help="The field name on the user profile containing the value for res_id for action") + 'action_id': fields.many2one('ir.actions.act_window', + string="Action", + help="The action that will be called to update the goal value."), + 'res_id_field': fields.char("ID Field of user", + help="The field name on the user profile (res.users) containing the value for res_id for action.") } _order = 'sequence' @@ -321,26 +318,34 @@ class gamification_goal(osv.Model): In case of a manual goal, should return a wizard to update the value :return: action description in a dictionnary """ + print("get_action") goal = self.browse(cr, uid, goal_id, context=context) if goal.type_id.action_id: - try: - model, xml_id = goal.type_id.action_id.split('.', 1) - action = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, model, xml_id, context=context) + action_obj = goal.type_id.action_id + action = { + 'name': action_obj.name, + 'view_type': action_obj.view_type, + 'view_mode': action_obj.view_mode, + 'res_model': action_obj.res_model, + 'domain': action_obj.domain, + 'context': action_obj.context, + 'type': 'ir.actions.act_window', + 'search_view_id': action_obj.search_view_id.id, + 'views': [(v.view_id.id, v.view_mode) for v in action_obj.view_ids] + } - if goal.type_id.res_id_field: - current_user = self.pool.get('res.users').browse(cr, uid, uid, context) - # eg : company_id.id - field_names = goal.type_id.res_id_field.split('.') - res = current_user.__getitem__(field_names[0]) - for field_name in field_names[1:]: - res = res.__getitem__(field_name) - action['res_id'] = res - action['view_mode'] = 'form' # if one element to display, should see it in form mode - action['target'] = 'new' - print(action) - return action - except ValueError: - _logger.warning("Invalid XML ID '%s' for goal action.", goal.type_id.action_id) + if goal.type_id.res_id_field: + current_user = self.pool.get('res.users').browse(cr, uid, uid, context) + # eg : company_id.id + field_names = goal.type_id.res_id_field.split('.') + res = current_user.__getitem__(field_names[0]) + for field_name in field_names[1:]: + res = res.__getitem__(field_name) + action['res_id'] = res + action['view_mode'] = 'form' # if one element to display, should see it in form mode + action['target'] = 'new' + print(action) + return action if goal.computation_mode == 'manually': action = { @@ -352,9 +357,7 @@ class gamification_goal(osv.Model): } action['context'] = {'default_goal_id': goal_id, 'default_current': goal.current} action['res_model'] = 'gamification.goal.wizard' - print(action) return action - print(False) return False def changed_users_avatar(self, cr, uid, ids, context): diff --git a/addons/gamification/goal_base_data.xml b/addons/gamification/goal_base_data.xml index 656758b630d..de88331caec 100644 --- a/addons/gamification/goal_base_data.xml +++ b/addons/gamification/goal_base_data.xml @@ -9,7 +9,7 @@ count [('id','=',user_id),('partner_id.tz', '!=', False)] - base.action_res_users_my + id @@ -18,7 +18,7 @@ In your user perference manually - base.action_res_users_my + id @@ -29,7 +29,7 @@ count [('user_ids', 'in', user_id), ('name', '!=', 'Your Company')] - base.action_res_company_form_my + company_id.id @@ -38,7 +38,7 @@ count [('user_ids', 'in', user_id),('logo', '!=', False)] - base.action_res_company_form + company_id.id diff --git a/addons/gamification/goal_view.xml b/addons/gamification/goal_view.xml index c6ed02491df..12658b541c6 100644 --- a/addons/gamification/goal_view.xml +++ b/addons/gamification/goal_view.xml @@ -114,6 +114,7 @@ + @@ -203,31 +204,36 @@
-
diff --git a/addons/gamification/plan.py b/addons/gamification/plan.py index 27fdd89546c..1ce9a5da61e 100644 --- a/addons/gamification/plan.py +++ b/addons/gamification/plan.py @@ -96,23 +96,41 @@ class gamification_goal_plan(osv.Model): return res + def _planline_count(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + for plan in self.browse(cr, uid, ids, context): + res[plan.id] = len(plan.planline_ids) + return res + _columns = { 'name': fields.char('Plan Name', required=True, translate=True), + 'state': fields.selection([ + ('draft', 'Draft'), + ('inprogress', 'In Progress'), + ('done', 'Done'), + ], + string='State', + 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)."), + 'user_ids': fields.many2many('res.users', string='Users', help="List of users to which the goal will be set"), - 'manager_id': fields.many2one('res.users', required=True, - string='Responsible', help="The user responsible for the plan."), + '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', string='Planline', help="list of goals that will be set", required=True), - '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_count': fields.function(_planline_count, type='integer', string="Planlines"), + 'period': fields.selection([ - ('once', 'No Periodicity'), + ('once', 'Non recurring'), ('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly'), @@ -121,20 +139,11 @@ class gamification_goal_plan(osv.Model): string='Periodicity', help='Period of automatic goal assigment. If none is selected, should be launched manually.', required=True), - 'start_date': fields.date('Starting 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)."), - 'state': fields.selection([ - ('draft', 'Draft'), - ('inprogress', 'In Progress'), - ('done', 'Done'), - ], - string='State', - required=True), 'visibility_mode': fields.selection([ - ('board', 'Leader Board'), - ('progressbar', 'Personal Progressbar') + ('progressbar', 'Individual Goals'), + ('board', 'Leader Board (Group Ranking)'), ], - string="Visibility", - help='How are displayed the results, shared or in a single progressbar', + string="Display Mode", required=True), 'report_message_frequency': fields.selection([ ('never','Never'), @@ -150,8 +159,8 @@ class gamification_goal_plan(osv.Model): string='Send a copy to', 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 for Manual Goals', - 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."), + 'remind_update_delay': fields.integer('Non-updated manual goals will be reminded after', + help="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', @@ -163,9 +172,9 @@ class gamification_goal_plan(osv.Model): 'state': 'draft', 'visibility_mode' : 'progressbar', 'report_message_frequency' : 'onchange', - 'last_report_date' : fields.date.today, - 'start_date' : fields.date.today, - 'manager_id' : lambda s, cr, uid, c: uid, + 'last_report_date': fields.date.today, + 'start_date': fields.date.today, + 'manager_id': lambda s, cr, uid, c: uid, } def write(self, cr, uid, ids, vals, context=None): @@ -228,7 +237,6 @@ class gamification_goal_plan(osv.Model): for plan in self.browse(cr, uid, ids, context=context): if plan.autojoin_group_id: - print("subscribe from group", plan.autojoin_group_id, [user.id for user in plan.autojoin_group_id.users]) self.plan_subscribe_users(cr, uid, ids, [user.id for user in plan.autojoin_group_id.users], context=context) self.generate_goals_from_plan(cr, uid, [plan.id], context=context) @@ -305,30 +313,6 @@ class gamification_goal_plan(osv.Model): return True - def action_show_related_goals(self, cr, uid, ids, context=None): - """ This opens goal view with a restriction to the list of goals from this plan only - @return: the goal view - """ - # get ids of related goals - goal_obj = self.pool.get('gamification.goal') - related_goal_ids = [] - goal_ids = goal_obj.search(cr, uid, [('plan_id', 'in', ids)], context=context) - for plan in self.browse(cr, uid, ids, context=context): - for planline in plan.planline_ids: - goal_ids = goal_obj.search(cr, uid, [('planline_id', '=', planline.id)], context=context) - related_goal_ids.extend(goal_ids) - - # process the new view - if context is None: - context = {} - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'gamification','goals_from_plan_act', context=context) - res['context'] = context - res['context'].update({ - 'default_id': related_goal_ids, - }) - 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): @@ -588,4 +572,5 @@ class gamification_goal_planline(osv.Model): 'type_condition': fields.related('type_id', 'condition', type="selection", readonly=True, string="Condition", selection=[('lower', '<='), ('higher', '>=')]), 'type_unit': fields.related('type_id', 'unit', type="char", readonly=True, string="Unit"), + 'type_monetary': fields.related('type_id', 'monetary', type="boolean", readonly=True, string="Monetary"), } diff --git a/addons/gamification/plan_view.xml b/addons/gamification/plan_view.xml index c4c30f1af13..514bb1d85ae 100644 --- a/addons/gamification/plan_view.xml +++ b/addons/gamification/plan_view.xml @@ -5,7 +5,7 @@ Goal Plans gamification.goal.plan - tree,form + kanban,tree,form

Click to create a goal plan. @@ -34,9 +34,15 @@ gamification.goal - form Related Goals - kanban,tree,form + kanban,tree + {'search_default_group_by_type': True, 'search_default_inprogress': True, 'default_plan_id': active_id} + +

+ 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. +

+
@@ -45,7 +51,7 @@
-
+
-
- - - + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - -
- X -
-
- -
-
-
-
-
-
-
+ + + + -
+ + +
+
- - - - - - - - - +
@@ -145,6 +125,44 @@ + + Goal Plan Kanban + gamification.goal.plan + + + + + + + +
+
+ í + +
+
+ +

+ +
+ + + +
+
+
+
+
+
+
+
@@ -153,9 +171,7 @@ - - diff --git a/addons/gamification/res_users.py b/addons/gamification/res_users.py index bde044c8fff..b773f189784 100644 --- a/addons/gamification/res_users.py +++ b/addons/gamification/res_users.py @@ -50,13 +50,14 @@ class res_users_gamification_group(osv.Model): serialized_goals_info['planlines'] = [] for planline_board in goals_info: + print("planline_board", planline_board.name) vals = {'type_name': planline_board['goal_type'].name, 'type_description': planline_board['goal_type'].description, 'type_condition': planline_board['goal_type'].condition, 'type_computation_mode': planline_board['goal_type'].computation_mode, 'type_monetary': planline_board['goal_type'].monetary, 'type_unit': planline_board['goal_type'].unit, - 'type_action': planline_board['goal_type'].action_id, + 'type_action': True if planline_board['goal_type'].action_id else False, 'goals': []} for goal in planline_board['board_goals']: vals['goals'].append({ @@ -84,6 +85,7 @@ class res_users_gamification_group(osv.Model): serialized_goals_info['goals'] = [] for goal in goals_info['goals']: + print("goal", goal.type_id.name) serialized_goals_info['goals'].append({ 'id': goal.id, 'type_name': goal.type_id.name, @@ -91,13 +93,14 @@ class res_users_gamification_group(osv.Model): 'type_condition': goal.type_id.condition, 'type_monetary': goal.type_id.monetary, 'type_unit': goal.type_id.unit, - 'type_action': goal.type_id.action_id, + 'type_action': True if goal.type_id.action_id else False, 'state': goal.state, 'completeness': goal.completeness, 'computation_mode': goal.computation_mode, 'current': goal.current, 'target_goal': goal.target_goal, }) + print("goal", True if goal.type_id.action_id else False) all_goals_info.append(serialized_goals_info) return all_goals_info diff --git a/addons/gamification/static/src/css/goal.css b/addons/gamification/static/src/css/goal.css index f3134f704b8..41bc282df5b 100644 --- a/addons/gamification/static/src/css/goal.css +++ b/addons/gamification/static/src/css/goal.css @@ -1,7 +1,8 @@ /* Kanban views */ -.openerp .oe_notebook_page .oe_kanban_view .oe_kanban_card.oe_kanban_goal, +.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_goal, .openerp .oe_kanban_view .oe_kanban_card.oe_kanban_badge { width: 220px; + min-height: 160px; } .openerp .oe_kanban_view .oe_kanban_card.oe_kanban_color_reached { background-color: #A1FF81; @@ -18,7 +19,9 @@ font-size: 0.9em; } - +.oe_kanban_badge_avatars { + margin-top: 8px; +} .oe_kanban_badge_avatars img { width: 30px; height: 30px; @@ -29,6 +32,7 @@ } + /* Mail Sidebar */ .openerp .oe_mail_wall .oe_mail_wall_aside { diff --git a/addons/gamification/static/src/js/gamification.js b/addons/gamification/static/src/js/gamification.js index dcee68197ae..4aa456964c5 100644 --- a/addons/gamification/static/src/js/gamification.js +++ b/addons/gamification/static/src/js/gamification.js @@ -27,13 +27,10 @@ openerp.gamification = function(instance) { self.get_goal_todo_info(); }); }, - // 'click a.oe_show_description': function(event) { - // var goal_id = parseInt(event.currentTarget.id); - // this.$el.find('.oe_type_description_'+goal_id).toggle(10); - // }, 'click a.oe_goal_action': function(event) { var self = this; var goal_id = parseInt(event.currentTarget.id, 10); + console.log("oe_goal_action"); var goal_action = new instance.web.Model('gamification.goal').call('get_action', [goal_id]).then(function(res) { goal_action['action'] = res; }); @@ -62,13 +59,13 @@ openerp.gamification = function(instance) { }, get_goal_todo_info: function() { var self = this; + console.log("get_goal_todo_info"); 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.$el.find('.oe_type_description').hide(); self.render_money_fields(self.goals_info.info[0].currency); self.render_progress_bars(); } @@ -116,6 +113,7 @@ openerp.gamification = function(instance) { start: function() { this._super(); var self = this; + console.log("start"); var sidebar = new instance.gamification.Sidebar(self); sidebar.appendTo($('.oe_mail_wall_aside')); } diff --git a/addons/hr_evaluation/hr_evaluation_view.xml b/addons/hr_evaluation/hr_evaluation_view.xml index e3118ce791a..23618b5e9c5 100644 --- a/addons/hr_evaluation/hr_evaluation_view.xml +++ b/addons/hr_evaluation/hr_evaluation_view.xml @@ -416,15 +416,15 @@ gamification.goal form - Related Goals - kanban,tree,form - {'search_default_group_by_type': True} + Goals + tree,kanban,form + {'search_default_group_by_user': True, 'search_default_group_by_type': True} - + - + - + @@ -26,11 +26,6 @@ - - - - -