mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-18 04:12:08 +02:00
854 lines
37 KiB
Python
854 lines
37 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
from psycopg2.errors import UniqueViolation
|
|
from freezegun import freeze_time
|
|
|
|
from odoo import fields, Command
|
|
from odoo.fields import Domain
|
|
from odoo.tests import Form, users, new_test_user, HttpCase, tagged, TransactionCase
|
|
from odoo.addons.hr.tests.common import TestHrCommon
|
|
from odoo.tools import mute_logger
|
|
from odoo.exceptions import ValidationError
|
|
from psycopg2.errors import NotNullViolation
|
|
|
|
class TestHrEmployee(TestHrCommon):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.user_without_image = self.env['res.users'].create({
|
|
'name': 'Marc Demo',
|
|
'email': 'mark.brown23@example.com',
|
|
'image_1920': False,
|
|
'login': 'demo_1',
|
|
'password': 'demo_123'
|
|
})
|
|
self.employee_without_image = self.env['hr.employee'].create({
|
|
'user_id': self.user_without_image.id,
|
|
'image_1920': False
|
|
})
|
|
|
|
def test_employee_must_have_active_version(self):
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Batman'
|
|
})
|
|
self.assertEqual(len(employee.version_ids), 1)
|
|
employee_version = employee.version_id
|
|
with self.assertRaises(ValidationError, msg="An employee should always have a version"):
|
|
employee.write({'version_ids': False})
|
|
with self.assertRaises(ValidationError, msg="An employee should always have a version"):
|
|
employee_version.unlink()
|
|
with self.assertRaises(ValidationError, msg="An employee should always have a version"):
|
|
employee_version.write({
|
|
'employee_id': self.employee_without_image.id
|
|
})
|
|
with self.assertRaises(ValidationError, msg="An employee should always have an active version"):
|
|
employee_version.write({'active': False})
|
|
|
|
def test_employee_smart_button_multi_company(self):
|
|
partner = self.env['res.partner'].create({'name': 'Partner Test'})
|
|
company_A = self.env['res.company'].create({'name': 'company_A'})
|
|
company_B = self.env['res.company'].create({'name': 'company_B'})
|
|
self.env['hr.employee'].create({
|
|
'name': 'employee_A',
|
|
'work_contact_id': partner.id,
|
|
'company_id': company_A.id,
|
|
})
|
|
self.env['hr.employee'].create({
|
|
'name': 'employee_B',
|
|
'work_contact_id': partner.id,
|
|
'company_id': company_B.id
|
|
})
|
|
|
|
partner.with_company(company_A)._compute_employees_count()
|
|
self.assertEqual(partner.employees_count, 1)
|
|
partner.with_company(company_B)._compute_employees_count()
|
|
self.assertEqual(partner.employees_count, 1)
|
|
single_company_action = partner.with_company(company_B).action_open_employees()
|
|
self.assertEqual(single_company_action.get('view_mode'), 'form')
|
|
partner.with_company(company_A).with_company(company_B)._compute_employees_count()
|
|
self.assertEqual(partner.employees_count, 2)
|
|
multi_company_action = partner.with_company(company_A).with_company(company_B).action_open_employees()
|
|
self.assertEqual(multi_company_action.get('view_mode'), 'kanban')
|
|
|
|
def test_employee_linked_partner(self):
|
|
user_partner = self.user_without_image.partner_id
|
|
work_contact = self.employee_without_image.work_contact_id
|
|
self.assertEqual(user_partner, work_contact)
|
|
|
|
def test_employee_resource(self):
|
|
_tz = 'Pacific/Apia'
|
|
self.res_users_hr_officer.company_id.resource_calendar_id.tz = _tz
|
|
Employee = self.env['hr.employee'].with_user(self.res_users_hr_officer)
|
|
employee_form = Form(Employee)
|
|
employee_form.name = 'Raoul Grosbedon'
|
|
employee_form.work_email = 'raoul@example.com'
|
|
employee = employee_form.save()
|
|
self.assertEqual(employee.tz, _tz)
|
|
|
|
def test_employee_timezone(self):
|
|
self.res_users_hr_officer.tz = "Africa/Cairo"
|
|
Employee = self.env['hr.employee'].with_user(self.res_users_hr_officer)
|
|
employee_form = Form(Employee)
|
|
employee_form.user_id = self.res_users_hr_officer
|
|
employee_form.name = 'Youssef Ahmed'
|
|
employee_form.work_email = 'yoahm@example.com'
|
|
employee = employee_form.save()
|
|
|
|
# validate timezone sync between employee & user
|
|
self.assertEqual(employee.tz, self.res_users_hr_officer.tz)
|
|
|
|
# validate that we can change timezone on user
|
|
self.res_users_hr_officer.tz = "Europe/Brussels"
|
|
self.assertEqual(self.res_users_hr_officer.tz, employee.tz)
|
|
|
|
# validate that we can change timezone on employee
|
|
employee.tz = "Europe/London"
|
|
self.assertEqual(self.res_users_hr_officer.tz, employee.tz)
|
|
|
|
# Check False value on employee
|
|
with mute_logger('odoo.sql_db'), self.assertRaises(NotNullViolation):
|
|
employee.tz = False
|
|
|
|
# Check False value on user
|
|
with mute_logger('odoo.sql_db'), self.assertRaises(NotNullViolation):
|
|
self.res_users_hr_officer.tz = False
|
|
|
|
# Check None value on user's calendar
|
|
with mute_logger('odoo.sql_db'), self.assertRaises(NotNullViolation):
|
|
self.res_users_hr_officer.company_id.resource_calendar_id.write({'tz': None})
|
|
|
|
def test_employee_from_user(self):
|
|
_tz = 'Pacific/Apia'
|
|
_tz2 = 'America/Tijuana'
|
|
self.res_users_hr_officer.company_id.resource_calendar_id.tz = _tz
|
|
self.res_users_hr_officer.tz = _tz2
|
|
Employee = self.env['hr.employee'].with_user(self.res_users_hr_officer)
|
|
employee_form = Form(Employee)
|
|
employee_form.name = 'Raoul Grosbedon'
|
|
employee_form.work_email = 'raoul@example.com'
|
|
employee_form.user_id = self.res_users_hr_officer
|
|
employee = employee_form.save()
|
|
self.assertEqual(employee.name, 'Raoul Grosbedon')
|
|
self.assertEqual(employee.work_email, self.res_users_hr_officer.email)
|
|
self.assertEqual(employee.tz, self.res_users_hr_officer.tz)
|
|
|
|
def test_employee_computed_from_user(self):
|
|
self.res_users_hr_officer.name = 'Raoul Grosbedon'
|
|
self.res_users_hr_officer.email = 'raoul@example.com'
|
|
Employee = self.env['hr.employee']
|
|
employee_form = Form(Employee)
|
|
employee_form.user_id = self.res_users_hr_officer
|
|
self.assertEqual(employee_form.name, 'Raoul Grosbedon')
|
|
self.assertEqual(employee_form.work_email, 'raoul@example.com')
|
|
employee = employee_form.save()
|
|
self.assertEqual(employee.name, 'Raoul Grosbedon')
|
|
self.assertEqual(employee.work_email, 'raoul@example.com')
|
|
|
|
def test_employee_from_manager_tz_no_reset(self):
|
|
_tz = 'Pacific/Apia'
|
|
self.res_users_hr_manager.tz = False
|
|
Employee = self.env['hr.employee'].with_user(self.res_users_hr_manager)
|
|
employee_form = Form(Employee)
|
|
employee_form.name = 'Raoul Grosbedon'
|
|
employee_form.work_email = 'raoul@example.com'
|
|
employee_form.tz = _tz
|
|
employee_form.user_id = self.res_users_hr_manager
|
|
employee = employee_form.save()
|
|
self.assertEqual(employee.name, 'Raoul Grosbedon')
|
|
self.assertEqual(employee.work_email, self.res_users_hr_manager.email)
|
|
self.assertEqual(employee.tz, _tz)
|
|
|
|
def test_employee_has_avatar_even_if_it_has_no_image(self):
|
|
self.assertTrue(self.employee_without_image.avatar_128)
|
|
self.assertTrue(self.employee_without_image.avatar_256)
|
|
self.assertTrue(self.employee_without_image.avatar_512)
|
|
self.assertTrue(self.employee_without_image.avatar_1024)
|
|
self.assertTrue(self.employee_without_image.avatar_1920)
|
|
|
|
def test_employee_has_same_avatar_as_corresponding_user(self):
|
|
self.assertEqual(self.employee_without_image.avatar_1920, self.user_without_image.avatar_1920)
|
|
|
|
def test_employee_member_of_department(self):
|
|
dept, dept_sub, dept_sub_sub, dept_other, dept_parent = self.env['hr.department'].create([
|
|
{
|
|
'name': 'main',
|
|
},
|
|
{
|
|
'name': 'sub',
|
|
},
|
|
{
|
|
'name': 'sub-sub',
|
|
},
|
|
{
|
|
'name': 'other',
|
|
},
|
|
{
|
|
'name': 'parent',
|
|
},
|
|
])
|
|
dept_sub.parent_id = dept
|
|
dept_sub_sub.parent_id = dept_sub
|
|
dept.parent_id = dept_parent
|
|
emp, emp_sub, emp_sub_sub, emp_other, emp_parent = self.env['hr.employee'].with_user(self.res_users_hr_officer).create([
|
|
{
|
|
'name': 'employee',
|
|
'department_id': dept.id,
|
|
},
|
|
{
|
|
'name': 'employee sub',
|
|
'department_id': dept_sub.id,
|
|
},
|
|
{
|
|
'name': 'employee sub sub',
|
|
'department_id': dept_sub_sub.id,
|
|
},
|
|
{
|
|
'name': 'employee other',
|
|
'department_id': dept_other.id,
|
|
},
|
|
{
|
|
'name': 'employee parent',
|
|
'department_id': dept_parent.id,
|
|
},
|
|
])
|
|
self.res_users_hr_officer.employee_id = emp
|
|
self.assertTrue(emp.member_of_department)
|
|
self.assertTrue(emp_sub.member_of_department)
|
|
self.assertTrue(emp_sub_sub.member_of_department)
|
|
self.assertFalse(emp_other.member_of_department)
|
|
self.assertFalse(emp_parent.member_of_department)
|
|
employees = emp + emp_sub + emp_sub_sub + emp_other + emp_parent
|
|
self.assertEqual(
|
|
employees.filtered_domain(employees.version_id._search_part_of_department('in', [True])),
|
|
emp + emp_sub + emp_sub_sub)
|
|
self.assertEqual(
|
|
employees.filtered_domain(['!'] + employees.version_id._search_part_of_department('in', [True])),
|
|
emp_other + emp_parent)
|
|
|
|
def test_employee_create_from_user(self):
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Test User 3 - employee'
|
|
})
|
|
user_1, user_2, user_3 = self.env['res.users'].create([
|
|
{
|
|
'name': 'Test User',
|
|
'login': 'test_user',
|
|
'email': 'test_user@odoo.com',
|
|
},
|
|
{
|
|
'name': 'Test User 2',
|
|
'login': 'test_user_2',
|
|
'email': 'test_user_2@odoo.com',
|
|
'create_employee': True,
|
|
},
|
|
{
|
|
'name': 'Test User 3',
|
|
'login': 'test_user_3',
|
|
'email': 'test_user_3@odoo.com',
|
|
'create_employee_id': employee.id,
|
|
},
|
|
])
|
|
# Test that creating an user does not create an employee by default
|
|
self.assertFalse(user_1.employee_id)
|
|
# Test that setting create_employee does create the associated employee
|
|
self.assertTrue(user_2.employee_id)
|
|
# Test that creating an user with a given employee associates the employee correctly
|
|
self.assertEqual(user_3.employee_id, employee)
|
|
|
|
def test_employee_create_from_signup(self):
|
|
# Test that an employee is not created when signin up on the website
|
|
partner = self.env['res.partner'].create({
|
|
'name': 'test partner'
|
|
})
|
|
self.env['res.users'].signup({
|
|
'name': 'Test User',
|
|
'login': 'test_user',
|
|
'email': 'test_user@odoo.com',
|
|
'password': 'test_user_password',
|
|
'partner_id': partner.id,
|
|
})
|
|
self.assertFalse(self.env['res.users'].search([('login', '=', 'test_user')]).employee_id)
|
|
|
|
def test_employee_update_work_contact_id(self):
|
|
"""
|
|
Check that the `work_contact_id` information is no longer
|
|
updated when an employee's `user_id` is added to another employee.
|
|
"""
|
|
user = self.env['res.users'].create({
|
|
'name': 'Test',
|
|
'login': 'test',
|
|
'email': 'test@example.com',
|
|
})
|
|
employee_A, employee_B = self.env['hr.employee'].create([
|
|
{
|
|
'name': 'Employee A',
|
|
'user_id': user.id,
|
|
'work_email': 'employee_A@example.com',
|
|
},
|
|
{
|
|
'name': 'Employee B',
|
|
'user_id': False,
|
|
'work_email': 'employee_B@example.com',
|
|
}
|
|
])
|
|
employee_A.user_id = False
|
|
employee_B.user_id = user.id
|
|
employee_B.work_email = 'new_email@example.com'
|
|
self.assertEqual(employee_A.work_email, 'employee_A@example.com')
|
|
self.assertEqual(employee_B.work_email, 'new_email@example.com')
|
|
self.assertFalse(employee_A.work_contact_id)
|
|
self.assertEqual(employee_B.work_contact_id, user.partner_id)
|
|
|
|
def test_availability_user_infos_employee(self):
|
|
""" Ensure that all the user infos needed to display the avatar popover card
|
|
are available on the model hr.employee.
|
|
"""
|
|
user = self.env['res.users'].create([{
|
|
'name': 'Test user',
|
|
'login': 'test',
|
|
'email': 'test@odoo.perso',
|
|
'phone': '+32488990011',
|
|
}])
|
|
employee = self.env['hr.employee'].create([{
|
|
'name': 'Test employee',
|
|
'user_id': user.id,
|
|
}])
|
|
user_fields = ['email', 'phone', 'im_status']
|
|
for field in user_fields:
|
|
self.assertEqual(employee[field], user[field])
|
|
|
|
def test_set_user_on_new_employee(self):
|
|
test_company = self.env['res.company'].create({
|
|
'name': 'Test User Company',
|
|
})
|
|
self.env['hr.employee'].create({
|
|
'name': 'Hr Officer - employee',
|
|
'user_id': self.res_users_hr_officer.id,
|
|
'company_id': test_company.id,
|
|
})
|
|
|
|
self.res_users_hr_officer.write({'company_ids': test_company.ids, 'company_id': test_company.id})
|
|
|
|
# Try to set the user with existing employee in the company, on a new employee form
|
|
employee_form = Form(self.env['hr.employee'].with_user(self.res_users_hr_officer).with_company(company=test_company.id))
|
|
employee_form.name = "Second employee"
|
|
employee_form.user_id = self.res_users_hr_officer
|
|
with mute_logger('odoo.sql_db'), self.assertRaises(UniqueViolation), self.assertRaises(ValidationError):
|
|
employee_form.save()
|
|
|
|
employee_2 = self.env['hr.employee'].create({
|
|
'name': 'Hr 2 - employee',
|
|
'company_id': test_company.id,
|
|
})
|
|
|
|
# Try to set the user with existing employee in the company, on another existing employee
|
|
employee_2_form = Form(employee_2.with_user(self.res_users_hr_officer).with_company(company=test_company.id))
|
|
employee_2_form.user_id = self.res_users_hr_officer
|
|
with mute_logger('odoo.sql_db'), self.assertRaises(UniqueViolation), self.assertRaises(ValidationError):
|
|
employee_2_form.save()
|
|
|
|
|
|
@users('admin')
|
|
def test_change_user_on_employee(self):
|
|
test_other_user = self.env['res.users'].create({
|
|
'name': 'Test Other User',
|
|
'login': 'test_other_user',
|
|
})
|
|
test_other_user.partner_id.company_id = self.env.company
|
|
test_company = self.env['res.company'].create({
|
|
'name' : 'Test User Company',
|
|
})
|
|
self.env.user.write({'company_ids': test_company.ids, 'company_id': test_company.id})
|
|
test_user = self.env['res.users'].create({
|
|
'name': 'Test User',
|
|
'login': 'test_user',
|
|
})
|
|
test_user.partner_id.company_id = test_company
|
|
bank_account = self.env['res.partner.bank'].create({
|
|
'acc_number' : '1234567',
|
|
'partner_id' : test_user.partner_id.id,
|
|
})
|
|
test_employee = self.env['hr.employee'].create({
|
|
'name': 'Test User - employee',
|
|
'user_id': test_user.id,
|
|
'company_id': test_company.id,
|
|
'bank_account_ids': [Command.link(bank_account.id)],
|
|
})
|
|
# change user -> bank account change company
|
|
with Form(test_employee) as employee_form:
|
|
employee_form.user_id = test_other_user
|
|
# change user back -> check that there is no company error
|
|
with Form(test_employee) as employee_form:
|
|
employee_form.user_id = test_user
|
|
|
|
def test_change_user_on_employee_keep_partner(self):
|
|
"""
|
|
Check that removing user from employee keeps the link in
|
|
work_contact_id until the user is assigned to another employee.
|
|
"""
|
|
user = self.env['res.users'].create({
|
|
'name': 'Test User',
|
|
'login': 'test_user',
|
|
})
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Test User - employee',
|
|
'user_id': user.id,
|
|
})
|
|
# remove user
|
|
employee.user_id = None
|
|
self.assertEqual(employee.work_contact_id, user.partner_id)
|
|
self.assertFalse(employee.user_id)
|
|
# create new employee from user
|
|
user._compute_company_employee()
|
|
user.action_create_employee()
|
|
self.assertTrue(len(user.employee_ids) == 1, "Test user should have exactly one employee associated with it")
|
|
# previous employee shouldn't have a work_contact_id anymore, as the partner is reassigned
|
|
self.assertFalse(employee.work_contact_id)
|
|
# the new employee should be associated to both the user and its partner
|
|
new_employee = user.employee_ids
|
|
self.assertEqual(new_employee.work_contact_id, user.partner_id)
|
|
self.assertEqual(new_employee.user_id, user)
|
|
|
|
def test_change_user_on_employee_multi_company(self):
|
|
"""
|
|
Removing user from employee keeps the link in work_contact_id in the correct company until the user
|
|
is assigned to another employee, and does not affect employees in other companies. When the unique
|
|
constraint of one employee per user in one company is triggered, the work_contact_id for the
|
|
existing employee is nor removed, and employees in other companies are not affected.
|
|
"""
|
|
company_A = self.env['res.company'].create({'name': 'company_A'})
|
|
company_B = self.env['res.company'].create({'name': 'company_B'})
|
|
user = self.env['res.users'].create({
|
|
'name': 'Test User',
|
|
'login': 'test_user',
|
|
})
|
|
partner = user.partner_id
|
|
employee_A = self.env['hr.employee'].create({
|
|
'name': 'employee_A',
|
|
'user_id': user.id,
|
|
'company_id': company_A.id,
|
|
})
|
|
employee_B = self.env['hr.employee'].create({
|
|
'name': 'employee_B',
|
|
'user_id': user.id,
|
|
'company_id': company_B.id
|
|
})
|
|
# Creating an employee in one company does not remove the link with employee in the other company
|
|
self.assertEqual(user.with_company(company_A).employee_id, employee_A)
|
|
self.assertEqual(user.with_company(company_B).employee_id, employee_B)
|
|
# Partner is linked to both employees
|
|
partner.with_company(company_A).with_company(company_B)._compute_employees_count()
|
|
self.assertEqual(partner.employees_count, 2)
|
|
# Remove user from employee in one company does not affect link user-employee in the other company
|
|
employee_A.user_id = None
|
|
self.assertEqual(user.with_company(company_A).employee_id.ids, [])
|
|
self.assertEqual(user.with_company(company_B).employee_id, employee_B)
|
|
# Partner still linked to both employees
|
|
partner.with_company(company_A).with_company(company_B)._compute_employees_count()
|
|
self.assertEqual(partner.employees_count, 2)
|
|
# Creating a new employee for a user in company A does not affect link user-employee in the other company
|
|
new_employee_A = self.env['hr.employee'].create({
|
|
'name': 'new_employee_A',
|
|
'user_id': user.id,
|
|
'company_id': company_A.id,
|
|
})
|
|
# User cannot be assigned to more than one employee in the same company. work_contact_id should not be removed.
|
|
with mute_logger('odoo.sql_db'), self.assertRaises(UniqueViolation), self.assertRaises(ValidationError):
|
|
self.env['hr.employee'].create({
|
|
'name': 'new_employee_B',
|
|
'user_id': user.id,
|
|
'company_id': company_B.id,
|
|
})
|
|
self.assertEqual(user.with_company(company_A).employee_id, new_employee_A)
|
|
self.assertEqual(user.with_company(company_B).employee_id, employee_B)
|
|
self.assertEqual(partner.employee_ids, employee_B + new_employee_A)
|
|
|
|
def test_avatar(self):
|
|
# Check simple employee has a generated image (initials)
|
|
employee_georgette = self.env['hr.employee'].create({'name': 'Georgette Pudubec'})
|
|
self.assertTrue(employee_georgette.image_1920)
|
|
self.assertTrue(employee_georgette.avatar_1920)
|
|
|
|
self.assertTrue(employee_georgette.work_contact_id)
|
|
self.assertTrue(employee_georgette.work_contact_id.image_1920)
|
|
self.assertTrue(employee_georgette.work_contact_id.avatar_1920)
|
|
|
|
# Check user has a generate image
|
|
user_norbert = self.env['res.users'].create({'name': 'Norbert Comidofisse', 'login': 'Norbert6870'})
|
|
self.assertTrue(user_norbert.image_1920)
|
|
self.assertTrue(user_norbert.avatar_1920)
|
|
|
|
# Check that linked employee got user image
|
|
employee_norbert = self.env['hr.employee'].create({'name': 'Norbert Employee', 'user_id': user_norbert.id})
|
|
self.assertEqual(employee_norbert.image_1920, user_norbert.image_1920)
|
|
self.assertEqual(employee_norbert.avatar_1920, user_norbert.avatar_1920)
|
|
|
|
def test_badge_validation(self):
|
|
# check employee's barcode should be a sequence of digits and alphabets
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Badge Employee'
|
|
})
|
|
|
|
employee_form = Form(employee)
|
|
employee_form.barcode = 'Test@badge1'
|
|
with self.assertRaises(ValidationError):
|
|
employee_form.save()
|
|
|
|
employee_form.barcode = 'Testàë@badge'
|
|
with self.assertRaises(ValidationError):
|
|
employee_form.save()
|
|
|
|
employee_form.barcode = 'Testbadge2'
|
|
employee_form.save()
|
|
|
|
self.assertEqual(employee_form.barcode, 'Testbadge2')
|
|
|
|
def test_departure_wizard(self):
|
|
""" Test the archiving wizard in the case of multiple employees """
|
|
employee_A, employee_B, employee_C = self.env['hr.employee'].create([
|
|
{
|
|
'name': f'Employee {code}',
|
|
'user_id': False,
|
|
'work_email': f'employee_{code}@example.com',
|
|
} for code in ['A', 'B', 'C']
|
|
])
|
|
archiving_employees = [employee.id for employee in (employee_A, employee_C)]
|
|
|
|
wizard = self.env['hr.departure.wizard'].with_context(
|
|
employee_termination=True,
|
|
active_ids=archiving_employees,
|
|
).create({})
|
|
wizard.action_register_departure()
|
|
|
|
all_employees = employee_A | employee_B | employee_C
|
|
self.assertEqual(all_employees.filtered(lambda e: e.active), employee_B, "Employees should have been archived")
|
|
|
|
def test_search_hr_employee_no_access(self):
|
|
new_user = new_test_user(self.env, 'employee')
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Test Employee',
|
|
})
|
|
domain = Domain([
|
|
('name', '=', 'Test Employee'),
|
|
('active', '=', True)
|
|
]).optimize(self.env['hr.employee'])
|
|
with self.assertNoLogs('odoo.domains'):
|
|
self.assertEqual(
|
|
employee.ids,
|
|
self.env['hr.employee'].with_user(new_user).search(domain).ids,
|
|
)
|
|
|
|
def test_is_flexible(self):
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Employee',
|
|
})
|
|
self.assertTrue(employee.resource_calendar_id)
|
|
self.assertFalse(employee.is_flexible)
|
|
self.assertFalse(employee.is_fully_flexible)
|
|
|
|
employee.resource_calendar_id.flexible_hours = True
|
|
self.assertTrue(employee.is_flexible)
|
|
self.assertFalse(employee.is_fully_flexible)
|
|
|
|
employee.resource_calendar_id = False
|
|
self.assertTrue(employee.is_flexible)
|
|
self.assertTrue(employee.is_fully_flexible)
|
|
|
|
def test_resource_calendar_sync_with_employee_one(self):
|
|
calendar = self.env['resource.calendar'].create({
|
|
'name': 'test calendar',
|
|
'flexible_hours': True,
|
|
})
|
|
self.assertTrue(self.employee.resource_id)
|
|
self.assertTrue(self.employee.resource_calendar_id)
|
|
self.assertEqual(self.employee.resource_calendar_id, self.employee.resource_id.calendar_id)
|
|
self.assertNotEqual(self.employee.resource_calendar_id, calendar)
|
|
self.assertTrue(self.employee.resource_calendar_id, self.employee.resource_id.calendar_id)
|
|
old_calendar = self.employee.resource_calendar_id
|
|
old_version = self.employee.version_id
|
|
old_version.date_version = old_version.date_version - relativedelta(days=1)
|
|
self.employee.resource_calendar_id = calendar
|
|
self.assertEqual(self.employee.resource_id.calendar_id, calendar)
|
|
version = self.employee.create_version({'resource_calendar_id': old_calendar.id, 'date_version': fields.Date.today()})
|
|
self.assertEqual(self.employee.current_version_id, version)
|
|
self.assertNotEqual(self.employee.current_version_id, old_version)
|
|
self.assertEqual(self.employee.resource_calendar_id, old_calendar)
|
|
self.assertEqual(self.employee.resource_id.calendar_id, old_calendar)
|
|
|
|
def test_job_title(self):
|
|
first_job = self.env['hr.job'].create({'name': "first job"})
|
|
second_job = self.env['hr.job'].create({'name': "second job"})
|
|
|
|
with Form(self.employee_without_image) as employee_form:
|
|
# Assign first job to employee, job title should be job name
|
|
employee_form.job_id = first_job
|
|
self.assertEqual(employee_form.job_title, first_job.name)
|
|
|
|
# Change job title, job name should not change
|
|
employee_form.job_title = "custom job title"
|
|
self.assertEqual(first_job.name, "first job")
|
|
|
|
# Change the name of the first job, job title should not be updated
|
|
first_job.name = "first job modified"
|
|
self.assertEqual(employee_form.job_title, "custom job title")
|
|
employee_form.save()
|
|
|
|
# Assign second job to employee, job title should be second job name
|
|
employee_form.job_id = second_job
|
|
self.assertEqual(employee_form.job_title, second_job.name)
|
|
|
|
# Switch back to first job, job title should be first job name
|
|
employee_form.job_id = first_job
|
|
self.assertEqual(employee_form.job_title, first_job.name)
|
|
|
|
def test_flexible_working_hours(self):
|
|
"""
|
|
Test to verifie that get_unusual_days() return false for flexible work schedule
|
|
"""
|
|
|
|
# Creating a flexible working schedule
|
|
calendar_flex = self.env['resource.calendar'].create([
|
|
{
|
|
'tz': "Europe/Brussels",
|
|
'name': 'flexible hours',
|
|
'flexible_hours': "True",
|
|
},
|
|
])
|
|
employeeA = self.env['hr.employee'].create({
|
|
'name': 'Employee',
|
|
})
|
|
|
|
# Testing employeA on regular working schedule
|
|
days = employeeA._get_unusual_days(str(datetime(2025, 1, 1)), str(datetime(2025, 12, 31)))
|
|
self.assertTrue(days)
|
|
self.assertTrue(days['2025-01-04'])
|
|
|
|
# Assigning flexible work hours to employeeA
|
|
employeeA.resource_calendar_id = calendar_flex.id
|
|
days = employeeA._get_unusual_days(str(datetime(2025, 1, 1)), str(datetime(2025, 12, 31)))
|
|
self.assertTrue(days)
|
|
self.assertFalse(days['2025-01-04'])
|
|
|
|
def test_user_creation_from_employee_with_invalid_email(self):
|
|
employee = self.env['hr.employee'].create({
|
|
'name': 'Test Employee',
|
|
'work_email': 'test'
|
|
})
|
|
|
|
action = employee.action_create_users()
|
|
self.assertEqual(action['params']['message'], f'You need to set a valid work email address for {employee.name}')
|
|
self.assertFalse(employee.user_id)
|
|
|
|
def test_user_creation_from_employee_multi_emails(self):
|
|
employees = self.env['hr.employee'].create([
|
|
{
|
|
'name': 'Existing Email Employee',
|
|
'work_email': self.user_without_image.email,
|
|
}, {
|
|
'name': 'New Employee',
|
|
'work_email': 'newuser@example.com',
|
|
}, {
|
|
'name': 'Invalid Email Employee',
|
|
'work_email': 'invalid-email',
|
|
}, {
|
|
'name': 'Without Email Employee',
|
|
'work_email': False,
|
|
}, {
|
|
'name': 'Formatted Email Employee',
|
|
'work_email': f'"John Doe" <{self.user_without_image.email_normalized}>',
|
|
}, {
|
|
'name': 'Multi Email Employee',
|
|
'work_email': '"Name1" <name@test.example.com>, "Name 2" <name2@test.example.com>',
|
|
}, {
|
|
'name': 'Duplicate Email Employee 1',
|
|
'work_email': 'duplicate@example.com',
|
|
}, {
|
|
'name': 'Duplicate Email Employee 2',
|
|
'work_email': 'duplicate@example.com',
|
|
},
|
|
])
|
|
# Add an existing employee who already has a user to the employee list
|
|
employees += self.employee_without_image
|
|
context = {'selected_ids': employees.ids}
|
|
confirmed_employees = self.env['hr.employee'].with_context(context).browse(employees.ids)
|
|
action = confirmed_employees.action_create_users()
|
|
|
|
params = action.get('params')
|
|
self.assertEqual(params.get('message'), f"The following employees have the same work email address: {employees[6].name}, {employees[7].name}")
|
|
params = params.get('next').get('params')
|
|
self.assertEqual(params.get('message'), f"User already exists with the same email for Employees {employees[0].name}, {employees[4].name}")
|
|
params = params.get('next').get('params')
|
|
self.assertEqual(params.get('message'), f"You need to set a valid work email address for {employees[2].name}, {employees[5].name}")
|
|
params = params.get('next').get('params')
|
|
self.assertEqual(params.get('message'), f"You need to set the work email address for {employees[3].name}")
|
|
params = params.get('next').get('params')
|
|
self.assertEqual(params.get('message'), f"User already exists for Those Employees {employees[8].name}")
|
|
params = params.get('next').get('params')
|
|
self.assertEqual(params.get('message'), f"Users {employees[1].name} creation successful")
|
|
self.assertTrue(employees[1].user_id)
|
|
|
|
def test_user_contact_phone_sync(self):
|
|
partner = self.env['res.partner'].create({'name': 'Partner Test'})
|
|
first_company = self.env['res.company'].create({'name': 'First Company'})
|
|
first_employee = self.env['hr.employee'].create({
|
|
'name': 'First Employee',
|
|
'work_contact_id': partner.id,
|
|
'company_id': first_company.id,
|
|
})
|
|
first_employee.write({'work_phone': '12345', 'work_email': 'first_employee@test.com'})
|
|
self.assertEqual(first_employee.work_phone, partner.phone)
|
|
self.assertEqual(first_employee.work_email, partner.email)
|
|
partner.write({'phone': '67890', 'email': 'partner@test.com'})
|
|
self.assertEqual(partner.phone, first_employee.work_phone)
|
|
self.assertEqual(partner.email, first_employee.work_email)
|
|
|
|
second_company = self.env['res.company'].create({'name': 'Second Company'})
|
|
second_employee = self.env['hr.employee'].create({
|
|
'name': 'Second Employee',
|
|
'work_contact_id': partner.id,
|
|
'company_id': second_company.id,
|
|
})
|
|
second_employee.write({'work_phone': '112233', 'work_email': 'second_employee@test.com'})
|
|
self.assertNotEqual(second_employee.work_phone, partner.phone)
|
|
self.assertNotEqual(second_employee.work_phone, first_employee.work_phone)
|
|
self.assertNotEqual(second_employee.work_email, partner.email)
|
|
self.assertNotEqual(second_employee.work_email, first_employee.work_email)
|
|
partner.write({'phone': '445566', 'email': 'partner_updated@test.com'})
|
|
self.assertNotEqual(partner.phone, second_employee.work_phone)
|
|
self.assertNotEqual(partner.phone, first_employee.work_phone)
|
|
self.assertNotEqual(partner.email, second_employee.work_email)
|
|
self.assertNotEqual(partner.email, first_employee.work_email)
|
|
|
|
|
|
@tagged('-at_install', 'post_install')
|
|
class TestHrEmployeeLinks(HttpCase):
|
|
def test_shared_private_link_permissions(self):
|
|
"""
|
|
Employees not part of group_hr_user are not supposed to be able to see
|
|
private employees pages (e.g.: from a shared link).
|
|
The tour will check if the correct redirection warning appears when such
|
|
case happens.
|
|
"""
|
|
user_amy = new_test_user(
|
|
self.env,
|
|
name="Amy Rose",
|
|
login='amy',
|
|
groups='base.group_user' # cannot access private employee profiles
|
|
)
|
|
employee_sonic = self.env['hr.employee'].create({
|
|
'name': 'Sonic the Hedgehog',
|
|
})
|
|
with mute_logger('odoo.http'): # ignore raised RedirectWarning
|
|
self.start_tour(
|
|
f"/odoo/employees/{employee_sonic.id}",
|
|
"check_public_employee_link_redirect",
|
|
login=user_amy.login,
|
|
)
|
|
|
|
|
|
@tagged('-at_install', 'post_install')
|
|
class TestVersionCron(TransactionCase):
|
|
"""Test the behavior of CRONs affecting hr.version"""
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
# Will be used for default employee version address (contains phone)
|
|
cls.env.user.company_id = cls.env['res.company'].create(
|
|
{'name': 'Pokémon Center', 'phone': '+32404040404'}
|
|
)
|
|
|
|
# Employee has a default version that will be overridden
|
|
with freeze_time("2020-10-07"):
|
|
cls.employee = cls.env['hr.employee'].create(
|
|
{
|
|
'name': 'Charizard',
|
|
'work_phone': '+32404040404',
|
|
"distance_home_work": 32,
|
|
"distance_home_work_unit": 'miles',
|
|
}
|
|
)
|
|
|
|
def test_version_cron_update_no_fields(self):
|
|
"""
|
|
Employees should not see their fields be updated if the CRON does not
|
|
change their version.
|
|
"""
|
|
with freeze_time('2023-10-06'):
|
|
self.employee.create_version(
|
|
{'date_version': '2023-10-07', "distance_home_work": 40}
|
|
)
|
|
|
|
# Saving current employee data to compare later on
|
|
employee_values = {}
|
|
# some fields cannot be accessed. We need to filter them out
|
|
employee_fields = [
|
|
field
|
|
for field in self.env['hr.employee']._fields
|
|
if hasattr(self.employee, field)
|
|
]
|
|
for field in employee_fields:
|
|
employee_values[field] = self.employee[field]
|
|
|
|
# Should not change to new version
|
|
with freeze_time('2023-10-06'):
|
|
self.env['hr.employee']._cron_update_current_version_id()
|
|
|
|
for field in employee_fields:
|
|
self.assertEqual(
|
|
employee_values[field],
|
|
self.employee[field],
|
|
f"""No field should change if _cron_update_current_version_id() does not change the version.
|
|
However, the field {field} changed""",
|
|
)
|
|
|
|
def test_version_cron_update_fields(self):
|
|
"""
|
|
Employees should see some of their field be changed if the CRON changes
|
|
their version.
|
|
"""
|
|
with freeze_time('2023-10-06'):
|
|
self.employee.create_version(
|
|
{'date_version': '2023-10-07', "distance_home_work": 40}
|
|
)
|
|
current_home_distance = self.employee.distance_home_work
|
|
current_version = self.employee.current_version_id
|
|
# Should change to new version
|
|
with freeze_time('2023-10-07'):
|
|
self.env['hr.employee']._cron_update_current_version_id()
|
|
|
|
self.assertNotEqual(
|
|
current_version,
|
|
self.employee.current_version_id,
|
|
"current_version_id should have changed after calling _cron_update_current_version_id()",
|
|
)
|
|
self.assertNotEqual(
|
|
current_home_distance,
|
|
self.employee.distance_home_work,
|
|
"distance_home_work should have changed after calling _cron_update_current_version_id()",
|
|
)
|
|
|
|
|
|
@tagged('-at_install', 'post_install')
|
|
class TestHrEmployeeWebJson(HttpCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
# JSON route needs to be enabled for the tests
|
|
self.env['ir.config_parameter'].sudo().set_param('web.json.enabled', True)
|
|
|
|
def test_webjson_employees(self):
|
|
# Check that json employees can be accessed
|
|
url = "/json/1/employees"
|
|
self.env['ir.config_parameter'].set_param('web.json.enabled', True)
|
|
self.authenticate('admin', 'admin')
|
|
CSRF_USER_HEADERS = {
|
|
"Sec-Fetch-Dest": "document",
|
|
"Sec-Fetch-Mode": "navigate",
|
|
"Sec-Fetch-Site": 'none',
|
|
"Sec-Fetch-User": "?1",
|
|
}
|
|
res = self.url_open(url, headers=CSRF_USER_HEADERS)
|
|
self.assertEqual(res.status_code, 200)
|