odoo18/addons_extensions/hr_recruitment_extended/models/hr_recruitment.py

197 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from datetime import date
from datetime import timedelta
import datetime
class Job(models.Model):
_inherit = 'hr.job'
secondary_skill_ids = fields.Many2many('hr.skill', "hr_job_secondary_hr_skill_rel",
'hr_job_id', 'hr_skill_id', "Secondary Skills")
locations = fields.Many2many('hr.location')
target_from = fields.Date(string="This is the date in which we starting the recruitment process", default=fields.Date.today)
target_to = fields.Date(string='This is the target end date')
hiring_history = fields.One2many('recruitment.status.history', 'job_id', string='History')
def buttion_view_applicants(self):
if self.skill_ids:
a = self.env['hr.candidate'].search([])
applicants = self.env['hr.candidate']
for i in a:
if all(skill in i.skill_ids for skill in self.skill_ids):
applicants += i
else:
applicants = self.env['hr.candidate'].search([])
action = self.env['ir.actions.act_window']._for_xml_id('hr_recruitment.action_hr_candidate')
action['domain'] = [('id', 'in', applicants.ids)]
action['context'] = dict(self._context)
return action
def hr_job_end_date_update(self):
# Find all jobs where the target_to is today's date
hr_jobs = self.sudo().search([('target_to', '=', fields.Date.today() - timedelta(days=1))])
# stage_ids = self.env['hr.recruitment.stage'].sudo().search([('hired_stage','=',True)])
for job in hr_jobs:
# Determine the hiring period
date_from = job.target_from
date_end = job.target_to
# Fetch hired applicants related to this job
hired_applicants = self.env['hr.applicant'].search([
('job_id', '=', job.id),
('stage_id.hired_stage', '=', True)
])
# Get today's date in the datetime format (with time set to midnight)
today_start = fields.Datetime.today()
# Get today's date at the end of the day (23:59:59) to include all records created today
today_end = fields.Datetime.today().now()
# Search for records where create_date is today
hiring_history_today = self.env['recruitment.status.history'].sudo().search([
('create_date', '>=', today_start),
('create_date', '<=', today_end),
('job_id','=',job.id)
])
# Create a hiring history record
if not hiring_history_today:
self.env['recruitment.status.history'].create({
'date_from': date_from,
'date_end': date_end,
'target': len(hired_applicants), # Number of hired applicants
'job_id': job.id,
'hired': [(6, 0, hired_applicants.ids)] # Many2many write operation
})
tomorrow_date = fields.Date.today() + timedelta(days=1)
jobs_ending_tomorrow = self.sudo().search([('target_to', '=', tomorrow_date)])
for job in jobs_ending_tomorrow:
# Fetch recruiters (assuming job has a field recruiter_id or similar)
recruiter = job.sudo().user_id # Replacne with the appropriate field name
if recruiter:
# Send mail
template = self.env.ref(
'hr_recruitment_extended.template_recruitment_deadline_alert') # Replace with your email template XML ID
if template:
template.sudo().send_mail(recruiter.id, force_send=True)
recruitment_history = self.env['recruitment.status.history'].sudo().search([('job_id','!=',False)])
for recruitment in recruitment_history:
# Determine the hiring period
if recruitment.date_from and recruitment.job_id:
# Use `date_end` or today's date if `date_end` is not provided
date_end = fields.Datetime.to_datetime(fields.Date.to_string(recruitment.date_end)) + datetime.timedelta(days=1,seconds=-1) or fields.Datetime.today().now()
current_hired_applicants = recruitment.hired
# Search for applicants matching the conditions
hired_applicants = self.env['hr.applicant'].search([
('date_closed', '>=', fields.Datetime.to_datetime(fields.Date.to_string(recruitment.date_from))),
('date_closed', '<=', date_end),
('job_id', '=', recruitment.job_id.id)
])
# Filter out the applicants that are already in the 'hired' field
new_hired_applicants = hired_applicants - current_hired_applicants
# Add the missing applicants to the 'hired' field
recruitment.hired = current_hired_applicants | new_hired_applicants
return True
class HrCandidate(models.Model):
_inherit = "hr.candidate"
first_name = fields.Char(string='First Name',required=True, help="This is the person's first name, given at birth or during a naming ceremony. Its the name people use to address you.")
middle_name = fields.Char(string='Middle Name', help="This is an extra name that comes between the first name and last name. Not everyone has a middle name")
last_name = fields.Char(string='Last Name',required=True, help="This is the family name, shared with other family members. Its usually the last name.")
alternate_phone = fields.Char(string='Alternate Phone')
@api.constrains('partner_name')
def partner_name_constrain(self):
for rec in self:
if any(char.isdigit() for char in rec.partner_name):
raise ValidationError(_("Enter Valid Name"))
class HRApplicant(models.Model):
_inherit = 'hr.applicant'
current_location = fields.Char('Current Location')
preferred_location = fields.Many2many('hr.location',string="Preferred Location's")
current_organization = fields.Char('Current Organization')
alternate_phone = fields.Char(related="candidate_id.alternate_phone", readonly=False)
exp_type = fields.Selection([('fresher','Fresher'),('experienced','Experienced')], default='fresher', required=True)
total_exp = fields.Integer(string="Total Experience")
relevant_exp = fields.Integer(string="Relevant Experience")
total_exp_type = fields.Selection([('month',"Month's"),('year',"Year's")])
relevant_exp_type = fields.Selection([('month',"Month's"),('year',"Year's")])
notice_period = fields.Integer(string="Notice Period")
notice_period_type = fields.Selection([('day',"Day's"),('month',"Month's"),('year',"Year's")], string='Type')
current_ctc = fields.Float(string="Current CTC", aggregator="avg", help="Applicant Current Salary", tracking=True, groups="hr_recruitment.group_hr_recruitment_user")
salary_expected = fields.Float("Expected CTC", aggregator="avg", help="Salary Expected by Applicant", tracking=True, groups="hr_recruitment.group_hr_recruitment_user")
salary_negotiable = fields.Boolean(string="Salary Negotiable")
np_negotiable = fields.Boolean(string="NP Negotiable")
holding_offer = fields.Char(string="Holding Offer")
applicant_comments = fields.Text(string='Applicant Comments')
recruiter_comments = fields.Text(string='Recruiter Comments')
class Location(models.Model):
_name = 'hr.location'
_rec_name = 'location_name'
# SQL Constraint to ensure the combination of location_name, zip_code, country_id, and state is unique
_sql_constraints = [
('unique_location_zip_state_country',
'UNIQUE(location_name, zip_code, country_id, state)',
'The selected Location, Zip Code, Country, and State combination already exists.')
]
location_name = fields.Char(string='Location', required=True)
zip_code = fields.Char(string = 'Zip Code')
country_id = fields.Many2one('res.country','Country',groups="hr.group_hr_user")
state = fields.Many2one("res.country.state", string="State",
domain="[('country_id', '=?', country_id)]",
groups="hr.group_hr_user")
@api.constrains('location_name')
def _check_location_name(self):
for record in self:
if record.location_name.isdigit():
raise ValidationError("Location name should not be a number. Please enter a valid location name.")
@api.constrains('zip_code')
def _check_zip_code(self):
for record in self:
if record.zip_code and not record.zip_code.isdigit(): # Check if zip_code exists and is not digit
raise ValidationError("Zip Code should contain only numeric characters. Please enter a valid zip code.")
class RecruitmentHistory(models.Model):
_name='recruitment.status.history'
date_from = fields.Date(string='Date From')
date_end = fields.Date(string='Date End')
target = fields.Integer(string='Target')
job_id = fields.Many2one('hr.job', string='Job Position') # Ensure this field exists
hired = fields.Many2many('hr.applicant')
@api.depends('date_from', 'date_end', 'job_id')
def _total_hired_users(self):
for rec in self:
if rec.date_from:
# Use `date_end` or today's date if `date_end` is not provided
date_end = rec.date_end or date.today()
# Search for applicants matching the conditions
hired_applicants = self.env['hr.applicant'].search([
('date_closed', '>=', rec.date_from),
('date_closed', '<=', date_end),
('job_id', '=', rec.job_id.id)
])
rec.hired = hired_applicants
else:
rec.hired = False