OCA reporting engine fork for dev and update.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
4.7 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Yannick Vaucher
  5. # Copyright 2013 Camptocamp SA
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. import time
  22. import base64
  23. from PyPDF2 import PdfFileReader, PdfFileWriter
  24. from StringIO import StringIO
  25. from openerp.netsvc import ExportService
  26. from openerp.report import report_sxw
  27. from openerp import pooler
  28. _POLLING_DELAY = 0.25
  29. def assemble_pdf(pdf_list):
  30. """
  31. Assemble a list of pdf
  32. """
  33. # Even though we are using PyPDF2 we can't use PdfFileMerger
  34. # as this issue still exists in mostly used wktohtml reports version
  35. # http://code.google.com/p/wkhtmltopdf/issues/detail?id=635
  36. #merger = PdfFileMerger()
  37. #merger.append(fileobj=StringIO(invoice_pdf))
  38. #merger.append(fileobj=StringIO(bvr_pdf))
  39. #with tempfile.TemporaryFile() as merged_pdf:
  40. #merger.write(merged_pdf)
  41. #return merged_pdf.read(), 'pdf'
  42. output = PdfFileWriter()
  43. for pdf in pdf_list:
  44. reader = PdfFileReader(StringIO(pdf))
  45. for page in range(reader.getNumPages()):
  46. output.addPage(reader.getPage(page))
  47. s = StringIO()
  48. output.write(s)
  49. return s.getvalue()
  50. class PDFReportAssembler(report_sxw.report_sxw):
  51. """ PDFReportAssembler allows to put 2 pdf reports in one single pdf"""
  52. def _generate_all_pdf(self, cr, uid, ids, data, report_ids, context=None):
  53. """
  54. Return a list of pdf encoded in base64
  55. """
  56. pool = pooler.get_pool(cr.dbname)
  57. report_obj = pool.get('ir.actions.report.xml')
  58. spool = ExportService._services['report']
  59. pdf_reports = []
  60. report_list = report_obj.browse(cr, uid, report_ids, context=context)
  61. for report in report_list:
  62. report_key = spool.exp_report(cr.dbname, uid, report.report_name,
  63. ids, datas=data, context=context)
  64. while 1:
  65. res = spool.exp_report_get(cr.dbname, uid, report_key)
  66. if res.get('state'):
  67. break
  68. time.sleep(_POLLING_DELAY)
  69. pdf = base64.b64decode(res.get('result'))
  70. pdf_reports.append(pdf)
  71. return pdf_reports
  72. def _get_report_ids(self, cr, uid, ids, context=None):
  73. """
  74. Hook to define the list of report to print
  75. """
  76. return []
  77. def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
  78. """Call both report to assemble both pdf"""
  79. report_ids = self._get_report_ids(cr, uid, ids, context=context)
  80. pdf_reports = self._generate_all_pdf(cr, uid, ids, data, report_ids, context=context)
  81. pdf_assemblage = assemble_pdf(pdf_reports)
  82. return pdf_assemblage, 'pdf'
  83. def create(self, cr, uid, ids, data, context=None):
  84. """We override the create function in order to handle generator
  85. Code taken from report openoffice. Thanks guys :) """
  86. pool = pooler.get_pool(cr.dbname)
  87. ir_obj = pool.get('ir.actions.report.xml')
  88. report_xml_ids = ir_obj.search(cr, uid,
  89. [('report_name', '=', self.name[7:])], context=context)
  90. if report_xml_ids:
  91. report_xml = ir_obj.browse(cr,
  92. uid,
  93. report_xml_ids[0],
  94. context=context)
  95. report_xml.report_rml = None
  96. report_xml.report_rml_content = None
  97. report_xml.report_sxw_content_data = None
  98. report_xml.report_sxw_content = None
  99. report_xml.report_sxw = None
  100. else:
  101. return super(PDFReportAssembler, self).create(cr, uid, ids, data, context)
  102. if report_xml.report_type != 'assemblage':
  103. return super(PDFReportAssembler, self).create(cr, uid, ids, data, context)
  104. result = self.create_source_pdf(cr, uid, ids, data, report_xml, context)
  105. if not result:
  106. return (False, False)
  107. return result