recruitment bug fixes

This commit is contained in:
pranaysaidurga 2026-06-26 17:26:33 +05:30
parent 08569e0ae0
commit 1b34ae2c5c
13 changed files with 223 additions and 43 deletions

View File

@ -29,6 +29,7 @@
'data/sequence.xml',
'data/mail_template.xml',
'data/templates.xml',
'views/submission_share_history.xml',
'views/job_category.xml',
'views/hr_location.xml',
'views/stages.xml',

View File

@ -14,7 +14,7 @@
<t t-set="user_names"
t-value="', '.join(object.user_id.mapped('name')) if object.user_id else 'Recruiter'"/>
<t t-set="location_names"
t-value="', '.join(object.locations.mapped('name')) if object.locations else 'N/A'"/>
t-value="', '.join(object.locations.mapped('location_name')) if object.locations else 'N/A'"/>
<div style="font-family: Arial, sans-serif; font-size: 14px; color: #333; line-height: 1.5; padding: 20px;">
@ -669,7 +669,7 @@
<t t-set="locations">
<t t-if="object.hr_job_recruitment.locations">
<t t-set="locations_str"
t-value="', '.join(object.hr_job_recruitment.locations.mapped('name'))"/>
t-value="', '.join(object.hr_job_recruitment.locations.mapped('location_name'))"/>
<t t-set="locations" t-value="locations_str"/>
</t>
<t t-else="">
@ -784,7 +784,7 @@
<field name="body_html" type="html">
<t t-set="job_name" t-value="object.job_id.name or object.name or object.display_name or ''"/>
<t t-set="recruitment_name" t-value="object.recruitment_sequence or object.display_name or ''"/>
<t t-set="locations" t-value="', '.join(object.locations.mapped('name')) if object.locations else ''"/>
<t t-set="locations" t-value="', '.join(object.locations.mapped('location_name')) if object.locations else ''"/>
<t t-set="primary_skills" t-value="', '.join(object.skill_ids.mapped('name')) if object.skill_ids else ''"/>
<t t-set="secondary_skills" t-value="', '.join(object.secondary_skill_ids.mapped('name')) if object.secondary_skill_ids else ''"/>
<div style="margin: 0; padding: 0; font-size: 13px; line-height: 1.6;">

View File

@ -1,9 +1,10 @@
from . import submission_share_history
from . import hr_recruitment
from . import hr_job_recruitment
from . import stages
from . import applicant_request_forms
from . import hr_applicant_stage_comment
from . import hr_applicant
from . import applicant_request_forms
from . import hr_applicant_stage_comment
from . import hr_applicant
from . import hr_job
from . import res_partner
from . import candidate_experience

View File

@ -61,6 +61,30 @@ class HRApplicant(models.Model):
)
stage_comment_count = fields.Integer(compute='_compute_stage_comment_count')
stage_comment_tooltips = fields.Json(compute='_compute_stage_comment_tooltips')
submission_tracker = fields.One2many('recruitment.share.tracker','applicant_id')
submission_count = fields.Integer(
string="Submission Count",
compute="_compute_submission_count",
)
def _compute_submission_count(self):
for rec in self:
rec.submission_count = len(rec.submission_tracker)
def action_open_submissions_wizard(self):
self.ensure_one()
return {
"type": "ir.actions.act_window",
"name": "Submission History",
"res_model": "recruitment.share.tracker",
"view_mode": "list",
"views": [
(self.env.ref("hr_recruitment_extended.view_recruitment_share_tracker_list_popup").id, "list"),
],
"domain": [("applicant_id", "=", self.id)],
"target": "new",
}
@api.depends('is_on_hold')
def _compute_hold_state(self):

View File

@ -175,6 +175,7 @@ class HRJobRecruitment(models.Model):
requested_by = fields.Many2one('res.partner', string="Requested By",
default=lambda self: self.env.user.partner_id, domain="[('contact_type','=',recruitment_type)]", tracking=True)
submission_tracker = fields.One2many('recruitment.share.tracker','job_recruitment_id')
def action_toggle_chatter_visibility(self):
for record in self:
record.hide_chatter_suggestion = not record.hide_chatter_suggestion
@ -405,6 +406,7 @@ class HRJobRecruitment(models.Model):
'default_template_id': self.env.ref(
'hr_recruitment_extended.job_recruitment_share_email_template'
).id,
'default_is_job_recruitment': True,
},
}

View File

@ -0,0 +1,51 @@
from odoo import api, fields, models
class RecruitmentShareTracker(models.Model):
_name = "recruitment.share.tracker"
_description = "Recruitment Share Tracker"
_order = "date desc, id desc"
date = fields.Datetime(
string="Date",
required=True,
default=fields.Datetime.now,
)
share_type = fields.Selection(
[
("job", "Job"),
("applicant", "Applicant"),
],
string="Share Type",
required=True,
)
reference = fields.Char(
string="Reference",
)
applicant_id = fields.Many2one(
"hr.applicant",
string="Applicant",
ondelete="set null",
)
job_recruitment_id = fields.Many2one(
"hr.job.recruitment",
string="Job Position",
ondelete="set null",
)
email_from = fields.Char(
string="Email From",
)
email_to = fields.Char(
string="Email To",
)
is_client_submission = fields.Boolean(
string="Client Submission",
default=False,
)

