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

842 lines
35 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date
from psycopg2.errors import CheckViolation
from odoo.tests import tagged
from odoo.tests.common import freeze_time
from odoo.exceptions import AccessError, ValidationError
from odoo.tools import mute_logger
from odoo.addons.hr.tests.common import TestHrCommon
from odoo.addons.mail.tests.common import mail_new_test_user
@tagged('post_install', '-at_install')
class TestHrVersion(TestHrCommon):
def test_dates_constraints(self):
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01'
})
self.assertFalse(employee.contract_date_start)
self.assertFalse(employee.contract_date_end)
employee.write({
'contract_date_start': '2020-01-01',
'contract_date_end': False
})
self.assertEqual(employee.contract_date_start, date(2020, 1, 1))
self.assertFalse(employee.contract_date_end)
employee.write({
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31'
})
self.assertEqual(employee.contract_date_start, date(2020, 1, 1))
self.assertEqual(employee.contract_date_end, date(2020, 12, 31))
employee.write({
'contract_date_start': False,
'contract_date_end': False
})
self.assertFalse(employee.contract_date_start)
self.assertFalse(employee.contract_date_end)
with self.assertRaises(CheckViolation), mute_logger('odoo.sql_db'):
employee.write({
'contract_date_start': False,
'contract_date_end': '2020-12-31'
})
with self.assertRaises(ValidationError):
employee.write({
'contract_date_start': '2021-01-01',
'contract_date_end': '2020-12-31'
})
def test_contracts_no_overlap(self):
# Simple overlap cases
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31'
})
with self.assertRaises(ValidationError):
employee.create_version({
'date_version': '2019-06-01',
'contract_date_start': '2019-06-01',
'contract_date_end': '2020-05-31'
})
with self.assertRaises(ValidationError):
employee.create_version({
'date_version': '2020-06-01',
'contract_date_start': '2020-06-01',
'contract_date_end': '2021-05-31'
})
with self.assertRaises(ValidationError):
employee.create_version({
'date_version': '2020-02-01',
'contract_date_start': '2020-02-01',
'contract_date_end': '2020-10-31'
})
# It should not detect overlap with archived versions
employee.create_version({
'active': False,
'date_version': '2019-06-01',
'contract_date_start': '2019-06-01',
'contract_date_end': '2020-05-31'
})
def test_occupation_dates(self):
"""
Occupation dates are global for the employee, they are a list of intervals
(date_from, date_to) where the employee is in contract (date_from and date_to included).
"""
# A single version and no contract
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01'
})
self.assertEqual(employee._get_all_contract_dates(), [])
# A single version and contract
employee.write({
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31'
})
occupation_dates = [(date(2020, 1, 1), date(2020, 12, 31))]
self.assertEqual(employee._get_all_contract_dates(), occupation_dates)
# 2 versions with 1 contract each
employee.create_version({
'date_version': '2021-01-01',
'contract_date_start': '2021-01-01',
'contract_date_end': '2023-12-31'
})
occupation_dates = [
(date(2020, 1, 1), date(2020, 12, 31)),
(date(2021, 1, 1), date(2023, 12, 31)),
]
self.assertEqual(employee._get_all_contract_dates(), occupation_dates)
# 3 versions with 2 sharing the same contract
employee.create_version({
'date_version': '2022-01-01',
})
self.assertEqual(employee._get_all_contract_dates(), occupation_dates)
# 4 versions with 2 sharing the same contract, the last one is permanent
employee.create_version({
'date_version': '2025-01-01',
'contract_date_start': '2025-01-01',
})
occupation_dates = [
(date(2020, 1, 1), date(2020, 12, 31)),
(date(2021, 1, 1), date(2023, 12, 31)),
(date(2025, 1, 1), False),
]
self.assertEqual(employee._get_all_contract_dates(), occupation_dates)
def test_dates_new_version_out_of_contract(self):
"""
If the new version falls on a period out of contract, clear the dates
"""
# Create a new version after the end of the current contract
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31',
})
version = employee.create_version({
'date_version': '2021-01-01'
})
self.assertFalse(version.contract_date_start)
self.assertFalse(version.contract_date_end)
# Forcing the contract_date_start and or contract_date_end in the 'create' should override False
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31',
})
version = employee.create_version({
'date_version': '2021-01-01',
'contract_date_start': '2021-01-01',
'contract_date_end': '2021-12-31'
})
self.assertEqual(version.contract_date_start, date(2021, 1, 1))
self.assertEqual(version.contract_date_end, date(2021, 12, 31))
# Create a new version before the start of the current contract
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31',
})
version = employee.create_version({'date_version': '2019-01-01'})
self.assertFalse(version.contract_date_start)
self.assertFalse(version.contract_date_end)
# Create a new version between two contracts
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31'
})
employee.create_version({
'date_version': '2022-01-01',
'contract_date_start': '2022-01-01',
'contract_date_end': '2022-12-31'
})
version = employee.create_version({
'date_version': '2021-01-01',
})
self.assertFalse(version.contract_date_start)
self.assertFalse(version.contract_date_end)
def test_dates_new_version_in_contract(self):
"""
If the new version falls on some contract, copy its contract dates
"""
# Create a new version on a permanent contract
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
})
version = employee.create_version({
'date_version': '2021-01-01'
})
self.assertEqual(version.contract_date_start, date(2020, 1, 1))
self.assertFalse(version.contract_date_end)
# Create a new version on a fixed term contract
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'contract_date_start': '2020-01-01',
'contract_date_end': '2021-12-31'
})
version = employee.create_version({'date_version': '2021-01-01'})
self.assertEqual(version.contract_date_start, date(2020, 1, 1))
self.assertEqual(version.contract_date_end, date(2021, 12, 31))
# Create a new version on any contract interval regardless of the version valid at that date
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31'
})
employee.create_version({
'date_version': '2022-01-01',
'contract_date_start': '2021-01-01',
'contract_date_end': '2022-12-31'
})
version = employee.create_version({
'date_version': '2021-01-01',
})
self.assertEqual(version.contract_date_start, date(2021, 1, 1))
self.assertEqual(version.contract_date_end, date(2022, 12, 31))
def test_dates_synchronisation(self):
"""
All versions that share or will share (at the end of a 'write')
the same contract_date_start are synchronized.
"""
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2021-12-31',
})
v1 = employee.version_id
v2 = employee.create_version({
'date_version': '2021-01-01',
'contract_date_end': '2022-12-31',
})
self.assertEqual(v2.contract_date_end, date(2022, 12, 31))
self.assertEqual(v1.contract_date_end, v2.contract_date_end)
v1.write({
'contract_date_start': '2021-01-01',
})
self.assertEqual(v1.contract_date_start, date(2021, 1, 1))
self.assertEqual(v1.contract_date_start, v2.contract_date_start)
v2.write({
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31',
})
self.assertEqual(v2.contract_date_start, date(2020, 1, 1))
self.assertEqual(v1.contract_date_start, v2.contract_date_start)
self.assertEqual(v2.contract_date_end, date(2020, 12, 31))
self.assertEqual(v1.contract_date_end, v2.contract_date_end)
v3 = employee.create_version({
'date_version': '2030-01-01',
'contract_date_start': '2030-01-01',
})
versions = []
for i in range(10):
versions.append(employee.create_version({
'date_version': f'20{31 + i}-01-01',
}))
v3.write({
'contract_date_end': '2040-12-31',
})
for version in versions:
self.assertEqual(version.contract_date_end, date(2040, 12, 31))
def test_1_version_contract_synchronisation(self):
"""
When an employee has only one version, the contract_date_start should
be synchronized with the date_version.
"""
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
version = employee.version_id
employee.write({'contract_date_start': '2019-01-01'})
self.assertEqual(version.contract_date_start, version.date_version)
# date_version should not be reset if the contract_date_start is set to False
employee.write({'contract_date_start': False})
self.assertEqual(version.date_version, date(2019, 1, 1))
employee.write({'contract_date_start': '2021-01-01'})
self.assertEqual(version.contract_date_start, version.date_version)
def test_2_versions_contract_synchronisation(self):
"""
When an employee has two versions, the synchronisation should stop
"""
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
v1 = employee.version_id
employee.write({'contract_date_start': '2019-01-01'})
self.assertEqual(v1.contract_date_start, v1.date_version)
v2 = employee.create_version({'date_version': '2021-01-01'})
employee.write({'contract_date_start': '2020-01-01'})
self.assertEqual(v1.date_version, date(2019, 1, 1))
self.assertEqual(v2.date_version, date(2021, 1, 1))
# Archived versions do not count.
# So if we archive v2, the synchronisation should start again.
v2.active = False
employee.write({'contract_date_start': '2021-01-01'})
self.assertEqual(v1.contract_date_start, v1.date_version)
def test_in_out_contract(self):
"""
Check that an employee is in or out of the contract at a specific date.
"""
# If no contract dates are defined, the employee is not considered in contract
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
self.assertFalse(employee._is_in_contract(date(2010, 1, 1)))
self.assertFalse(employee._is_in_contract(date(2020, 1, 1)))
self.assertFalse(employee._is_in_contract(date(2030, 1, 1)))
# In a permanent contract, the employee is contract since the contract_date_start
employee.contract_date_start = '2020-01-01'
self.assertFalse(employee._is_in_contract(date(2010, 1, 1)))
self.assertTrue(employee._is_in_contract(date(2020, 1, 1)))
self.assertTrue(employee._is_in_contract(date(2030, 1, 1)))
# In a fixed term contract, the employee is contract in between the contract dates
employee.contract_date_end = '2029-12-31'
self.assertFalse(employee._is_in_contract(date(2010, 1, 1)))
self.assertTrue(employee._is_in_contract(date(2020, 1, 1)))
self.assertFalse(employee._is_in_contract(date(2030, 1, 1)))
def test_cron_update_current_version(self):
cron = self.env.ref('hr.ir_cron_data_employee_update_current_version')
with freeze_time(date(2020, 1, 1)), self.enter_registry_test_mode():
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
v1 = employee.version_id
v2 = employee.create_version({
'date_version': '2020-01-02'
})
self.assertEqual(v1, employee.current_version_id)
cron.method_direct_trigger()
self.assertEqual(v1, employee.current_version_id)
with freeze_time(date(2020, 1, 2)), self.enter_registry_test_mode():
self.assertEqual(v1, employee.current_version_id)
cron.method_direct_trigger()
self.assertEqual(v2, employee.current_version_id)
def test_related_fields_on_version(self):
""" Some groups have been added to avoid users with basic access to HR app see some critical (like wage field for instance)
This test makes sure the groups added in version fields is also in the employee fields related.
However, to define the same groups in employee fields, we have to redefine the related fields (readonly=False, related='version_id.{field_name})
Otherwise, the field we loose the linked with the version field and could be readonly instead of editable.
"""
version_fields = {
f_name: field
for f_name, field in self.env['hr.version']._fields.items()
if field.groups and field.groups not in ['hr.group_hr_user', 'base.group_user'] and not (field.related and field.related.startswith('employee_id'))
}
employee_fields = {
f_name: field
for f_name, field in self.env['hr.employee']._fields.items()
if f_name in version_fields
}
fields_without_group = []
fields_without_related = []
fields_readonly = []
for f_name, field in employee_fields.items():
v_field = version_fields[f_name]
if not (field.groups and field.groups != v_field):
fields_without_group.append(f_name)
elif not (field.related and field.related == f'version_id.{f_name}'):
fields_without_related.append(f_name)
elif field.readonly != v_field.readonly:
fields_readonly.append(f_name)
self.assertFalse(fields_without_group, "Inconsistency between some employee fields and version ones (those employees fields should have the same groups than related one in version")
self.assertFalse(fields_without_related, "Some employee fields have the same name than the version ones but they are not related")
self.assertFalse(fields_readonly, "(Readonly) Inconsistency between some employee fields and version ones, the both fields (in version and employee) have to be readonly or editable")
def test_multi_edit_contract_sync_same_contract(self):
"""
Test the multi-edit contract sync feature when the targeted versions share the same contract.
"""
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31',
})
versions = employee.version_id
versions |= employee.create_version({'date_version': '2020-04-01'})
versions |= employee.create_version({'date_version': '2020-08-01'})
versions[:2].contract_date_end = "2020-9-30"
for version in versions:
self.assertEqual(version.contract_date_end, date(2020, 9, 30))
def test_multi_edit_contract_sync_different_contract(self):
"""
Test the multi-edit contract sync feature when the targeted versions have different contracts.
"""
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-5-31',
})
versions = employee.version_id
versions |= employee.create_version({'date_version': '2020-04-01'})
versions |= employee.create_version({
'date_version': '2020-08-01',
'contract_date_start': '2020-08-01',
})
with self.assertRaises(ValidationError):
versions[:2].contract_date_end = "2020-9-30"
def test_multi_edit_other(self):
"""
Test the multi-edit when the targeted versions have different contracts
Different fields than contract_date_start and contract_date_end are changed.
"""
jobA = self.env['hr.job'].create({'name': "Job A"})
jobB = self.env['hr.job'].create({'name': "Job B"})
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-5-31',
'job_id': jobA.id,
})
versions = employee.version_id
versions |= employee.create_version({'date_version': '2020-04-01'})
versions |= employee.create_version({
'date_version': '2020-08-01',
'contract_date_start': '2020-08-01',
'job_id': jobA.id,
})
versions[1:].job_id = jobB.id
self.assertEqual(versions[0].job_id.id, jobA.id)
for version in versions[1:]:
self.assertEqual(version.job_id.id, jobB.id)
def test_multi_edit_other_and_contract_date_sync(self):
"""
Test the multi-edit when the targeted versions have the same contract
Different contract_dates and other fields are changed.
"""
jobA = self.env['hr.job'].create({'name': "Job A"})
jobB = self.env['hr.job'].create({'name': "Job B"})
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-12-31',
'job_id': jobA.id,
})
versions = employee.version_id
versions |= employee.create_version({'date_version': '2020-04-01'})
versions |= employee.create_version({'date_version': '2020-08-01'})
versions[1:].write({
"contract_date_end": "2020-9-30",
"job_id": jobB.id,
})
self.assertEqual(versions[0].job_id.id, jobA.id)
self.assertEqual(versions[0].contract_date_end, date(2020, 9, 30))
for version in versions[1:]:
self.assertEqual(version.job_id.id, jobB.id)
self.assertEqual(version.contract_date_end, date(2020, 9, 30))
def test_delete_version(self):
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
v1 = employee.version_id
v2 = employee.create_version({
'date_version': '2021-01-01',
})
v3 = employee.create_version({
'date_version': '2022-01-01',
})
self.assertEqual(employee.current_version_id, v3)
v3.unlink()
self.assertEqual(employee.current_version_id, v2)
v1.unlink()
self.assertEqual(employee.current_version_id, v2)
with self.assertRaises(ValidationError):
v2.unlink()
def test_multi_edit_multi_employees_no_contract(self):
"""
Test the multi-edit when there is one version per employee, without contract
"""
employee_john, employee_rob = self.env['hr.employee'].create([
{
'name': 'John Doe',
'date_version': '2020-01-01',
},
{
'name': 'Rob Carter',
'date_version': '2020-10-18',
}
])
versions = (employee_john | employee_rob).version_id
versions.write({
'contract_date_start': '2021-10-10'
})
self.assertEqual(versions[0].contract_date_start, date(2021, 10, 10))
self.assertEqual(versions[1].contract_date_start, date(2021, 10, 10))
def test_multi_edit_multi_employees_mix_contract(self):
"""
Test the multi-edit when there is one version per employee, some with contract
"""
employee_john, employee_rob = self.env['hr.employee'].create([
{
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
},
{
'name': 'Rob Carter',
'date_version': '2020-10-18',
}
])
versions = (employee_john | employee_rob).version_id
versions.write({
'contract_date_start': '2021-10-10'
})
self.assertEqual(versions[0].contract_date_start, date(2021, 10, 10))
self.assertEqual(versions[1].contract_date_start, date(2021, 10, 10))
def test_multi_edit_multi_employees_all_contract(self):
"""
Test the multi-edit when there is one version per employee, all with different contract
"""
employee_john, employee_rob = self.env['hr.employee'].create([
{
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
},
{
'name': 'Rob Carter',
'date_version': '2020-10-18',
'contract_date_start': '2020-10-18',
}
])
versions = (employee_john | employee_rob).version_id
versions |= employee_john.create_version({
'date_version': '2021-08-01',
'contract_date_start': '2020-01-01',
})
versions.write({
'contract_date_start': '2021-10-10'
})
self.assertEqual(versions[0].contract_date_start, date(2021, 10, 10))
self.assertEqual(versions[1].contract_date_start, date(2021, 10, 10))
self.assertEqual(versions[2].contract_date_start, date(2021, 10, 10))
def test_multi_edit_multi_employees_incompatible(self):
"""
Test the multi-edit when there is one version per employee, one with incompatible dates
"""
employee_john, employee_rob = self.env['hr.employee'].create([
{
'name': 'John Doe',
'date_version': '2020-01-01',
'contract_date_start': '2020-01-01',
'contract_date_end': '2020-10-10'
},
{
'name': 'Rob Carter',
'date_version': '2020-10-18',
'contract_date_start': '2020-10-18',
}
])
versions = (employee_john | employee_rob).version_id
versions |= employee_john.create_version({
'date_version': '2021-08-01',
'contract_date_start': '2021-08-01',
})
with self.assertRaises(ValidationError):
versions.write({
'contract_date_start': '2021-10-10'
})
def test_hr_version_fields_tracking(self):
tracking_blacklist = {
"__last_update",
"active_employee",
"activity_ids",
"company_country_id",
"contract_wage",
"country_code",
"create_date",
"create_uid",
"currency_id",
"date_end",
"date_start",
"departure_description",
"display_name",
"id",
"is_current",
"is_flexible",
"is_fully_flexible",
"is_future",
"is_in_contract",
"is_past",
"job_title",
"last_modified_date",
"last_modified_on",
"last_modified_uid",
"member_of_department",
"message_follower_ids",
"message_ids",
"message_partner_ids",
"rating_ids",
"template_warning",
"tz",
"website_message_ids",
"work_location_name",
"work_location_type",
"write_date",
"write_uid",
}
hr_version_model = self.env['hr.version']
fields_without_tracking = []
for field_name, field in hr_version_model._fields.items():
if field_name in tracking_blacklist:
continue
if field.compute and not field.inverse:
continue
if field.related:
continue
if hasattr(field, 'store') and field.store is False:
continue
if hasattr(field, 'tracking') and not field.tracking:
fields_without_tracking.append(field_name)
self.assertFalse(
fields_without_tracking,
f"The following hr.version fields should have tracking=True: {fields_without_tracking}",
)
def test_related_fields_on_version_onchange(self):
""" This test is to ensure that each _onchange method on version has a corresponding _onchange on employee that calls it. """
version_methods = {method for method in dir(self.env['hr.version']) if method.startswith('_onchange')}
employee_methods = {method for method in dir(self.env['hr.employee']) if method.startswith('_onchange')}
not_implemented_onchanges = version_methods - employee_methods
self.assertFalse(
not_implemented_onchanges,
f"""The following _onchange methods on hr.version should have corresponding methods implemented on hr.employee: {not_implemented_onchanges}\n
You might need to implement methods with the same name on hr.employee and call the corresponding self.version_id._onchange inside"""
)
def test_search_on_version_fields(self):
Department = self.env['hr.department'].with_context(tracking_disable=True)
rd_dep = Department.create({
'name': 'Research and devlopment',
})
employee1, employee2 = employees = self.env['hr.employee'].create([
{
'contract_date_start': '2020-10-10',
'wage': 3000,
'name': 'Employee1',
'hr_responsible_id': self.res_users_hr_manager.id,
'department_id': rd_dep.id,
},
{
'contract_date_start': '2022-10-10',
'wage': 2000,
'name': 'Employee2',
},
])
internal_user = mail_new_test_user(
self.env,
email='internal_user@example.com',
login='internal_user',
name='Internal User',
)
self.employee.department_id = rd_dep
self.employee.user_id = internal_user
HrEmployeePublic_with_internal_user = self.env['hr.employee.public'].with_user(internal_user)
with self.assertRaises(AccessError, msg="Internal user should not be able to access to hr.employee model"):
HrEmployeePublic_with_internal_user.search([
('employee_id.contract_date_start', '<', '2022-01-01'),
('id', 'in', employees.ids),
])
with self.assertRaises(AccessError, msg="Internal user should not be able to access to hr.employee model"):
HrEmployeePublic_with_internal_user.search([('employee_id.wage', '=', 2000), ('id', 'in', employees.ids)])
with self.assertRaises(AccessError, msg="Internal user should not be able to access to hr.employee model"):
HrEmployeePublic_with_internal_user.search([('employee_id.version_id.wage', '=', 2000), ('id', 'in', employees.ids)])
self.assertEqual(
HrEmployeePublic_with_internal_user.search([('name', '=', 'Employee2'), ('id', 'in', employees.ids)]),
self.env['hr.employee.public'].browse(employee2.id),
)
self.assertEqual(
HrEmployeePublic_with_internal_user.search([('member_of_department', '=', True), ('id', 'in', employees.ids)]),
self.env['hr.employee.public'].browse(employee1.id),
)
HrEmployee_with_office_user = self.env['hr.employee'].with_user(self.res_users_hr_officer)
self.employee.user_id = self.res_users_hr_officer
with self.assertRaises(AccessError, msg="HR Officer should not be able to access to 'payroll fields'"):
HrEmployee_with_office_user.search([('contract_date_start', '<', '2022-01-01'), ('id', 'in', employees.ids)])
with self.assertRaises(AccessError, msg="HR Officer should not be able to access to 'payroll fields'"):
HrEmployee_with_office_user.search([('wage', '=', 2000), ('id', 'in', employees.ids)])
with self.assertRaises(AccessError, msg="HR Officer should not be able to access to 'payroll fields'"):
HrEmployee_with_office_user.search([('version_id.wage', '=', 2000), ('id', 'in', employees.ids)])
self.assertEqual(HrEmployee_with_office_user.search([('name', '=', 'Employee1'), ('id', 'in', employees.ids)]), employee1)
self.assertEqual(HrEmployee_with_office_user.search([('hr_responsible_id', '=', self.res_users_hr_manager.id), ('id', 'in', employees.ids)]), employee1)
self.assertEqual(HrEmployee_with_office_user.search([('version_id.hr_responsible_id', '=', self.res_users_hr_manager.id), ('id', 'in', employees.ids)]), employee1)
self.assertEqual(HrEmployee_with_office_user.search([('member_of_department', '=', True), ('id', 'in', employees.ids)]), employee1)
if payroll_group := self.env.ref('hr_payroll.group_hr_payroll_user', raise_if_not_found=False):
self.res_users_hr_manager.group_ids += payroll_group
HrEmployee_with_manager_user = self.env['hr.employee'].with_user(self.res_users_hr_manager)
self.employee.user_id = self.res_users_hr_manager
self.assertEqual(HrEmployee_with_manager_user.search([('contract_date_start', '<', '2022-01-01'), ('id', 'in', employees.ids)]), employee1)
self.assertEqual(HrEmployee_with_manager_user.search([('wage', '=', 2000), ('id', 'in', employees.ids)]), employee2)
self.assertEqual(HrEmployee_with_manager_user.search([('version_id.wage', '=', 2000), ('id', 'in', employees.ids)]), employee2)
self.assertEqual(HrEmployee_with_manager_user.search([('hr_responsible_id', '=', self.res_users_hr_manager.id), ('id', 'in', employees.ids)]), employee1)
self.assertEqual(HrEmployee_with_manager_user.search([('version_id.hr_responsible_id', '=', self.res_users_hr_manager.id), ('id', 'in', employees.ids)]), employee1)
self.assertEqual(HrEmployee_with_manager_user.search([('member_of_department', '=', True), ('id', 'in', employees.ids)]), employee1)
def test_archive_or_unassign_all_versions(self):
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
another_employee = self.env['hr.employee'].create({
'name': 'Jane Doe'
})
employee.create_version({
'date_version': '2021-01-01',
})
# make sure there are at least 2 versions
self.assertEqual(len(employee.version_ids), 2)
# attempt to archive all versions
with self.assertRaises(ValidationError):
employee.version_ids.action_archive()
# attempt to reassign all versions
with self.assertRaises(ValidationError):
employee.version_ids.write({"employee_id": another_employee.id})
def test_unlink_version_except_one(self):
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
version = employee.create_version({
'date_version': '2021-01-01',
})
self.assertEqual(len(employee.version_ids), 2)
version.unlink()
self.assertEqual(len(employee.version_ids), 1)
def test_date_version_sync_contract_date_start_for_single_version(self):
"""
This test is to ensure that in case when an employee has only one version, writing contract_date_start on the employee
will synchronize the version.date_version with that contract_date_start
"""
with freeze_time(date(2025, 12, 20)), self.enter_registry_test_mode():
employee = self.env['hr.employee'].create({
'name': 'John Doe',
})
version = employee.version_id
self.assertEqual(version.date_version, date(2025, 12, 20))
employee.write({'contract_date_start': '2025-12-10'})
self.assertEqual(version.contract_date_start, date(2025, 12, 10))
self.assertEqual(version.date_version, date(2025, 12, 10))
# date_version should not be reset if contract_date_start is cleared
employee.write({'contract_date_start': False})
self.assertEqual(version.date_version, date(2025, 12, 10))
# and setting it again should re-sync
employee.write({'contract_date_start': '2025-12-15'})
self.assertEqual(version.contract_date_start, date(2025, 12, 15))
self.assertEqual(version.date_version, date(2025, 12, 15))