diff options
| author | jbm-odoo <jbm@odoo.com> | 2019-10-10 09:54:11 +0000 |
|---|---|---|
| committer | Yannick Tivisse <yti@odoo.com> | 2019-11-06 11:55:34 +0000 |
| commit | b2a2d0a73055cb3a7cc2fb823d399407019fac9f (patch) | |
| tree | 13aaa744321ad70178676e9b9d124bc3ce6259ce /addons/hr_recruitment | |
| parent | 90fa3e3c60e9b96e8d9ba071ae655a576d949a96 (diff) | |
[IMP] hr_recruitment: Add refuse reason and a wizard when archiving
Purpose
=======
Like in crm, having a refusal reason to get some metrics on recruitment
+ recruitement dashboard
id=2003841
closes odoo/odoo#38467
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Diffstat (limited to 'addons/hr_recruitment')
| -rw-r--r-- | addons/hr_recruitment/__init__.py | 1 | ||||
| -rw-r--r-- | addons/hr_recruitment/__manifest__.py | 1 | ||||
| -rw-r--r-- | addons/hr_recruitment/data/hr_recruitment_data.xml | 11 | ||||
| -rw-r--r-- | addons/hr_recruitment/data/hr_recruitment_demo.xml | 5 | ||||
| -rw-r--r-- | addons/hr_recruitment/models/hr_recruitment.py | 42 | ||||
| -rw-r--r-- | addons/hr_recruitment/security/ir.model.access.csv | 1 | ||||
| -rw-r--r-- | addons/hr_recruitment/views/hr_recruitment_views.xml | 55 | ||||
| -rw-r--r-- | addons/hr_recruitment/wizard/__init__.py | 4 | ||||
| -rw-r--r-- | addons/hr_recruitment/wizard/applicant_refuse_reason.py | 14 | ||||
| -rw-r--r-- | addons/hr_recruitment/wizard/applicant_refuse_reason_views.xml | 28 |
10 files changed, 157 insertions, 5 deletions
diff --git a/addons/hr_recruitment/__init__.py b/addons/hr_recruitment/__init__.py index 8134f974fbf..52497701d2b 100644 --- a/addons/hr_recruitment/__init__.py +++ b/addons/hr_recruitment/__init__.py @@ -2,3 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import models +from . import wizard diff --git a/addons/hr_recruitment/__manifest__.py b/addons/hr_recruitment/__manifest__.py index d1e5abc2fd8..73f6719ff1b 100644 --- a/addons/hr_recruitment/__manifest__.py +++ b/addons/hr_recruitment/__manifest__.py @@ -31,6 +31,7 @@ 'views/hr_job_views.xml', 'views/mail_activity_views.xml', 'views/digest_views.xml', + 'wizard/applicant_refuse_reason_views.xml', ], 'demo': [ 'data/hr_recruitment_demo.xml', diff --git a/addons/hr_recruitment/data/hr_recruitment_data.xml b/addons/hr_recruitment/data/hr_recruitment_data.xml index 66f75fe5fc3..1bfcfc3cd11 100644 --- a/addons/hr_recruitment/data/hr_recruitment_data.xml +++ b/addons/hr_recruitment/data/hr_recruitment_data.xml @@ -382,5 +382,16 @@ <field name="fold" eval="True"/> </record> + <!-- applicant refuse reason --> + <record id="refuse_reason_1" model="hr.applicant.refuse.reason"> + <field name="name">Doesn't fit the job requirements</field> + </record> + <record id="refuse_reason_2" model="hr.applicant.refuse.reason"> + <field name="name">The applicant is not interested anymore</field> + </record> + <record id="refuse_reason_3" model="hr.applicant.refuse.reason"> + <field name="name">The applicant gets a better offer</field> + </record> + </data> </odoo> diff --git a/addons/hr_recruitment/data/hr_recruitment_demo.xml b/addons/hr_recruitment/data/hr_recruitment_demo.xml index c31f1317f0f..193cfe6b3f4 100644 --- a/addons/hr_recruitment/data/hr_recruitment_demo.xml +++ b/addons/hr_recruitment/data/hr_recruitment_demo.xml @@ -44,6 +44,7 @@ <field name="name">Sales Manager</field> <field name="job_id" ref="hr.job_marketing"/> <field name="department_id" ref="hr.dep_sales"/> + <field name="medium_id" ref="utm.utm_medium_direct"/> <field name="type_id" ref="degree_graduate"/> <field name="categ_ids" eval="[(6,0,[ref('tag_applicant_sales')])]"/> <field name="user_id" ref="base.user_demo"/> @@ -68,6 +69,7 @@ <field name="name">Developer PHP</field> <field name="job_id" ref="hr.job_developer"/> <field name="department_id" ref="hr.dep_rd"/> + <field name="medium_id" ref="utm.utm_medium_email"/> <field name="type_id" ref="degree_graduate"/> <field name="categ_ids" eval="[(6,0,[ref('tag_applicant_it')])]"/> <field name="user_id" ref="base.user_admin"/> @@ -92,6 +94,7 @@ <field name="name">Developer Python</field> <field name="job_id" ref="hr.job_developer"/> <field name="department_id" ref="hr.dep_rd"/> + <field name="medium_id" ref="utm.utm_medium_email"/> <field name="type_id" ref="degree_graduate"/> <field name="categ_ids" eval="[(6,0,[ref('tag_applicant_it')])]"/> <field name="user_id" ref="base.user_admin"/> @@ -160,6 +163,7 @@ </record> <record id="hr_case_yrsexperienceinphp0" model="hr.applicant"> <field name="name">Marketing Job</field> + <field eval="(datetime.now()+relativedelta(months=-2)).strftime('%Y-%m-03 01:00:00')" name="create_date"/> <field name="job_id" ref="hr.job_marketing"/> <field name="department_id" ref="hr.dep_sales"/> <field name="type_id" ref="degree_graduate"/> @@ -170,6 +174,7 @@ </record> <record id="hr_case_marketingjob0" model="hr.applicant"> <field name="name">More than 5 yrs Experience in PHP</field> + <field eval="(datetime.now()+relativedelta(months=-1)).strftime('%Y-%m-08 01:00:00')" name="create_date"/> <field name="job_id" ref="hr.job_developer"/> <field name="department_id" ref="hr.dep_rd"/> <field name="type_id" ref="degree_licenced"/> diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py index e7b8595092e..f0ebe71a7f5 100644 --- a/addons/hr_recruitment/models/hr_recruitment.py +++ b/addons/hr_recruitment/models/hr_recruitment.py @@ -165,6 +165,7 @@ class Applicant(models.Model): legend_normal = fields.Char(related='stage_id.legend_normal', string='Kanban Ongoing', readonly=False) application_count = fields.Integer(compute='_compute_application_count', help='Applications with the same email') meeting_count = fields.Integer(compute='_compute_meeting_count', help='Meeting Count') + refuse_reason_id = fields.Many2one('hr.applicant.refuse.reason', string='Refuse Reason', tracking=True) @api.depends('date_open', 'date_closed') def _compute_day(self): @@ -488,12 +489,39 @@ class Applicant(models.Model): return dict_act_window def archive_applicant(self): - self.write({'active': False}) + return { + 'type': 'ir.actions.act_window', + 'name': _('Refuse Reason'), + 'res_model': 'applicant.get.refuse.reason', + 'view_mode': 'form', + 'target': 'new', + 'context': {'default_applicant_ids': self.ids, 'active_test': False}, + 'views': [[False, 'form']] + } def reset_applicant(self): """ Reinsert the applicant into the recruitment pipe in the first stage""" - default_stage_id = self._default_stage_id() - self.write({'active': True, 'stage_id': default_stage_id}) + default_stage = dict() + for job_id in self.mapped('job_id'): + default_stage[job_id.id] = self.env['hr.recruitment.stage'].search( + ['|', + ('job_ids', '=', False), + ('job_ids', '=', job_id.id), + ('fold', '=', False) + ], order='sequence asc', limit=1).id + for applicant in self: + applicant.write( + {'stage_id': default_stage[applicant.job_id.id], 'refuse_reason_id': False}) + + def toggle_active(self): + res = super(Applicant, self).toggle_active() + applicant_active = self.filtered(lambda applicant: applicant.active) + if applicant_active: + applicant_active.reset_applicant() + applicant_inactive = self.filtered(lambda applicant: not applicant.active) + if applicant_inactive: + return applicant_inactive.archive_applicant() + return res class ApplicantCategory(models.Model): @@ -506,3 +534,11 @@ class ApplicantCategory(models.Model): _sql_constraints = [ ('name_uniq', 'unique (name)', "Tag name already exists !"), ] + + +class ApplicantRefuseReason(models.Model): + _name = "hr.applicant.refuse.reason" + _description = 'Refuse Reason of Applicant' + + name = fields.Char('Description', required=True, translate=True) + active = fields.Boolean('Active', default=True) diff --git a/addons/hr_recruitment/security/ir.model.access.csv b/addons/hr_recruitment/security/ir.model.access.csv index a30b91b9667..c33c641e7b7 100644 --- a/addons/hr_recruitment/security/ir.model.access.csv +++ b/addons/hr_recruitment/security/ir.model.access.csv @@ -3,6 +3,7 @@ access_hr_applicant_user,hr.applicant.user,model_hr_applicant,group_hr_recruitme access_hr_recruitment_stage_user,hr.recruitment.stage.user,model_hr_recruitment_stage,group_hr_recruitment_user,1,0,0,0
access_hr_recruitment_stage_manager,hr.recruitment.stage.manager,model_hr_recruitment_stage,group_hr_recruitment_user,1,1,1,1
access_hr_recruitment_degree,hr.recruitment.degree,model_hr_recruitment_degree,group_hr_recruitment_user,1,1,1,1
+access_hr_recruitment_refuse_reason,hr.applicant.refuse.reason,model_hr_applicant_refuse_reason,group_hr_recruitment_user,1,1,1,1
access_res_partner_hr_user,res.partner.user,base.model_res_partner,group_hr_recruitment_user,1,1,1,1
access_calendar_event_hruser,calendar.event.hruser,calendar.model_calendar_event,group_hr_recruitment_user,1,1,1,1
access_hr_recruitment_source_hr_officer,hr.recruitment.source,model_hr_recruitment_source,group_hr_recruitment_user,1,1,1,1
diff --git a/addons/hr_recruitment/views/hr_recruitment_views.xml b/addons/hr_recruitment/views/hr_recruitment_views.xml index 6d47e50c0e9..3b515db7953 100644 --- a/addons/hr_recruitment/views/hr_recruitment_views.xml +++ b/addons/hr_recruitment/views/hr_recruitment_views.xml @@ -71,8 +71,8 @@ <header> <button string="Create Employee" name="create_employee_from_applicant" type="object" class="oe_highlight" attrs="{'invisible': ['|',('emp_id', '!=', False),('active', '=', False)]}" confirm="Are you sure?"/> - <button string="Refuse" name="archive_applicant" type="object" attrs="{'invisible': [('active', '=', False)]}"/> - <button string="Restore" name="reset_applicant" type="object" attrs="{'invisible': [('active', '=', True)]}"/> + <button string="Refuse" name="toggle_active" type="object" attrs="{'invisible': [('active', '=', False)]}"/> + <button string="Restore" name="toggle_active" type="object" attrs="{'invisible': [('active', '=', True)]}"/> <field name="stage_id" widget="statusbar" options="{'clickable': '1', 'fold_field': 'fold'}" attrs="{'invisible': [('active', '=', False),('emp_id', '=', False)]}"/> </header> <sheet> @@ -108,6 +108,7 @@ <group> <group> <field name="partner_id" invisible="1" /> + <field name="refuse_reason_id" attrs="{'invisible': [('active', '=', True)]}"/> <field name="email_from" widget="email"/> <field name="email_cc" groups="base.group_no_one"/> <field name="partner_phone" widget="phone"/> @@ -189,6 +190,7 @@ <field name="user_id"/> <field name="stage_id" domain="[]"/> <field name="categ_ids"/> + <field name="refuse_reason_id"/> <field name="attachment_ids" filter_domain="[('attachment_ids.index_content', 'ilike', self)]" string="Attachments"/> <filter string="My Applications" name="my_applications" domain="[('user_id', '=', uid)]"/> <filter string="Unassigned" name="unassigned" domain="[('user_id', '=', False)]"/> @@ -213,6 +215,7 @@ <filter string="Job" name="job" domain="[]" context="{'group_by': 'job_id'}"/> <filter string="Degree" name="degree" domain="[]" context="{'group_by': 'type_id'}"/> <filter string="Stage" name="stage" domain="[]" context="{'group_by': 'stage_id'}"/> + <filter string="Refuse Reason" name="refuse_reason_id" domain="[]" context="{'group_by': 'refuse_reason_id'}"/> <filter string="Creation Date" name="creation_date" context="{'group_by': 'create_date'}"/> <filter string="Last Stage Update" name="last_stage_update" context="{'group_by': 'date_last_stage_update'}"/> </group> @@ -501,6 +504,46 @@ </field> </record> + <!-- + hr.applicant.refuse.reason views + --> + <record id="hr_applicant_refuse_reason_view_form" model="ir.ui.view"> + <field name="name">Applicant refuse reason form</field> + <field name="model">hr.applicant.refuse.reason</field> + <field name="arch" type="xml"> + <form string="Refuse Reason"> + <sheet> + <widget name="web_ribbon" text="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/> + <div class="oe_title"> + <div class="oe_edit_only"> + <label for="name"/> + </div> + <h1> + <field name="name"/> + </h1> + <field name="active" invisible="1"/> + </div> + </sheet> + </form> + </field> + </record> + + <record id="hr_applicant_refuse_reason_view_tree" model="ir.ui.view"> + <field name="name">Applicant refuse reason tree</field> + <field name="model">hr.applicant.refuse.reason</field> + <field name="arch" type="xml"> + <tree string="Refuse Reason" editable="bottom"> + <field name="name"/> + </tree> + </field> + </record> + + <record id="hr_applicant_refuse_reason_action" model="ir.actions.act_window"> + <field name="name">Refuse Reasons</field> + <field name="res_model">hr.applicant.refuse.reason</field> + <field name="view_mode">tree,form</field> + </record> + ######################## JOB OPPORTUNITIES (menu) ########################### <record model="ir.actions.act_window" id="crm_case_categ0_act_job"> <field name="name">Applications</field> @@ -570,6 +613,13 @@ <!-- ALL JOBS REQUESTS --> <menuitem parent="menu_hr_recruitment_configuration" id="menu_hr_job_position_config" action="action_hr_job_config" sequence="10"/> + + <menuitem + id="menu_hr_applicant_refuse_reason" + action="hr_applicant_refuse_reason_action" + parent="menu_hr_recruitment_configuration" + sequence="10"/> + <menuitem name="Applications" parent="menu_hr_recruitment_root" @@ -933,6 +983,7 @@ action = act </record> <menuitem name="Reporting" id="report_hr_recruitment" parent="menu_hr_recruitment_root" sequence="99"/> + <menuitem name="Recruitment Analysis" id="hr_applicant_report_menu" parent="report_hr_recruitment" sequence="50" action="hr_applicant_action_analysis"/> <record id="action_hr_recruitment_report_filtered_department" model="ir.actions.act_window"> diff --git a/addons/hr_recruitment/wizard/__init__.py b/addons/hr_recruitment/wizard/__init__.py new file mode 100644 index 00000000000..6a456a24112 --- /dev/null +++ b/addons/hr_recruitment/wizard/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import applicant_refuse_reason diff --git a/addons/hr_recruitment/wizard/applicant_refuse_reason.py b/addons/hr_recruitment/wizard/applicant_refuse_reason.py new file mode 100644 index 00000000000..ffb0259a571 --- /dev/null +++ b/addons/hr_recruitment/wizard/applicant_refuse_reason.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +from odoo import api, fields, models + + +class ApplicantGetRefuseReason(models.TransientModel): + _name = 'applicant.get.refuse.reason' + _description = 'Get Refuse Reason' + + refuse_reason_id = fields.Many2one('hr.applicant.refuse.reason', 'Refuse Reason') + applicant_ids = fields.Many2many('hr.applicant') + + def action_refuse_reason_apply(self): + return self.applicant_ids.write({'refuse_reason_id': self.refuse_reason_id.id}) diff --git a/addons/hr_recruitment/wizard/applicant_refuse_reason_views.xml b/addons/hr_recruitment/wizard/applicant_refuse_reason_views.xml new file mode 100644 index 00000000000..7de80d1d11f --- /dev/null +++ b/addons/hr_recruitment/wizard/applicant_refuse_reason_views.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<odoo> + <record id="applicant_get_refuse_reason_view_form" model="ir.ui.view"> + <field name="name">applicant.get.refuse.reason.form</field> + <field name="model">applicant.get.refuse.reason</field> + <field name="arch" type="xml"> + <form string="Refuse Reason"> + <group class="oe_title"> + <field name="refuse_reason_id"/> + <field name="applicant_ids" invisible="1"/> + </group> + <footer> + <button name="action_refuse_reason_apply" string="Submit" type="object" class="btn-primary"/> + <button string="Cancel" class="btn-secondary" special="cancel"/> + </footer> + </form> + </field> + </record> + + <record id="applicant_get_refuse_reason_action" model="ir.actions.act_window"> + <field name="name">Refuse Reason</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">applicant.get.refuse.reason</field> + <field name="view_mode">form</field> + <field name="view_id" ref="applicant_get_refuse_reason_view_form"/> + <field name="target">new</field> + </record> +</odoo> |