View File

@ -1,6 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_location,hr.location,model_hr_location,base.group_user,1,1,1,1
access_recruitment_share_tracker_user,recruitment.share.tracker.user,model_recruitment_share_tracker,hr_recruitment.group_hr_recruitment_user,1,1,1,1
access_job_category_user,job.category.user,model_job_category,base.group_user,1,0,0,0
access_job_category_manager,job.category.manager,model_job_category,hr_recruitment.group_hr_recruitment_user,1,1,1,1
@ -35,4 +36,5 @@ access_applicant_stage_comment_wizard,applicant.stage.comment.wizard.user,model_
access_hr_application_public,hr.applicant.public.access,hr_recruitment.model_hr_applicant,base.group_public,1,0,0,0
access_hr_application_group_hr,hr.applicant.hr.access,hr_recruitment.model_hr_applicant,hr.group_hr_manager,1,1,0,0
access_applicant_request_forms_hr_user,access.applicant.request.forms.hr.user,model_applicant_request_forms,hr.group_hr_user,1,1,1,1
access_hr_skill,access.hr.skill.user,hr_skills.model_hr_skill,base.group_public,1,0,0,0
access_hr_skill,access.hr.skill.user,hr_skills.model_hr_skill,base.group_public,1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_location hr.location model_hr_location base.group_user 1 1 1 1
3 access_job_category_user access_recruitment_share_tracker_user job.category.user recruitment.share.tracker.user model_job_category model_recruitment_share_tracker base.group_user hr_recruitment.group_hr_recruitment_user 1 0 1 0 1 0 1
4 access_job_category_user job.category.user model_job_category base.group_user 1 0 0 0
5 access_job_category_manager job.category.manager model_job_category hr_recruitment.group_hr_recruitment_user 1 1 1 1
6 access_hr_job_recruitment_user access.hr.job.recruitment.user model_hr_job_recruitment base.group_user 1 1 0 0
7 access_hr_job_recruitment_manager access.hr.job.recruitment.manager model_hr_job_recruitment hr_recruitment.group_hr_recruitment_user 1 1 1 1
36
37
38
39
40

View File

@ -90,6 +90,10 @@
<button name="action_open_stage_comment_wizard" type="object" class="oe_stat_button" icon="fa-comments">
<field name="stage_comment_count" widget="statinfo" string="Stage Notes"/>
</button>
<button name="action_open_submissions_wizard" type="object" class="oe_stat_button" icon="fa-file-text-o" invisible="not submission_tracker">
<field name="submission_count" widget="statinfo" string="Share History"/>
</button>
</xpath>
<xpath expr="//page[@name='application_details']/group[1]" position="after">
<group string="Client Submission">

View File

@ -201,6 +201,20 @@
<separator string="Process Details"/>
<field name="job_details" nolabel="1"/>
</page>
<page string="Submission History" name="submission_tracker" invisible="not submission_tracker">
<field name="submission_tracker">
<list create="0" edit="0" delete="0">
<field name="date"/>
<field name="share_type" column_invisible="1"/>
<field name="reference"/>
<field name="applicant_id" column_invisible="1"/>
<field name="job_recruitment_id" column_invisible="1"/>
<field name="email_from"/>
<field name="email_to"/>
<field name="is_client_submission" column_invisible="1"/>
</list>
</field>
</page>
</notebook>
</sheet>
<chatter open_attachments="True" invisible="hide_chatter_suggestion"/>
@ -484,7 +498,7 @@
active="0"
sequence="2"/>
<menuitem name="JP"
<menuitem name="Job Position"
id="menu_hr_job_descriptions"
parent="hr_recruitment.menu_hr_recruitment_root"
action="action_hr_job_recruitment_awaiting_published"

View File

@ -338,6 +338,7 @@
<record id="hr_recruitment.action_hr_candidate" model="ir.actions.act_window">
<field name="search_view_id" ref="hr_recruitment.hr_candidate_view_search"/>
<field name="context">{'search_default_my_candidates': 1,'active_test': False}</field>
<field name="view_mode">kanban,list,form,activity</field>
</record>
<menuitem

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_recruitment_share_tracker_list_popup" model="ir.ui.view">
<field name="name">recruitment.share.tracker.popup.list</field>
<field name="model">recruitment.share.tracker</field>
<field name="arch" type="xml">
<list create="0"
edit="0"
delete="0"
open_form_view="0">
<field name="date"/>
<field name="share_type"/>
<field name="reference"/>
<field name="email_from"/>
<field name="email_to"/>
<field name="is_client_submission"/>
</list>
</field>
</record>
</odoo>

View File

