272 lines
17 KiB
Python
272 lines
17 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import json
|
|
|
|
from odoo.exceptions import UserError
|
|
from odoo.addons.hr_referral.tests.common import TestHrReferralBase
|
|
|
|
|
|
class TestHrReferral(TestHrReferralBase):
|
|
|
|
def test_referral_share_is_new(self):
|
|
self.job_dev = self.job_dev.with_user(self.richard_user.id)
|
|
|
|
self.env['hr.referral.link.to.share'].with_user(self.richard_user.id).create({'job_id': self.job_dev.id}).url
|
|
links = self.env['link.tracker'].search([('campaign_id', '=', self.job_dev.utm_campaign_id.id)])
|
|
self.assertEqual(len(links), 1, "It should have created only one link tracker")
|
|
|
|
self.env['hr.referral.link.to.share'].with_user(self.steve_user.id).create({'job_id': self.job_dev.id}).url
|
|
links = self.env['link.tracker'].search([('campaign_id', '=', self.job_dev.utm_campaign_id.id)])
|
|
self.assertEqual(len(links), 2, "It should have created 2 different links tracker (one for each user)")
|
|
|
|
def test_referral_change_referrer(self):
|
|
# Create an applicant
|
|
job_applicant = self.env['hr.applicant'].create({
|
|
'partner_name': 'Technical worker',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id
|
|
})
|
|
self.assertEqual(job_applicant.ref_user_id, self.richard_user, "Referral is created with the right user")
|
|
points_richard = self.env['hr.referral.points'].search([('ref_user_id', '=', self.richard_user.id)])
|
|
self.assertEqual(job_applicant.stage_id.points, sum(points_richard.mapped('points')), "Right amount of referral points are created.")
|
|
# We change the referrer on the job applicant, Richard will lose all his points and Steve will get points
|
|
job_applicant.ref_user_id = self.steve_user.id
|
|
self.assertEqual(job_applicant.ref_user_id, self.steve_user, "Referral is modified with as user Steve")
|
|
points_richard = self.env['hr.referral.points'].search([('ref_user_id', '=', self.richard_user.id)])
|
|
self.assertEqual(sum(points_richard.mapped('points')), 0, "Richard has no more points")
|
|
points_steve = self.env['hr.referral.points'].search([('ref_user_id', '=', self.steve_user.id)])
|
|
self.assertEqual(sum(points_steve.mapped('points')), job_applicant.stage_id.points, "Right amount of referral points are created for Steve")
|
|
|
|
def test_referral_add_points(self):
|
|
with self.assertRaises(UserError):
|
|
self.mug_shop.sudo().buy()
|
|
job_applicant = self.env['hr.applicant'].create({
|
|
'partner_name': 'Technical worker',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id
|
|
})
|
|
self.assertEqual(job_applicant.earned_points, job_applicant.stage_id.points, "Richard received points corresponding to the first stage.")
|
|
stages = self.env['hr.recruitment.stage'].search([('job_ids', '=', False)])
|
|
# We jump some stages of process, multiple points must be given
|
|
job_applicant.stage_id = stages[-2]
|
|
self.assertEqual(job_applicant.earned_points, sum(stages[:-1].mapped('points')), "Richard received points corresponding to the before last stage.")
|
|
self.assertEqual(job_applicant.referral_state, 'progress', "Referral stay in progress")
|
|
job_applicant.stage_id = stages[-1]
|
|
self.assertEqual(job_applicant.earned_points, sum(stages.mapped('points')), "Richard received points corresponding to the last stage.")
|
|
self.assertEqual(job_applicant.referral_state, 'hired', "Referral is hired")
|
|
self.mug_shop.sudo().buy()
|
|
shopped_item = self.env['hr.referral.points'].search([('ref_user_id', '=', self.richard_user.id), ('hr_referral_reward_id', '!=', False)])
|
|
self.assertEqual(shopped_item.points, -self.mug_shop.cost, "The item bought decrease the number of points.")
|
|
|
|
def test_referral_multi_company(self):
|
|
self.job_dev = self.job_dev.with_user(self.richard_user.id)
|
|
self.env['hr.referral.link.to.share'].with_user(self.richard_user.id).create({'job_id': self.job_dev.id}).url
|
|
|
|
job_applicant = self.env['hr.applicant'].create({
|
|
'partner_name': 'Technical worker',
|
|
'company_id': self.company_1.id,
|
|
'job_id': self.job_dev.id,
|
|
'source_id': self.richard_user.utm_source_id.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
})
|
|
points_richard_c1 = self.env['hr.referral.points'].search([('ref_user_id', '=', self.richard_user.id), ('company_id', '=', self.company_1.id)])
|
|
points_richard_c2 = self.env['hr.referral.points'].search([('ref_user_id', '=', self.richard_user.id), ('company_id', '=', self.company_2.id)])
|
|
# All points are created for employee of company 1 as it's a job offer from company 1. No point in company 2.
|
|
self.assertEqual(job_applicant.stage_id.points, sum(points_richard_c1.mapped('points')), "Right amount of referral points are created.")
|
|
self.assertEqual(0, sum(points_richard_c2.mapped('points')), "Right amount of referral points are created.")
|
|
|
|
# This user has no point in company 2 so if he miss as much points as the price of this object (this object is in company 2).
|
|
self.assertEqual(self.red_mug_shop.points_missing, self.red_mug_shop.cost, "10 points are missing")
|
|
|
|
def test_referral_no_hired_stage(self):
|
|
"""
|
|
Test Case: Referral Program - Applicant passing through 'not hired' stages
|
|
|
|
This test ensures that:
|
|
- Points from referral stages are only awarded for stages marked `use_in_referral=True`.
|
|
- Stages with `use_in_referral=False` (e.g., parking or draft stages) do not award points.
|
|
- Points are not duplicated when moving back to already scored stages.
|
|
- Dashboard reflects progress accurately.
|
|
- Final stage marks the applicant as 'hired' even if later stages exist but are not marked for referral.
|
|
|
|
Scenario Flow:
|
|
1. Create custom stages that are excluded from referral (`use_in_referral=False`).
|
|
2. Move applicant across various stages and verify:
|
|
- Earned points are correct.
|
|
- Number of referral lines is correct.
|
|
- Dashboard reflects correct progression.
|
|
3. Ensure jumping over or into 'not hired' stages does not affect point tally incorrectly.
|
|
"""
|
|
self.env.ref('hr_recruitment.stage_job0').use_in_referral = False
|
|
self.env.ref('hr_recruitment.stage_job3').use_in_referral = False
|
|
stage_parking_1 = self.env['hr.recruitment.stage'].create({
|
|
'name': 'parking1',
|
|
'use_in_referral': False,
|
|
'job_ids': [(6, 0, self.job_dev.ids)],
|
|
'sequence': 15,
|
|
'points': 500, # points must be ignored for 'not hired stage'
|
|
})
|
|
stage_parking_2 = self.env['hr.recruitment.stage'].create({
|
|
'name': 'parking2',
|
|
'use_in_referral': False,
|
|
'job_ids': [(6, 0, self.job_dev.ids)],
|
|
'sequence': 16,
|
|
'points': 1000, # points must be ignored for 'not hired stage'
|
|
})
|
|
job_applicant = self.env['hr.applicant'].create({
|
|
'partner_name': 'Technical worker',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id,
|
|
'stage_id': self.env.ref('hr_recruitment.stage_job1').id,
|
|
})
|
|
|
|
self.assertEqual(self.job_dev.max_points, 85, "Max points for this job is 85 (points for the 3 'not hired stage' are ignored).")
|
|
self.assertEqual(job_applicant.earned_points, self.env.ref('hr_recruitment.stage_job1').points, "Richard received points corresponding to the first stage.")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 1, "Richard received points corresponding to the first stage.")
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual(len(info_dashboard), 4, "In dashboard, we have only not 'not hired stage'.")
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, False, False, False], "In dashboard, we have only not 'not hired stage' and state are correct.")
|
|
|
|
# Move to stage 3 (not hired) → should add points for skipped stage 2
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job3')
|
|
total_points = self.env.ref('hr_recruitment.stage_job1').points + self.env.ref('hr_recruitment.stage_job2').points
|
|
self.assertEqual(job_applicant.earned_points, total_points, "As he jump to a 'not hired stage', he receive points for other stages and the jumped stages are ignored.")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 2, "Richard received points corresponding to the first and second stage.")
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, True, False, False], "In dashboard, we have only not 'not hired stage' and state are correct.")
|
|
|
|
# Move back to stage 1 → new line add in received points as points removed for stage 2
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job1')
|
|
self.assertEqual(job_applicant.earned_points, self.env.ref('hr_recruitment.stage_job1').points, "As he jump from a 'not hired stage' to the stage where he was before the 'not hired stage', he receive no points.")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 3, "Richard received points corresponding to the first and second stages, including the second stage again when we moved the applicant back.")
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, False, False, False], "In dashboard, we have only not 'not hired stage' and state are correct.")
|
|
|
|
# Move to stage 3 again → stage 2 points should be added again
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job3')
|
|
total_points = self.env.ref('hr_recruitment.stage_job1').points + self.env.ref('hr_recruitment.stage_job2').points
|
|
self.assertEqual(job_applicant.earned_points, total_points, "As he jump to a 'not hired stage', he receive points for other stages and the jumped stages are ignored.")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 4, "Richard received points corresponding to the second stage again.")
|
|
|
|
# We jump from not hired stage to another stage. All points between last valuable stage (stage 1) and new stage (stage 4) must be added
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job4')
|
|
self.assertEqual(job_applicant.earned_points, 35, "He received points for stage 2 and stage 4 (in addition to stage 1 that he already received).")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 5, "3 lines in received points (3 new [2 for stage 2 and 1 for stage 4], 1 old [for stage 1] and 1 for remove [for stage 2]).")
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, True, True, False], "In dashboard, we have only not 'not hired stage' and state are correct.")
|
|
|
|
# We jump between differents 'not hired stage' = > Nothing change
|
|
job_applicant.stage_id = stage_parking_1 # points get for stage 5
|
|
job_applicant.stage_id = stage_parking_2 # no points get for this 'not hired stage'
|
|
job_applicant.stage_id = stage_parking_1 # no points get for this 'not hired stage'
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job3') # remove points for 4 and 5 stage
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job4') # We come back to previous not 'not hired stage'
|
|
self.assertEqual(job_applicant.earned_points, 35, "Nothing change as it was only 'not hired stage'.")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 9, "Total line added in received points.")
|
|
|
|
# The applicant reach last not 'not hired stage'
|
|
job_applicant.stage_id = self.env.ref('hr_recruitment.stage_job5')
|
|
self.assertEqual(job_applicant.earned_points, 85, "He received all points.")
|
|
self.assertEqual(len(job_applicant.referral_points_ids), 10, "We add a line in received points.")
|
|
self.assertEqual(job_applicant.referral_state, 'hired', "Referral is hired, even if stage (not hired) exist with bigger sequence.")
|
|
|
|
def test_referral_no_point_done_stage(self):
|
|
""" Make sure stages use in referral with points = 0 are properly mark as done
|
|
"""
|
|
final_stage = self.env.ref('hr_recruitment.stage_job5')
|
|
# Change final sequence since we want new stage to be in between
|
|
final_stage.sequence = 20
|
|
stage_parking_1 = self.env['hr.recruitment.stage'].create({
|
|
'name': 'parking1',
|
|
'use_in_referral': True,
|
|
'job_ids': [(6, 0, self.job_dev.ids)],
|
|
'sequence': 15,
|
|
'points': 0,
|
|
})
|
|
stage_parking_2 = self.env['hr.recruitment.stage'].create({
|
|
'name': 'parking2',
|
|
'use_in_referral': True,
|
|
'job_ids': [(6, 0, self.job_dev.ids)],
|
|
'sequence': 16,
|
|
'points': 0,
|
|
})
|
|
job_applicant = self.env['hr.applicant'].create({
|
|
'partner_name': 'Technical worker',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id,
|
|
'stage_id': self.env.ref('hr_recruitment.stage_job1').id,
|
|
})
|
|
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, True, False, False, False, False, False, False])
|
|
job_applicant.stage_id = stage_parking_2
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, True, True, True, True, True, True, False], "parking1 and parking2 should be marked as done")
|
|
job_applicant.stage_id = stage_parking_1
|
|
info_dashboard = json.loads(job_applicant.shared_item_infos)
|
|
self.assertEqual([x['done'] for x in info_dashboard], [True, True, True, True, True, True, False, False], 'parking2 should not be marked as done anymore')
|
|
|
|
def test_referral_reset_applicant(self):
|
|
"""Test that reset_applicant correctly resets the referral state to 'progress'"""
|
|
# Create an applicant in 'progress' state
|
|
applicant = self.env['hr.applicant'].create({
|
|
'partner_name': 'Test Applicant',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id,
|
|
'referral_state': 'progress'
|
|
})
|
|
# Change state to 'hired'
|
|
applicant.write({'referral_state': 'hired'})
|
|
self.assertEqual(applicant.referral_state, 'hired', "Applicant referral state should be 'hired'")
|
|
# Reset the applicant
|
|
applicant.reset_applicant()
|
|
# Check if the referral state is reset to 'progress'
|
|
self.assertEqual(applicant.referral_state, 'progress', "After reset_applicant, referral state should be 'progress'")
|
|
# Test resetting from 'closed' state
|
|
applicant.write({'referral_state': 'closed'})
|
|
self.assertEqual(applicant.referral_state, 'closed', "Applicant referral state should be 'closed'")
|
|
# Reset the applicant again
|
|
applicant.reset_applicant()
|
|
# Check if the referral state is reset to 'progress'
|
|
self.assertEqual(applicant.referral_state, 'progress', "After reset_applicant, referral state should be 'progress'")
|
|
|
|
def test_referral_reset_applicant_batch(self):
|
|
"""Test that reset_applicant correctly works when called on multiple records"""
|
|
# Create applicants with different referral states
|
|
applicants = self.env['hr.applicant'].create([
|
|
{
|
|
'partner_name': 'Applicant 1',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id,
|
|
'referral_state': 'hired'
|
|
},
|
|
{
|
|
'partner_name': 'Applicant 2',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.steve_user.id,
|
|
'company_id': self.company_1.id,
|
|
'referral_state': 'closed'
|
|
},
|
|
{
|
|
'partner_name': 'Applicant 3',
|
|
'job_id': self.job_dev.id,
|
|
'ref_user_id': self.richard_user.id,
|
|
'company_id': self.company_1.id,
|
|
'referral_state': 'progress'
|
|
}
|
|
])
|
|
# Test initial states
|
|
self.assertEqual(applicants[0].referral_state, 'hired')
|
|
self.assertEqual(applicants[1].referral_state, 'closed')
|
|
self.assertEqual(applicants[2].referral_state, 'progress')
|
|
# Reset all applicants at once
|
|
applicants.reset_applicant()
|
|
# Verify all records have been reset to 'progress'
|
|
for applicant in applicants:
|
|
self.assertEqual(applicant.referral_state, 'progress', f"Applicant {applicant.partner_name} should have referral_state 'progress' after reset")
|