Merge pull request #119 from odoo-dev/saas-4-report-fixes-sle
[FIX] Multiple report fixes including better handling of rendering a report with one worker (and the removal of the workers creation) and some report views changes (address block more to the left)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-8">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<address t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
<span t-field="o.partner_id.vat"/>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-6">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<span t-field="o.name"/><br/>
|
||||
<span t-raw="addresses[o.id].replace('\n\n', '\n').replace('\n', '<br>')"/>
|
||||
<span t-field="o.vat"/>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-6">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
<span t-field="o.partner_id.vat"/>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<tr>
|
||||
<td><strong>Address</strong></td>
|
||||
<td colspan="3">
|
||||
<div t-filed="o.employee_id.address_home_id"
|
||||
<div t-field="o.employee_id.address_home_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="oe_structure"/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-7">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<div t-field="user.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-xs-offset-2">
|
||||
<div class="col-xs-5 col-xs-offset-1">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-xs-offset-2">
|
||||
<div class="col-xs-5 col-xs-offset-1">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-xs-offset-2">
|
||||
<div class="col-xs-5 col-xs-offset-1">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name", "phone", "fax"], "no_marker": true}'/>
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@ class ReportController(Controller):
|
||||
# Misc. route utils
|
||||
#------------------------------------------------------
|
||||
@route(['/report/barcode', '/report/barcode/<type>/<path:value>'], 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:
|
||||
<img t-att-src="'/report/barcode/QR/%s' % o.name"/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<field name="page_width">0</field>
|
||||
<field name="orientation">Portrait</field>
|
||||
<field name="margin_top">40</field>
|
||||
<field name="margin_bottom">20</field>
|
||||
<field name="margin_bottom">23</field>
|
||||
<field name="margin_left">7</field>
|
||||
<field name="margin_right">7</field>
|
||||
<field name="header_line" eval="False" />
|
||||
|
||||
@@ -25,10 +25,8 @@ 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 re
|
||||
import time
|
||||
import psutil
|
||||
import signal
|
||||
import base64
|
||||
import logging
|
||||
import tempfile
|
||||
@@ -52,15 +50,19 @@ 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]
|
||||
version = re.search('([0-9.]+)', out).group(0)
|
||||
if LooseVersion(version) < LooseVersion('0.12.0'):
|
||||
_logger.warning('Upgrade wkhtmltopdf to (at least) 0.12.0')
|
||||
_logger.info('Upgrade wkhtmltopdf to (at least) 0.12.0')
|
||||
wkhtmltopdf_state = 'upgrade'
|
||||
wkhtmltopdf_state = 'ok'
|
||||
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):
|
||||
@@ -342,19 +344,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))
|
||||
|
||||
command_args.extend(['--load-error-handling', 'ignore'])
|
||||
|
||||
# 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):
|
||||
@@ -365,61 +368,46 @@ 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:
|
||||
# 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 = command + command_args + local_command_args
|
||||
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 != 0:
|
||||
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
|
||||
@@ -445,7 +433,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()
|
||||
|
||||
@@ -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.<br><br><a href="http://wkhtmltopdf.org/" target="_blank">\
|
||||
wkhtmltopdf.org</a>'), 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.<br><br><a href="http://wkhtmltopdf.org/" \
|
||||
target="_blank">wkhtmltopdf.org</a>'), 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.<br><br><a href="http://wkhtmltopdf.org/" target="_blank">\
|
||||
wkhtmltopdf.org</a>'), 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.<br><br><a href="http://wkhtmltopdf.org/" \
|
||||
target="_blank">wkhtmltopdf.org</a>'), 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);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-8">
|
||||
<div class="col-xs-5 col-xs-offset-7">
|
||||
<address t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
<span t-field="o.partner_id.vat"/>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-xs-offset-2">
|
||||
<div class="col-xs-5 col-xs-offset-1">
|
||||
<div t-field="o.partner_id"
|
||||
t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}' />
|
||||
</div>
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user