@ -1,65 +1,123 @@
from odoo import models, fields, api
from odoo.exceptions import UserError
class ClientSubmissionsMailTemplateWizard(models.TransientModel):
_name = 'client.submission.mails.template.wizard'
_description = 'Client Submission Mails Template Wizard'
template_id = fields.Many2one('mail.template', string='Email Template')
submit_date = fields.Date(string='Submission Date', required=True, default=fields.Date.today())
send_email_from_odoo = fields.Boolean(string="Send Email From Odoo", default=False)
is_job_recruitment = fields.Boolean(string='Is Job Recruitment', default=False)
is_client_submission = fields.Boolean(string='Is Client Submission?', default=False)
send_email_from_odoo = fields.Boolean(string="Send Email", default=True)
email_from = fields.Char('Email From')
email_to = fields.Char('Email To')
email_cc = fields.Text('Email CC')
email_subject = fields.Char()
email_body = fields.Html(
'Body', render_engine='qweb', render_options={'post_process': True},
prefetch=True, translate=True, sanitize='email_outgoing',
'Body',
render_engine='qweb',
render_options={'post_process': True},
prefetch=True,
translate=True,
sanitize='email_outgoing',
)
@api.onchange('template_id')
def _onchange_template_id(self):
""" Update the email body and recipients based on the selected template. """
if self.template_id:
record_id = self.env.context.get('active_id')
if record_id:
record = self.env[self.template_id.model].browse(record_id)
"""Update the email fields based on the selected template."""
if not self.template_id:
return
if not record.exists():
raise UserError("The record does not exist or is not accessible.")
record_id = self.env.context.get('active_id')
active_model = self.env.context.get('active_model')
# Fetch email template
email_template = self.env['mail.template'].browse(self.template_id.id)
if not record_id:
return
if not email_template:
raise UserError("Email template not found.")
record = self.env[self.template_id.model].browse(record_id)
self.email_from = record.user_id.partner_id.email
self.email_to = record.requested_by.email
self.email_body = email_template.body_html # Assign the rendered email bodyc
self.email_subject = email_template.subject
if not record.exists():
raise UserError("The record does not exist or is not accessible.")
self.email_from = record.user_id.partner_id.email
if active_model == 'hr.applicant':
self.email_to = record.hr_job_recruitment.requested_by.email
else:
self.email_to = record.requested_by.email
self.email_subject = self.template_id.subject
self.email_body = self.template_id.body_html
def action_send_email(self):
""" Send email to the selected partners """
"""Send email and create recruitment share tracker."""
self.ensure_one()
record_id = self.env.context.get('active_id')
for rec in self:
record = self.env[self.template_id.model].browse(record_id)
if rec.send_email_from_odoo:
template = self.env.ref('hr_recruitment_extended.application_client_submission_email_template')
values = {
'email_from': rec.email_from,
'email_to': rec.email_to,
'email_cc': rec.email_cc,
'subject' : rec.email_subject,
'body_html': rec.email_body,
}
render_ctx = dict(client_name=record.hr_job_recruitment.requested_by.name)
# Use 'with_context' to override the email template fields dynamically
template.sudo().with_context(**render_ctx).send_mail(self.env.context.get('active_id'),email_values=values, force_send=True)
model_name = self.env.context.get('active_model')
record = self.env[self.template_id.model].browse(record_id)
tracker_values = {
'date': fields.Datetime.now(),
'is_client_submission': self.is_client_submission,
}
if model_name == 'hr.applicant':
tracker_values.update({
'share_type': 'applicant',
'reference': "%s/%s" % (
record.hr_job_recruitment.recruitment_sequence,
record.candidate_id.candidate_sequence,
),
'applicant_id': record.id,
})
else:
tracker_values.update({
'share_type': 'job',
'reference': record.recruitment_sequence,
'job_recruitment_id': record.id,
})
if self.send_email_from_odoo:
# Use the selected template
template = self.template_id
values = {
'email_from': self.email_from,
'email_to': self.email_to,
'email_cc': self.email_cc,
'subject': self.email_subject,
'body_html': self.email_body,
}
if model_name == 'hr.applicant':
client_name = record.hr_job_recruitment.requested_by.name
else:
client_name = record.requested_by.name
render_ctx = {
'client_name': client_name,
}
tracker_values['email_from'] = self.email_from,
tracker_values['email_to'] = self.email_to,
template.sudo().with_context(**render_ctx).send_mail(
record.id,
email_values=values,
force_send=True,
)
if self.is_client_submission and model_name == 'hr.applicant':
record.sudo().write({
'submitted_to_client': True,
'client_submission_date': rec.submit_date,
'client_submission_date': self.submit_date,
'submitted_stage': record.recruitment_stage_id.id,
})
return {'type': 'ir.actions.act_window_close'} # Close wizard after sending
self.env['recruitment.share.tracker'].sudo().create(tracker_values)
return {'type': 'ir.actions.act_window_close'}

View File

@ -9,6 +9,8 @@
<form>
<group>
<field name="submit_date"/>
<field name="is_job_recruitment" invisible="1"/>
<field name="is_client_submission" invisible="is_job_recruitment"/>
<field name="send_email_from_odoo"/>
<separator string="Section Title"/>
<field name="template_id" options="{'no_create': True}" invisible="not send_email_from_odoo" required="send_email_from_odoo" readonly="1" force_save="1"/>