[IMP] Added the possibility to define ultra-specific reports outputing any king of file. These reports are of type 'controller' because they redirects to a controller that must returns a response containing the http headers 'content-type' and 'content-disposition'. The route for this controller is specified in the report_file field. Added an XLS version of the tax report for the POC (testable by setting 'report_vat' type to controller and setting '/report/account.report_vat_xls' in the 'report_file' field).

bzr revid: sle@openerp.com-20140221163320-g5ouoywsuduoi0qe
This commit is contained in:
Simon Lejeune 2014-02-21 17:33:20 +01:00
parent 65dc368cdd
commit ffa475afcd
5 changed files with 114 additions and 35 deletions

View File

@ -22,6 +22,11 @@
from openerp.addons.web import http
from openerp.addons.web.http import request
from common_report_header import common_report_header
try:
import cStringIO as StringIO
except ImportError:
import StringIO
import xlwt
class tax_report(http.Controller, common_report_header):
@ -224,4 +229,43 @@ class tax_report(http.Controller, common_report_header):
return result_accounts
@http.route(['/report/account.report_vat_xls'], type='http', auth='user', website=True, multilang=True)
def report_account_tax_xls(self, **data):
report_obj = request.registry['report']
self.cr, self.uid, self.pool = request.cr, request.uid, request.registry
data = report_obj.eval_params(data)
res = {}
self.period_ids = []
period_obj = self.pool.get('account.period')
self.display_detail = data['form']['display_detail']
res['periods'] = ''
res['fiscalyear'] = data['form'].get('fiscalyear_id', False)
if data['form'].get('period_from', False) and data['form'].get('period_to', False):
self.period_ids = period_obj.build_ctx_periods(self.cr, self.uid, data['form']['period_from'], data['form']['period_to'])
content = ''
lines = self._get_lines(self._get_basedon(data), company_id=data['form']['company_id'])
if lines:
xls = StringIO.StringIO()
xls_workbook = xlwt.Workbook()
vat_sheet = xls_workbook.add_sheet('report_vat')
for x in range(0, len(lines)):
for y in range(0, len(lines[0])):
vat_sheet.write(x, y, lines[x].values()[y])
xls_workbook.save(xls)
xls.seek(0)
content = xls.read()
response = request.make_response(content, headers=[
('Content-Type', 'application/vnd.ms-excel'),
('Content-Disposition', 'attachment; filename=report_vat.xls;')
])
return response
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -7,7 +7,7 @@
<div class="page">
<h2>Tax Statement</h2>
<div class="row">
<div class="row mt32 mb32">
<div class="col-xs-3">
<strong>Chart of Tax:</strong>
<p t-esc="account"/>

View File

