Tower: upload at_accounting 18.0.1.7 (via marketplace)

This commit is contained in:
2026-04-28 07:34:08 +00:00
parent 776bcc1f7f
commit 60687c611a

View File

@@ -0,0 +1,310 @@
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools.misc import get_lang
class AccountReportSend(models.TransientModel):
_name = 'account.report.send'
_description = "Account Report Send"
partner_ids = fields.Many2many(
comodel_name='res.partner',
compute='_compute_partner_ids',
)
mode = fields.Selection(
selection=[
('single', "Single Recipient"),
('multi', "Multiple Recipients"),
],
compute='_compute_mode',
readonly=False,
store=True,
)
# == PRINT ==
enable_download = fields.Boolean()
checkbox_download = fields.Boolean(string="Download")
# == MAIL ==
enable_send_mail = fields.Boolean(default=True)
checkbox_send_mail = fields.Boolean(string="Email", default=True)
display_mail_composer = fields.Boolean(compute='_compute_send_mail_extra_fields')
warnings = fields.Json(compute='_compute_warnings')
send_mail_readonly = fields.Boolean(compute='_compute_send_mail_extra_fields')
mail_template_id = fields.Many2one(
comodel_name='mail.template',
string="Email template",
domain="[('model', '=', 'res.partner')]",
)
account_report_id = fields.Many2one(
comodel_name='account.report',
string="Report",
)
report_options = fields.Json()
mail_lang = fields.Char(
string="Lang",
compute='_compute_mail_lang',
)
mail_partner_ids = fields.Many2many(
comodel_name='res.partner',
string="Recipients",
compute='_compute_mail_partner_ids',
store=True,
readonly=False,
)
mail_subject = fields.Char(
string="Subject",
compute='_compute_mail_subject_body',
store=True,
readonly=False,
)
mail_body = fields.Html(
string="Contents",
sanitize_style=True,
compute='_compute_mail_subject_body',
store=True,
readonly=False,
)
mail_attachments_widget = fields.Json(
compute='_compute_mail_attachments_widget',
store=True,
readonly=False,
)
@api.model
def default_get(self, fields_list):
# EXTENDS 'base'
results = super().default_get(fields_list)
context_options = self._context.get('default_report_options', {})
if 'account_report_id' in fields_list and 'account_report_id' not in results:
report_id = context_options.get('report_id', False)
results['account_report_id'] = report_id
results['report_options'] = context_options
return results
@api.model
def _get_mail_field_value(self, partner, mail_template, mail_lang, field, **kwargs):
if not mail_template:
return
return mail_template\
.with_context(lang=mail_lang)\
._render_field(field, partner.ids, **kwargs)[partner._origin.id]
def _get_default_mail_attachments_widget(self, partner, mail_template):
return self._get_placeholder_mail_attachments_data(partner) \
+ self._get_mail_template_attachments_data(mail_template)
def _get_wizard_values(self):
self.ensure_one()
options = self.report_options
if not options.get('partner_ids', []):
options['partner_ids'] = self.partner_ids.ids
return {
'mail_template_id': self.mail_template_id.id,
'checkbox_download': self.checkbox_download,
'checkbox_send_mail': self.checkbox_send_mail,
'report_options': options,
}
def _get_placeholder_mail_attachments_data(self, partner):
""" Returns all the placeholder data.
Should be extended to add placeholder based on the checkboxes.
:param: partner: The partner for which this report is generated.
:returns: A list of dictionary for each placeholder.
* id: str: The (fake) id of the attachment, this is needed in rendering in t-key.
* name: str: The name of the attachment.
* mimetype: str: The mimetype of the attachment.
* placeholder bool: Should be true to prevent download / deletion.
"""
self.ensure_one()
filename = f"{partner.name} - {self.account_report_id.get_default_report_filename(self.report_options, 'pdf')}"
return [{
'id': f'placeholder_{filename}',
'name': filename,
'mimetype': 'application/pdf',
'placeholder': True,
}]
@api.model
def _get_mail_template_attachments_data(self, mail_template):
""" Returns all the placeholder data and mail template data
"""
return [
{
'id': attachment.id,
'name': attachment.name,
'mimetype': attachment.mimetype,
'placeholder': False,
'mail_template_id': mail_template.id,
}
for attachment in mail_template.attachment_ids
]
# -------------------------------------------------------------------------
# COMPUTE METHODS
# -------------------------------------------------------------------------
@api.depends('partner_ids')
def _compute_mode(self):
for wizard in self:
wizard.mode = 'single' if len(wizard.partner_ids) == 1 else 'multi'
@api.depends('checkbox_send_mail')
def _compute_send_mail_extra_fields(self):
for wizard in self:
wizard.display_mail_composer = wizard.mode == 'single'
partners_without_mail_data = wizard.mail_partner_ids.filtered(lambda x: not x.email)
wizard.send_mail_readonly = partners_without_mail_data == wizard.mail_partner_ids
@api.depends('mail_partner_ids', 'checkbox_send_mail', 'send_mail_readonly')
def _compute_warnings(self):
for wizard in self:
warnings = {}
partners_without_mail = wizard.mail_partner_ids.filtered(lambda x: not x.email)
if wizard.send_mail_readonly or (wizard.checkbox_send_mail and partners_without_mail):
warnings['account_missing_email'] = {
'message': _("Partner(s) should have an email address."),
'action_text': _("View Partner(s)"),
'action': partners_without_mail._get_records_action(name=_("Check Partner(s) Email(s)"))
}
wizard.warnings = warnings
@api.depends('partner_ids')
def _compute_mail_lang(self):
for wizard in self:
if wizard.mode == 'single':
wizard.mail_lang = wizard.partner_ids.lang
else:
wizard.mail_lang = get_lang(self.env).code
@api.depends('account_report_id', 'report_options')
def _compute_partner_ids(self):
for wizard in self:
wizard.partner_ids = wizard.account_report_id._get_report_send_recipients(wizard.report_options)
@api.depends('account_report_id', 'report_options')
def _compute_mail_partner_ids(self):
for wizard in self:
wizard.mail_partner_ids = wizard.partner_ids
@api.depends('mail_template_id', 'mail_lang', 'mode')
def _compute_mail_subject_body(self):
for wizard in self:
if wizard.mode == 'single' and wizard.mail_template_id:
wizard.mail_subject = self._get_mail_field_value(wizard.mail_partner_ids, wizard.mail_template_id, wizard.mail_lang, 'subject')
wizard.mail_body = self._get_mail_field_value(wizard.mail_partner_ids, wizard.mail_template_id, wizard.mail_lang, 'body_html', options={'post_process': True})
else:
wizard.mail_subject = wizard.mail_body = None
@api.depends('mail_template_id', 'mode')
def _compute_mail_attachments_widget(self):
for wizard in self:
if wizard.mode == 'single':
wizard.mail_attachments_widget = wizard._get_default_mail_attachments_widget(wizard.mail_partner_ids, wizard.mail_template_id)
else:
wizard.mail_attachments_widget = []
@api.model
def _action_download(self, attachments):
""" Download the PDF attachment, or a zip of attachments if there are more than one. """
return {
'type': 'ir.actions.act_url',
'url': f'/account_reports/download_attachments/{",".join(map(str, attachments.ids))}',
'close': True,
}
def _process_send_and_print(self, report, options, recipient_partner_ids=None, wizard=None):
""" Generate a report for one partner based on the options (send_and_print_values stored on the report).
:param options: dict of report options (should contain one partner id in options['partner_ids'])
:param recipient_partner_ids: list of partner ids that will receive the mail message.
:param wizard: account.report.send wizard if exists. Indicates if sending by cron.
"""
wizard_vals = report.send_and_print_values if not wizard else wizard._get_wizard_values()
to_email = wizard_vals['checkbox_send_mail']
to_download = wizard_vals['checkbox_download']
mail_template_id = self.env['mail.template'].browse(wizard_vals['mail_template_id'])
if wizard:
attachments_ids = [att['id'] for att in wizard.mail_attachments_widget or [] if not att['placeholder']]
else:
attachments_ids = mail_template_id.attachment_ids.ids
options['unfold_all'] = True
partner_ids = options.get('partner_ids', [])
partners = self.env['res.partner'].browse(partner_ids)
if not recipient_partner_ids:
recipient_partner_ids = partners.filtered('email').ids
downloadable_attachments = self.env['ir.attachment']
for partner in partners:
options['partner_ids'] = partner.ids
report_attachment = partner._get_partner_account_report_attachment(report, options)
if to_email and recipient_partner_ids:
if wizard and wizard.mode == 'single':
subject = self.mail_subject
body = self.mail_body
else:
subject = self._get_mail_field_value(partner, mail_template_id, partner.lang, 'subject')
body = self._get_mail_field_value(partner, mail_template_id, partner.lang, 'body_html', options={'post_process': True})
partner.message_post(
body=body,
subject=subject,
partner_ids=recipient_partner_ids,
attachment_ids=attachments_ids + report_attachment.ids,
)
if to_download:
downloadable_attachments += report_attachment
if downloadable_attachments:
return self._action_download(downloadable_attachments)
def action_send_and_print(self, force_synchronous=False):
""" Create the documents and send them to the end customers.
If we are sending multiple statements and not downloading them we will process the moves asynchronously.
:param force_synchronous: Flag indicating if the method should be done synchronously.
"""
self.ensure_one()
if self.mode == 'multi' and self.checkbox_send_mail and not self.mail_template_id:
raise UserError(_('Please select a mail template to send multiple statements.'))
force_synchronous = force_synchronous or self.checkbox_download
process_later = self.mode == 'multi' and not force_synchronous
if process_later:
# Set sending information on report
if self.account_report_id.send_and_print_values:
raise UserError(_('There are currently reports waiting to be sent, please try again later.'))
self.account_report_id.send_and_print_values = self._get_wizard_values()
self.env.ref('at_accounting.ir_cron_account_report_send')._trigger()
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'type': 'info',
'title': _('Sending statements'),
'message': _('Statements are being sent in the background.'),
'next': {'type': 'ir.actions.act_window_close'},
},
}
options = {
**self.report_options,
'partner_ids': self.partner_ids.ids,
}
return self._process_send_and_print(
report=self.account_report_id,
options=options,
recipient_partner_ids=self.mail_partner_ids.ids,
wizard=self,
)