mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-23 05:32:07 +02:00
842 lines
35 KiB
Python
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))
|