From 32fc38ef58dc4b4f1ff4e176ff4fa03b9c427397 Mon Sep 17 00:00:00 2001 From: yhu-odoo Date: Thu, 26 Dec 2019 15:35:26 +0000 Subject: [PATCH] [IMP] hr_appraisal: Improve employee archiving flow PURPOSE ======= When you close a payroll (employees), there are often a lot of document linked. Archiving an employee should archive the contract, cancel future leaves, archive the private address Specification ============= Add departure date (hr): - Add a Date field to both hr.departure.wizard and hr.employee. In the wizard, the field is required. - In toggle_active() method in hr.employee, set departure_date to false when unarchive the employee. - If user has a current running contract, a user error will raise if user enter a departure date earlier than the start date of the contract. Add checkbox to set a closing date on hr.contract (hr.contract): - In the hr.departure.wizard, set the departure date to be the end date of runing contract. Set the states of all draft contracts to "cancel". Add checkbox to free car (hr.fleet): - In the hr.departure.wizard, set end_date to fleet.vehicle.assignation.log, if there is no end_date or end_date > departure_date - Go through fleet.vehicle, find records with dirver_id to be the employee, set it to False. Add checkbox to archive private address (hr): - when the private address not link to a internel user, set employee.address_home_id.active to Flase - unarchive it after the employee unarchived Add checkbox to cancel future appraisals (hr.appraisal) - find all appraisals link to the employee and state in ['new', 'pending'], set their state to 'cancel'. Add checkbox to cancel future leaves (hr.holidays): - only consider leaves are not in state ['refuse', 'cancel'], find leaves with to_date > departure_date, set their state to 'cancel'. PR #42526 Task 2153106 Related: odoo/enterprise#7471 Signed-off-by: Yannick Tivisse (yti) --- addons/hr/models/hr_employee.py | 7 ++++- addons/hr/views/hr_employee_views.xml | 1 + addons/hr/wizard/hr_departure_wizard.py | 20 ++++++-------- .../hr/wizard/hr_departure_wizard_views.xml | 9 ++++--- addons/hr_contract/__init__.py | 1 + addons/hr_contract/__manifest__.py | 1 + addons/hr_contract/wizard/__init__.py | 4 +++ .../hr_contract/wizard/hr_departure_wizard.py | 24 +++++++++++++++++ .../wizard/hr_departure_wizard_views.xml | 16 +++++++++++ addons/hr_fleet/__init__.py | 1 + addons/hr_fleet/__manifest__.py | 1 + addons/hr_fleet/wizard/__init__.py | 4 +++ addons/hr_fleet/wizard/hr_departure_wizard.py | 27 +++++++++++++++++++ .../wizard/hr_departure_wizard_views.xml | 13 +++++++++ addons/hr_holidays/__manifest__.py | 1 + addons/hr_holidays/wizard/__init__.py | 1 + .../hr_holidays/wizard/hr_departure_wizard.py | 20 ++++++++++++++ .../wizard/hr_departure_wizard_views.xml | 13 +++++++++ 18 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 addons/hr_contract/wizard/__init__.py create mode 100644 addons/hr_contract/wizard/hr_departure_wizard.py create mode 100644 addons/hr_contract/wizard/hr_departure_wizard_views.xml create mode 100644 addons/hr_fleet/wizard/__init__.py create mode 100644 addons/hr_fleet/wizard/hr_departure_wizard.py create mode 100644 addons/hr_fleet/wizard/hr_departure_wizard_views.xml create mode 100644 addons/hr_holidays/wizard/hr_departure_wizard.py create mode 100644 addons/hr_holidays/wizard/hr_departure_wizard_views.xml diff --git a/addons/hr/models/hr_employee.py b/addons/hr/models/hr_employee.py index 4f2bdafd323..0324babaf23 100644 --- a/addons/hr/models/hr_employee.py +++ b/addons/hr/models/hr_employee.py @@ -114,6 +114,7 @@ class HrEmployeePrivate(models.Model): ('retired', 'Retired') ], string="Departure Reason", groups="hr.group_hr_user", copy=False, tracking=True) departure_description = fields.Text(string="Additional Information", groups="hr.group_hr_user", copy=False, tracking=True) + departure_date = fields.Date(string="Departure Date", groups="hr.group_hr_user", copy=False, tracking=True) message_main_attachment_id = fields.Many2one(groups="hr.group_hr_user") _sql_constraints = [ @@ -273,10 +274,14 @@ class HrEmployeePrivate(models.Model): def toggle_active(self): res = super(HrEmployeePrivate, self).toggle_active() - self.filtered(lambda employee: employee.active).write({ + unarchived_employees = self.filtered(lambda employee: employee.active) + unarchived_employees.write({ 'departure_reason': False, 'departure_description': False, + 'departure_date': False }) + archived_addresses = unarchived_employees.mapped('address_home_id').filtered(lambda addr: not addr.active) + archived_addresses.toggle_active() if len(self) == 1 and not self.active: return { 'type': 'ir.actions.act_window', diff --git a/addons/hr/views/hr_employee_views.xml b/addons/hr/views/hr_employee_views.xml index 6ee8eb06309..c94bd150f9e 100644 --- a/addons/hr/views/hr_employee_views.xml +++ b/addons/hr/views/hr_employee_views.xml @@ -113,6 +113,7 @@ + diff --git a/addons/hr/wizard/hr_departure_wizard.py b/addons/hr/wizard/hr_departure_wizard.py index c01b00c7fba..5e7782a1648 100644 --- a/addons/hr/wizard/hr_departure_wizard.py +++ b/addons/hr/wizard/hr_departure_wizard.py @@ -22,22 +22,18 @@ class HrDepartureWizard(models.TransientModel): ('retired', 'Retired') ], string="Departure Reason", default="fired") departure_description = fields.Text(string="Additional Information") - plan_id = fields.Many2one('hr.plan', default=lambda self: self.env['hr.plan'].search([], limit=1)) + departure_date = fields.Date(string="Departure Date", required=True, default=fields.Date.today) employee_id = fields.Many2one('hr.employee', string='Employee', required=True) + archive_private_address = fields.Boolean('Archive Private Address', default=True) def action_register_departure(self): employee = self.employee_id employee.departure_reason = self.departure_reason employee.departure_description = self.departure_description + employee.departure_date = self.departure_date - if not employee.user_id.partner_id: - return - - for activity_type in self.plan_id.plan_activity_type_ids: - self.env['mail.activity'].create({ - 'res_id': employee.user_id.partner_id.id, - 'res_model_id': self.env['ir.model']._get('res.partner').id, - 'activity_type_id': activity_type.activity_type_id.id, - 'summary': activity_type.summary, - 'user_id': activity_type.get_responsible_id(employee).id, - }) + if self.archive_private_address: + # ignore contact links to internal users + private_address = employee.address_home_id + if private_address and private_address.active and not self.env['res.users'].search([('partner_id', '=', private_address.id)]): + private_address.toggle_active() diff --git a/addons/hr/wizard/hr_departure_wizard_views.xml b/addons/hr/wizard/hr_departure_wizard_views.xml index 4b096235fc3..22b3b2b7157 100644 --- a/addons/hr/wizard/hr_departure_wizard_views.xml +++ b/addons/hr/wizard/hr_departure_wizard_views.xml @@ -7,16 +7,19 @@
- - + + + + +
diff --git a/addons/hr_contract/__init__.py b/addons/hr_contract/__init__.py index dc5e6b693d1..2ae6446f9dc 100644 --- a/addons/hr_contract/__init__.py +++ b/addons/hr_contract/__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_contract/__manifest__.py b/addons/hr_contract/__manifest__.py index f05b650c937..c3df359512d 100644 --- a/addons/hr_contract/__manifest__.py +++ b/addons/hr_contract/__manifest__.py @@ -24,6 +24,7 @@ You can assign several contracts per employee. 'data/hr_contract_data.xml', 'views/hr_contract_views.xml', 'views/assets.xml', + 'wizard/hr_departure_wizard_views.xml', ], 'demo': ['data/hr_contract_demo.xml'], 'installable': True, diff --git a/addons/hr_contract/wizard/__init__.py b/addons/hr_contract/wizard/__init__.py new file mode 100644 index 00000000000..ea671ff9df8 --- /dev/null +++ b/addons/hr_contract/wizard/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import hr_departure_wizard diff --git a/addons/hr_contract/wizard/hr_departure_wizard.py b/addons/hr_contract/wizard/hr_departure_wizard.py new file mode 100644 index 00000000000..84abad579a9 --- /dev/null +++ b/addons/hr_contract/wizard/hr_departure_wizard.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, _ +from odoo.exceptions import UserError + + +class HrDepartureWizard(models.TransientModel): + _inherit = 'hr.departure.wizard' + + set_date_end = fields.Boolean(string="Set Contract End Date", default=True) + + def action_register_departure(self): + """If set_date_end is checked, set the departure date as the end date to current running contract, + and cancel all draft contracts""" + current_contract = self.employee_id.contract_id + if current_contract and current_contract.date_start > self.departure_date: + raise UserError(_("Departure date can't be earlier than the start date of current contract.")) + + super(HrDepartureWizard, self).action_register_departure() + if self.set_date_end: + self.employee_id.contract_ids.filtered(lambda c: c.state == 'draft').write({'state': 'cancel'}) + if current_contract: + self.employee_id.contract_id.write({'date_end': self.departure_date}) diff --git a/addons/hr_contract/wizard/hr_departure_wizard_views.xml b/addons/hr_contract/wizard/hr_departure_wizard_views.xml new file mode 100644 index 00000000000..d336d93899e --- /dev/null +++ b/addons/hr_contract/wizard/hr_departure_wizard_views.xml @@ -0,0 +1,16 @@ + + + + hr.departure.wizard.view.form.extend + hr.departure.wizard + + + + + + + + + + + diff --git a/addons/hr_fleet/__init__.py b/addons/hr_fleet/__init__.py index c48d23bbb1d..c158f87e14f 100644 --- a/addons/hr_fleet/__init__.py +++ b/addons/hr_fleet/__init__.py @@ -3,3 +3,4 @@ from . import controllers from . import models +from . import wizard diff --git a/addons/hr_fleet/__manifest__.py b/addons/hr_fleet/__manifest__.py index ba674b4e788..d12cc85a810 100644 --- a/addons/hr_fleet/__manifest__.py +++ b/addons/hr_fleet/__manifest__.py @@ -10,6 +10,7 @@ 'data': [ 'views/employee_views.xml', 'views/fleet_vehicle_views.xml', + 'wizard/hr_departure_wizard_views.xml' ], 'auto_install': True, } diff --git a/addons/hr_fleet/wizard/__init__.py b/addons/hr_fleet/wizard/__init__.py new file mode 100644 index 00000000000..ea671ff9df8 --- /dev/null +++ b/addons/hr_fleet/wizard/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import hr_departure_wizard diff --git a/addons/hr_fleet/wizard/hr_departure_wizard.py b/addons/hr_fleet/wizard/hr_departure_wizard.py new file mode 100644 index 00000000000..73311599914 --- /dev/null +++ b/addons/hr_fleet/wizard/hr_departure_wizard.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models + + +class HrDepartureWizard(models.TransientModel): + _inherit = 'hr.departure.wizard' + + release_campany_car = fields.Boolean("Release Company Car", default=True) + + def action_register_departure(self): + super(HrDepartureWizard, self).action_register_departure() + if self.release_campany_car: + self._free_campany_car() + + def _free_campany_car(self): + """Find all fleet.vehichle.assignation.log records that link to the employee, if there is no + end date or end date > departure date, update the date. Also check fleet.vehicle to see if + there is any record with its dirver_id to be the employee, set them to False.""" + drivers = self.employee_id.user_id.partner_id | self.employee_id.sudo().address_home_id + assignations = self.env['fleet.vehicle.assignation.log'].search([('driver_id', 'in', drivers.ids)]) + for assignation in assignations: + if self.departure_date and (not assignation.date_end or assignation.date_end > self.departure_date): + assignation.write({'date_end': self.departure_date}) + cars = self.env['fleet.vehicle'].search([('driver_id', 'in', drivers.ids)]) + cars.write({'driver_id': False}) diff --git a/addons/hr_fleet/wizard/hr_departure_wizard_views.xml b/addons/hr_fleet/wizard/hr_departure_wizard_views.xml new file mode 100644 index 00000000000..72c38a786d4 --- /dev/null +++ b/addons/hr_fleet/wizard/hr_departure_wizard_views.xml @@ -0,0 +1,13 @@ + + + + hr.departure.wizard.view.form.extend2 + hr.departure.wizard + + + + + + + + diff --git a/addons/hr_holidays/__manifest__.py b/addons/hr_holidays/__manifest__.py index f41b34cc4cf..dcac711d856 100644 --- a/addons/hr_holidays/__manifest__.py +++ b/addons/hr_holidays/__manifest__.py @@ -40,6 +40,7 @@ A synchronization with an internal agenda (Meetings of the CRM module) is also p 'views/mail_activity_views.xml', 'wizard/hr_holidays_summary_employees_views.xml', + 'wizard/hr_departure_wizard_views.xml', 'report/hr_holidays_templates.xml', 'report/hr_holidays_reports.xml', diff --git a/addons/hr_holidays/wizard/__init__.py b/addons/hr_holidays/wizard/__init__.py index c69c60bfbfb..2b891270d1e 100644 --- a/addons/hr_holidays/wizard/__init__.py +++ b/addons/hr_holidays/wizard/__init__.py @@ -2,3 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import hr_holidays_summary_employees +from . import hr_departure_wizard diff --git a/addons/hr_holidays/wizard/hr_departure_wizard.py b/addons/hr_holidays/wizard/hr_departure_wizard.py new file mode 100644 index 00000000000..784d4f3ae3d --- /dev/null +++ b/addons/hr_holidays/wizard/hr_departure_wizard.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from datetime import datetime, timedelta + +from odoo import api, fields, models + + +class HrDepartureWizard(models.TransientModel): + _inherit = 'hr.departure.wizard' + + cancel_leaves = fields.Boolean("Cancel Future Leaves", default=True) + + def action_register_departure(self): + super(HrDepartureWizard, self).action_register_departure() + if self.cancel_leaves: + future_leaves = self.env['hr.leave'].search([('employee_id', '=', self.employee_id.id), + ('date_to', '>', self.departure_date), + ('state', 'not in', ['cancel', 'refuse'])]) + future_leaves.write({'state': 'cancel'}) diff --git a/addons/hr_holidays/wizard/hr_departure_wizard_views.xml b/addons/hr_holidays/wizard/hr_departure_wizard_views.xml new file mode 100644 index 00000000000..02dd43c90bd --- /dev/null +++ b/addons/hr_holidays/wizard/hr_departure_wizard_views.xml @@ -0,0 +1,13 @@ + + + + hr.departure.wizard.view.form.extend3 + hr.departure.wizard + + + + + + + +