@ -83,11 +83,18 @@ class Report(http.Controller):
'docs': docs,
}
return request.registry['report'].render(request.cr, request.uid, [], report.report_file,
return request.registry['report'].render(request.cr, request.uid, [], report.report_name,
docargs, context=request.context)
@http.route(['/report/pdf/<path:path>'], type='http', auth="user", website=True)
def report_pdf(self, path=None, landscape=False, **post):
"""Route converting any reports to pdf. It will get the html-rendered report, extract
header, page and footer in order to prepare minimal html pages that will be further passed
to wkhtmltopdf.
:param path: URL of the report (e.g. /report/account.report_invoice/1)
:returns: a response with 'application/pdf' headers and the pdf as content
"""
cr, uid, context = request.cr, request.uid, request.context
# Get the report we are working on.
@ -136,14 +143,14 @@ class Report(http.Controller):
paperformat = report.paperformat_id
# Get the html report.
html = self._get_url_content('/' + path, post)
html = self._get_url_content('/' + path, post)[0]
# Get some css and script in order to build a minimal html page for the report.
# This page will later be sent to wkhtmltopdf.
css = self._get_url_content('/report/static/src/css/reset.min.css')
css += self._get_url_content('/web/static/lib/bootstrap/css/bootstrap.css')
css += self._get_url_content('/website/static/src/css/website.css')
subst = self._get_url_content('/report/static/src/js/subst.js')
css = self._get_url_content('/report/static/src/css/reset.min.css')[0]
css += self._get_url_content('/web/static/lib/bootstrap/css/bootstrap.css')[0]
css += self._get_url_content('/website/static/src/css/website.css')[0]
subst = self._get_url_content('/report/static/src/js/subst.js')[0]
headerhtml = []
contenthtml = []
@ -240,7 +247,7 @@ class Report(http.Controller):
except UnicodeDecodeError:
pass
return content
return tuple([content, response.headers])
def _generate_wkhtml_pdf(self, headers, footers, bodies, landscape,
paperformat, spec_paperformat_args=None, save_in_attachment=None):
@ -440,31 +447,19 @@ class Report(http.Controller):
merged.close()
return content
@http.route('/report/downloadpdf/', type='http', auth="user")
def report_pdf_attachment(self, data, token):
"""This function is only used by 'qwebactionmanager.js' in order to trigger the download of
a pdf report.
:param data: The JSON.stringified report internal url
:returns: Response with a filetoken cookie and an attachment header
"""
url = simplejson.loads(data)
pdf = self._get_url_content(url)
response = self._make_pdf_response(pdf)
response.set_cookie('fileToken', token)
response.headers.add('Content-Disposition', 'attachment; filename=report.pdf;')
return response
@http.route(['/report/barcode', '/report/barcode/<type>/<value>'], type='http', auth="user")
def barcode(self, type, value, width=300, height=50):
"""Contoller able to render barcode images thanks to reportlab.
Sample: <img t-att-src="'/report/barcode/QR/%s' % o.name"/>
Samples:
<img t-att-src="'/report/barcode/QR/%s' % o.name"/>
<img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('QR', o.name, 200, 200)"/>
:param type: Accepted types: 'Codabar', 'Code11', 'Code128', 'EAN13', 'EAN8', 'Extended39',
'Extended93', 'FIM', 'I2of5', 'MSI', 'POSTNET', 'QR', 'Standard39', 'Standard93',
'UPCA', 'USPS_4State'
"""
try:
width, height = int(width), int(height)
barcode = createBarcodeImageInMemory(
type, value=value, format='png', width=width, height=height
)
@ -474,3 +469,29 @@ class Report(http.Controller):
raise exceptions.HTTPException(description='Please upgrade reportlab to at least 3.0.')
return request.make_response(barcode, headers=[('Content-Type', 'image/png')])
@http.route('/report/download/', type='http', auth="user")
def report_attachment(self, data, token):
"""This function is only used by 'qwebactionmanager.js' in order to trigger the download of
a report.
:param data: The JSON.stringified report internal url
:returns: Response with a filetoken cookie and an attachment header
"""
requestcontent = simplejson.loads(data)
url, type = requestcontent[0], requestcontent[1]
file, fileheaders = self._get_url_content(url)
if type == 'qweb-pdf':
response = self._make_pdf_response(file)
response.headers.add('Content-Disposition', 'attachment; filename=report.pdf;')
elif type == 'controller':
response = request.make_response(file)
response.headers.add('Content-Disposition', fileheaders['Content-Disposition'])
response.headers.add('Content-Type', fileheaders['Content-Type'])
else:
return
response.headers.add('Content-Length', len(file))
response.set_cookie('fileToken', token)
return response

View File

@ -241,6 +241,7 @@ class report(osv.Model):
'type': 'ir.actions.report.xml',
'report_name': report.report_name,
'report_type': report.report_type,
'report_file': report.report_file,
}
if datas:

View File

@ -9,13 +9,22 @@ openerp.report = function(instance) {
action.context = instance.web.pyeval.eval('contexts',eval_contexts);
// QWeb reports
if ('report_type' in action && (action.report_type == 'qweb-html' || action.report_type == 'qweb-pdf')) {
var report_url = '';
if (action.report_type == 'qweb-html') {
report_url = '/report/' + action.report_name;
} else {
report_url = '/report/pdf/report/' + action.report_name;
if ('report_type' in action && (action.report_type == 'qweb-html' || action.report_type == 'qweb-pdf' || action.report_type == 'controller')) {
var report_url = ''
switch (action.report_type) {
case 'qweb-html':
report_url = '/report/' + action.report_name;
break;
case 'qweb-pdf':
report_url = '/report/pdf/report/' + action.report_name;
break;
case 'controller':
report_url = action.report_file;
break;
default:
report_url = '/report/' + action.report_name;
break;
}
// single/multiple id(s): no query string
@ -27,7 +36,7 @@ openerp.report = function(instance) {
} else {
_.each(action.datas.form, function(value, key) {
// will be erased when all wizards are rewritten
if(key.substring(0, 12) === 'used_context') {
if (key.substring(0, 12) === 'used_context') {
delete action.datas.form[key];
}
@ -43,11 +52,15 @@ openerp.report = function(instance) {
instance.web.unblockUI();
return;
} else {
// Trigger the download of the pdf report
// Trigger the download of the pdf/custom controller report
var c = openerp.webclient.crashmanager;
var response = new Array()
response[0] = report_url
response[1] = action.report_type
this.session.get_file({
url: '/report/downloadpdf',
data: {data: JSON.stringify(report_url)},
url: '/report/download',
data: {data: JSON.stringify(response)},
complete: openerp.web.unblockUI,
error: c.rpc_error.bind(c)
});