From 8927f28bd63e59e8f8be599d37c2e4fdd5580dac Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Wed, 26 Jan 2022 13:08:41 +0000 Subject: [PATCH] [FIX] hr_contract: Exclude gaps on first contract date computation Purpose ======= This field is used for several things, like the simple holiday pay recovery. Normally, we expect the HR officers to create a new employee, instead of unarchiving the old one, but this could happen. If someone leaves the company, and come back, take the new entry date as first contract date instead of the original one. closes odoo/odoo#83493 Taskid: 2745947 X-original-commit: a17c601fffca149a5c4d7be2924fb581ae408299 Related: odoo/enterprise#23790 Signed-off-by: Yannick Tivisse (yti) --- addons/hr_contract/models/hr_employee.py | 32 +++++++++++++++++++---- addons/hr_contract/tests/test_contract.py | 12 +++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/addons/hr_contract/models/hr_employee.py b/addons/hr_contract/models/hr_employee.py index 3cc3ab03e7f..b395c4dc27d 100644 --- a/addons/hr_contract/models/hr_employee.py +++ b/addons/hr_contract/models/hr_employee.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from datetime import date from odoo import api, fields, models from odoo.osv import expression @@ -22,14 +23,35 @@ class Employee(models.Model): self.ensure_one() return self.sudo().contract_ids.filtered(lambda c: c.state != 'cancel') + def _get_first_contract_date(self, no_gap=True): + self.ensure_one() + def remove_gap(contracts): + # We do not consider a gap of more than 4 days to be a same occupation + # contracts are considered to be ordered correctly + if not contracts: + return self.env['hr.contract'] + if len(contracts) == 1: + return contracts + current_contract = contracts[0] + older_contracts = contracts[1:] + current_date = current_contract.date_start + for i, other_contract in enumerate(older_contracts): + # Consider current_contract.date_end being false as an error and cut the loop + gap = (current_date - (other_contract.date_end or date(2100, 1, 1))).days + current_date = other_contract.date_start + if gap >= 4: + return older_contracts[0:i] + current_contract + return older_contracts + current_contract + + contracts = self._get_first_contracts().sorted('date_start', reverse=True) + if no_gap: + contracts = remove_gap(contracts) + return min(contracts.mapped('date_start')) if contracts else False + @api.depends('contract_ids.state', 'contract_ids.date_start') def _compute_first_contract_date(self): for employee in self: - contracts = employee._get_first_contracts() - if contracts: - employee.first_contract_date = min(contracts.mapped('date_start')) - else: - employee.first_contract_date = False + employee.first_contract_date = employee._get_first_contract_date() @api.depends('contract_id', 'contract_id.state', 'contract_id.kanban_state') def _compute_contract_warning(self): diff --git a/addons/hr_contract/tests/test_contract.py b/addons/hr_contract/tests/test_contract.py index 7f4b9ed8d60..6b53060bb01 100644 --- a/addons/hr_contract/tests/test_contract.py +++ b/addons/hr_contract/tests/test_contract.py @@ -89,3 +89,15 @@ class TestHrContracts(TestContractCommon): contract = self.create_contract('draft', 'normal', date(2018, 1, 1), date(2018, 1, 2)) contract.state = 'open' self.assertEqual(self.employee.contract_id, contract) + + def test_first_contract_date(self): + self.create_contract('open', 'normal', date(2018, 1, 1), date(2018, 1, 31)) + self.assertEqual(self.employee.first_contract_date, date(2018, 1, 1)) + + # New contract, no gap + self.create_contract('open', 'normal', date(2017, 1, 1), date(2017, 12, 31)) + self.assertEqual(self.employee.first_contract_date, date(2017, 1, 1)) + + # New contract, with gap + self.create_contract('open', 'normal', date(2016, 1, 1), date(2016, 1, 31)) + self.assertEqual(self.employee.first_contract_date, date(2017, 1, 1))