Initial commit: Hr packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 62531cd146
2820 changed files with 1432848 additions and 0 deletions

View file

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_recruitment_process
from . import test_recruitment
from . import test_utm
from . import test_recruitment_interviewer

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import tagged, TransactionCase
@tagged('recruitment')
class TestRecruitment(TransactionCase):
def test_duplicate_email(self):
# Tests that duplicate email match ignores case
# And that no match is found when there is none
dup1, dup2, no_dup = self.env['hr.applicant'].create([
{
'name': 'Application 1',
'email_from': 'laurie.poiret@aol.ru',
},
{
'name': 'Application 2',
'email_from': 'laurie.POIRET@aol.ru',
},
{
'name': 'Application 3',
'email_from': 'laure.poiret@aol.ru',
},
])
self.assertEqual(dup1.application_count, 1)
self.assertEqual(dup2.application_count, 1)
self.assertEqual(no_dup.application_count, 0)
def test_application_count(self):
""" Test that we find same applicants based on simmilar mail,
phone or mobile phone.
"""
A, B, C, D, E, F = self.env['hr.applicant'].create([
{
'name': 'Application A',
'email_from': 'abc@odoo.com',
'partner_phone': '123',
'partner_mobile': '14-15-16',
},
{
'name': 'Application B',
'partner_phone': '456',
'partner_mobile': '11-12-13',
},
{
'name': 'Application C',
'email_from': 'def@odoo.com',
'partner_phone': '123',
'partner_mobile': '14-15-16',
},
{
'name': 'Application D',
'email_from': 'def@odoo.com',
'partner_phone': '456',
'partner_mobile': '14-15-16',
},
{
'name': 'Application E',
},
{
'name': 'Application F',
'partner_phone': '11-12-13', # In case phone is configured in a wrong field
}
])
self.assertEqual(A.application_count, 2) # C, D
self.assertEqual(B.application_count, 2) # D, F
self.assertEqual(C.application_count, 2) # A, D
self.assertEqual(D.application_count, 3) # A, B, C
self.assertEqual(E.application_count, 0)
self.assertEqual(F.application_count, 1) # B

View file

