diff --git a/addons/hr_skills/data/hr_resume_data.xml b/addons/hr_skills/data/hr_resume_data.xml index b5fbde4443f..8c948d35ac9 100644 --- a/addons/hr_skills/data/hr_resume_data.xml +++ b/addons/hr_skills/data/hr_resume_data.xml @@ -3,10 +3,12 @@ Experience + 1 Education + 2 diff --git a/addons/hr_skills/data/hr_resume_demo.xml b/addons/hr_skills/data/hr_resume_demo.xml index 79cd1a4ea8c..3f431865491 100644 --- a/addons/hr_skills/data/hr_resume_demo.xml +++ b/addons/hr_skills/data/hr_resume_demo.xml @@ -20,118 +20,99 @@ A1 10 - 5 A2 40 - 10 B1 60 - 15 B2 75 - 20 C1 85 - 25 C2 100 - 35 Beginner 15 - 1 Elementary 25 - 5 Intermediate 50 - 15 Advanced 80 - 25 Expert 100 - 35 L1 25 - 1 L2 50 - 5 L3 75 - 15 L4 100 - 25 L1 25 - 1 L2 50 - 5 L3 75 - 15 L4 100 - 25 @@ -279,7 +260,6 @@ Odoo SA - 5 @@ -291,7 +271,6 @@ Burtho Inc. - 15 diff --git a/addons/hr_skills/models/hr_resume.py b/addons/hr_skills/models/hr_resume.py index bfea9306cee..7725a5c05ac 100644 --- a/addons/hr_skills/models/hr_resume.py +++ b/addons/hr_skills/models/hr_resume.py @@ -30,6 +30,7 @@ class Employee(models.Model): class ResumeLine(models.Model): _name = 'hr.resume.line' _description = "Resumé line of an employee" + _order = "line_type_id, date_end desc, date_start desc" employee_id = fields.Many2one('hr.employee', required=True, ondelete='cascade') name = fields.Char(required=True) @@ -37,7 +38,9 @@ class ResumeLine(models.Model): date_end = fields.Date() description = fields.Text(string="Description") line_type_id = fields.Many2one('hr.resume.line.type', string="Type") - sequence = fields.Integer(default=100) + + # Used to apply specific template on a line + display_type = fields.Selection([('classic', 'Classic')], string="Display Type", default='classic') _sql_constraints = [ ('date_check', "CHECK ((date_start <= date_end OR date_end = NULL))", "The start date must be anterior to the end date."), @@ -47,5 +50,7 @@ class ResumeLine(models.Model): class ResumeLineType(models.Model): _name = 'hr.resume.line.type' _description = "Type of a resumé line" + _order = "sequence" name = fields.Char(required=True) + sequence = fields.Integer('Sequence', default=10) diff --git a/addons/hr_skills/models/hr_skills.py b/addons/hr_skills/models/hr_skills.py index 5b75a5ac146..4eeb950a71b 100644 --- a/addons/hr_skills/models/hr_skills.py +++ b/addons/hr_skills/models/hr_skills.py @@ -17,6 +17,7 @@ class EmployeeSkill(models.Model): _name = 'hr.employee.skill' _description = "Skill level for an employee" _rec_name = 'skill_id' + _order = "skill_level_id" employee_id = fields.Many2one('hr.employee', required=True, ondelete='cascade') skill_id = fields.Many2one('hr.skill', required=True) @@ -44,11 +45,11 @@ class EmployeeSkill(models.Model): class SkillLevel(models.Model): _name = 'hr.skill.level' _description = "Skill Level" + _order = "level_progress desc" skill_type_id = fields.Many2one('hr.skill.type') name = fields.Char(required=True) level_progress = fields.Integer(string="Progress", help="Progress from zero knowledge (0%) to fully mastered (100%).") - sequence = fields.Integer(default=100) class SkillType(models.Model): diff --git a/addons/hr_skills/static/src/css/hr_skills.scss b/addons/hr_skills/static/src/css/hr_skills.scss index cb1a7072922..439b082cdcf 100644 --- a/addons/hr_skills/static/src/css/hr_skills.scss +++ b/addons/hr_skills/static/src/css/hr_skills.scss @@ -1,4 +1,9 @@ .o_form_sheet { + .o_resume_table th, + .o_resume_table td { + border: none; + } + .o_resume_line { width: 100%; } @@ -12,10 +17,14 @@ } td.o_skill_cell { - width: 33%; + white-space: normal !important; } .o_group_resume tbody tr.o_resume_group_header th { font-weight: normal; } + + .o_resume_line_desc { + white-space: normal; + } } diff --git a/addons/hr_skills/static/src/js/resume_widget.js b/addons/hr_skills/static/src/js/resume_widget.js index 7bb2023b76f..10cbfbfc874 100644 --- a/addons/hr_skills/static/src/js/resume_widget.js +++ b/addons/hr_skills/static/src/js/resume_widget.js @@ -103,10 +103,15 @@ var AbstractGroupedOne2ManyRenderer = ListRenderer.extend({ return record.data[self.groupBy].res_id; }); + var groupTitle; var $body = $(''); for (var key in grouped_by) { var group = grouped_by[key]; - var groupTitle = group[0].data[self.groupBy].data.display_name; + if (key === 'undefined') { + groupTitle = _t("Other"); + } else { + groupTitle = group[0].data[self.groupBy].data.display_name; + } var $title_row = $(self._renderGroupRow(groupTitle)); $body.append($title_row); @@ -148,21 +153,14 @@ var ResumeLineRenderer = AbstractGroupedOne2ManyRenderer.extend({ _getCreateLineContext: function (group) { var ctx = this._super(group); - return group ? _.extend({ default_line_type_id: group[0].data[this.groupBy].data.id }, ctx) : ctx; + return group ? _.extend({default_line_type_id: group[0].data[this.groupBy] && group[0].data[this.groupBy].data.id || ""}, ctx) : ctx; }, _render: function () { var self = this; return this._super().then(function () { - // Allow to sort records - self.$el.find('.o_list_view').sortable({ - axis: 'y', - items: '.o_data_row', - helper: 'clone', - handle: '.o_row_handle', - stop: self._resequence.bind(self), - }); - self.$el.find('table').removeClass('table table-striped o_list_view_ungrouped'); + self.$el.find('table').removeClass('table-striped o_list_view_ungrouped'); + self.$el.find('table').addClass('o_resume_table'); }); }, }); @@ -176,7 +174,7 @@ var SkillsRenderer = AbstractGroupedOne2ManyRenderer.extend({ _renderRow: function (record) { var $row = this._super(record); // Add progress bar widget at the end of rows - var $td = $('', {class: 'o_data_cell'}); + var $td = $('', {class: 'o_data_cell o_skill_cell'}); var progress = new FieldProgressBar(this, 'level_progress', record, { current_value: record.data.level_progress, attrs: this.arch.attrs, diff --git a/addons/hr_skills/static/src/xml/resume_templates.xml b/addons/hr_skills/static/src/xml/resume_templates.xml index 89d7352f464..7da6ea3434a 100644 --- a/addons/hr_skills/static/src/xml/resume_templates.xml +++ b/addons/hr_skills/static/src/xml/resume_templates.xml @@ -2,25 +2,23 @@ - - - - - -
-
-
- - - + + +
+
+
+ - + +
+
+
+

