diff --git a/CHANGELOG b/CHANGELOG
index bcc290f06d..abbd3b59f8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,4 @@
+* Handle errors in move template expression
* Rename split lines into reschedule lines
* Add optional credit type on account
* Always require a date to compute taxes
diff --git a/exceptions.py b/exceptions.py
index a573d01495..1742ee2f59 100644
--- a/exceptions.py
+++ b/exceptions.py
@@ -73,6 +73,10 @@ class MoveDatesError(ValidationError):
pass
+class MoveTemplateExpressionError(UserError):
+ pass
+
+
class CancelWarning(UserWarning):
pass
diff --git a/message.xml b/message.xml
index 9c690e5921..da6c47bc71 100644
--- a/message.xml
+++ b/message.xml
@@ -133,6 +133,14 @@ this repository contains the full copyright notices and license terms. -->
Use the current period to cancel the move?
+
+ Failed to evaluate expression "%(expression)s" from template "%(template)s" with error:
+"%(error)s"
+
+
+ The value "%(value)s" of "%(expression)s" from template "%(template)s" is not a number.
+
+
You cannot modify any reconciliation.
diff --git a/move_template.py b/move_template.py
index 2861b470b4..2333400ce2 100644
--- a/move_template.py
+++ b/move_template.py
@@ -3,8 +3,9 @@
from decimal import Decimal
from xml.sax.saxutils import quoteattr
-from simpleeval import simple_eval
+from simpleeval import InvalidExpression, simple_eval
+from trytond.i18n import gettext
from trytond.model import (
DeactivableMixin, ModelSQL, ModelView, fields, sequence_ordered)
from trytond.pool import Pool
@@ -14,6 +15,8 @@ from trytond.transaction import Transaction
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
+from .exceptions import MoveTemplateExpressionError
+
class MoveTemplate(DeactivableMixin, ModelSQL, ModelView):
'Account Move Template'
@@ -202,8 +205,23 @@ class MoveLineTemplate(ModelSQL, ModelView):
Keyword = pool.get('account.move.template.keyword')
line = Line()
- amount = simple_eval(decistmt(self.amount),
- functions={'Decimal': Decimal}, names=values)
+ try:
+ amount = simple_eval(decistmt(self.amount),
+ functions={'Decimal': Decimal}, names=values)
+ except InvalidExpression as e:
+ raise MoveTemplateExpressionError(
+ gettext('account.msg_move_template_invalid_expression',
+ expression=values,
+ template=self.move.rec_name,
+ error=e)) from e
+
+ if not isinstance(amount, Decimal):
+ raise MoveTemplateExpressionError(
+ gettext('account.msg_move_template_expession_not_number',
+ value=amount,
+ expression=self.move.name,
+ template=self.move.rec_name))
+
amount = self.move.company.currency.round(amount)
if self.operation == 'debit':
line.debit = amount
@@ -213,8 +231,15 @@ class MoveLineTemplate(ModelSQL, ModelView):
if self.party:
line.party = values.get(self.party)
if self.description:
- line.description = self.description.format(
- **dict(Keyword.format_values(self.move, values)))
+ try:
+ line.description = self.description.format(
+ **dict(Keyword.format_values(self.move, values)))
+ except KeyError as e:
+ raise MoveTemplateExpressionError(
+ gettext('account.msg_move_template_invalid_expression',
+ expression=values,
+ template=self.move.name,
+ error=e)) from e
line.tax_lines = [t.get_line(values) for t in self.taxes]
return line
@@ -258,8 +283,21 @@ class TaxLineTemplate(ModelSQL, ModelView):
TaxLine = pool.get('account.tax.line')
line = TaxLine()
- amount = simple_eval(decistmt(self.amount),
- functions={'Decimal': Decimal}, names=values)
+ try:
+ amount = simple_eval(decistmt(self.amount),
+ functions={'Decimal': Decimal}, names=values)
+ except InvalidExpression as e:
+ raise MoveTemplateExpressionError(
+ gettext('account.msg_template_invalid_expression',
+ expression=values,
+ template=self.line.rec_name,
+ error=e)) from e
+
+ if not isinstance(amount, Decimal):
+ raise MoveTemplateExpressionError(
+ gettext('account.msg_not_number',
+ result=amount,
+ expression=self.move.rec_name))
amount = self.line.move.company.currency.round(amount)
line.amount = amount
line.type = self.type