oca-ocb-hr/odoo-bringout-oca-ocb-hr/hr/tests/test_hr_contract_versions.py
Ernad Husremovic e1d89e11e3 19.0 vanilla
2026-03-09 09:31:00 +01:00

594 lines
21 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
@tagged('post_install', '-at_install')
class TestHrContractVersions(TransactionCase):
"""
TestHrContractVersions is responsible for testing the behavior and validity of versions
with contracts.
This class tests 2 helper methods: `_get_contract_versions()` and `_get_contracts()`
There are multiple scenarios:
- No contract, 1 version
- 1 contract with 1 version
- 1 contract with 5 versions
- 2 contracts with 1 version each
- 2 contracts with 3 versions each
For each of them, multiple tests are performed with different start_date, end_date and use_latest_version
"""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.company = cls.env['res.company'].create({
'name': 'Test Company',
'country_id': cls.env.ref('base.us').id,
})
cls.env.user.company_id = cls.company
cls.employee = cls.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2025-01-01'
})
def create_version(self, date_version):
return self.employee.create_version({
'date_version': date_version,
})
def create_versions(self, *dates):
res = self.env["hr.version"]
for date_version in dates:
res |= self.create_version(date_version)
return res
def assert_get_contract_versions(self, date_start, date_end, versions_per_contract_expected):
versions_per_contract = self.employee._get_contract_versions(date_start, date_end)[self.employee.id]
self.assertEqual(len(versions_per_contract), len(versions_per_contract_expected), "%s contract should be found" % len(versions_per_contract_expected))
for vpc, vpc_e in zip(versions_per_contract.values(), versions_per_contract_expected):
self.assertEqual(vpc, vpc_e, "invalid number of versions (%s instead of %s) for this contract : contract_date_start : %s" % (len(vpc), len(vpc_e), vpc_e[0].contract_date_start))
def assert_get_contracts(self, date_start, date_end, use_latest_version, contracts_expected):
contracts = self.employee._get_contracts(date_start, date_end, use_latest_version)[self.employee.id]
for c, c_e in zip(contracts, contracts_expected):
self.assertEqual(c, c_e, "invalid contracts")
def test_0contract_1version(self):
"""
We should retrieve no versions, because no contract is defined
"""
for date_version in ['2025-01-01', '2025-06-01', '2025-12-31']:
self.employee.date_version = date_version
for date_start in (None, date(2025, 3, 1)):
for date_end in (None, date(2025, 6, 15)):
for use_latest_version in (True, False):
self.assert_get_contract_versions(
date_start,
date_end,
[]
)
self.assert_get_contracts(
date_start,
date_end,
use_latest_version,
[]
)
""" Timeline for this test
V : versions
C : first version of the contract
= : contract
1/
04/01 7/31
2025|C---------=====================----------|
01/01 06/01 12/31
2/
04/01 7/31
2025|----------==========C==========----------|
01/01 06/01 12/31
3/
04/01 7/31
2025|----------=====================---------C|
01/01 06/01 12/31
"""
def test_1contract_1version(self):
"""
We should always retrieve the only existing version
"""
unique_version = self.employee.version_id
unique_version.contract_date_start = date(2025, 4, 1)
unique_version.contract_date_end = date(2025, 7, 31)
for date_version in ['2025-01-01', '2025-06-01', '2025-12-31']:
unique_version.date_version = date_version
for date_start in (None, date(2025, 3, 1), date(2025, 4, 1)):
for date_end in (None, date(2025, 4, 1), date(2025, 6, 15), date(2025, 7, 31)):
for use_latest_version in (True, False):
self.assert_get_contract_versions(
date_start,
date_end,
[unique_version]
)
self.assert_get_contracts(
date_start,
date_end,
use_latest_version,
unique_version
)
""" Timeline for this setup
V : versions
C : first version of the contract
= : contract
04/01=========================07/31
2025|C---------V---------------V------V--------VV---------|
01/01 04/01 06/01 07/01 07/31;08/01
"""
def setup_1contract_5version(self):
contract_versions = self.employee.version_id | self.create_versions(
date(2025, 4, 1),
date(2025, 6, 1),
date(2025, 7, 1),
date(2025, 7, 31)
)
contract_versions.contract_date_start = date(2025, 4, 1)
contract_versions.contract_date_end = date(2025, 7, 31)
versions_not_in_contract = self.create_version(date(2025, 8, 1))
return contract_versions, versions_not_in_contract
def test_1contract_5version(self):
# All versions of the contract should be retrieved
expected_contract_versions, _ = self.setup_1contract_5version()
self.assert_get_contract_versions(
None,
None,
[expected_contract_versions]
)
# The last version of the contract should be retrieved
self.assert_get_contracts(
None,
None,
True,
expected_contract_versions[-1]
)
# The first version of the contract should be retrieved
self.assert_get_contracts(
None,
None,
False,
expected_contract_versions[0]
)
def test_1contract_5version_w_date_start(self):
# All versions of the contract should be retrieved
expected_contract_versions, _ = self.setup_1contract_5version()
self.assert_get_contract_versions(
date(2025, 3, 1),
None,
[expected_contract_versions]
)
# The last version of the contract should be retrieved
self.assert_get_contracts(
date(2025, 3, 1),
None,
True,
expected_contract_versions[-1]
)
# We need to retrieve the version closest and before the start date. (first version of the contract)
self.assert_get_contracts(
date(2025, 3, 1),
None,
False,
expected_contract_versions[0]
)
# We need to retrieve the version closest and before the start date. (second version of the contract)
self.assert_get_contracts(
date(2025, 4, 1),
None,
False,
expected_contract_versions[0]
)
def test_1contract_5version_w_date_start_date_end(self):
# all versions of the contract should be retrieved (even if versions are not in the range)
expected_contract_versions, _ = self.setup_1contract_5version()
self.assert_get_contract_versions(
date(2025, 5, 15),
date(2025, 6, 15),
[expected_contract_versions]
)
# We need to retrieve the version closest and before the end date.
self.assert_get_contracts(
date(2025, 4, 15),
date(2025, 6, 15),
True,
expected_contract_versions[2]
)
# We need to retrieve the version closest and before the start date.
self.assert_get_contracts(
date(2025, 4, 15),
date(2025, 6, 15),
False,
expected_contract_versions[1]
)
# We need to retrieve the version closest and before the end date.
self.assert_get_contracts(
date(2025, 6, 15),
date(2025, 7, 15),
True,
expected_contract_versions[3]
)
# We need to retrieve the version closest and before the start date.
self.assert_get_contracts(
date(2025, 6, 15),
date(2025, 8, 15),
False,
expected_contract_versions[2]
)
def test_1contract_5version_w_date_end(self):
# All versions of the contract should be retrieved
expected_contract_versions, _ = self.setup_1contract_5version()
self.assert_get_contract_versions(
None,
date(2025, 8, 31),
[expected_contract_versions]
)
# We need to retrieve the version closest and before the end date. (last version of the contract)
self.assert_get_contracts(
None,
date(2025, 8, 31),
True,
expected_contract_versions[-1]
)
# We need to retrieve the version closest and before the end date. (last version of the contract)
self.assert_get_contracts(
None,
date(2025, 7, 31),
True,
expected_contract_versions[-1]
)
# We need to retrieve the version closest and before the end date. (second to last version of the contract)
self.assert_get_contracts(
None,
date(2025, 7, 30),
True,
expected_contract_versions[-2]
)
# The first version of the contract should be retrieved
self.assert_get_contracts(
None,
date(2025, 8, 31),
False,
expected_contract_versions[0]
)
""" Timeline for this setup
V : versions
C : first version of the contract
= : contract
4/01 5/15 6/15 7/31
2025|C---------====================-C-====================----------|
01/01 06/01
"""
def setup_2contract_1version_each(self):
contract_1_version = self.employee.version_id
contract_1_version.contract_date_start = date(2025, 4, 1)
contract_1_version.contract_date_end = date(2025, 5, 15)
contract_2_version = self.create_version(date(2025, 6, 1))
contract_2_version.contract_date_start = date(2025, 6, 15)
contract_2_version.contract_date_end = date(2025, 7, 31)
return contract_1_version, contract_2_version
def test_2contract_1version_each(self):
# all versions of all contracts
contract_1_version, contract_2_version = self.setup_2contract_1version_each()
self.assert_get_contract_versions(
None,
None,
[contract_1_version, contract_2_version]
)
# the latest version of each contract
self.assert_get_contracts(
None,
None,
True,
contract_1_version | contract_2_version
)
# the first version of each contract
self.assert_get_contracts(
None,
None,
False,
contract_1_version | contract_2_version
)
def test_2contract_1version_each_w_date_start(self):
# all versions of all contracts
contract_1_version, contract_2_version = self.setup_2contract_1version_each()
self.assert_get_contract_versions(
date(2025, 3, 1),
None,
[contract_1_version, contract_2_version]
)
# all versions of the second contract
self.assert_get_contract_versions(
date(2025, 6, 15),
None,
[contract_2_version]
)
# the latest version of each contract
self.assert_get_contracts(
date(2025, 3, 1),
None,
True,
contract_1_version | contract_2_version
)
# the first before the start date, of each contract
self.assert_get_contracts(
date(2025, 3, 1),
None,
False,
contract_1_version | contract_2_version
)
def test_2contract_1version_each_w_date_start_date_end(self):
# no versions, because no contract active in the range, even if versions are in the range
contract_1_version, contract_2_version = self.setup_2contract_1version_each()
self.assert_get_contract_versions(
date(2025, 5, 16),
date(2025, 6, 14),
[]
)
# all versions of each contract
self.assert_get_contract_versions(
date(2025, 5, 15),
date(2025, 6, 15),
[contract_1_version, contract_2_version]
)
# the first version before the end date, of the contract active in the range
self.assert_get_contracts(
date(2025, 5, 15),
date(2025, 6, 14),
True,
contract_1_version
)
# the first version before the start date, of the contract active in the range
self.assert_get_contracts(
date(2025, 5, 15),
date(2025, 6, 14),
False,
contract_1_version
)
# the first version before the end date, of the contract active in the range
self.assert_get_contracts(
date(2025, 5, 16),
date(2025, 6, 15),
True,
contract_2_version
)
# the first version before the start date, of the contract active in the range
self.assert_get_contracts(
date(2025, 5, 16),
date(2025, 6, 15),
False,
contract_2_version
)
# the first version before the end date, of the contract active in the range
self.assert_get_contracts(
date(2025, 5, 15),
date(2025, 6, 15),
True,
[contract_1_version, contract_2_version]
)
# the first version before the start date, of the contract active in the range
self.assert_get_contracts(
date(2025, 5, 15),
date(2025, 6, 15),
False,
[contract_1_version, contract_2_version]
)
def test_2contract_1version_each_w_date_end(self):
# all versions of all contracts
contract_1_version, contract_2_version = self.setup_2contract_1version_each()
self.assert_get_contract_versions(
None,
date(2025, 8, 31),
[contract_1_version, contract_2_version]
)
# all versions of the first contract
self.assert_get_contract_versions(
None,
date(2025, 6, 15),
[contract_1_version, contract_2_version]
)
# all versions of the first contract
self.assert_get_contract_versions(
None,
date(2025, 6, 14),
[contract_1_version]
)
# the first before the end date, of each contract
self.assert_get_contracts(
None,
date(2025, 8, 31),
True,
contract_1_version | contract_2_version
)
# the first version of each contract
self.assert_get_contracts(
None,
date(2025, 8, 31),
False,
contract_1_version | contract_2_version
)
""" Timeline for this setup
V : versions
C : first version of the contract
= : contract
4/01============5/15 6/15============7/31
2025|C---------V------------------VV------C-------V------------------VV---------|
1/1 4/1 5/15;5/16 6/1 6/15 7/31;8/1
"""
def setup_2contract_3version_each(self):
contract_1_versions = self.employee.version_id | self.create_versions(
date(2025, 4, 1),
date(2025, 5, 15),
)
contract_1_versions.contract_date_start = date(2025, 4, 1)
contract_1_versions.contract_date_end = date(2025, 5, 15)
versions_not_in_contract = self.create_version(date(2025, 5, 16))
contract_2_versions = self.create_versions(
date(2025, 6, 1),
date(2025, 6, 15),
date(2025, 7, 31),
)
contract_2_versions.contract_date_start = date(2025, 6, 15)
contract_2_versions.contract_date_end = date(2025, 7, 31)
versions_not_in_contract |= self.create_version(date(2025, 8, 1))
return contract_1_versions, contract_2_versions, versions_not_in_contract
def test_2contract_3version_each(self):
# all versions of all contracts
contract_1_version, contract_2_version, _ = self.setup_2contract_3version_each()
self.assert_get_contract_versions(
None,
None,
[contract_1_version, contract_2_version]
)
# the latest version of each contract
self.assert_get_contracts(
None,
None,
True,
contract_1_version[-1] | contract_2_version[-1]
)
# the first version of each contract
self.assert_get_contracts(
None,
None,
False,
contract_1_version[0] | contract_2_version[0]
)
def test_2contract_3version_each_w_date_start(self):
# all versions of all contracts
contract_1_version, contract_2_version, _ = self.setup_2contract_3version_each()
self.assert_get_contract_versions(
date(2025, 3, 1),
None,
[contract_1_version, contract_2_version]
)
# the latest version of each contract
self.assert_get_contracts(
date(2025, 3, 1),
None,
True,
contract_1_version[-1] | contract_2_version[-1]
)
# the first before the start date, of each contract
self.assert_get_contracts(
date(2025, 3, 1),
None,
False,
contract_1_version[0] | contract_2_version[0]
)
# the first before the start date, of each contract
self.assert_get_contracts(
date(2025, 4, 1),
None,
False,
contract_1_version[1] | contract_2_version[0]
)
def test_2contract_3version_each_w_date_start_date_end(self):
# all versions of all contracts
contract_1_version, contract_2_version, _ = self.setup_2contract_3version_each()
self.assert_get_contract_versions(
date(2025, 5, 16),
date(2025, 6, 14),
[]
)
# the first before the end date, of the contract active in the range
self.assert_get_contracts(
date(2025, 4, 15),
date(2025, 6, 15),
True,
[contract_1_version[-1], contract_2_version[1]]
)
# the first before the start date, of the contract active in the range
self.assert_get_contracts(
date(2025, 4, 15),
date(2025, 6, 15),
False,
[contract_1_version[0], contract_2_version[0]]
)
# the first before the end date, of the contract active in the range
self.assert_get_contracts(
date(2025, 6, 15),
date(2025, 7, 31),
True,
contract_2_version[-1]
)
# the first before the start date, of the contract active in the range
self.assert_get_contracts(
date(2025, 6, 15),
date(2025, 7, 31),
False,
contract_2_version[1]
)
def test_2contract_3version_each_w_date_end(self):
# all versions of all contracts
contract_1_version, contract_2_version, _ = self.setup_2contract_3version_each()
self.assert_get_contract_versions(
None,
date(2025, 8, 31),
[contract_1_version, contract_2_version]
)
# the first before the end date, of each contract
self.assert_get_contracts(
None,
date(2025, 8, 31),
True,
contract_1_version[-1] | contract_2_version[-1]
)
# the first before the end date, of each contract
self.assert_get_contracts(
None,
date(2025, 7, 31),
True,
contract_1_version[-1] | contract_2_version[-1]
)
# the first before the end date, of each contract
self.assert_get_contracts(
None,
date(2025, 7, 30),
True,
contract_1_version[-1] | contract_2_version[-2]
)
# the latest version of each contract
self.assert_get_contracts(
None,
date(2025, 8, 31),
False,
contract_1_version[0] | contract_2_version[0]
)