From 1b34ae2c5c0865dd7285e778195bf2d1581752c9 Mon Sep 17 00:00:00 2001 From: pranaysaidurga Date: Fri, 26 Jun 2026 17:26:33 +0530 Subject: [PATCH] recruitment bug fixes --- .../hr_recruitment_extended/__manifest__.py | 1 + .../data/mail_template.xml | 6 +- .../models/__init__.py | 7 +- .../models/hr_applicant.py | 24 ++++ .../models/hr_job_recruitment.py | 2 + .../models/submission_share_history.py | 51 +++++++ .../security/ir.model.access.csv | 4 +- .../views/hr_applicant_views.xml | 4 + .../views/hr_job_recruitment.xml | 16 ++- .../views/hr_recruitment.xml | 1 + .../views/submission_share_history.xml | 20 +++ .../client_submission_mail_template_wizard.py | 128 +++++++++++++----- ...client_submission_mail_template_wizard.xml | 2 + 13 files changed, 223 insertions(+), 43 deletions(-) create mode 100644 addons_extensions/hr_recruitment_extended/models/submission_share_history.py create mode 100644 addons_extensions/hr_recruitment_extended/views/submission_share_history.xml diff --git a/addons_extensions/hr_recruitment_extended/__manifest__.py b/addons_extensions/hr_recruitment_extended/__manifest__.py index d48cd2c0d..3a39282b4 100644 --- a/addons_extensions/hr_recruitment_extended/__manifest__.py +++ b/addons_extensions/hr_recruitment_extended/__manifest__.py @@ -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', diff --git a/addons_extensions/hr_recruitment_extended/data/mail_template.xml b/addons_extensions/hr_recruitment_extended/data/mail_template.xml index 4cc0162b5..10c704b32 100644 --- a/addons_extensions/hr_recruitment_extended/data/mail_template.xml +++ b/addons_extensions/hr_recruitment_extended/data/mail_template.xml @@ -14,7 +14,7 @@ + t-value="', '.join(object.locations.mapped('location_name')) if object.locations else 'N/A'"/>
@@ -669,7 +669,7 @@ + t-value="', '.join(object.hr_job_recruitment.locations.mapped('location_name'))"/> @@ -784,7 +784,7 @@ - +
diff --git a/addons_extensions/hr_recruitment_extended/models/__init__.py b/addons_extensions/hr_recruitment_extended/models/__init__.py index e87225262..0636edb40 100644 --- a/addons_extensions/hr_recruitment_extended/models/__init__.py +++ b/addons_extensions/hr_recruitment_extended/models/__init__.py @@ -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 diff --git a/addons_extensions/hr_recruitment_extended/models/hr_applicant.py b/addons_extensions/hr_recruitment_extended/models/hr_applicant.py index 4010d4888..75ecf7f44 100644 --- a/addons_extensions/hr_recruitment_extended/models/hr_applicant.py +++ b/addons_extensions/hr_recruitment_extended/models/hr_applicant.py @@ -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): diff --git a/addons_extensions/hr_recruitment_extended/models/hr_job_recruitment.py b/addons_extensions/hr_recruitment_extended/models/hr_job_recruitment.py index b8b35ba08..6e8ef76ca 100644 --- a/addons_extensions/hr_recruitment_extended/models/hr_job_recruitment.py +++ b/addons_extensions/hr_recruitment_extended/models/hr_job_recruitment.py @@ -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, }, } diff --git a/addons_extensions/hr_recruitment_extended/models/submission_share_history.py b/addons_extensions/hr_recruitment_extended/models/submission_share_history.py new file mode 100644 index 000000000..b22ce3268 --- /dev/null +++ b/addons_extensions/hr_recruitment_extended/models/submission_share_history.py @@ -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, + ) \ No newline at end of file diff --git a/addons_extensions/hr_recruitment_extended/security/ir.model.access.csv b/addons_extensions/hr_recruitment_extended/security/ir.model.access.csv index 7ca70add2..391deaad1 100644 --- a/addons_extensions/hr_recruitment_extended/security/ir.model.access.csv +++ b/addons_extensions/hr_recruitment_extended/security/ir.model.access.csv @@ -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 \ No newline at end of file +access_hr_skill,access.hr.skill.user,hr_skills.model_hr_skill,base.group_public,1,0,0,0 + diff --git a/addons_extensions/hr_recruitment_extended/views/hr_applicant_views.xml b/addons_extensions/hr_recruitment_extended/views/hr_applicant_views.xml index 3528775de..4dcd1632a 100644 --- a/addons_extensions/hr_recruitment_extended/views/hr_applicant_views.xml +++ b/addons_extensions/hr_recruitment_extended/views/hr_applicant_views.xml @@ -90,6 +90,10 @@ + + diff --git a/addons_extensions/hr_recruitment_extended/views/hr_job_recruitment.xml b/addons_extensions/hr_recruitment_extended/views/hr_job_recruitment.xml index 5b5e0a27a..2a89d280a 100644 --- a/addons_extensions/hr_recruitment_extended/views/hr_job_recruitment.xml +++ b/addons_extensions/hr_recruitment_extended/views/hr_job_recruitment.xml @@ -201,6 +201,20 @@ + + + + + + + + + + + + + + @@ -484,7 +498,7 @@ active="0" sequence="2"/> - {'search_default_my_candidates': 1,'active_test': False} + kanban,list,form,activity + + + recruitment.share.tracker.popup.list + recruitment.share.tracker + + + + + + + + + + + + \ No newline at end of file diff --git a/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.py b/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.py index 84bcc41c7..761d36367 100644 --- a/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.py +++ b/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.py @@ -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'} \ No newline at end of file diff --git a/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.xml b/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.xml index 05d11d1ac..70553c153 100644 --- a/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.xml +++ b/addons_extensions/hr_recruitment_extended/wizards/client_submission_mail_template_wizard.xml @@ -9,6 +9,8 @@
+ +