219 lines
11 KiB
Python
219 lines
11 KiB
Python
from odoo import api, fields, models, Command
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class EsgMetricAskFeedback(models.TransientModel):
|
|
_name = 'esg.metric.ask.feedback'
|
|
_inherit = ['mail.composer.mixin']
|
|
_description = "Stakeholder Reviews for CSRD Metrics"
|
|
|
|
metric_ids = fields.One2many('esg.metric', compute='_compute_metric_ids', required=True)
|
|
template_id = fields.Many2one(default=lambda self: self.env.ref('esg_csrd.mail_template_esg_metric_ask_feedback', raise_if_not_found=False),
|
|
domain=lambda self: [('model_id', '=', self.env['ir.model']._get('esg.metric').id)])
|
|
author_id = fields.Many2one(
|
|
'res.partner', string='Author', required=True,
|
|
default=lambda self: self.env.user.partner_id.id,
|
|
)
|
|
survey_template_id = fields.Many2one('survey.survey')
|
|
partner_ids = fields.Many2many('res.partner', string="Stakeholders", required=True)
|
|
deadline = fields.Date(string="Answer Deadline", required=True)
|
|
|
|
@api.depends_context('default_metric_ids')
|
|
def _compute_metric_ids(self):
|
|
metric_ids = self.env.context.get('default_metric_ids', [])
|
|
self.metric_ids = self.env['esg.metric'].browse(metric_ids)
|
|
|
|
# Overrides of mail.composer.mixin
|
|
@api.depends('survey_template_id') # fake trigger otherwise not computed in new mode
|
|
def _compute_render_model(self):
|
|
self.render_model = 'survey.user_input'
|
|
|
|
@api.depends('metric_ids')
|
|
def _compute_subject(self):
|
|
for wizard in self.filtered(lambda w: w.metric_ids and w.template_id):
|
|
wizard.subject = self.env._(
|
|
'Invitation to Participate in CSRD Double Materiality Stakeholder Review for %(company_name)s Company',
|
|
company_name=self.env.company.name,
|
|
)
|
|
|
|
@api.depends('template_id', 'partner_ids')
|
|
def _compute_body(self):
|
|
for wizard in self:
|
|
langs = set(wizard.partner_ids.mapped('lang')) - {False}
|
|
if len(langs) == 1:
|
|
wizard = wizard.with_context(lang=langs.pop())
|
|
super(EsgMetricAskFeedback, wizard)._compute_body()
|
|
|
|
@api.onchange('partner_ids')
|
|
def _onchange_partner_ids(self):
|
|
emailless_partners = self.partner_ids.filtered(lambda p: not p.email)
|
|
if emailless_partners:
|
|
warning = {
|
|
'title': self.env._('Missing email'),
|
|
'message': self.env._('The following partners do not have any email: \n%s',
|
|
', '.join(emailless_partners.mapped('name'))),
|
|
'type': 'notification',
|
|
}
|
|
self.partner_ids = self.partner_ids - emailless_partners
|
|
return {'warning': warning}
|
|
|
|
def _prepare_survey_anwers(self, partners):
|
|
answers = self.env['survey.user_input']
|
|
partners_info = partners.mapped(lambda partner: {
|
|
'id': partner.id,
|
|
'email': partner.email,
|
|
'partner_id': partner,
|
|
})
|
|
emails = [p['email'] for p in partners_info]
|
|
partner_ids = [p['id'] for p in partners_info]
|
|
|
|
if not self.survey_template_id:
|
|
survey_template_id = self.env.ref('esg_csrd.esg_metric_review_template', raise_if_not_found=False)
|
|
if not survey_template_id:
|
|
raise UserError(self.env._('No Metric Review Survey Template found.'))
|
|
self.survey_template_id = survey_template_id.copy()
|
|
self.survey_template_id.title = "Stakeholder Review for CSRD Report"
|
|
self.survey_template_id.user_id = self.env.user.id
|
|
questions_create_vals = []
|
|
metric_to_question_create_vals = []
|
|
iro_type_labels = dict(self.env['esg.metric']._fields['type']._description_selection(self.env))
|
|
sequence = 1
|
|
for metric_type, metrics in self.metric_ids.sorted('esrs_id').grouped('type').items():
|
|
for metric in metrics:
|
|
questions_create_vals.append({
|
|
'survey_id': self.survey_template_id.id,
|
|
'title': f'{iro_type_labels[metric_type]}: {metric.name}',
|
|
'is_page': True,
|
|
'sequence': sequence,
|
|
})
|
|
sequence += 1
|
|
question_vals = {
|
|
'survey_id': self.survey_template_id.id,
|
|
'question_type': 'simple_choice',
|
|
'constr_mandatory': True,
|
|
'suggested_answer_ids': [
|
|
Command.create({'value': 'Negligible', 'sequence': 1, 'answer_score': 1.0}),
|
|
Command.create({'value': 'Low', 'sequence': 2, 'answer_score': 2.0}),
|
|
Command.create({'value': 'Moderate', 'sequence': 3, 'answer_score': 3.0}),
|
|
Command.create({'value': 'High', 'sequence': 4, 'answer_score': 4.0}),
|
|
Command.create({'value': 'Critical', 'sequence': 5, 'answer_score': 5.0}),
|
|
],
|
|
}
|
|
question = self.env['survey.question'].sudo().create({
|
|
**question_vals,
|
|
'title': f'How critical is the {iro_type_labels[metric_type]} of {metric.name} on people and environment impacted by your activities?',
|
|
'sequence': sequence,
|
|
})
|
|
metric_to_question_create_vals.append({
|
|
'metric_id': metric.id,
|
|
'question_id': question.id,
|
|
'metric_score_type': 'impact',
|
|
})
|
|
sequence += 1
|
|
title_part = ''
|
|
if metric_type == 'opportunity':
|
|
title_part = 'developing this opportunity'
|
|
elif metric_type == 'risk':
|
|
title_part = 'facing that risk'
|
|
else:
|
|
title_part = 'being exposed to this impact'
|
|
question = self.env['survey.question'].sudo().create({
|
|
**question_vals,
|
|
'title': f'What would be the financial impact on your company of {title_part}?',
|
|
'sequence': sequence,
|
|
})
|
|
metric_to_question_create_vals.append({
|
|
'metric_id': metric.id,
|
|
'question_id': question.id,
|
|
'metric_score_type': 'financial',
|
|
})
|
|
sequence += 1
|
|
questions_create_vals.append({
|
|
'survey_id': self.survey_template_id.id,
|
|
'title': 'Comments (optional)',
|
|
'question_type': 'text_box',
|
|
'question_placeholder': 'Explain your rating or provide context',
|
|
'sequence': sequence,
|
|
})
|
|
sequence += 1
|
|
self.env['survey.question'].sudo().create(questions_create_vals)
|
|
self.env['esg.metric.to.survey.question'].create(metric_to_question_create_vals)
|
|
|
|
existing_metric_to_questions = self.env['esg.metric.to.survey.question'].search([
|
|
('metric_id', 'in', self.metric_ids.ids),
|
|
])
|
|
existing_answers = self.env['survey.user_input'].search([
|
|
('user_input_line_ids.question_id', 'in', existing_metric_to_questions.question_id.ids),
|
|
'|',
|
|
'&', ('partner_id', 'in', partner_ids), ('partner_id', '!=', False),
|
|
'&', ('email', 'in', emails), ('email', '!=', False),
|
|
])
|
|
partners_done = []
|
|
if existing_answers:
|
|
existing_answer_emails = existing_answers.filtered('email').mapped('email')
|
|
existing_answer_partners_id = existing_answers.filtered('partner_id').mapped('partner_id')
|
|
for partner_data in partners_info:
|
|
if partner_data.get('email') in existing_answer_emails or partner_data.get('partner_id') in existing_answer_partners_id:
|
|
partners_done.append(partner_data)
|
|
existing_answers = existing_answers.sorted(lambda answer: answer.create_date, reverse=True)
|
|
for partner_done in partners_done:
|
|
answers |= existing_answers\
|
|
.filtered(lambda a:
|
|
(a.partner_id and a.partner_id == partner_done.get('partner_id'))
|
|
or (a.email and a.email == partner_done.get('email'))
|
|
)[:1]
|
|
|
|
partners_done_ids = [p['id'] for p in partners_done]
|
|
for new_partner in partners_info:
|
|
if new_partner['id'] in partners_done_ids:
|
|
continue
|
|
answers |= self.survey_template_id.sudo()._create_answer(
|
|
partner=new_partner['partner_id'], email=new_partner['email'], check_attempts=False, deadline=self.deadline)
|
|
return answers
|
|
|
|
def _send_mail(self, answer):
|
|
""" Create mail specific for recipient containing notably its access token """
|
|
ctx = {
|
|
'logged_user': self.env.user.name,
|
|
'company_name': self.env.company.name,
|
|
'deadline': self.deadline,
|
|
}
|
|
body = self.with_context(**ctx)._render_field('body', answer.ids)[answer.id]
|
|
mail_values = {
|
|
'email_from': self.author_id.email_formatted,
|
|
'author_id': self.author_id.id,
|
|
'model': None,
|
|
'res_id': None,
|
|
'subject': self.subject,
|
|
'body_html': body,
|
|
'auto_delete': True,
|
|
}
|
|
if answer.partner_id:
|
|
mail_values['recipient_ids'] = [Command.link(answer.partner_id.id)]
|
|
else:
|
|
mail_values['email_to'] = answer.email
|
|
|
|
mail_values['body_html'] = self.env['mail.render.mixin']._render_encapsulate(
|
|
'mail.mail_notification_light', mail_values['body_html'],
|
|
context_record=self.survey_template_id,
|
|
)
|
|
return self.env['mail.mail'].sudo().create(mail_values)
|
|
|
|
def action_send(self):
|
|
self.ensure_one()
|
|
|
|
if fields.Date.today() > self.deadline:
|
|
raise UserError(self.env._("Please set an Answer Deadline in the future"))
|
|
|
|
answers = self._prepare_survey_anwers(self.partner_ids)
|
|
answers.sudo().write({'deadline': self.deadline})
|
|
for answer in answers:
|
|
self._send_mail(answer)
|
|
|
|
for metric in self.metric_ids:
|
|
metric.survey_ids |= self.survey_template_id
|
|
metric.message_post(body=self.env._(
|
|
"A new Stakeholder Review was requested for %s", ', '.join(self.partner_ids.mapped('name'))
|
|
))
|
|
return {'type': 'ir.actions.act_window_close'}
|