@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import AccessError
from odoo.tests.common import new_test_user
from odoo.addons.mail.tests.common import MailCommon
class TestRecruitmentInterviewer(MailCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.simple_user = new_test_user(cls.env, 'smp',
groups='base.group_user', name='Simple User', email='smp@example.com')
cls.interviewer_user = new_test_user(cls.env, 'itw',
groups='base.group_user,hr_recruitment.group_hr_recruitment_interviewer',
name='Recruitment Interviewer', email='itw@example.com')
cls.manager_user = new_test_user(cls.env, 'mng',
groups='base.group_user,hr_recruitment.group_hr_recruitment_manager',
name='Recruitment Manager', email='mng@example.com')
cls.job = cls.env['hr.job'].create({
'name': 'super nice job',
'user_id': cls.manager_user.id,
})
def test_interviewer_group(self):
"""
Test that adding a user as interviewer to a job / applicant adds
that user in the Interviewer group. Also checks that removing the
user will remove them when they are no longer required (e.g. no
longer interviewer of any job/applicant).
"""
interviewer_group = self.env.ref('hr_recruitment.group_hr_recruitment_interviewer')
self.assertFalse(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should not be interviewer")
self.job.interviewer_ids = self.simple_user.ids
self.assertTrue(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should be added as interviewer")
self.job.write({'interviewer_ids': [(5, 0, 0)]})
self.assertFalse(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should be removed from interviewer")
applicant = self.env['hr.applicant'].create({
'name': 'toto',
'partner_name': 'toto',
'job_id': self.job.id,
'interviewer_ids': self.simple_user.ids,
})
self.assertTrue(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should be added as interviewer")
applicant.interviewer_ids = False
self.assertFalse(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should be removed from interviewer")
self.job.interviewer_ids = self.simple_user.ids
applicant.interviewer_ids = self.simple_user.ids
self.assertTrue(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should be added as interviewer")
applicant.interviewer_ids = False
self.assertTrue(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should stay interviewer")
self.job.write({'interviewer_ids': [(5, 0, 0)]})
applicant.interviewer_ids = self.simple_user.ids
self.assertTrue(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should stay interviewer")
applicant.interviewer_ids = False
self.assertFalse(interviewer_group.id in self.simple_user.groups_id.ids, "Simple User should be removed from interviewer")
# A Manager should not be added to the Interviewer group
self.assertFalse(interviewer_group.id in self.manager_user.groups_id.ids, "Manager User should not be interviewer")
applicant.interviewer_ids = self.manager_user.ids
self.assertFalse(interviewer_group.id in self.manager_user.groups_id.ids, "Manager User should not be added in Interviewer group")
def test_interviewer_access_rights(self):
applicant = self.env['hr.applicant'].create({
'name': 'toto',
'partner_name': 'toto',
'job_id': self.job.id,
})
with self.assertRaises(AccessError):
applicant.with_user(self.interviewer_user).read()
applicant = self.env['hr.applicant'].create({
'name': 'toto',
'partner_name': 'toto',
'job_id': self.job.id,
'interviewer_ids': self.interviewer_user.ids,
})
applicant.with_user(self.interviewer_user).read()
self.job.interviewer_ids = self.interviewer_user.ids
applicant = self.env['hr.applicant'].create({
'name': 'toto',
'partner_name': 'toto',
'job_id': self.job.id,
})
applicant.with_user(self.interviewer_user).read()
# An interviewer can change the interviewers
applicant.with_user(self.interviewer_user).interviewer_ids = self.simple_user.ids
self.assertEqual(self.simple_user, applicant.interviewer_ids)
with self.assertRaises(AccessError):
applicant.with_user(self.interviewer_user).create_employee_from_applicant()
def test_interviewer_chatter(self):
self.manager_user.notification_type = 'email'
self.interviewer_user.notification_type = 'email'
applicant = self.env['hr.applicant'].create({
'name': 'toto',
'partner_name': 'toto',
'job_id': self.job.id,
'interviewer_ids': self.interviewer_user.ids,
})
applicant.message_subscribe(partner_ids=[self.interviewer_user.partner_id.id])
with self.mock_mail_gateway():
message = applicant.message_post(body='A super secret message', message_type='comment', subtype_xmlid='mail.mt_comment')
with self.assertRaises(AccessError):
message.with_user(self.interviewer_user).read()
try:
self._find_mail_mail_wpartners(self.interviewer_user.partner_id, None)
except AssertionError:
pass
else:
raise AssertionError('No mail.mail should be sent to members of Interviewer group')
self.assertSentEmail(self.env.user.partner_id, [self.manager_user.partner_id])

View file

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import common
from odoo.addons.hr.tests.common import TestHrCommon
from odoo.modules.module import get_module_resource
class TestRecruitmentProcess(TestHrCommon):
def test_00_recruitment_process(self):
""" Test recruitment process """
self.dep_rd = self.env['hr.department'].create({
'name': 'Research & Development',
})
self.job_developer = self.env['hr.job'].create({
'name': 'Experienced Developer',
'department_id': self.dep_rd.id,
'no_of_recruitment': 5,
})
self.employee_niv = self.env['hr.employee'].create({
'name': 'Sharlene Rhodes',
})
self.job_developer = self.job_developer.with_user(self.res_users_hr_officer.id)
self.employee_niv = self.employee_niv.with_user(self.res_users_hr_officer.id)
# Create a new HR Recruitment Officer
self.res_users_hr_recruitment_officer = self.env['res.users'].create({
'company_id': self.env.ref('base.main_company').id,
'name': 'HR Recruitment Officer',
'login': "hrro",
'email': "hrofcr@yourcompany.com",
'groups_id': [(6, 0, [self.env.ref('hr_recruitment.group_hr_recruitment_user').id])]
})
# An applicant is interested in the job position. So he sends a resume by email.
# In Order to test process of Recruitment so giving HR officer's rights
with open(get_module_resource('hr_recruitment', 'tests', 'resume.eml'), 'rb') as request_file:
request_message = request_file.read()
self.env['mail.thread'].with_user(self.res_users_hr_recruitment_officer).message_process(
'hr.applicant', request_message, custom_values={"job_id": self.job_developer.id})
# After getting the mail, I check the details of the new applicant.
applicant = self.env['hr.applicant'].search([('email_from', 'ilike', 'Richard_Anderson@yahoo.com')], limit=1)
self.assertTrue(applicant, "Applicant is not created after getting the mail")
resume_ids = self.env['ir.attachment'].search([
('name', '=', 'resume.pdf'),
('res_model', '=', self.env['hr.applicant']._name),
('res_id', '=', applicant.id)])
self.assertEqual(applicant.name, 'Application for the post of Jr.application Programmer.', 'Applicant name does not match.')
self.assertEqual(applicant.stage_id, self.env.ref('hr_recruitment.stage_job1'),
"Stage should be 'Initial qualification' and is '%s'." % (applicant.stage_id.name))
self.assertTrue(resume_ids, 'Resume is not attached.')
# I assign the Job position to the applicant
applicant.write({'job_id': self.job_developer.id})
# I schedule meeting with applicant for interview.
applicant_meeting = applicant.action_makeMeeting()
self.assertEqual(applicant_meeting['context']['default_name'], 'Application for the post of Jr.application Programmer.',
'Applicant name does not match.')
def test_01_hr_application_notification(self):
new_job_application_mt = self.env.ref(
"hr_recruitment.mt_job_applicant_new"
)
new_application_mt = self.env.ref(
"hr_recruitment.mt_applicant_new"
)
user = self.env["res.users"].with_context(no_reset_password=True).create(
{
"name": "user_1",
"login": "user_1",
"email": "user_1@example.com",
"groups_id": [
(4, self.env.ref("hr.group_hr_manager").id),
(4, self.env.ref("hr_recruitment.group_hr_recruitment_manager").id),
],
}
)
job = self.env["hr.job"].create({"name": "Test Job for Notification"})
# Make test user follow Test HR Job
self.env["mail.followers"].create(
{
"res_model": "hr.job",
"res_id": job.id,
"partner_id": user.partner_id.id,
"subtype_ids": [(4, new_job_application_mt.id)],
}
)
application = self.env["hr.applicant"].create(
{"name": "Test Job Application for Notification", "job_id": job.id}
)
new_application_message = application.message_ids.filtered(
lambda m: m.subtype_id == new_application_mt
)
self.assertTrue(
user.partner_id in new_application_message.notified_partner_ids
)

View file

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.utm.tests.common import TestUTMCommon
from odoo.exceptions import AccessError, UserError
from odoo.tests.common import new_test_user, tagged, users
@tagged('post_install', '-at_install', 'utm_consistency')
class TestUTMConsistencyHrRecruitment(TestUTMCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.hr_recruitment_source = cls.env['hr.recruitment.source'].create({
'name': 'Recruitment Source'
})
@users('__system__')
def test_utm_consistency(self):
# the source is automatically created when creating a recruitment source
utm_source = self.hr_recruitment_source.source_id
with self.assertRaises(UserError):
# can't unlink the source as it's used by a mailing.mailing as its source
# unlinking the source would break all the mailing statistics
utm_source.unlink()
# you are not supposed to delete the 'utm_campaign_job' record as it is hardcoded in
# the creation of the alias of the recruitment source
with self.assertRaises(UserError):
self.env.ref('hr_recruitment.utm_campaign_job').unlink()
def test_create_alias(self):
"""This ensures that users who are not recruitment officers are not allowed to
create a mail alias for the recruiting source while who are recruitment officers are
"""
simple_user = new_test_user(self.env, 'smp',
groups='base.group_user', name='Simple User', email='smp@example.com')
interviewer_user = new_test_user(self.env, 'itw',
groups='base.group_user,hr_recruitment.group_hr_recruitment_interviewer',
name='Recruitment Interviewer', email='itw@example.com')
recruitment_officer_user = new_test_user(self.env, 'rec_off',
groups='base.group_user,hr_recruitment.group_hr_recruitment_user',
name='Recruitment Officer', email='rec_off@example.com')
with self.assertRaises(AccessError):
self.hr_recruitment_source.with_user(simple_user).create_alias()
with self.assertRaises(AccessError):
self.hr_recruitment_source.with_user(interviewer_user).create_alias()
try:
self.hr_recruitment_source.with_user(recruitment_officer_user).create_alias()
except AccessError:
self.fail("Recruitment Officer should be able to create mail alias for hr.recruitment.source.")