+
-
-

- -
-
- + + diff --git a/addons/hr_skills/static/tests/widget_tests.js b/addons/hr_skills/static/tests/widget_tests.js index 3bee4c4ee29..00cdc648401 100644 --- a/addons/hr_skills/static/tests/widget_tests.js +++ b/addons/hr_skills/static/tests/widget_tests.js @@ -82,21 +82,21 @@ odoo.define('hr_skills.field_one_to_many_group_tests', function (require) { fields: { name: { string: "Name", type: "char" }, line_type_id: { string: "Type", relation: 'line_type', type: "many2one" }, - sequence: { string: "Sequence", type: "int", default:10 }, description: { string: "Description", type: "text" }, date_start: { string: "Date start", type: "date" }, date_end: { string: "Date end", type: "date" }, trululu: { string: "Trululu", type: "many2one", relation: 'partner' }, + display_type: { string: "display type", type: "selection"}, }, records: [{ id: 37, name: "ULB", line_type_id: 50, - sequence: 5, date_start: "2017-01-25", date_end: "2019-01-25", description: 'Hello', trululu: 1, + display_type: 'classic', }, { id: 38, name: "UCL", @@ -105,14 +105,15 @@ odoo.define('hr_skills.field_one_to_many_group_tests', function (require) { date_end: "2014-01-25", description: 'World', trululu: 1, + display_type: 'classic', }, { id: 39, name: "KUL", line_type_id: 51, - sequence: 15, date_start: "2008-01-25", description: 'Hi', trululu: 1, + display_type: 'classic', }], onchanges: {}, }, @@ -145,7 +146,7 @@ odoo.define('hr_skills.field_one_to_many_group_tests', function (require) { '' + '' + '' + - '' + + '' + '' + '' + '', @@ -193,7 +194,6 @@ odoo.define('hr_skills.field_one_to_many_group_tests', function (require) { '' + '' + '' + - '' + '' + '' + '', @@ -248,7 +248,6 @@ odoo.define('hr_skills.field_one_to_many_group_tests', function (require) { '' + '' + '' + - '' + '' + '' + '', diff --git a/addons/hr_skills/views/hr_views.xml b/addons/hr_skills/views/hr_views.xml index fd92c8bd588..98f2a73e59e 100644 --- a/addons/hr_skills/views/hr_views.xml +++ b/addons/hr_skills/views/hr_views.xml @@ -37,7 +37,7 @@ - + @@ -65,10 +65,10 @@ - +
@@ -105,10 +105,10 @@ - +
@@ -158,7 +158,6 @@ hr.skill.level - diff --git a/addons/hr_skills_slides/__init__.py b/addons/hr_skills_slides/__init__.py new file mode 100644 index 00000000000..dc5e6b693d1 --- /dev/null +++ b/addons/hr_skills_slides/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/hr_skills_slides/__manifest__.py b/addons/hr_skills_slides/__manifest__.py new file mode 100644 index 00000000000..d85aa5829b9 --- /dev/null +++ b/addons/hr_skills_slides/__manifest__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Skills e-learning', + 'category': 'Hidden', + 'version': '1.0', + 'summary': 'Add completed courses to resumé of your employees', + 'description': + """ +E-learning and Skills for HR +============================ + +This module add completed courses to resumé for employees. + """, + 'depends': ['hr_skills', 'website_slides'], + 'data': [ + 'views/hr_templates.xml', + 'data/hr_resume_data.xml', + ], + 'qweb': [ + 'static/src/xml/resume_templates.xml', + ], + 'auto_install': True, +} diff --git a/addons/hr_skills_slides/data/hr_resume_data.xml b/addons/hr_skills_slides/data/hr_resume_data.xml new file mode 100644 index 00000000000..92edc9db157 --- /dev/null +++ b/addons/hr_skills_slides/data/hr_resume_data.xml @@ -0,0 +1,10 @@ + + + + + Internal Training + 26 + + + + diff --git a/addons/hr_skills_slides/models/__init__.py b/addons/hr_skills_slides/models/__init__.py new file mode 100644 index 00000000000..c9c3eb273a8 --- /dev/null +++ b/addons/hr_skills_slides/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import slide_channel diff --git a/addons/hr_skills_slides/models/slide_channel.py b/addons/hr_skills_slides/models/slide_channel.py new file mode 100644 index 00000000000..f6053abdd14 --- /dev/null +++ b/addons/hr_skills_slides/models/slide_channel.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class ChannelUsersRelation(models.Model): + _inherit = 'slide.channel.partner' + + def _post_completion_hook(self): + partner_has_completed = {channel_partner.partner_id.id: channel_partner.channel_id for channel_partner in self} + employees = self.env['hr.employee'].sudo().search([('user_id.partner_id', 'in', list(partner_has_completed.keys()))]) + for employee in employees: + line_type = self.env.ref('hr_skills_slides.resume_type_training', raise_if_not_found=False) + channel = partner_has_completed[employee.user_id.partner_id.id] + self.env['hr.resume.line'].create({ + 'employee_id': employee.id, + 'name': channel.name, + 'date_start': fields.Date.today(), + 'date_end': fields.Date.today(), + 'description': channel.description, + 'line_type_id': line_type and line_type.id, + 'display_type': 'course', + 'channel_id': channel.id + }) + return super()._post_completion_hook() + + +class ResumeLine(models.Model): + _inherit = 'hr.resume.line' + + display_type = fields.Selection(selection_add=[('course', 'Course')]) + channel_id = fields.Many2one('slide.channel', string="Course", readonly=True) diff --git a/addons/hr_skills_slides/static/src/scss/hr_skills.scss b/addons/hr_skills_slides/static/src/scss/hr_skills.scss new file mode 100644 index 00000000000..40edfefed6e --- /dev/null +++ b/addons/hr_skills_slides/static/src/scss/hr_skills.scss @@ -0,0 +1,6 @@ +.o_resume_line { + .o_resume_line_icon.icon_circle { + color: $o-enterprise-primary-color; + vertical-align: middle; + } +} diff --git a/addons/hr_skills_slides/static/src/xml/resume_templates.xml b/addons/hr_skills_slides/static/src/xml/resume_templates.xml new file mode 100644 index 00000000000..bcad8b1284e --- /dev/null +++ b/addons/hr_skills_slides/static/src/xml/resume_templates.xml @@ -0,0 +1,24 @@ + + + + + + + +
+
+ +
+
+

+ +
+
+ +
+
+ +
+
+
+
diff --git a/addons/hr_skills_slides/views/hr_templates.xml b/addons/hr_skills_slides/views/hr_templates.xml new file mode 100644 index 00000000000..be9ae969d56 --- /dev/null +++ b/addons/hr_skills_slides/views/hr_templates.xml @@ -0,0 +1,20 @@ + + + + + + hr.resume.line.form + hr.resume.line + + + + + + + + + diff --git a/addons/hr_skills_survey/__init__.py b/addons/hr_skills_survey/__init__.py new file mode 100644 index 00000000000..dc5e6b693d1 --- /dev/null +++ b/addons/hr_skills_survey/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/hr_skills_survey/__manifest__.py b/addons/hr_skills_survey/__manifest__.py new file mode 100644 index 00000000000..339c0b65a14 --- /dev/null +++ b/addons/hr_skills_survey/__manifest__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Skills Certification', + 'category': 'Hidden', + 'version': '1.0', + 'summary': 'Add certification to resumé of your employees', + 'description': + """ +Certification and Skills for HR +=============================== + +This module add certification to resumé for employees. + """, + 'depends': ['hr_skills', 'survey'], + 'data': [ + 'views/hr_templates.xml', + 'data/hr_resume_data.xml', + ], + 'qweb': [ + 'static/src/xml/resume_templates.xml', + ], + 'auto_install': True, +} diff --git a/addons/hr_skills_survey/data/hr_resume_data.xml b/addons/hr_skills_survey/data/hr_resume_data.xml new file mode 100644 index 00000000000..8a53cbab253 --- /dev/null +++ b/addons/hr_skills_survey/data/hr_resume_data.xml @@ -0,0 +1,10 @@ + + + + + Internal Certification + 25 + + + + diff --git a/addons/hr_skills_survey/models/__init__.py b/addons/hr_skills_survey/models/__init__.py new file mode 100644 index 00000000000..25325ac6482 --- /dev/null +++ b/addons/hr_skills_survey/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import survey_user diff --git a/addons/hr_skills_survey/models/survey_user.py b/addons/hr_skills_survey/models/survey_user.py new file mode 100644 index 00000000000..43e85b40cca --- /dev/null +++ b/addons/hr_skills_survey/models/survey_user.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models +from odoo.tools import html2plaintext + + +class SurveyUserInput(models.Model): + _inherit = 'survey.user_input' + + def _send_certification(self): + """ Will add certification to employee's resumé if + - The survey is a certification + - The user is linked to an employee + - The user succeeded the test + At the end, super is call to send by mail""" + certificate_user_inputs = self.filtered(lambda user_input: user_input.survey_id.certificate and user_input.quizz_passed) + partner_has_completed = {user_input.partner_id.id: user_input.survey_id for user_input in certificate_user_inputs} + employees = self.env['hr.employee'].sudo().search([('user_id.partner_id', 'in', certificate_user_inputs.mapped('partner_id').ids)]) + for employee in employees: + line_type = self.env.ref('hr_skills_survey.resume_type_certification', raise_if_not_found=False) + survey = partner_has_completed.get(employee.user_id.partner_id.id) + self.env['hr.resume.line'].create({ + 'employee_id': employee.id, + 'name': survey.title, + 'date_start': fields.Date.today(), + 'date_end': fields.Date.today(), + 'description': html2plaintext(survey.description), + 'line_type_id': line_type and line_type.id, + 'display_type': 'certification', + 'survey_id': survey.id + }) + return super(SurveyUserInput, self)._send_certification() + + +class ResumeLine(models.Model): + _inherit = 'hr.resume.line' + + display_type = fields.Selection(selection_add=[('certification', 'Certification')]) + survey_id = fields.Many2one('survey.survey', string='Certification', readonly=True) diff --git a/addons/hr_skills_survey/static/src/scss/hr_skills.scss b/addons/hr_skills_survey/static/src/scss/hr_skills.scss new file mode 100644 index 00000000000..864fb11dd43 --- /dev/null +++ b/addons/hr_skills_survey/static/src/scss/hr_skills.scss @@ -0,0 +1,5 @@ +.o_resume_line { + .o_resume_line_icon.icon_trophy { + color: theme-color('warning'); + } +} diff --git a/addons/hr_skills_survey/static/src/xml/resume_templates.xml b/addons/hr_skills_survey/static/src/xml/resume_templates.xml new file mode 100644 index 00000000000..2734f5ba6d1 --- /dev/null +++ b/addons/hr_skills_survey/static/src/xml/resume_templates.xml @@ -0,0 +1,25 @@ + + + + + + + +
+
+ +
+
+

+ +
+
+ +
+
+ +
+
+
+ +
diff --git a/addons/hr_skills_survey/views/hr_templates.xml b/addons/hr_skills_survey/views/hr_templates.xml new file mode 100644 index 00000000000..365a7240e52 --- /dev/null +++ b/addons/hr_skills_survey/views/hr_templates.xml @@ -0,0 +1,20 @@ + + + + + + hr.resume.line.form + hr.resume.line + + + + + + + + + diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index f504ecc03fd..c68961aace1 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -60,6 +60,7 @@ class ChannelUsersRelation(models.Model): result = super(ChannelUsersRelation, (self - to_complete))._write(values) completion_values = dict(values, completed=True) super(ChannelUsersRelation, to_complete)._write(completion_values) + to_complete._post_completion_hook() else: result = super(ChannelUsersRelation, self)._write(values) @@ -69,6 +70,8 @@ class ChannelUsersRelation(models.Model): users.add_karma(partner_karma[user.partner_id.id]) return result + def _post_completion_hook(self): + pass class Channel(models.Model): """ A channel is a container of slides. """