134 lines
6.4 KiB
Python
134 lines
6.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, models, fields, _
|
|
from odoo.exceptions import UserError
|
|
from odoo.models import check_method_name
|
|
|
|
import json
|
|
import base64
|
|
import types
|
|
from urllib.parse import urlparse, parse_qs
|
|
|
|
|
|
class ReportExportWizard(models.TransientModel):
|
|
""" Wizard allowing to export an accounting report in several different formats
|
|
at once, saving them as attachments.
|
|
"""
|
|
_name = 'account_reports.export.wizard'
|
|
_description = "Export wizard for accounting's reports"
|
|
|
|
export_format_ids = fields.Many2many(string="Export to", comodel_name='account_reports.export.wizard.format', relation="dms_acc_rep_export_wizard_format_rel")
|
|
report_id = fields.Many2one(string="Parent Report Id", comodel_name='account.report', required=True)
|
|
doc_name = fields.Char(string="Documents Name", help="Name to give to the generated documents.")
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
wizards = super().create(vals_list)
|
|
for wizard in wizards:
|
|
wizard.doc_name = wizard.report_id.name
|
|
|
|
# We create one export format object per available export type of the report,
|
|
# with the right generation function associated to it.
|
|
# This is done so to allow selecting them as Many2many tags in the wizard.
|
|
for button_dict in self._context.get('account_report_generation_options', {}).get('buttons', []):
|
|
if button_dict.get('file_export_type'):
|
|
self.env['account_reports.export.wizard.format'].create({
|
|
'name': button_dict['file_export_type'],
|
|
'fun_to_call': button_dict['action'],
|
|
'fun_param': button_dict.get('action_param'),
|
|
'export_wizard_id': wizard.id,
|
|
})
|
|
return wizards
|
|
|
|
def export_report(self):
|
|
self.ensure_one()
|
|
created_attachments = self.env['ir.attachment']
|
|
for vals in self._get_attachments_to_save():
|
|
created_attachments |= self.env['ir.attachment'].create(vals)
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Generated Documents'),
|
|
'view_mode': 'kanban,form',
|
|
'res_model': 'ir.attachment',
|
|
'domain': [('id', 'in', created_attachments.ids)],
|
|
}
|
|
|
|
def _get_attachments_to_save(self):
|
|
self.ensure_one()
|
|
to_create_attachments = []
|
|
report_options = self.env.context['account_report_generation_options']
|
|
for format in self.export_format_ids:
|
|
# format.fun_to_call is a button function, so it has to be public
|
|
fun_name = format.fun_to_call
|
|
check_method_name(fun_name)
|
|
if self.report_id.custom_handler_model_id and hasattr(self.env[self.report_id.custom_handler_model_name], fun_name):
|
|
report_function = getattr(self.env[self.report_id.custom_handler_model_name], fun_name)
|
|
else:
|
|
report_function = getattr(self.report_id, fun_name)
|
|
report_function_params = [format.fun_param] if format.fun_param else []
|
|
report_action = report_function(report_options, *report_function_params)
|
|
|
|
to_create_attachments.append(format.apply_export(report_action))
|
|
|
|
return to_create_attachments
|
|
|
|
|
|
class ReportExportWizardOption(models.TransientModel):
|
|
_name = 'account_reports.export.wizard.format'
|
|
_description = "Export format for accounting's reports"
|
|
|
|
name = fields.Char(string="Name", required=True)
|
|
fun_to_call = fields.Char(string="Function to Call", required=True)
|
|
fun_param = fields.Char(string="Function Parameter")
|
|
export_wizard_id = fields.Many2one(string="Parent Wizard", comodel_name='account_reports.export.wizard', required=True, ondelete='cascade')
|
|
|
|
def apply_export(self, report_action):
|
|
self.ensure_one()
|
|
|
|
if report_action['type'] == 'ir_actions_account_report_download':
|
|
report_options = json.loads(report_action['data']['options'])
|
|
|
|
# file_generator functions are always public for ir_actions_account_report_download
|
|
file_generator = report_action['data']['file_generator']
|
|
check_method_name(file_generator)
|
|
report = self.export_wizard_id.report_id
|
|
if report.custom_handler_model_id and hasattr(self.env[report.custom_handler_model_name], file_generator):
|
|
generation_function = getattr(self.env[report.custom_handler_model_name], file_generator)
|
|
else:
|
|
generation_function = getattr(report, file_generator)
|
|
export_result = generation_function(report_options)
|
|
|
|
# We use the options from the action, as the action may have added or modified
|
|
# stuff into them (see l10n_es_reports, with BOE wizard)
|
|
file_content = base64.encodebytes(export_result['file_content']) if isinstance(export_result['file_content'], bytes) else export_result['file_content']
|
|
# We need to unpack the content in case of a generator
|
|
if isinstance(file_content, types.GeneratorType):
|
|
file_content = base64.encodebytes(b''.join(file_content))
|
|
file_name = f"{self.export_wizard_id.doc_name or self.export_wizard_id.report_id.name}.{export_result['file_type']}"
|
|
mimetype = self.export_wizard_id.report_id.get_export_mime_type(export_result['file_type'])
|
|
|
|
elif report_action['type'] == 'ir.actions.act_url':
|
|
query_params = parse_qs(urlparse(report_action['url']).query)
|
|
model = query_params['model'][0]
|
|
model_id = int(query_params['id'][0])
|
|
wizard = self.env[model].browse(model_id)
|
|
file_name = wizard[query_params['filename_field'][0]]
|
|
file_content = wizard[query_params['field'][0]]
|
|
mimetype = self.env['account.report'].get_export_mime_type(file_name.split('.')[-1])
|
|
|
|
else:
|
|
raise UserError(_("One of the formats chosen can not be exported in the DMS"))
|
|
|
|
return self.get_attachment_vals(file_name, file_content, mimetype, report_options)
|
|
|
|
def get_attachment_vals(self, file_name, file_content, mimetype, log_options_dict):
|
|
self.ensure_one()
|
|
return {
|
|
'name': file_name,
|
|
'company_id': self.env.company.id,
|
|
'datas': file_content,
|
|
'mimetype': mimetype,
|
|
'description': json.dumps(log_options_dict)
|
|
}
|