mirror of
https://gitlab.com/flectra-community/l10n-switzerland-flectra.git
synced 2024-12-24 21:31:44 +00:00
173 lines
5.7 KiB
Python
173 lines
5.7 KiB
Python
|
# Copyright 2012-2017 Camptocamp SA
|
||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||
|
import os
|
||
|
import tempfile
|
||
|
import io
|
||
|
import logging
|
||
|
from contextlib import closing
|
||
|
|
||
|
from flectra import models, fields, api
|
||
|
|
||
|
|
||
|
_logger = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
try:
|
||
|
import PyPDF2
|
||
|
except (ImportError, IOError) as err:
|
||
|
_logger.debug(err)
|
||
|
|
||
|
|
||
|
class IrActionsReportReportlab(models.Model):
|
||
|
|
||
|
_inherit = 'ir.actions.report'
|
||
|
|
||
|
report_type = fields.Selection(selection_add=[('reportlab-pdf',
|
||
|
'Report renderer')],ondelete={'reportlab-pdf': 'cascade'})
|
||
|
|
||
|
#@api.multi
|
||
|
def _generate_one_slip_per_page_from_invoice_pdf(self, res_ids):
|
||
|
"""Generate payment slip PDF(s) from report model.
|
||
|
|
||
|
If there are many pdf they are merged in memory or on
|
||
|
file system based on company settings
|
||
|
|
||
|
:return: the generated PDF content
|
||
|
"""
|
||
|
user_model = self.env['res.users']
|
||
|
slip_model = self.env['l10n_ch.payment_slip']
|
||
|
invoice_model = self.env['account.move']
|
||
|
company = user_model.browse(self.env.uid).company_id
|
||
|
invoices = invoice_model.browse(res_ids)
|
||
|
|
||
|
docs = slip_model._compute_pay_slips_from_invoices(invoices)
|
||
|
|
||
|
pdfdocuments = []
|
||
|
temporary_files = []
|
||
|
|
||
|
for doc in docs:
|
||
|
pdfreport_fd, pdfreport_path = tempfile.mkstemp(
|
||
|
suffix='.pdf', prefix='report.tmp.')
|
||
|
temporary_files.append(pdfreport_path)
|
||
|
|
||
|
with closing(os.fdopen(pdfreport_fd, 'wb')) as pdfreport:
|
||
|
pdf = doc._draw_payment_slip(a4=True, b64=False,
|
||
|
out_format='PDF',
|
||
|
report_name=self.report_name)
|
||
|
pdfreport.write(pdf)
|
||
|
|
||
|
pdfdocuments.append(pdfreport_path)
|
||
|
|
||
|
# Return the entire document
|
||
|
if len(pdfdocuments) == 1:
|
||
|
entire_report_path = pdfdocuments[0]
|
||
|
else:
|
||
|
if company.merge_mode == 'in_memory':
|
||
|
content = self.merge_pdf_in_memory(pdfdocuments)
|
||
|
entire_report_path = False
|
||
|
else:
|
||
|
entire_report_path = self.merge_pdf_on_disk(pdfdocuments)
|
||
|
|
||
|
if entire_report_path:
|
||
|
with open(entire_report_path, 'rb') as pdfdocument:
|
||
|
content = pdfdocument.read()
|
||
|
if entire_report_path not in temporary_files:
|
||
|
temporary_files.append(entire_report_path)
|
||
|
|
||
|
# Manual cleanup of the temporary files
|
||
|
for temporary_file in temporary_files:
|
||
|
try:
|
||
|
os.unlink(temporary_file)
|
||
|
except (OSError, IOError):
|
||
|
_logger.error(
|
||
|
'Error when trying to remove file %s' % temporary_file)
|
||
|
|
||
|
return content
|
||
|
|
||
|
@api.model
|
||
|
def _get_report_from_name(self, report_name):
|
||
|
"""Return also report of report_type reportlab-pdf and not only qweb
|
||
|
"""
|
||
|
report = super()._get_report_from_name(report_name)
|
||
|
if not report:
|
||
|
report = self.search([
|
||
|
('report_type', '=', 'reportlab-pdf'),
|
||
|
('report_name', '=', report_name)],
|
||
|
limit=1
|
||
|
)
|
||
|
return report
|
||
|
|
||
|
#@api.multi
|
||
|
def render_reportlab_pdf(self, res_ids=None, data=None):
|
||
|
if (self.report_name != 'l10n_ch_payment_slip.'
|
||
|
'one_slip_per_page_from_invoice') or not res_ids:
|
||
|
return
|
||
|
|
||
|
save_in_attachment = {}
|
||
|
|
||
|
# Dispatch the records by ones having an attachment and ones
|
||
|
# requesting a call to reportlab. (copied from render_qweb_pdf)
|
||
|
Model = self.env[self.model]
|
||
|
records = Model.browse(res_ids)
|
||
|
rl_records = Model
|
||
|
if self.attachment:
|
||
|
for rec in records:
|
||
|
attachment_id = self.retrieve_attachment(rec)
|
||
|
if attachment_id:
|
||
|
save_in_attachment[rec.id] = attachment_id
|
||
|
if not self.attachment_use or not attachment_id:
|
||
|
rl_records += rec
|
||
|
else:
|
||
|
rl_records = records
|
||
|
res_ids = rl_records.ids
|
||
|
|
||
|
if save_in_attachment and not res_ids:
|
||
|
_logger.info('The PDF report has been generated from attachments.')
|
||
|
return self._post_pdf(save_in_attachment), 'pdf'
|
||
|
|
||
|
pdf_content = self._generate_one_slip_per_page_from_invoice_pdf(
|
||
|
res_ids)
|
||
|
if res_ids:
|
||
|
_logger.info(
|
||
|
'The PDF report has been generated for records %s.' % (
|
||
|
str(res_ids))
|
||
|
)
|
||
|
return self._post_pdf(save_in_attachment, pdf_content=pdf_content,
|
||
|
res_ids=res_ids), 'pdf'
|
||
|
return pdf_content, 'pdf'
|
||
|
|
||
|
# TODO consider https://github.com/OCA/reporting-engine/issues/241
|
||
|
|
||
|
def merge_pdf_in_memory(self, docs):
|
||
|
merger = PyPDF2.PdfFileMerger()
|
||
|
for doc in docs:
|
||
|
merger.append(doc)
|
||
|
buff = io.BytesIO()
|
||
|
try:
|
||
|
# The writer close the reader file here
|
||
|
merger.write(buff)
|
||
|
return buff.getvalue()
|
||
|
except IOError:
|
||
|
raise
|
||
|
finally:
|
||
|
buff.close()
|
||
|
|
||
|
def merge_pdf_on_disk(self, docs):
|
||
|
merger = PyPDF2.PdfFileMerger()
|
||
|
for doc in docs:
|
||
|
merger.append(doc)
|
||
|
buff, buff_path = tempfile.mkstemp(
|
||
|
suffix='.pdf',
|
||
|
prefix='credit_control_slip_merged')
|
||
|
try:
|
||
|
buff = os.fdopen(buff, 'w+b')
|
||
|
# The writer close the reader file here
|
||
|
buff.seek(0)
|
||
|
merger.write(buff)
|
||
|
buff.seek(0)
|
||
|
return buff_path
|
||
|
except IOError:
|
||
|
raise
|
||
|
finally:
|
||
|
buff.close()
|