From 35c5e56718e1ce8ca3747f90ba5c06d8f9d20b1c Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 11:57:45 +0200 Subject: [PATCH 1/8] [FIX] address div more to the left on external reports --- addons/account/views/report_invoice.xml | 2 +- addons/account/views/report_overdue.xml | 2 +- addons/account_followup/views/report_followup.xml | 2 +- addons/hr_payroll/views/report_payslip.xml | 2 +- addons/lunch/views/report_lunchorder.xml | 2 +- addons/mrp_repair/views/report_mrprepairorder.xml | 2 +- addons/purchase/views/report_purchaseorder.xml | 2 +- addons/purchase/views/report_purchasequotation.xml | 2 +- addons/report/data/report_paperformat.xml | 2 +- addons/report_intrastat/views/report_intrastatinvoice.xml | 2 +- addons/sale/views/report_saleorder.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml index 6c4b701c6cf..a250eb9ebf7 100644 --- a/addons/account/views/report_invoice.xml +++ b/addons/account/views/report_invoice.xml @@ -5,7 +5,7 @@
-
+
diff --git a/addons/account/views/report_overdue.xml b/addons/account/views/report_overdue.xml index bc522aa8b9d..df3934ff0de 100644 --- a/addons/account/views/report_overdue.xml +++ b/addons/account/views/report_overdue.xml @@ -5,7 +5,7 @@
-
+

diff --git a/addons/account_followup/views/report_followup.xml b/addons/account_followup/views/report_followup.xml index 6c79fe4cc55..c0d98e7bb28 100644 --- a/addons/account_followup/views/report_followup.xml +++ b/addons/account_followup/views/report_followup.xml @@ -7,7 +7,7 @@
-
+
diff --git a/addons/hr_payroll/views/report_payslip.xml b/addons/hr_payroll/views/report_payslip.xml index 5ac9dfa557e..b30cb089d1a 100644 --- a/addons/hr_payroll/views/report_payslip.xml +++ b/addons/hr_payroll/views/report_payslip.xml @@ -19,7 +19,7 @@ Address -
diff --git a/addons/lunch/views/report_lunchorder.xml b/addons/lunch/views/report_lunchorder.xml index 93d43f6521d..30401bc142b 100644 --- a/addons/lunch/views/report_lunchorder.xml +++ b/addons/lunch/views/report_lunchorder.xml @@ -8,7 +8,7 @@
-
+
diff --git a/addons/mrp_repair/views/report_mrprepairorder.xml b/addons/mrp_repair/views/report_mrprepairorder.xml index 0ea3f22167c..2897fee1fd9 100644 --- a/addons/mrp_repair/views/report_mrprepairorder.xml +++ b/addons/mrp_repair/views/report_mrprepairorder.xml @@ -22,7 +22,7 @@

VAT:

-
+
diff --git a/addons/purchase/views/report_purchaseorder.xml b/addons/purchase/views/report_purchaseorder.xml index c03e535ff75..bd1f1846cd5 100644 --- a/addons/purchase/views/report_purchaseorder.xml +++ b/addons/purchase/views/report_purchaseorder.xml @@ -23,7 +23,7 @@

VAT:

-
+
diff --git a/addons/purchase/views/report_purchasequotation.xml b/addons/purchase/views/report_purchasequotation.xml index 68e8995ddd8..7f6c8f5bb78 100644 --- a/addons/purchase/views/report_purchasequotation.xml +++ b/addons/purchase/views/report_purchasequotation.xml @@ -23,7 +23,7 @@

VAT:

