ATS CHANGES

This commit is contained in:
Pranay 2025-04-17 12:20:46 +05:30 committed by raman
parent c9555b962e
commit baa6dec075
10 changed files with 269 additions and 55 deletions

View File

@ -0,0 +1,10 @@
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from datetime import date
from datetime import timedelta
import datetime
class approvalRequiredDocs(models.Model):
_name = "approval.req.docs"
name = fields.Char(string='name')

View File

@ -6,6 +6,7 @@ from datetime import datetime
from odoo.exceptions import ValidationError
import warnings
from odoo.tools.mimetypes import guess_mimetype, fix_filename_extension
class HRApplicant(models.Model):
@ -17,9 +18,16 @@ class HRApplicant(models.Model):
submitted_to_client = fields.Boolean(string="Submitted_to_client", default=False, readonly=True, tracking=True)
client_submission_date = fields.Datetime(string="Submission Date")
submitted_stage = fields.Many2one('hr.recruitment.stage')
refused_stage = fields.Many2one('hr.recruitment.stage')
refused_comments = fields.Text()
refused_stage = fields.Many2one('hr.recruitment.stage', string="Reject Stage")
refused_comments = fields.Text(string='Reject Comments')
is_on_hold = fields.Boolean(string="Is On Hold", default=False)
def hold_unhold_button(self):
for rec in self:
if rec.is_on_hold:
rec.is_on_hold = False
else:
rec.is_on_hold = True
@api.constrains('candidate_id','hr_job_recruitment')
def hr_applicant_constrains(self):
for rec in self:
@ -92,7 +100,7 @@ class HRApplicant(models.Model):
""")
refused_state = fields.Many2one('hr.recruitment.stage', readonly=True, force_save=True)
refused_state = fields.Many2one('hr.recruitment.stage', readonly=True, force_save=True, string="Reject state")
hr_job_recruitment = fields.Many2one('hr.job.recruitment')
job_id = fields.Many2one('hr.job', related='hr_job_recruitment.job_id', store=True)
@ -126,7 +134,35 @@ class HRApplicant(models.Model):
approval_required = fields.Boolean(related='recruitment_stage_id.require_approval')
application_submitted = fields.Boolean(string="Application Submitted")
resume = fields.Binary(related='candidate_id.resume', readonly=False, compute_sudo=True)
resume_type = fields.Char(related='candidate_id.resume_type', readonly=False, compute_sudo=True)
resume_name = fields.Char(related='candidate_id.resume_name', readonly=False, compute_sudo=True)
@api.onchange('resume')
def onchange_resume(self):
for rec in self:
if rec.resume:
attachment = self.env.ref("hr_recruitment_extended.employee_recruitment_attachments_preview")
file = attachment.write({
'datas': rec.resume,
})
if file:
rec.resume_type = attachment.mimetype
else:
rec.resume_type = ''
rec.resume_name = ''
def preview_resume(self):
pass
# for record in self:
# if record.resume:
# attachment = self.env.ref("hr_recruitment_extended.employee_recruitment_attachments_preview")
# attachment.datas = record.resume
# return {
# 'name': "File Preview",
# 'type': 'ir.actions.act_url',
# 'url': f'/web/content/{attachment.id}?download=false',
# 'target': 'current', # Opens in a new tab
# }
def submit_to_client(self):
for rec in self:

View File

@ -83,12 +83,12 @@ class HRJobRecruitment(models.Model):
for job in self:
job.new_application_count = new_applicant_count.get(job.id, 0)
application_count = fields.Integer(compute='_compute_application_count', string="Application Count")
all_application_count = fields.Integer(compute='_compute_all_application_count', string="All Application Count")
application_count = fields.Integer(compute='_compute_application_count', string="Application Count", tracking=True)
all_application_count = fields.Integer(compute='_compute_all_application_count', string="All Application Count", tracking=True)
new_application_count = fields.Integer(
compute='_compute_new_application_count', string="New Application",
help="Number of applications that are new in the flow (typically at first step of the flow)")
applicant_hired = fields.Integer(compute='_compute_applicant_hired', string="Applicants Hired")
applicant_hired = fields.Integer(compute='_compute_applicant_hired', string="Applicants Hired", tracking=True)
def _get_default_favorite_user_ids(self):
"""this function is used to set the default users i.e current user"""
@ -104,24 +104,24 @@ class HRJobRecruitment(models.Model):
else:
return self.env.company.partner_id
job_id = fields.Many2one('hr.job', required=True)
name = fields.Char(string='Job Position', required=True, index='trigram', translate=True, related='job_id.name')
job_id = fields.Many2one('hr.job', required=True, tracking=True)
name = fields.Char(string='Job Position', required=True, index='trigram', translate=True, related='job_id.name', tracking=True)
recruitment_sequence = fields.Char(string='Recruitment Sequence', readonly=False, default='/', copy=False)
recruitment_sequence = fields.Char(string='Recruitment Sequence', readonly=False, default='/', copy=False, tracking=True)
favorite_user_ids = fields.Many2many('res.users', 'job_recruitment_favorite_user_rel', 'job_id', 'user_id', default=_get_default_favorite_user_ids)
favorite_user_ids = fields.Many2many('res.users', 'job_recruitment_favorite_user_rel', 'job_id', 'user_id', default=_get_default_favorite_user_ids, tracking=True)
secondary_skill_ids = fields.Many2many('hr.skill', "hr_job_recruitment_hr_skill_rel",
'job_recruitment_id', 'hr_skill_id', "Secondary Skills")
'job_recruitment_id', 'hr_skill_id', "Secondary Skills", tracking=True)
no_of_recruitment = fields.Integer(string='Number of Positions', copy=False,
help='Number of new employees you expect to recruit.', default=1)
help='Number of new employees you expect to recruit.', default=1, tracking=True)
no_of_eligible_submissions = fields.Integer(string='Eligible Submissions', copy=False,
help='Number of Submissions you expected to send.', default=1)
help='Number of Submissions you expected to send.', default=1, tracking=True)
submission_status = fields.Selection([('zero','Zero Submissions'),('partial','Partial Submissions'),('filled','Filled Submissions')],default='zero', compute="_compute_submission_status", store=True)
submission_status = fields.Selection([('zero','Zero Submissions'),('partial','Partial Submissions'),('filled','Filled Submissions')],default='zero', compute="_compute_submission_status", store=True, tracking=True)
@api.onchange("no_of_recruitment")
def onchange_no_of_recruitments(self):
@ -131,36 +131,36 @@ class HRJobRecruitment(models.Model):
rec.no_of_eligible_submissions = rec.no_of_recruitment
locations = fields.Many2many('hr.location')
locations = fields.Many2many('hr.location', tracking=True)
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')
default=fields.Date.today, tracking=True)
target_to = fields.Date(string='This is the target end date', tracking=True)
# hiring_history = fields.One2many('recruitment.status.history', 'job_id', string='History')
is_favorite = fields.Boolean(compute='_compute_is_favorite', inverse='_inverse_is_favorite',store=True)
department_id = fields.Many2one('hr.department', string='Department', check_company=True)
description = fields.Html(string='Job Description', sanitize_attributes=False)
requirements = fields.Text('Requirements')
is_favorite = fields.Boolean(compute='_compute_is_favorite', inverse='_inverse_is_favorite',store=True, tracking=True)
department_id = fields.Many2one('hr.department', string='Department', check_company=True, tracking=True)
description = fields.Html(string='Job Description', tracking=True, sanitize_attributes=False)
requirements = fields.Text('Requirements', tracking=True)
expected_employees = fields.Integer(compute='_compute_employees', string='Total Forecasted Employees', store=True,
help='Expected number of employees for this job position after new recruitment.')
no_of_employee = fields.Integer(compute='_compute_employees', string="Current Number of Employees", store=True,
help='Number of employees currently occupying this job position.')
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company, exportable=False)
contract_type_id = fields.Many2one('hr.contract.type', string='Employment Type')
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company, tracking=True, exportable=False)
contract_type_id = fields.Many2one('hr.contract.type', string='Employment Type', tracking=True)
# active = fields.Boolean(default=True)
user_id = fields.Many2one('res.users', "Recruiter",
domain="[('share', '=', False), ('company_ids', 'in', company_id)]",
default=lambda self: self.env.user,
tracking=True, help="The Recruiter will be the default value for all Applicants in this job \
position. The Recruiter is automatically added to all meetings with the Applicant.")
interviewer_ids = fields.Many2many('res.users', string='Interviewers', domain="[('share', '=', False), ('company_ids', 'in', company_id)]", help="The Interviewers set on the job position can see all Applicants in it. They have access to the information, the attachments, the meeting management and they can refuse him. You don't need to have Recruitment rights to be set as an interviewer.")
skill_ids = fields.Many2many('hr.skill','hr_job_recruitment_hr_primary_skill_rel','job_id', 'user_id', string="Primary Skills")
interviewer_ids = fields.Many2many('res.users', string='Interviewers', domain="[('share', '=', False), ('company_ids', 'in', company_id)]", tracking=True, help="The Interviewers set on the job position can see all Applicants in it. They have access to the information, the attachments, the meeting management and they can refuse him. You don't need to have Recruitment rights to be set as an interviewer.")
skill_ids = fields.Many2many('hr.skill','hr_job_recruitment_hr_primary_skill_rel','job_id', 'user_id', string="Primary Skills", tracking=True)
address_id = fields.Many2one(
'res.partner', "Job Location", default=_default_address_id,
domain="[('is_company','=',True),('contact_type','=',recruitment_type)]",
help="Select the location where the applicant will work. Addresses listed here are defined on the company's contact information.", exportable=False)
recruitment_type = fields.Selection([('internal','In-House'),('external','Client-Side')], required=True, default='internal')
help="Select the location where the applicant will work. Addresses listed here are defined on the company's contact information.", exportable=False, tracking=True)
recruitment_type = fields.Selection([('internal','In-House'),('external','Client-Side')], required=True, default='internal', tracking=True)
requested_by = fields.Many2one('res.partner', string="Requested By",
default=lambda self: self.env.user.partner_id, domain="[('contact_type','=',recruitment_type)]")
default=lambda self: self.env.user.partner_id, domain="[('contact_type','=',recruitment_type)]", tracking=True)
@api.onchange('recruitment_type')
def _onchange_recruitment_type(self):
@ -203,33 +203,35 @@ class HRJobRecruitment(models.Model):
return """
[('is_client','=',True)]
"""
document_ids = fields.One2many('ir.attachment', compute='_compute_document_ids', string="Documents", readonly=True)
documents_count = fields.Integer(compute='_compute_document_ids', string="Document Count")
color = fields.Integer("Color Index")
application_ids = fields.One2many('hr.applicant', 'hr_job_recruitment', "Job Applications")
document_ids = fields.One2many('ir.attachment', compute='_compute_document_ids', string="Documents", readonly=True, tracking=True)
documents_count = fields.Integer(compute='_compute_document_ids', string="Document Count", tracking=True)
color = fields.Integer("Color Index", tracking=True)
application_ids = fields.One2many('hr.applicant', 'hr_job_recruitment', "Job Applications", tracking=True)
no_of_hired_employee = fields.Integer(
compute='_compute_no_of_hired_employee',
string='Hired', copy=False,
help='Number of hired employees for this job position during recruitment phase.',
store=True)
store=True, tracking=True)
no_of_submissions = fields.Integer(
compute='_compute_no_of_submissions',
string='Submitted', copy=False, store=True,
help='Number of Application submissions for this job position during recruitment phase.',
help='Number of Application submissions for this job position during recruitment phase.', tracking=True
)
no_of_refused_submissions = fields.Integer(
compute='_compute_no_of_refused_submissions',
string='Hired', copy=False,
help='Number of Refused Application submissions for this job position during recruitment phase.',
)
tracking=True)
experience = fields.Many2one('candidate.experience', string="Experience")
experience = fields.Many2one('candidate.experience', string="Experience", tracking=True)
budget = fields.Char(string='Budget')
budget = fields.Char(string='Budget', tracking=True)
job_category = fields.Many2one("job.category", string="Category")
job_category = fields.Many2one("job.category", string="Category", tracking=True)
job_priority = fields.Selection([('low','Low'),('medium','Medium'),('high','High')], string="Pirority")
job_priority = fields.Selection([('low','Low'),('medium','Medium'),('high','High')], string="Pirority", tracking=True)
recruitment_status = fields.Selection([('open','Open'),('closed','Closed'),('hold','Hold'),('modified','Modified'),('cancelled','Cancelled')], default='open', tracking=True)
@api.onchange('job_id','job_category')
def onchange_job_id(self):
@ -445,6 +447,6 @@ class HRJobRecruitment(models.Model):
class HRSkill(models.Model):
_inherit = 'hr.skill'
job_recruitment_id = fields.Many2one('hr.job.recruitment')
job_recruitment_id = fields.Many2one('hr.job.recruitment', tracking=True)

View File

@ -27,10 +27,27 @@ class HrCandidate(models.Model):
candidate_image = fields.Image()
employee_code = fields.Char(related="employee_id.employee_id")
resume = fields.Binary()
resume_type = fields.Char()
resume_name = fields.Char()
applications_stages_stat = fields.Many2many('application.stage.status',string="Applications History", compute="_compute_applications_stages_stat")
# availability_status = fields.Selection([('available','Available'),('not_available','Not Available'),('hired','Hired'),('abscond','Abscond')])
@api.onchange('resume')
def onchange_resume(self):
for rec in self:
if rec.resume:
attachment = self.env.ref("hr_recruitment_extended.employee_recruitment_attachments_preview")
file = attachment.write({
'datas':rec.resume,
})
if file:
rec.resume_type = attachment.mimetype
else:
rec.resume_type = ''
rec.resume_name = ''
def action_open_applications(self):
self.ensure_one()
return {

View File

@ -18,7 +18,17 @@
<field name="model">hr.applicant</field>
<field name="inherit_id" ref="hr_recruitment.hr_applicant_view_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='archive_applicant']" position="attributes">
<attribute name="string">Reject</attribute>
</xpath>
<xpath expr="//button[@name='archive_applicant']" position="before">
<field name="is_on_hold" invisible="1" force_save="1"/>
<button name="hold_unhold_button" string="HOLD" type="object" class="btn-primary"
groups="hr_recruitment.group_hr_recruitment_user"
invisible="application_status in ['refused'] or is_on_hold"/>
<button name="hold_unhold_button" string="UN HOLD" type="object" class="btn-primary"
groups="hr_recruitment.group_hr_recruitment_user"
invisible="application_status in ['refused'] or not is_on_hold"/>
<button string="Submit" name="submit_for_approval" type="object" class="oe_stat_button"
invisible="not approval_required or application_submitted" groups="base.group_user"/>
<button string="Approve" name="approve_applicant" type="object" class="oe_stat_button"
@ -27,6 +37,7 @@
<button name="submit_to_client" string="Send to Client" type="object" class="btn-primary"
groups="hr_recruitment.group_hr_recruitment_user"
invisible="submitted_to_client or application_status in ['refused']"/>
</xpath>
<xpath expr="//field[@name='kanban_state']" position="after">
<div class="o_employee_avatar m-0 p-0">
@ -59,7 +70,7 @@
<xpath expr="//field[@name='stage_id']" position="before">
<field name="recruitment_stage_id" widget="statusbar_duration"
options="{'clickable': '1', 'fold_field': 'fold'}" invisible="not active and not employee_id"
readonly="approval_required" force_save="1"/>
readonly="approval_required or is_on_hold" force_save="1"/>
</xpath>
<!-- <xpath expr="//form" position="after">-->
<!-- </xpath>-->
@ -117,7 +128,7 @@
<field name="recruitment_attachment_id"/>
<field name="name"/>
<field name="recruitment_attachment_type"/>
<field name="file" widget="binary" options="{'download':true}"/>
<field name="file" widget="binary" options="{'download':true}" filename="name"/>
<button name="action_preview_file"
type="object"
string="Preview"
@ -147,6 +158,12 @@
<field name="model">hr.applicant</field>
<field name="inherit_id" ref="hr_recruitment.hr_applicant_view_search_bis"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='refused']" position="attributes">
<attribute name="string">Rejected</attribute>
</xpath>
<xpath expr="//filter[@name='refuse_reason_id']" position="attributes">
<attribute name="string">Reject Reason</attribute>
</xpath>
<xpath expr="//search/field[@name='job_id']" position="after">
<field name="hr_job_recruitment"/>
<field name="recruitment_stage_id" domain="[]"/>
@ -168,6 +185,16 @@
</field>
</record>
<record id="hr_kanban_view_applicant_view_inherit" model="ir.ui.view">
<field name="name">hr.applicant.view.kanban.inherit</field>
<field name="model">hr.applicant</field>
<field name="inherit_id" ref="hr_recruitment.hr_kanban_view_applicant"/>
<field name="arch" type="xml">
<xpath expr="//kanban" position="attributes">
<attribute name="default_group_by">recruitment_stage_id</attribute>
</xpath>
</field>
</record>
<record id="hr_kanban_view_applicant_inherit" model="ir.ui.view">
<field name="name">hr.applicant.view.kanban.inherit</field>
<field name="model">hr.applicant</field>
@ -184,6 +211,7 @@
<field name="user_id"/>
<field name="active"/>
<field name="application_status"/>
<field name="is_on_hold" invisible="1"/>
<field name="company_id"
invisible="1"/> <!-- We need to keep this field as it is used in the domain of user_id in the model -->
<progressbar field="kanban_state" colors='{"done": "success", "blocked": "danger"}'/>
@ -192,7 +220,7 @@
<a role="menuitem" name="action_create_meeting" type="object" class="dropdown-item">Schedule
Interview
</a>
<a role="menuitem" name="archive_applicant" type="object" class="dropdown-item">Refuse</a>
<a role="menuitem" name="archive_applicant" type="object" class="dropdown-item">Reject</a>
<a t-if="record.active.raw_value" role="menuitem" type="archive" class="dropdown-item">Archive
</a>
<a t-if="!record.active.raw_value" role="menuitem" type="unarchive" class="dropdown-item">
@ -203,6 +231,7 @@
</t>
</t>
<t t-name="card">
<widget name="web_ribbon" title="HOLD" bg_color="text-bg-success" invisible="not is_on_hold"/>
<widget name="web_ribbon" title="Hired" bg_color="text-bg-success" invisible="not date_closed"/>
<widget name="web_ribbon" title="Refused" bg_color="text-bg-danger"
invisible="application_status != 'refused'"/>
@ -296,6 +325,10 @@
<field name="name">Recruitment Analysis</field>
<field name="res_model">hr.applicant</field>
<field name="view_mode">graph,pivot</field>
<field name="view_ids"
eval="[(5, 0, 0),
(0, 0, {'view_mode': 'kanban', 'view_id': ref('hr_kanban_view_applicant_inherit')})]"/>
<field name="search_view_id" ref="hr_applicant_view_search_bis_inherit"/>
<field name="context">{
'search_default_creation_month': 1,
@ -317,4 +350,54 @@
</field>
</record>
<record id="hr_recruitment.hr_applicant_action_analysis" model="ir.actions.act_window">
<field name="search_view_id" ref="hr_applicant_view_search_bis_inherit"/>
<field name="context">
{'search_default_creation_month': 1, 'search_default_job_recruitment': 1,'active_test': False}
</field>
</record>
<record id="hr_recruitment_hr_applicant_view_pivot_inherit" model="ir.ui.view">
<field name="name">hr_recruitment.hr_applicant_view_pivot.inherit</field>
<field name="model">hr.applicant</field>
<field name="inherit_id" ref="hr_recruitment.hr_applicant_view_pivot"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='stage_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='stage_id']" position="before">
<field name="recruitment_stage_id" type="row"/>
</xpath>
<xpath expr="//field[@name='job_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='job_id']" position="before">
<field name="hr_job_recruitment" type="col"/>
</xpath>
</field>
</record>
<record id="hr_recruitment_hr_applicant_view_graph_inherit" model="ir.ui.view">
<field name="name">hr_recruitment.hr_applicant_view_graph.inherit</field>
<field name="model">hr.applicant</field>
<field name="inherit_id" ref="hr_recruitment.hr_applicant_view_graph"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='stage_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='stage_id']" position="before">
<field name="recruitment_stage_id" type="row"/>
</xpath>
<xpath expr="//field[@name='job_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='job_id']" position="before">
<field name="hr_job_recruitment" type="col"/>
</xpath>
</field>
</record>
</odoo>

View File

@ -6,7 +6,7 @@
<field name="inherit_id" ref="hr_recruitment.hr_applicant_view_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook" position="inside">
<page name="additional_info" string="Additional Info" invisible="not employee_id">
<page name="additional_info" string="Additional Info">
<group colspan="2">
<group string="Personal Details">
@ -14,7 +14,7 @@
name="action_validate_personal_details"
type="object"
class="btn btn-success"
invisible="personal_details_status == 'pending'">
invisible="personal_details_status == 'pending' or not employee_id">
<div>
Click here to save &amp; Update Employee Data
<field name="personal_details_status"
@ -29,7 +29,7 @@
name="action_validate_personal_details"
type="object"
class="btn btn-danger"
invisible="personal_details_status == 'validated'">
invisible="personal_details_status == 'validated' or not employee_id">
<div>
Click here to save, Validate and Update into Employee Data
<field name="personal_details_status"
@ -57,7 +57,7 @@
name="action_validate_contact_details"
type="object"
class="btn btn-success"
invisible="contact_details_status == 'pending'">
invisible="contact_details_status == 'pending' or not employee_id">
<div>
Click here to save &amp; Update Employee Data
<field name="contact_details_status"
@ -72,7 +72,7 @@
name="action_validate_contact_details"
type="object"
class="btn btn-danger"
invisible="contact_details_status == 'validated'">
invisible="contact_details_status == 'validated' or not employee_id">
<div>
Click here to save, Validate and Update into Employee Data
<field name="contact_details_status"
@ -111,7 +111,7 @@
</group>
</group>
<group string="Bank Details">
<group string="Bank Details" invisible="not employee_id">
<button string="Validate/update"
name="action_validate_bank_details"
type="object"
@ -150,7 +150,7 @@
</group>
</group>
<group string="Passport Details">
<group string="Passport Details" invisible="not employee_id">
<button string="Validate/update"
name="action_validate_passport_details"
type="object"
@ -188,7 +188,7 @@
</group>
</group>
<group string="Authentication Details">
<group string="Authentication Details" invisible="not employee_id">
<button string="Validate/update"
name="action_validate_authentication_details"
type="object"
@ -227,7 +227,7 @@
</group>
</group>
<group>
<group invisible="not employee_id">
<button string="Validate/update"
name="action_validate_family_education_employer_details"
type="object"

View File

@ -12,9 +12,12 @@
<field name="recruitment_type" optional="hide"/>
<field name="department_id"/>
<field name="no_of_recruitment"/>
<field name="no_of_eligible_submissions" optional="hide"/>
<field name="application_count" string="Applications"
groups="hr_recruitment.group_hr_recruitment_interviewer"/>
<field name="expected_employees" optional="hide"/>
<field name="no_of_submissions" optional="hide"/>
<field name="no_of_hired_employee" optional="hide"/>
<field name="message_needaction" column_invisible="True"/>
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
@ -25,6 +28,7 @@
<field name="user_id" widget="many2one_avatar_user" optional="hide"/>
<field name="no_of_employee"/>
<field name="job_priority" optional="hide"/>
<field name="submission_status" optional="hide"/>
</list>
@ -54,6 +58,7 @@
<form string="Job" js_class="recruitment_form_view">
<header>
<button name="send_mail_to_recruiters" type="object" string="Send Recruiters Notification" class="oe_highlight" groups="hr_recruitment.group_hr_recruitment_user"/>
<field name="recruitment_status" widget="statusbar" options="{'clickable': '1', 'fold_field': 'fold'}"/>
</header> <!-- inherited in other module -->
<field name="active" invisible="1"/>
<field name="company_id" invisible="1" on_change="1" can_create="True" can_write="True"/>
@ -218,6 +223,7 @@
<field name="model">hr.job.recruitment</field>
<field name="arch" type="xml">
<search string="Jobs">
<field name="recruitment_sequence" string="Job Sequence"/>
<field name="job_id" string="Job Position"/>
<field name="department_id" operator="child_of"/>
<field name="user_id" string="Primary Recruiter"/>
@ -225,6 +231,7 @@
<field name="no_of_submissions"/>
<field name="no_of_eligible_submissions"/>
<field name="submission_status"/>
<field name="requested_by"/>
<separator/>
<filter string="Published Records" name="published_records" domain="[('website_published','=',True)]"/>
<separator/>
@ -245,8 +252,24 @@
domain="[('message_needaction', '=', True)]"
groups="mail.group_mail_notification_type_inbox"/>
<separator/>
<separator/>
<filter name="open_status" string="Open"
domain="[('recruitment_status','=', 'open')]"/>
<filter name="closed_status" string="Closed"
domain="[('recruitment_status','=', 'closed')]"/>
<filter name="hold_status" string="Hold"
domain="[('recruitment_status','=', 'hold')]"/>
<filter name="modified_status" string="Open"
domain="[('recruitment_status','=', 'modified')]"/>
<filter name="cancelled_status" string="Open"
domain="[('recruitment_status','=', 'cancelled')]"/>
<separator/>
<filter name="archived" string="Archived" domain="[('active', '=', False)]"/>
<group expand="0" string="Group By">
<filter string="Category" name="category" domain="[]"
context="{'group_by': 'job_category'}"/>
<filter string="Department" name="department" domain="[]"
context="{'group_by': 'department_id'}"/>
<filter string="Company" name="company" domain="[]" context="{'group_by': 'company_id'}"
@ -255,6 +278,11 @@
context="{'group_by': 'contract_type_id'}"/>
<filter string="Submission Status" name="submission_status" domain="[]"
context="{'group_by': 'submission_status'}"/>
<filter string="Requested By" name="requested_by" domain="[]"
context="{'group_by': 'requested_by'}"/>
<filter string="Requested By Company" name="requested_by_company" domain="[]"
context="{'group_by': 'address_id'}"/>
</group>
</search>

View File

@ -175,7 +175,22 @@
<xpath expr="//field[@name='linkedin_profile']" position="after">
<field name="exp_type"/>
<field name="resume" force_save="1"/>
<label for="resume" string="Resume"/>
<div class="oe_row">
<field name="resume_name" invisible="1" force_save="1"/>
<field name="resume_type" invisible="1" force_save="1"/>
<field name="resume" force_save="1" filename="resume_name" widget="binary" options="{'download':true}"/>
<field name="resume"
widget="pdf_viewer"
filename="resume_name"
force_save="1"
invisible="not resume or not resume_type or 'pdf' not in resume_type" options="{'preview_image': 'resume','download': false,'no_delete':true,'no_edit':true}"/>
<field name="resume" force_save="1" widget="image" filename="resume_name"
invisible="not resume or not resume_type or 'image' not in resume_type" options="{'preview_image': 'resume','download': false,'no_delete':true,'no_edit':true}"/>
</div>
<field name="submitted_to_client" force_save="1" readonly="1" invisible="not submitted_to_client"/>
<field name="client_submission_date" force_save="1" readonly="1" invisible="not submitted_to_client"/>
<field name="submitted_stage" force_save="1" readonly="1" invisible="not submitted_to_client"/>
@ -264,7 +279,19 @@
<field name="alternate_phone"/>
</xpath>
<xpath expr="//field[@name='categ_ids']" position="after">
<field name="resume"/>
<label for="resume" string="Resume"/>
<div class="oe_row">
<field name="resume_name" invisible="1" force_save="1"/>
<field name="resume_type" invisible="1" force_save="1"/>
<field name="resume" force_save="1" filename="resume_name" widget="binary" options="{'download':true}"/>
<field name="resume"
widget="pdf_viewer"
filename="resume_name"
force_save="1"
invisible="not resume or not resume_type or 'pdf' not in resume_type" options="{'preview_image': 'resume','download': false,'no_delete':true,'no_edit':true}"/>
<field name="resume" force_save="1" widget="image" filename="resume_name"
invisible="not resume or not resume_type or 'image' not in resume_type" options="{'preview_image': 'resume','download': false,'no_delete':true,'no_edit':true}"/>
</div>
</xpath>
</field>
@ -278,6 +305,9 @@
<xpath expr="//field[@name='partner_name']" position="after">
<field name="candidate_sequence"/>
</xpath>
<xpath expr="//filter[@name='refused']" position="attributes">
<attribute name="string">Rejected</attribute>
</xpath>
</field>
</record>
<record id="hr_candidate_view_kanban_inherit" model="ir.ui.view">

View File

@ -10,7 +10,7 @@ from odoo.osv import expression
class ApplicantGetRefuseReason(models.TransientModel):
_inherit = 'applicant.get.refuse.reason'
refused_comments = fields.Text()
refused_comments = fields.Text(string="Reject Comments")
def action_refuse_reason_apply(self):
if self.send_mail:

View File

@ -9,6 +9,14 @@ class PostOnboardingAttachmentWizard(models.TransientModel):
string='Attachments to Request'
)
is_pre_onboarding_attachment_request = fields.Boolean(default=False)
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',
)
@api.model
def default_get(self, fields_list):