diff --git a/CHANGELOG b/CHANGELOG
index e11d75e800..e60cc36495 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,4 @@
+* Allow modify record name on the reports
* Add methods to format number and symbol on Lang
* Add format number with symbol on Report
* Allow locking tables by calling ModelSQL.lock without records
diff --git a/doc/topics/reports/index.rst b/doc/topics/reports/index.rst
index ab594ff673..3fe26b745d 100644
--- a/doc/topics/reports/index.rst
+++ b/doc/topics/reports/index.rst
@@ -56,6 +56,9 @@ When defining an ``ir.action.report`` the following attributes are available:
report is called with more than one record, a zip file containing all the
reports will be generated.
+ * ``record_name``: A Genshi Expression to compute the filename for each
+ record.
+
Report Usage
============
diff --git a/trytond/ir/action.py b/trytond/ir/action.py
index 4956af2250..6251aa56fb 100644
--- a/trytond/ir/action.py
+++ b/trytond/ir/action.py
@@ -6,6 +6,7 @@ from collections import defaultdict
from functools import partial
from sql import Null
+from genshi.template.text import TextTemplate
from trytond.cache import Cache, MemoryCache
from trytond.config import config
@@ -549,6 +550,10 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
], translate=False,
string='Extension', help='Leave empty for the same as template, '
'see LibreOffice documentation for compatible format.')
+ record_name = fields.Char(
+ "Record Name", translate=True,
+ help="A Genshi expression to compute the name using 'record'.\n"
+ "Leave empty for the default name.",)
module = fields.Char('Module', readonly=True, select=True)
_template_cache = MemoryCache('ir.action.report.template', context=False)
@@ -695,6 +700,23 @@ class ActionReport(ActionMixin, ModelSQL, ModelView):
def set_template_cached(self, template):
self._template_cache.set(self.id, template)
+ @classmethod
+ def validate(cls, reports):
+ super().validate(reports)
+ for report in reports:
+ report.check_record_name()
+
+ def check_record_name(self):
+ if not self.record_name:
+ return
+ try:
+ TextTemplate(self.record_name)
+ except Exception as exception:
+ raise ValidationError(
+ gettext('ir.msg_report_invalid_record_name',
+ report=self.rec_name,
+ exception=exception)) from exception
+
class ActionActWindow(ActionMixin, ModelSQL, ModelView):
"Action act window"
diff --git a/trytond/ir/message.xml b/trytond/ir/message.xml
index a5ede8e1d6..805a451753 100644
--- a/trytond/ir/message.xml
+++ b/trytond/ir/message.xml
@@ -238,6 +238,9 @@ this repository contains the full copyright notices and license terms. -->
Invalid email definition for report "%(name)s".
+
+ Invalid record name definition for report "%(report)s" with exception "%(exception)s".
+ Invalid view "%(view)s" for action "%(action)s".
diff --git a/trytond/ir/view/action_report_form.xml b/trytond/ir/view/action_report_form.xml
index 0acb0a3bb6..3a6c3e0cb5 100644
--- a/trytond/ir/view/action_report_form.xml
+++ b/trytond/ir/view/action_report_form.xml
@@ -22,7 +22,8 @@ this repository contains the full copyright notices and license terms. -->
-
+
+
diff --git a/trytond/report/report.py b/trytond/report/report.py
index 8fe33386bd..79772fa158 100644
--- a/trytond/report/report.py
+++ b/trytond/report/report.py
@@ -29,6 +29,7 @@ except ImportError:
weasyprint = None
from genshi.filters import Translator
+from genshi.template.text import TextTemplate
from trytond.i18n import gettext
from trytond.pool import Pool, PoolBase
@@ -161,8 +162,15 @@ class Report(URLMixin, PoolBase):
name_length = 0
record_count = len(records)
max_length = REPORT_NAME_MAX_LENGTH - len(str(record_count)) - 2
+ if action_report.record_name:
+ template = TextTemplate(action_report.record_name)
+ else:
+ template = None
for record in records[:5]:
- record_name = record.rec_name
+ if template:
+ record_name = template.generate(record=record).render()
+ else:
+ record_name = record.rec_name
name_length += len(record_name) + 1
if name_length > max_length:
break