304 lines
15 KiB
Python
304 lines
15 KiB
Python
|
|
import warnings
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
from operator import itemgetter
|
|
from werkzeug.urls import url_encode
|
|
|
|
from odoo import http, _
|
|
from odoo.addons.website_hr_recruitment.controllers.main import WebsiteHrRecruitment
|
|
from odoo.osv.expression import AND
|
|
from odoo.http import request
|
|
from odoo.tools import email_normalize
|
|
from odoo.tools.misc import groupby
|
|
import base64
|
|
from odoo.exceptions import UserError
|
|
|
|
from PIL import Image
|
|
from io import BytesIO
|
|
import re
|
|
import json
|
|
|
|
|
|
|
|
class website_hr_recruitment_applications(http.Controller):
|
|
|
|
@http.route(['/hr_recruitment/second_application_form/<int:applicant_id>'], type='http', auth="public", website=True)
|
|
def second_application_form(self, applicant_id, **kwargs):
|
|
"""Renders the website form for applicants to submit additional details."""
|
|
applicant = request.env['hr.applicant'].sudo().browse(applicant_id)
|
|
if not applicant.exists():
|
|
return request.not_found()
|
|
if applicant and applicant.send_second_application_form:
|
|
if applicant.second_application_form_status == 'done':
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
else:
|
|
return request.render("hr_recruitment_extended.applicant_form_template", {
|
|
'applicant': applicant
|
|
})
|
|
else:
|
|
return request.not_found()
|
|
|
|
|
|
|
|
@http.route(['/hr_recruitment/submit_second_application/<int:applicant_id>/submit'], type='http', auth="public",
|
|
methods=['POST'], website=True, csrf=False)
|
|
def process_application_form(self, applicant_id, **kwargs):
|
|
# Get the applicant
|
|
candidate_image_base64 = kwargs.pop('candidate_image_base64')
|
|
candidate_image = kwargs.pop('candidate_image')
|
|
experience_years = kwargs.pop('experience_years', 0)
|
|
experience_months = kwargs.pop('experience_months', 0)
|
|
if not len(str(experience_months)) > 0:
|
|
experience_months = 0
|
|
if not len(str(experience_years)) > 0:
|
|
experience_years = 0
|
|
# If there are months, convert everything to months
|
|
if int(experience_months) > 0:
|
|
kwargs['total_exp'] = (int(experience_years) * 12) + int(experience_months)
|
|
kwargs['total_exp_type'] = 'month'
|
|
else:
|
|
kwargs['total_exp'] = int(experience_years)
|
|
kwargs['total_exp_type'] = 'year'
|
|
|
|
applicant = request.env['hr.applicant'].sudo().browse(applicant_id)
|
|
if not applicant.exists():
|
|
return request.not_found() # Return 404 if applicant doesn't exist
|
|
|
|
if applicant.second_application_form_status == 'done':
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
|
|
|
|
kwargs['candidate_image'] = candidate_image_base64
|
|
|
|
applicant.write(kwargs)
|
|
applicant.candidate_id.candidate_image = candidate_image_base64
|
|
template = request.env.ref('hr_recruitment_extended.email_template_second_application_submitted',
|
|
raise_if_not_found=False)
|
|
if template and applicant.user_id.email:
|
|
template.sudo().send_mail(applicant.id, force_send=True)
|
|
|
|
applicant.second_application_form_status = 'done'
|
|
# Redirect to a Thank You page
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
|
|
|
|
|
|
@http.route(['/FTPROTECH/DocRequests/<int:applicant_id>'], type='http', auth="public",
|
|
website=True)
|
|
def doc_request_form(self, applicant_id, **kwargs):
|
|
"""Renders the website form for applicants to submit additional details."""
|
|
applicant = request.env['hr.applicant'].sudo().browse(applicant_id)
|
|
if not applicant.exists():
|
|
return request.not_found()
|
|
if applicant:
|
|
if applicant.doc_requests_form_status == 'done':
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
else:
|
|
return request.render("hr_recruitment_extended.doc_request_form_template", {
|
|
'applicant': applicant
|
|
})
|
|
else:
|
|
return request.not_found()
|
|
|
|
@http.route(['/FTPROTECH/submit/<int:applicant_id>/docRequest'], type='http', auth="public",
|
|
methods=['POST'], website=True, csrf=False)
|
|
def process_applicant_doc_submission_form(self, applicant_id, **post):
|
|
applicant = request.env['hr.applicant'].sudo().browse(applicant_id)
|
|
if not applicant.exists():
|
|
return request.not_found() # Return 404 if applicant doesn't exist
|
|
|
|
if applicant.doc_requests_form_status == 'done':
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
|
|
applicant_data = {
|
|
'applicant_id': int(post.get('applicant_id', 0)),
|
|
'candidate_image': post.get('candidate_image_base64', ''),
|
|
'doc_requests_form_status': 'done'
|
|
}
|
|
|
|
applicant_data = {k: v for k, v in applicant_data.items() if v != '' and v != 0}
|
|
# attachments
|
|
attachments_data_json = post.get('attachments_data_json', '[]')
|
|
attachments_data = json.loads(attachments_data_json) if attachments_data_json else []
|
|
|
|
if attachments_data:
|
|
applicant_data['joining_attachment_ids'] = [
|
|
(4, existing_id) for existing_id in
|
|
(applicant.joining_attachment_ids).ids
|
|
] + [
|
|
(0, 0, {
|
|
'name': attachment.get('file_name', ''),
|
|
'recruitment_attachment_id': attachment.get(
|
|
'attachment_rec_id', ''),
|
|
'file': attachment.get('file_content', '')
|
|
}) for attachment in attachments_data if
|
|
attachment.get('attachment_rec_id')
|
|
]
|
|
|
|
applicant.write(applicant_data)
|
|
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
|
|
|
|
|
|
|
|
@http.route(['/FTPROTECH/JoiningForm/<int:applicant_id>'], type='http', auth="public",
|
|
website=True)
|
|
def post_onboarding_form(self, applicant_id, **kwargs):
|
|
"""Renders the website form for applicants to submit additional details."""
|
|
applicant = request.env['hr.applicant'].sudo().browse(applicant_id)
|
|
if not applicant.exists():
|
|
return request.not_found()
|
|
if applicant and applicant.send_post_onboarding_form:
|
|
if applicant.post_onboarding_form_status == 'done':
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
else:
|
|
return request.render("hr_recruitment_extended.post_onboarding_form_template", {
|
|
'applicant': applicant
|
|
})
|
|
else:
|
|
return request.not_found()
|
|
|
|
|
|
@http.route(['/FTPROTECH/submit/<int:applicant_id>/JoinForm'], type='http', auth="public",
|
|
methods=['POST'], website=True, csrf=False)
|
|
def process_employee_joining_form(self,applicant_id,**post):
|
|
|
|
applicant = request.env['hr.applicant'].sudo().browse(applicant_id)
|
|
if not applicant.exists():
|
|
return request.not_found() # Return 404 if applicant doesn't exist
|
|
|
|
if applicant.post_onboarding_form_status == 'done':
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
private_state_id = request.env['res.country.state'].sudo().browse(int(post.get('present_state', 0)))
|
|
|
|
permanent_state_id = request.env['res.country.state'].sudo().browse(int(post.get('permanent_state', 0)))
|
|
|
|
applicant_data = {
|
|
'applicant_id': int(post.get('applicant_id', 0)),
|
|
'employee_id': int(post.get('employee_id', 0)),
|
|
'candidate_image': post.get('candidate_image_base64', ''),
|
|
'doj': datetime.strptime(post.get('doj'), '%Y-%m-%d').date() if post.get('doj', None) else '',
|
|
'email_from': post.get('email_from', ''),
|
|
'gender': post.get('gender', ''),
|
|
'partner_phone': post.get('partner_phone', ''),
|
|
'alternate_phone': post.get('alternate_phone', ''),
|
|
'birthday': post.get('birthday', ''),
|
|
'blood_group': post.get('blood_group', ''),
|
|
'private_street': post.get('present_street', ''),
|
|
'private_street2': post.get('present_street2', ''),
|
|
'private_city': post.get('present_city', ''),
|
|
'private_state_id': private_state_id.id if private_state_id else '',
|
|
'private_country_id': private_state_id.country_id.id if private_state_id else '',
|
|
'private_zip': post.get('present_zip', ''),
|
|
'permanent_street': post.get('permanent_street', ''),
|
|
'permanent_street2': post.get('permanent_street2', ''),
|
|
'permanent_city': post.get('permanent_city', ''),
|
|
'permanent_state_id': permanent_state_id.id if permanent_state_id else '',
|
|
'permanent_country_id': permanent_state_id.country_id.id if permanent_state_id else '',
|
|
'permanent_zip': post.get('permanent_zip', ''),
|
|
'marital': post.get('marital', ''),
|
|
'marriage_anniversary_date': post.get('marriage_anniversary_date', ''),
|
|
'full_name_as_in_bank': post.get('full_name_as_in_bank', ''),
|
|
'bank_name': post.get('bank_name', ''),
|
|
'bank_branch': post.get('bank_branch', ''),
|
|
'bank_account_no': post.get('bank_account_no', ''),
|
|
'bank_ifsc_code': post.get('bank_ifsc_code', ''),
|
|
'passport_no': post.get('passport_no', ''),
|
|
'passport_start_date': datetime.strptime(post.get('passport_start_date'), '%Y-%m-%d').date() if post.get('passport_start_date', None) else '',
|
|
'passport_end_date': datetime.strptime(post.get('passport_end_date'), '%Y-%m-%d').date() if post.get('passport_end_date', None) else '',
|
|
'passport_issued_location': post.get('passport_issued_location', ''),
|
|
'pan_no': post.get('pan_no', ''),
|
|
'identification_id': post.get('identification_id', ''),
|
|
'previous_company_pf_no': post.get('previous_company_pf_no', ''),
|
|
'previous_company_uan_no': post.get('previous_company_uan_no', ''),
|
|
'post_onboarding_form_status': 'done'
|
|
}
|
|
|
|
applicant_data = {k: v for k, v in applicant_data.items() if v != '' and v != 0}
|
|
|
|
# Get family details data from JSON
|
|
family_data_json = post.get('family_data_json', '[]')
|
|
family_data = json.loads(family_data_json) if family_data_json else []
|
|
|
|
if family_data:
|
|
applicant_data['family_details'] = [
|
|
(0, 0, {
|
|
'relation_type': member.get('relation', ''),
|
|
'name': str(member.get('name', '')),
|
|
'contact_no': member.get('contact', ''),
|
|
'dob': datetime.strptime(member.get('dob'), '%Y-%m-%d').date() if member.get('dob') else None,
|
|
'location': member.get('location', ''),
|
|
}) for member in family_data if member.get('name') and member.get('relation') # Optional filter to avoid empty members
|
|
]
|
|
# education details
|
|
education_data_json = post.get('education_data_json', '[]')
|
|
education_data = json.loads(education_data_json) if education_data_json else []
|
|
if education_data:
|
|
applicant_data['education_history'] = [
|
|
(0,0,{
|
|
'education_type': education.get('education_type',''),
|
|
'name': education.get('specialization', ''),
|
|
'university': education.get('university', ''),
|
|
'start_year': education.get('start_year', ''),
|
|
'end_year': education.get('end_year', ''),
|
|
'marks_or_grade': education.get('marks_or_grade','')
|
|
}) for education in education_data
|
|
]
|
|
|
|
employer_history_data_json = post.get('employer_history_data_json', '[]')
|
|
employer_data = json.loads(employer_history_data_json) if employer_history_data_json else []
|
|
|
|
if employer_data:
|
|
applicant_data['employer_history'] = [
|
|
(0, 0, {
|
|
'company_name': company.get('company_name', ''),
|
|
'designation': company.get('designation', ''),
|
|
'date_of_joining': self.safe_date_parse(company.get('date_of_joining')),
|
|
'last_working_day': self.safe_date_parse(company.get('last_working_day')),
|
|
'ctc': company.get('ctc', ''),
|
|
}) for company in employer_data
|
|
]
|
|
|
|
#attachments
|
|
attachments_data_json = post.get('attachments_data_json', '[]')
|
|
attachments_data = json.loads(attachments_data_json) if attachments_data_json else []
|
|
|
|
if attachments_data:
|
|
applicant_data['joining_attachment_ids'] = [
|
|
(4, existing_id) for existing_id in
|
|
(applicant.joining_attachment_ids).ids
|
|
] + [
|
|
(0, 0, {
|
|
'name': attachment.get('file_name', ''),
|
|
'recruitment_attachment_id': attachment.get(
|
|
'attachment_rec_id', ''),
|
|
'file': attachment.get('file_content', '')
|
|
}) for attachment in attachments_data if
|
|
attachment.get('attachment_rec_id')
|
|
]
|
|
|
|
applicant.write(applicant_data)
|
|
|
|
return request.render("hr_recruitment_extended.thank_you_template")
|
|
|
|
def safe_date_parse(self,date_str):
|
|
try:
|
|
return datetime.strptime(date_str, '%Y-%m-%d').date() if date_str else None
|
|
except (ValueError, TypeError):
|
|
return None
|
|
|
|
|
|
|
|
@http.route('/hr_recruitment_extended/fetch_related_state_ids', type='json', auth="public", website=True)
|
|
def fetch_preferred_state_ids(self, country_id=None):
|
|
state_ids = {}
|
|
states = http.request.env['res.country.state'].sudo()
|
|
|
|
if country_id:
|
|
for state_id in states.search([('country_id', '=?', country_id)]):
|
|
state_ids[state_id.id] = state_id.name
|
|
|
|
return state_ids
|