150 lines
6.3 KiB
Python
150 lines
6.3 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
|
|
from markupsafe import Markup
|
|
|
|
from odoo import fields, models, _
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class HrApplicant(models.Model):
|
|
_inherit = 'hr.applicant'
|
|
|
|
salary_offer_ids = fields.One2many('hr.contract.salary.offer', 'applicant_id')
|
|
salary_offers_count = fields.Integer(compute='_compute_salary_offers_count', compute_sudo=True)
|
|
proposed_contracts = fields.Many2many('hr.version', string="Proposed Contracts", domain="[('company_id', '=', company_id)]")
|
|
proposed_contracts_count = fields.Integer(compute="_compute_proposed_contracts_count", string="Proposed Contracts Count", compute_sudo=True)
|
|
|
|
def _compute_proposed_contracts_count(self):
|
|
versions_data = self.env['hr.version']._read_group(
|
|
domain=[
|
|
('applicant_id', 'in', self.ids),
|
|
('active', '=', True),
|
|
],
|
|
groupby=['applicant_id'],
|
|
aggregates=['__count'])
|
|
mapped_data = {applicant.id: count for applicant, count in versions_data}
|
|
for applicant in self:
|
|
applicant.proposed_contracts_count = mapped_data.get(applicant.id, 0)
|
|
|
|
def _compute_salary_offers_count(self):
|
|
offers_data = self.env['hr.contract.salary.offer']._read_group(
|
|
domain=[('applicant_id', 'in', self.ids)],
|
|
groupby=['applicant_id'],
|
|
aggregates=['__count'])
|
|
mapped_data = {applicant.id: count for applicant, count in offers_data}
|
|
for applicant in self:
|
|
applicant.salary_offers_count = mapped_data.get(applicant.id, 0)
|
|
|
|
def _move_to_hired_stage(self):
|
|
self.ensure_one()
|
|
first_hired_stage = self.env['hr.recruitment.stage'].search([
|
|
'|',
|
|
('job_ids', '=', False),
|
|
('job_ids', '=', self.job_id.id),
|
|
('hired_stage', '=', True)])
|
|
|
|
if first_hired_stage:
|
|
self.stage_id = first_hired_stage[0].id
|
|
|
|
def action_show_proposed_contracts(self):
|
|
self._check_interviewer_access()
|
|
action_vals = {
|
|
"type": "ir.actions.act_window",
|
|
"res_model": "hr.version",
|
|
"domain": [["applicant_id", "=", self.id], '|', ["active", "=", False], ["active", "=", True]],
|
|
"name": _("Proposed Contracts"),
|
|
"context": {'default_employee_id': self.employee_id.id, 'default_applicant_id': self.id},
|
|
}
|
|
if self.proposed_contracts_count == 1:
|
|
action_vals.update({
|
|
"views": [[False, "form"]],
|
|
"res_id": self.env['hr.version'].search([("applicant_id", "=", self.id)]).id,
|
|
})
|
|
else:
|
|
action_vals.update({
|
|
"views": [[False, "list"], [False, "form"]],
|
|
})
|
|
return action_vals
|
|
|
|
def action_show_offers(self):
|
|
self.ensure_one()
|
|
action = self.env['ir.actions.act_window']._for_xml_id('hr_contract_salary.hr_contract_salary_offer_action')
|
|
action['domain'] = [('applicant_id', '=', self.id)]
|
|
action['context'] = {'default_applicant_id': self.id}
|
|
if self.salary_offers_count == 1:
|
|
action.update({
|
|
"views": [[False, "form"]],
|
|
"res_id": self.salary_offer_ids.id,
|
|
})
|
|
return action
|
|
|
|
def archive_applicant(self):
|
|
message = _("The offer has been marked as refused when the linked applicant was declined.")
|
|
refuse_reason = self.env.ref("hr_contract_salary.refusal_reason_others", raise_if_not_found=False)
|
|
|
|
self.salary_offer_ids.sudo().filtered(lambda o: o.state != "refused").action_refuse_offer(message=message, refusal_reason=refuse_reason)
|
|
return super().archive_applicant()
|
|
|
|
def action_generate_offer(self):
|
|
if not self.partner_name:
|
|
raise UserError(_('Offer link can not be sent without an applicant name.'))
|
|
|
|
offer_validity_period = int(self.env['ir.config_parameter'].sudo().get_param(
|
|
'hr_contract_salary.access_token_validity', default=30))
|
|
offer_values = self._get_offer_values()
|
|
|
|
offer_values['validity_days_count'] = offer_validity_period
|
|
offer = self.env['hr.contract.salary.offer'].with_context(
|
|
default_contract_template_id=self._get_contract_template().id).create(offer_values)
|
|
|
|
self.message_post(
|
|
body=_("An %(offer)s for the applicant %(applicant_name)s has been created by %(user)s.",
|
|
offer=Markup("<a href='#' data-oe-model='hr.contract.salary.offer' data-oe-id='{offer_id}'>Offer</a>")
|
|
.format(offer_id=offer.id),
|
|
applicant_name=self.partner_name,
|
|
user=self.env.user.name
|
|
)
|
|
)
|
|
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'view_mode': 'form',
|
|
'res_model': 'hr.contract.salary.offer',
|
|
'res_id': offer.id,
|
|
'views': [(False, 'form')],
|
|
'context': {'active_model': 'hr.applicant', 'default_applicant_id': self.id}
|
|
}
|
|
|
|
def _get_offer_values(self):
|
|
self.ensure_one()
|
|
contract_template = self._get_contract_template()
|
|
return {
|
|
'company_id': contract_template.company_id.id or self.company_id.id or self.env.company.id,
|
|
'contract_template_id': contract_template.id,
|
|
'applicant_id': self.id,
|
|
'final_yearly_costs': contract_template.sudo().final_yearly_costs,
|
|
'job_title': self.job_id.name,
|
|
'employee_job_id': self.job_id.id,
|
|
'department_id': self.department_id.id,
|
|
}
|
|
|
|
def _get_contract_template(self):
|
|
contract_template = self.job_id.contract_template_id if self.job_id else False
|
|
if not contract_template:
|
|
contract_template = self.env['hr.version'].search(domain=[
|
|
('company_id', '=', self.company_id.id), ('employee_id', '=', False)
|
|
],
|
|
limit=1)
|
|
return contract_template
|
|
|
|
def unlink_archived_versions(self):
|
|
# TODO: depereceated method remove me in master
|
|
archived_versions = self.env['hr.version'].search([
|
|
('applicant_id', 'in', self.ids),
|
|
('active', '=', False)
|
|
])
|
|
if archived_versions:
|
|
archived_versions.sign_request_ids.write({'state': 'canceled', 'active': False})
|
|
archived_versions.unlink()
|