Add support for single record report
A single report render each record separately and return them in a zip file. To ensure the uniqueness of the file in the zip, it uses the id of the record but also the record name to be user-friendly. issue6640 review37581002
This commit is contained in:
1 parent
de8c68c646
commit
f110fccf44
5 files changed
+43
-12
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Add support for single record report
|
||||
* Add support for Flat OpenDocument
|
||||
* Add get_email in trytond.report
|
||||
* Replace plain extension by txt
|
||||
|
||||
@@ -50,6 +50,10 @@ When defining an `ir.action.report` the following attributes are available:
|
||||
|
||||
* ``template_extension``: The template format.
|
||||
|
||||
* ``single``: `True` if the template works only for one record. If such
|
||||
report is called with more than one record, a zip file containing all the
|
||||
reports will be generated.
|
||||
|
||||
|
||||
Report Usage
|
||||
============
|
||||
@@ -129,12 +133,12 @@ Accessing models from within the report
|
||||
---------------------------------------
|
||||
|
||||
By default instances of the models the report is for are passed in to the
|
||||
report via a list of objects called `objects`. These objects behave just as
|
||||
they would within trytond itself. You can access any of the models relations as
|
||||
well. For example within the invoice report each object is an invoice and you
|
||||
can access the name of the party of the invoice via `invoice.party.name`.
|
||||
Additional objects can be passed to a report. This is discussed below in
|
||||
`Passing custom data to a report`.
|
||||
report via a list of objects called `records` (or `record` if `single` is
|
||||
`True`). These records behave just as they would within trytond itself. You
|
||||
can access any of the models relations as well. For example within the invoice
|
||||
report each object is an invoice and you can access the name of the party of
|
||||
the invoice via `invoice.party.name`. Additional objects can be passed to a
|
||||
report. This is discussed below in `Passing custom data to a report`.
|
||||
|
||||
Within Tryton the underlying model the report can be found by following the
|
||||
Menu to ``Administration > UI > Actions > Report``. Furthermore in tryton the
|
||||
|
||||
@@ -409,6 +409,8 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
|
||||
action = fields.Many2One('ir.action', 'Action', required=True,
|
||||
ondelete='CASCADE')
|
||||
direct_print = fields.Boolean('Direct Print')
|
||||
single = fields.Boolean("Single",
|
||||
help="Check if the template works only for one record.")
|
||||
template_extension = fields.Selection([
|
||||
('odt', 'OpenDocument Text'),
|
||||
('odp', 'OpenDocument Presentation'),
|
||||
@@ -582,6 +584,10 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
|
||||
def default_direct_print():
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def default_single(cls):
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def default_template_extension():
|
||||
return 'odt'
|
||||
|
||||
@@ -23,6 +23,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="template_extension"/>
|
||||
<label name="extension"/>
|
||||
<field name="extension"/>
|
||||
<label name="single"/>
|
||||
<field name="single"/>
|
||||
<label name="direct_print"/>
|
||||
<field name="direct_print"/>
|
||||
<newline/>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import os
|
||||
import datetime
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import warnings
|
||||
import subprocess
|
||||
import zipfile
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from io import BytesIO
|
||||
|
||||
try:
|
||||
import html2text
|
||||
@@ -152,17 +154,32 @@ class Report(URLMixin, PoolBase):
|
||||
else:
|
||||
action_report = ActionReport(action_id)
|
||||
|
||||
records = None
|
||||
records = []
|
||||
model = action_report.model or data.get('model')
|
||||
if model:
|
||||
records = cls._get_records(ids, model, data)
|
||||
report_context = cls.get_context(records, data)
|
||||
oext, content = cls.convert(action_report,
|
||||
cls.render(action_report, report_context))
|
||||
if action_report.single and len(records) > 1:
|
||||
content = BytesIO()
|
||||
with zipfile.ZipFile(content, 'w') as content_zip:
|
||||
for record in records:
|
||||
oext, rcontent = cls._execute(
|
||||
[record], data, action_report)
|
||||
rfilename = '%s-%s.%s' % (
|
||||
record.id, record.rec_name, oext)
|
||||
content_zip.writestr(rfilename, rcontent)
|
||||
content = content.getvalue()
|
||||
oext = 'zip'
|
||||
else:
|
||||
oext, content = cls._execute(records, data, action_report)
|
||||
if not isinstance(content, unicode):
|
||||
content = bytearray(content) if bytes == str else bytes(content)
|
||||
return (oext, content, action_report.direct_print, action_report.name)
|
||||
|
||||
@classmethod
|
||||
def _execute(cls, records, data, action):
|
||||
report_context = cls.get_context(records, data)
|
||||
return cls.convert(action, cls.render(action, report_context))
|
||||
|
||||
@classmethod
|
||||
def _get_records(cls, ids, model, data):
|
||||
pool = Pool()
|
||||
@@ -200,6 +217,7 @@ class Report(URLMixin, PoolBase):
|
||||
report_context['context'] = Transaction().context
|
||||
report_context['user'] = User(Transaction().user)
|
||||
report_context['records'] = records
|
||||
report_context['record'] = records[0] if records else None
|
||||
report_context['format_date'] = cls.format_date
|
||||
report_context['format_currency'] = cls.format_currency
|
||||
report_context['format_number'] = cls.format_number
|
||||
|
||||
Reference in new issue
Block a user