-
+
diff --git a/addons/report/data/report_paperformat.xml b/addons/report/data/report_paperformat.xml index 275d65edd13..f05e0afb6f0 100644 --- a/addons/report/data/report_paperformat.xml +++ b/addons/report/data/report_paperformat.xml @@ -9,7 +9,7 @@ 0 Portrait 40 - 20 + 23 7 7 diff --git a/addons/report_intrastat/views/report_intrastatinvoice.xml b/addons/report_intrastat/views/report_intrastatinvoice.xml index c534f808c95..abf4bdd56ba 100644 --- a/addons/report_intrastat/views/report_intrastatinvoice.xml +++ b/addons/report_intrastat/views/report_intrastatinvoice.xml @@ -5,7 +5,7 @@
-
+
diff --git a/addons/sale/views/report_saleorder.xml b/addons/sale/views/report_saleorder.xml index c23e680e664..5c198c635a3 100644 --- a/addons/sale/views/report_saleorder.xml +++ b/addons/sale/views/report_saleorder.xml @@ -19,7 +19,7 @@

VAT:

-
+
From 4019b2b3345c044e41492404a2322c169b75a23e Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 12:56:56 +0200 Subject: [PATCH 2/8] [FIX] Report: do not raise when wkhtmltopdf returns a code 1. In most cases, it is due to some http requests which did not success *but* the pdf is still acceptable. Far from the best commit ever, but it avoids to completely crash when just a link to an image is wrong --- addons/report/models/report.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index fed6a2335ee..d744c917343 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -353,8 +353,6 @@ class Report(osv.Model): if paperformat: command_args.extend(self._build_wkhtmltopdf_args(paperformat, spec_paperformat_args)) - command_args.extend(['--load-error-handling', 'ignore']) - if landscape and '--orientation' in command_args: command_args_copy = list(command_args) for index, elem in enumerate(command_args_copy): @@ -417,7 +415,7 @@ class Report(osv.Model): if config['workers'] == 1: os.kill(ppid, signal.SIGTTOU) - if process.returncode != 0: + if process.returncode not in [0, 1]: raise osv.except_osv(_('Report (PDF)'), _('wkhtmltopdf failed with error code = %s. ' 'Message: %s') % (str(process.returncode), err)) From 1745c738eeac326a06f31d2fc4ecd0e0f71d5f86 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 12:59:05 +0200 Subject: [PATCH 3/8] [FIX] Report: double the default height/width of barcode image to avoid a blurred/unusable barcode once integrated in a report --- addons/report/controllers/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py index d3a683cccdc..800c10140b6 100644 --- a/addons/report/controllers/main.py +++ b/addons/report/controllers/main.py @@ -64,7 +64,7 @@ class ReportController(Controller): # Misc. route utils #------------------------------------------------------ @route(['/report/barcode', '/report/barcode//'], type='http', auth="user") - def report_barcode(self, type, value, width=300, height=50): + def report_barcode(self, type, value, width=600, height=100): """Contoller able to render barcode images thanks to reportlab. Samples: From 226579a80deac960b2345a8a7b47b683994deff8 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 13:01:42 +0200 Subject: [PATCH 4/8] [FIX] Report: removed psutil/signal/openerp worker crap --- addons/report/models/report.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index d744c917343..89979bb7220 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -20,15 +20,11 @@ ############################################################################## from openerp.osv import osv -from openerp.tools import config from openerp.tools.translate import _ from openerp.addons.web.http import request from openerp.tools.safe_eval import safe_eval as eval -import os import time -import psutil -import signal import base64 import logging import tempfile @@ -399,25 +395,15 @@ class Report(osv.Model): content_file.seek(0) try: - # If the server is running with only one worker, ask to create a secund to be able - # to serve the http request of wkhtmltopdf subprocess. - if config['workers'] == 1: - ppid = psutil.Process(os.getpid()).ppid - os.kill(ppid, signal.SIGTTIN) - wkhtmltopdf = command + command_args + command_arg_local wkhtmltopdf += [content_file.name] + [pdfreport.name] - process = subprocess.Popen(wkhtmltopdf, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + process = subprocess.Popen(wkhtmltopdf, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - if config['workers'] == 1: - os.kill(ppid, signal.SIGTTOU) - if process.returncode not in [0, 1]: raise osv.except_osv(_('Report (PDF)'), - _('wkhtmltopdf failed with error code = %s. ' + _('Wkhtmltopdf failed with error code = %s. ' 'Message: %s') % (str(process.returncode), err)) # Save the pdf in attachment if marked From 654df600c1c2ec398506058ae6a0e83fa0555627 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 13:02:59 +0200 Subject: [PATCH 5/8] [FIX] Report: less verbose error message --- addons/report/models/report.py | 40 ++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 89979bb7220..c76a6b72e0e 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -338,17 +338,20 @@ class Report(osv.Model): command_args = [] tmp_dir = tempfile.gettempdir() - # Passing the cookie to wkhtmltopdf in order to resolve URL. + # Passing the cookie to wkhtmltopdf in order to resolve internal links. try: if request: command_args.extend(['--cookie', 'session_id', request.session.sid]) except AttributeError: pass - # Display arguments + # Wkhtmltopdf arguments + command_args.extend(['--quiet']) # Less verbose error messages if paperformat: + # Convert the paperformat record into arguments command_args.extend(self._build_wkhtmltopdf_args(paperformat, spec_paperformat_args)) + # Force the landscape orientation if necessary if landscape and '--orientation' in command_args: command_args_copy = list(command_args) for index, elem in enumerate(command_args_copy): @@ -359,43 +362,38 @@ class Report(osv.Model): elif landscape and not '--orientation' in command_args: command_args.extend(['--orientation', 'landscape']) + # Execute WKhtmltopdf pdfdocuments = [] - # HTML to PDF thanks to WKhtmltopdf for index, reporthtml in enumerate(bodies): - command_arg_local = [] - pdfreport = tempfile.NamedTemporaryFile(suffix='.pdf', prefix='report.tmp.', - mode='w+b') - # Directly load the document if we have it + local_command_args = [] + pdfreport = tempfile.NamedTemporaryFile(suffix='.pdf', prefix='report.tmp.', mode='w+b') + + # Directly load the document if we already have it if save_in_attachment and save_in_attachment['loaded_documents'].get(reporthtml[0]): pdfreport.write(save_in_attachment['loaded_documents'].get(reporthtml[0])) pdfreport.seek(0) pdfdocuments.append(pdfreport) continue - # Header stuff + # Wkhtmltopdf handles header/footer as separate pages. Create them if necessary. if headers: - head_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.header.tmp.', - dir=tmp_dir, mode='w+') + head_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.header.tmp.', dir=tmp_dir, mode='w+') head_file.write(headers[index]) head_file.seek(0) - command_arg_local.extend(['--header-html', head_file.name]) - - # Footer stuff + local_command_args.extend(['--header-html', head_file.name]) if footers: - foot_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.footer.tmp.', - dir=tmp_dir, mode='w+') + foot_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.footer.tmp.', dir=tmp_dir, mode='w+') foot_file.write(footers[index]) foot_file.seek(0) - command_arg_local.extend(['--footer-html', foot_file.name]) + local_command_args.extend(['--footer-html', foot_file.name]) # Body stuff - content_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.body.tmp.', - dir=tmp_dir, mode='w+') + content_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.body.tmp.', dir=tmp_dir, mode='w+') content_file.write(reporthtml[1]) content_file.seek(0) try: - wkhtmltopdf = command + command_args + command_arg_local + wkhtmltopdf = command + command_args + local_command_args wkhtmltopdf += [content_file.name] + [pdfreport.name] process = subprocess.Popen(wkhtmltopdf, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -403,7 +401,7 @@ class Report(osv.Model): if process.returncode not in [0, 1]: raise osv.except_osv(_('Report (PDF)'), - _('Wkhtmltopdf failed with error code = %s. ' + _('Wkhtmltopdf failed (error code: %s). ' 'Message: %s') % (str(process.returncode), err)) # Save the pdf in attachment if marked @@ -429,7 +427,7 @@ class Report(osv.Model): except: raise - # Get and return the full pdf + # Return the entire document if len(pdfdocuments) == 1: content = pdfdocuments[0].read() pdfdocuments[0].close() From 58d3a6f3f7bf295a2328b557f8094811a67c9942 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 13:06:31 +0200 Subject: [PATCH 6/8] [FIX] Report: inform the user that he may not print a pdf report while his openerp is running with only one worker; adapt method to extract wkhtmltopdf version to also work on mac where the ouput of '--version' is different from gnu/linux binary --- addons/report/models/report.py | 23 +++++--- .../report/static/src/js/qwebactionmanager.js | 53 ++++++++++--------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index c76a6b72e0e..32752fa6e33 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -20,6 +20,7 @@ ############################################################################## from openerp.osv import osv +from openerp.tools import config from openerp.tools.translate import _ from openerp.addons.web.http import request from openerp.tools.safe_eval import safe_eval as eval @@ -48,15 +49,23 @@ try: ['wkhtmltopdf', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) except OSError: - _logger.error('You need wkhtmltopdf to print a pdf version of the reports.') + _logger.info('You need wkhtmltopdf to print a pdf version of the reports.') else: out, err = process.communicate() - version = out.splitlines()[1].strip() - version = version.split(' ')[1] - if LooseVersion(version) < LooseVersion('0.12.0'): - _logger.warning('Upgrade wkhtmltopdf to (at least) 0.12.0') - wkhtmltopdf_state = 'upgrade' - wkhtmltopdf_state = 'ok' + + for line in out.splitlines(): + line = line.strip() + if line.startswith('wkhtmltopdf 0.'): + version = line.split(' ')[1] + if LooseVersion(version) < LooseVersion('0.12.0'): + _logger.info('Upgrade wkhtmltopdf to (at least) 0.12.0') + wkhtmltopdf_state = 'upgrade' + else: + wkhtmltopdf_state = 'ok' + + if config['workers'] == 1: + _logger.info('You need to start OpenERP with at least two workers to print a pdf version of the reports.') + wkhtmltopdf_state = 'workers' class Report(osv.Model): diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js index 7e55661be86..cb0f3921482 100644 --- a/addons/report/static/src/js/qwebactionmanager.js +++ b/addons/report/static/src/js/qwebactionmanager.js @@ -54,34 +54,35 @@ openerp.report = function(instance) { if (action.report_type == 'qweb-html') { window.open(report_url, '_blank', 'height=900,width=1280'); instance.web.unblockUI(); - } else { + } else if (action.report_type === 'qweb-pdf') { // Trigger the download of the pdf/controller report - - if (action.report_type == 'qweb-pdf') { - (wkhtmltopdf_state = wkhtmltopdf_state || openerp.session.rpc('/report/check_wkhtmltopdf')).then(function (presence) { - // Fallback of qweb-pdf if wkhtmltopdf is not installed - if (presence == 'install' && action.report_type == 'qweb-pdf') { - self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \ - system. The report will be shown in html.

