Files
enterprise-addons/hr_sign/wizard/hr_contract_sign_document_wizard.py
T

221 lines
11 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from markupsafe import Markup
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _, Command
class HrContractSignDocumentWizard(models.TransientModel):
_name = 'hr.contract.sign.document.wizard'
_description = 'Sign document in contract'
def _group_hr_contract_domain(self):
group = self.env.ref('hr.group_hr_manager', raise_if_not_found=False)
return [('all_group_ids', 'in', group.ids)] if group else []
def _get_sign_template_ids(self):
list_template = self.env['sign.template']
for template in self.env['sign.template'].search([]):
distinct_responsible_count = len(template.sign_item_ids.mapped('responsible_id'))
if distinct_responsible_count == 2 or distinct_responsible_count == 1:
list_template |= template
return list_template
def _default_get_template_warning(self):
return not bool(self._get_sign_template_ids()) and _('No documents templates on the database.')
@api.model
def default_get(self, fields):
defaults = super().default_get(fields)
if 'responsible_id' in fields and not defaults.get('responsible_id') and defaults.get('version_id'):
contract = self.env['hr.version'].browse(defaults.get('version_id'))
defaults['responsible_id'] = contract.hr_responsible_id
else:
defaults['responsible_id'] = self.env.user
active_model = self.env.context.get('active_model', '')
if active_model == 'hr.version':
defaults['version_id'] = self.env.context.get('active_id')
elif active_model == 'hr.employee':
defaults['employee_ids'] = [Command.set(self.env.context.get('active_ids'))]
return defaults
version_id = fields.Many2one(
'hr.version', string='Contract',
compute='_compute_contract_id', store=True, readonly=False)
employee_ids = fields.Many2many(
'hr.employee', string='Employees',
compute='_compute_employee_ids', store=True, readonly=False)
responsible_id = fields.Many2one('res.users', string='Responsible', domain=_group_hr_contract_domain)
employee_role_id = fields.Many2one(
"sign.item.role", string="Employee Role",
required=True, domain="[('id', 'in', sign_template_responsible_ids)]",
compute='_compute_employee_role_id', store=True, readonly=False,
help="Employee's role on the templates to sign. The same role must be present in all the templates")
sign_template_responsible_ids = fields.Many2many(
'sign.item.role', compute='_compute_responsible_ids')
possible_template_ids = fields.Many2many('sign.template', compute='_compute_possible_template_ids')
sign_template_ids = fields.Many2many(
'sign.template', string='Documents to sign',
domain="[('id', 'in', possible_template_ids)]", help="""Select only documents with either 1 or 2 different signatories.
Documents with 1 signatory require only the employee's signature, while those with 2 signatories require signatures from both the employee and the HR responsible.
""", required=True)
has_both_template = fields.Boolean(compute='_compute_has_both_template')
template_warning = fields.Char(default=_default_get_template_warning, store=False)
subject = fields.Char(string="Subject", required=True, default='Signature Request')
message = fields.Html("Message")
cc_partner_ids = fields.Many2many('res.partner', string="Copy to")
attachment_ids = fields.Many2many('ir.attachment', bypass_search_access=True)
mail_to = fields.Selection([
('work', 'Work'),
('private', 'Private'),
], string='Email', help="""Email used to send the signature request.
- Work takes the email defined in "work email"
- Private takes the email defined in Private Information
- If the selected email is not defined, the available one will be used.""", default='work')
mail_displayed = fields.Char(compute='_compute_mail_displayed')
@api.depends('sign_template_responsible_ids')
def _compute_employee_role_id(self):
for wizard in self:
if wizard.employee_role_id not in wizard.sign_template_responsible_ids:
wizard.employee_role_id = False
if len(wizard.sign_template_responsible_ids) == 1:
wizard.employee_role_id = wizard.sign_template_responsible_ids._origin
@api.depends('sign_template_ids.sign_item_ids.responsible_id')
def _compute_responsible_ids(self):
for r in self:
responsible_ids = self.env['sign.item.role']
for sign_template_id in r.sign_template_ids:
if responsible_ids:
responsible_ids &= sign_template_id.sign_item_ids.responsible_id
else:
responsible_ids |= sign_template_id.sign_item_ids.responsible_id
r.sign_template_responsible_ids = responsible_ids
@api.depends('sign_template_ids')
def _compute_possible_template_ids(self):
possible_sign_templates = self._get_sign_template_ids()
for wizard in self:
if not wizard.sign_template_ids:
wizard.possible_template_ids = possible_sign_templates
else:
roles = wizard.sign_template_ids.sign_item_ids.responsible_id
wizard.possible_template_ids = possible_sign_templates.filtered(lambda t: t.sign_item_ids.responsible_id & roles)
@api.depends('version_id')
def _compute_employee_ids(self):
for wizard in self:
if wizard.version_id:
wizard.employee_ids |= wizard.version_id.employee_id
@api.depends('employee_ids')
def _compute_contract_id(self):
for wizard in self:
if wizard.version_id.employee_id not in wizard.employee_ids:
wizard.version_id = False
@api.depends('sign_template_ids')
def _compute_has_both_template(self):
for wizard in self:
wizard.has_both_template = bool(wizard.sign_template_ids.filtered(lambda t: len(t.sign_item_ids.mapped('responsible_id')) == 2))
@api.depends('employee_ids', 'mail_to')
def _compute_mail_displayed(self):
for wizard in self:
if len(wizard.employee_ids) == 1:
wizard.mail_displayed = wizard.employee_ids.private_email if self.mail_to == 'private' else wizard.employee_ids.work_email
else:
wizard.mail_displayed = False
def validate_signature(self):
self.ensure_one()
# Partner by employee
partner_by_employee = dict()
for employee in self.employee_ids:
email_choice = employee.private_email if self.mail_to == "private" else employee.work_email
if email_choice:
email_used = email_choice
else:
message_display = _("%s does not have a private email set.", employee.name) if self.mail_to == "private" else _("%s does not have a work email set.", employee.name)
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': message_display,
'sticky': False,
'type': 'danger',
}
}
partner_by_employee[employee] = employee._partner_find_from_emails_single([email_used])
sign_request = self.env['sign.request']
if not self.browse().has_access('create'):
sign_request = sign_request.sudo()
sign_values = []
sign_templates_employee_ids = self.sign_template_ids.filtered(lambda t: len(t.sign_item_ids.mapped('responsible_id')) == 1)
sign_templates_both_ids = self.sign_template_ids - sign_templates_employee_ids
for employee in self.employee_ids:
for sign_template_id in sign_templates_employee_ids:
sign_values.append((
sign_template_id, employee,
[{'role_id': self.employee_role_id.id,
'partner_id': partner_by_employee[employee].id}]
))
for sign_template_id in sign_templates_both_ids:
second_role = sign_template_id.sign_item_ids.responsible_id - self.employee_role_id
sign_values.append((
sign_template_id, employee,
[{'role_id': self.employee_role_id.id,
'partner_id': partner_by_employee[employee].id},
{'role_id': second_role.id,
'partner_id': self.responsible_id.partner_id.id}]
))
sign_requests = self.env['sign.request'].create([{
'template_id': sign_request_values[0].id,
'request_item_ids': [Command.create({
'partner_id': signer['partner_id'],
'role_id': signer['role_id'],
}) for signer in sign_request_values[2]],
'reference': sign_request_values[0].name,
'subject': self.subject,
'message': self.message,
'validity': fields.Date.today() + relativedelta(days=sign_request_values[0].signature_request_validity),
'attachment_ids': [(4, attachment.copy().id) for attachment in self.attachment_ids], # Attachments may not be bound to multiple sign requests
} for sign_request_values in sign_values])
sign_requests.message_subscribe(partner_ids=self.cc_partner_ids.ids)
if not self.browse().has_access('write'):
sign_requests = sign_requests.sudo()
for sign_request, sign_value in zip(sign_requests, sign_values):
sign_request.toggle_favorited()
employee = sign_value[1]
if self.version_id.employee_id == employee:
self.version_id.sign_request_ids += sign_request
else:
employee.sign_request_ids += sign_request
for employee in self.employee_ids:
if self.responsible_id and sign_templates_both_ids:
signatories_text = _('%(employee)s and %(responsible)s are the signatories.', employee=employee.display_name, responsible=self.responsible_id.display_name)
else:
signatories_text = _('Only %s has to sign.', employee.display_name)
employee.message_post(
body=(
_('%(user_name)s requested a new signature on the following documents:') + Markup('<br/><ul>%(documents)s</ul>%(signatories_text)s')
) % {
'user_name': self.env.user.display_name,
'documents': Markup('\n').join(Markup('<li>%s</li>') % name for name in self.sign_template_ids.mapped('name')),
'signatories_text': signatories_text
}
)
if len(sign_requests) == 1 and ((self.env.user.id in self.employee_ids.user_id.ids) or (self.env.user.id == self.responsible_id.id and sign_templates_both_ids)):
return sign_requests.go_to_document()
return True