summaryrefslogtreecommitdiff
path: root/addons/web/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/controllers')
-rw-r--r--addons/web/controllers/__init__.py2
-rw-r--r--addons/web/controllers/list_controller.py98
-rw-r--r--addons/web/controllers/main.py9
3 files changed, 105 insertions, 4 deletions
diff --git a/addons/web/controllers/__init__.py b/addons/web/controllers/__init__.py
index 48cc37266c6..2113dfa39c9 100644
--- a/addons/web/controllers/__init__.py
+++ b/addons/web/controllers/__init__.py
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from . import main, pivot
+from . import main, pivot, list_controller
diff --git a/addons/web/controllers/list_controller.py b/addons/web/controllers/list_controller.py
new file mode 100644
index 00000000000..7ac98b79220
--- /dev/null
+++ b/addons/web/controllers/list_controller.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import json
+from datetime import datetime
+
+from odoo import http
+from odoo.http import request
+from odoo.tools.misc import xlwt
+
+
+HEADER_BOLD = xlwt.easyxf("font: bold on; pattern: pattern solid, fore_colour gray25;")
+
+class TableListExporter(http.Controller):
+
+ def _write_group_header(self, worksheet, x, y, group, columns, group_depth=0):
+ aggregates = group.get('aggregateValues', {})
+ title = group.get('value')
+
+ if group.get('hideHeader'):
+ return x, y
+
+ title = '%s%s (%s)' % ('>' * group_depth, title, group.get('count', 0))
+ worksheet.write(x, y, title, HEADER_BOLD)
+ for column in columns[1:]: # No aggregates allowed in the first column
+ y += 1
+ worksheet.write(x, y, aggregates.get(column['field'], ''), HEADER_BOLD)
+ return x + 1, 0
+
+ def _write_record(self, worksheet, x, y, record, columns):
+ for column in columns:
+ worksheet.write(x, y, record[column['field']])
+ y += 1
+ return x + 1, 0
+
+ def _write_groups(self, worksheet, x, y, groups, columns, group_depth=0):
+ """
+ Write groups to the xls worksheet. Recursive if groups are nested (chained groupby)
+ :param worksheet:
+ :param x: start position where to write the group (vertical axis, pointing downward)
+ :param y: start position where to write the group (horizontal axis, pointing to the right)
+ :param groups: list of groups. Each group is a dict containing either records' data
+ or sub-groups. A group has the following structure:
+ 'data': list of records or list of sub-groups
+ 'isGrouped': True if data contains sub-groups
+ 'value': title of the group
+ 'count': number of records in the group
+ 'aggregateValues': dict container aggregated values of fields {field: aggregatedValue, ...}
+ 'hideHeader': self explanatory, used when the records are not grouped at all.
+ :param columns: list of displayed columns. Each column is a dict with the following keys:
+ 'field': field name
+ 'aggregateValue': aggregate for all records
+ 'string':
+ """
+ for group in groups:
+ x, y = self._write_group_header(worksheet, x, y, group, columns, group_depth)
+ if group['isGrouped']:
+ # Recursively write sub-groups
+ x, y = self._write_groups(worksheet, x, y, group['data'], columns, group_depth + 1)
+ else:
+ for record in group['data']:
+ x, y = self._write_record(worksheet, x, y, record, columns)
+ return x, y
+
+ def _write_worksheet(self, worksheet, data):
+ bold = xlwt.easyxf("font: bold on;")
+
+ columns = data['columns']
+ groups = data['groups']
+
+ # Write main header
+ for y, field in enumerate(columns):
+ worksheet.write(0, y, field['string'], bold)
+
+ # Write data
+ x, y = 1, 0
+ x, y = self._write_groups(worksheet, x, y, groups, columns)
+
+ # Write column aggregates
+ for y, field in enumerate(columns):
+ worksheet.write(x, y, field.get('aggregateValue', ''), bold)
+
+ @http.route('/web/list/export_xls', type='http', auth="user")
+ def export_xls(self, data, token):
+ data = json.loads(data)
+ title = data.get('title', 'export')
+ workbook = xlwt.Workbook()
+ worksheet = workbook.add_sheet(title)
+
+ self._write_worksheet(worksheet, data)
+
+ response = request.make_response(None,
+ headers=[('Content-Type', 'application/vnd.ms-excel'),
+ ('Content-Disposition', 'attachment; filename="%s - %s.xls"' % (title, datetime.now()))],
+ cookies={'fileToken': token})
+ workbook.save(response.stream)
+
+ return response
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index b2132850d08..cb8d4d82ecc 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1190,7 +1190,7 @@ class Binary(http.Controller):
'/web/partner_image/<int:rec_id>',
'/web/partner_image/<int:rec_id>/<string:field>',
'/web/partner_image/<int:rec_id>/<string:field>/<string:model>/'], type='http', auth="public")
- def content_image_partner(self, rec_id, field='image_64', model='res.partner', **kwargs):
+ def content_image_partner(self, rec_id, field='image_128', model='res.partner', **kwargs):
# other kwargs are ignored on purpose
return self._content_image(id=rec_id, model='res.partner', field=field,
placeholder='user_placeholder.jpg')
@@ -1833,8 +1833,11 @@ class ReportController(http.Controller):
response = self.report_routes(reportname, docids=docids, converter=converter, context=context)
else:
# Particular report:
- data = url_decode(url.split('?')[1]).items() # decoding the args represented in JSON
- response = self.report_routes(reportname, converter=converter, context=context, **dict(data))
+ data = dict(url_decode(url.split('?')[1]).items()) # decoding the args represented in JSON
+ if 'context' in data:
+ context, data_context = json.loads(context or '{}'), json.loads(data.pop('context'))
+ context = json.dumps({**context, **data_context})
+ response = self.report_routes(reportname, converter=converter, context=context, **data)
report = request.env['ir.actions.report']._get_report_from_name(reportname)
filename = "%s.%s" % (report.name, extension)