\ - wkhtmltopdf.org'), true); - report_url = report_url.substring(12) - window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024'); - instance.web.unblockUI(); - return; - } else { - if (presence == 'upgrade') { - self.do_notify(_t('Report'), _t('You should upgrade your version of\ - Wkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as\ - support for table-breaking between pages.

wkhtmltopdf.org'), true); - } - } - return trigger_download(self.session, response, c); - }); - } - else if (action.report_type == 'controller') { + (wkhtmltopdf_state = wkhtmltopdf_state || openerp.session.rpc('/report/check_wkhtmltopdf')).then(function (presence) { + // Fallback on html if wkhtmltopdf is not installed or if OpenERP is started with one worker + if (presence === 'install') { + self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \ +system. The report will be shown in html.

\ +wkhtmltopdf.org'), true); + report_url = report_url.substring(12) + window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024'); + instance.web.unblockUI(); + return; + } else if (presence === 'workers') { + self.do_notify(_t('Report'), _t('You need to start OpenERP with at least two \ +workers to print a pdf version of the reports.'), true); + report_url = report_url.substring(12) + window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024'); + instance.web.unblockUI(); + return; + } else if (presence === 'upgrade') { + self.do_notify(_t('Report'), _t('You should upgrade your version of\ + Wkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as\ + support for table-breaking between pages.

wkhtmltopdf.org'), true); + } return trigger_download(self.session, response, c); - } + }); + } else if (action.report_type === 'controller') { + return trigger_download(self.session, response, c); } } else { return self._super(action, options); From b50421e551ef120e0fa77cddec9247fd1ac982ed Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 13:11:27 +0200 Subject: [PATCH 7/8] [FIX] ir_actions: adapt render_report when called in a tests/qweb report context to generate the pdf only if a directory has been provided --- openerp/addons/base/ir/ir_actions.py | 16 ++++++++++------ openerp/tools/test_reports.py | 3 +-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 4e177959792..8aa968a3b3a 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -41,6 +41,7 @@ import openerp.workflow _logger = logging.getLogger(__name__) + class actions(osv.osv): _name = 'ir.actions.actions' _table = 'ir_actions' @@ -129,9 +130,15 @@ class ir_actions_report_xml(osv.osv): Look up a report definition and render the report for the provided IDs. """ new_report = self._lookup_report(cr, name) - # in order to use current yml test files with qweb reports - if isinstance(new_report, (str, unicode)): - return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf' + + if isinstance(new_report, (str, unicode)): # Qweb report + # The only case where a QWeb report is rendered with this method occurs when running + # yml tests originally written for RML reports. + if openerp.tools.config['test_enable'] and not tools.config['test_report_directory']: + # Only generate the pdf when a destination folder has been provided. + return self.pool['report'].get_html(cr, uid, res_ids, new_report, data=data, context=context), 'html' + else: + return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf' else: return new_report.create(cr, uid, res_ids, data, context) @@ -1170,7 +1177,4 @@ class ir_actions_act_client(osv.osv): } - - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/openerp/tools/test_reports.py b/openerp/tools/test_reports.py index c008c20ae29..305d2b0f115 100644 --- a/openerp/tools/test_reports.py +++ b/openerp/tools/test_reports.py @@ -87,8 +87,7 @@ def try_report(cr, uid, rname, ids, data=None, context=None, our_module=None, re if ('[[' in line) or ('[ [' in line): _logger.error("Report %s may have bad expression near: \"%s\".", rname, line[80:]) # TODO more checks, what else can be a sign of a faulty report? - elif res_format == 'foobar': - # TODO + elif res_format == 'html': pass else: _logger.warning("Report %s produced a \"%s\" chunk, cannot examine it", rname, res_format) From 1f97c40c9c109165caef58ee1a87f925b5c7d884 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 21 May 2014 14:05:18 +0200 Subject: [PATCH 8/8] [FIX] Report: get the wkhtmltopdf version in a cleaner way with a simple regex --- addons/report/models/report.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 32752fa6e33..6d118021775 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -25,6 +25,7 @@ from openerp.tools.translate import _ from openerp.addons.web.http import request from openerp.tools.safe_eval import safe_eval as eval +import re import time import base64 import logging @@ -52,16 +53,12 @@ except OSError: _logger.info('You need wkhtmltopdf to print a pdf version of the reports.') else: out, err = process.communicate() - - for line in out.splitlines(): - line = line.strip() - if line.startswith('wkhtmltopdf 0.'): - version = line.split(' ')[1] - if LooseVersion(version) < LooseVersion('0.12.0'): - _logger.info('Upgrade wkhtmltopdf to (at least) 0.12.0') - wkhtmltopdf_state = 'upgrade' - else: - wkhtmltopdf_state = 'ok' + version = re.search('([0-9.]+)', out).group(0) + if LooseVersion(version) < LooseVersion('0.12.0'): + _logger.info('Upgrade wkhtmltopdf to (at least) 0.12.0') + wkhtmltopdf_state = 'upgrade' + else: + wkhtmltopdf_state = 'ok' if config['workers'] == 1: _logger.info('You need to start OpenERP with at least two workers to print a pdf version of the reports.')