From 432a6cdbd5f7a2f5da5d6494edc36b0400a72d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 29 Dec 2018 14:20:29 +0100 Subject: [PATCH] Add ir.message and use custom exceptions issue3672 --- exceptions.py | 19 +++++++ journal.py | 2 +- message.xml | 40 ++++++++++++++ statement.py | 83 ++++++++++++++++++---------- tests/scenario_account_statement.rst | 8 +-- tests/scenario_statement_origin.rst | 2 +- tryton.cfg | 1 + 7 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 exceptions.py create mode 100644 message.xml diff --git a/exceptions.py b/exceptions.py new file mode 100644 index 0000000000..9a74270bc4 --- /dev/null +++ b/exceptions.py @@ -0,0 +1,19 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. +from trytond.exceptions import UserError, UserWarning + + +class ImportStatementError(UserError): + pass + + +class StatementValidateError(UserError): + pass + + +class StatementValidateWarning(UserWarning): + pass + + +class StatementPostError(UserError): + pass diff --git a/journal.py b/journal.py index e032cc6f22..91d9cba992 100644 --- a/journal.py +++ b/journal.py @@ -49,7 +49,7 @@ class Journal(ModelSQL, ModelView): cls._sql_constraints = [ ('bank_account_unique', Unique(t, t.bank_account, t.company), - "Only one journal is allowed per bank account."), + 'account_statement.msg_journal_bank_account_unique'), ] @classmethod diff --git a/message.xml b/message.xml new file mode 100644 index 0000000000..cdf80ac874 --- /dev/null +++ b/message.xml @@ -0,0 +1,40 @@ + + + + + + Only one journal is allowed per bank account. + + + To import statement, you must create a journal for account "%(account)s". + + + To import statement, the journal "%(journal)s" must have the currency "%(currency)s" instead of "%(journal_currency)s". + + + To validate statement "%(statement)s" you must change lines to have end balance of %(end_balance)s instead of %(amount)s. + + + To validate statement "%(statement)s" you must change lines to have total amount of %(total_amount)s instead of %(amount)s. + + + To validate statement "%(statement)s" you must add %(n)s line(s). + + + To validate statement "%(statement)s" you must remove %(n)s line(s). + + + To delete statement "%(statement)s" you must cancel it. + + + The validation of the statements will remove paid invoices from other statements. + + + To post statement "%(statement)s" you must create lines for pending %(amount)s of origin "%(origin)s". + + + Statement line amount cannot be zero. + + + diff --git a/statement.py b/statement.py index a2825d27b7..50f4b33517 100644 --- a/statement.py +++ b/statement.py @@ -9,14 +9,19 @@ from sql.conditionals import Coalesce from sql.aggregate import Max, Sum from trytond.config import config +from trytond.i18n import gettext from trytond.model import Workflow, ModelView, ModelSQL, fields, Check, \ sequence_ordered, DictSchemaMixin +from trytond.model.exceptions import AccessError from trytond.pyson import Eval, If, Bool from trytond.transaction import Transaction from trytond.pool import Pool from trytond.wizard import Wizard, StateView, StateAction, Button from trytond.modules.company import CompanyReport +from .exceptions import ( + StatementValidateError, StatementValidateWarning, StatementPostError) + __all__ = ['Statement', 'Line', 'LineGroup', 'Origin', 'OriginInformation', 'ImportStatementStart', 'ImportStatement', @@ -139,18 +144,6 @@ class Statement(Workflow, ModelSQL, ModelView): def __setup__(cls): super(Statement, cls).__setup__() cls._order[0] = ('id', 'DESC') - cls._error_messages.update({ - 'wrong_end_balance': 'End Balance must be "%s".', - 'wrong_total_amount': 'Total Amount must be "%s".', - 'wrong_number_of_lines': 'Number of Lines must be "%s".', - 'delete_cancel': ('Statement "%s" must be cancelled before ' - 'deletion.'), - 'paid_invoice_draft_statement': ('There are paid invoices on ' - 'draft statements.'), - 'post_with_pending_amount': ('Origin line "%(origin)s" ' - 'of statement "%(statement)s" still has a pending amount ' - 'of "%(amount)s".'), - }) cls._transitions |= set(( ('draft', 'validated'), ('draft', 'cancel'), @@ -377,7 +370,9 @@ class Statement(Workflow, ModelSQL, ModelView): cls.cancel(statements) for statement in statements: if statement.state != 'cancel': - cls.raise_user_error('delete_cancel', (statement.rec_name,)) + raise AccessError( + gettext('account_statement.msg_statement_delete_cancel', + statement=statement.rec_name)) super(Statement, cls).delete(statements) @classmethod @@ -390,12 +385,18 @@ class Statement(Workflow, ModelSQL, ModelView): pool = Pool() Lang = pool.get('ir.lang') - end_balance = (self.start_balance + amount = (self.start_balance + sum(l.amount for l in self.lines)) - if end_balance != self.end_balance: + if amount != self.end_balance: lang = Lang.get() - amount = lang.currency(end_balance, self.journal.currency) - self.raise_user_error('wrong_end_balance', amount) + end_balance = lang.currency( + self.end_balance, self.journal.currency) + amount = lang.currency(amount, self.journal.currency) + raise StatementValidateError( + gettext('account_statement.msg_statement_wrong_end_balance', + statement=self.rec_name, + end_balance=end_balance, + amount=amount)) def validate_amount(self): pool = Pool() @@ -404,13 +405,29 @@ class Statement(Workflow, ModelSQL, ModelView): amount = sum(l.amount for l in self.lines) if amount != self.total_amount: lang = Lang.get() + total_amount = lang.currency( + self.total_amount, self.journal.currency) amount = lang.currency(amount, self.journal.currency) - self.raise_user_error('wrong_total_amount', amount) + raise StatementValidateError( + gettext('account_statement.msg_statement_wrong_total_amount', + statement=self.rec_name, + total_amount=total_amount, + amount=amount)) def validate_number_of_lines(self): number = len(list(self.grouped_lines)) - if number != self.number_of_lines: - self.raise_user_error('wrong_number_of_lines', number) + if number > self.number_of_lines: + raise StatementValidateError( + gettext('account_statement' + '.msg_statement_wrong_number_of_lines_remove', + statement=self.rec_name, + n=number - self.number_of_lines)) + elif number < self.number_of_lines: + raise StatementValidateError( + gettext('account_statement' + '.msg_statement_wrong_number_of_lines_remove', + statement=self.rec_name, + n=self.number_of_lines - number)) @classmethod @ModelView.button @@ -418,6 +435,7 @@ class Statement(Workflow, ModelSQL, ModelView): def validate_statement(cls, statements): pool = Pool() Line = pool.get('account.statement.line') + Warning = pool.get('res.user.warning') for statement in statements: getattr(statement, 'validate_%s' % statement.validation)() @@ -433,7 +451,10 @@ class Statement(Workflow, ModelSQL, ModelView): ]) if common_lines: warning_key = '_'.join(str(l.id) for l in common_lines) - cls.raise_user_warning(warning_key, 'paid_invoice_draft_statement') + if Warning.check(warning_key): + raise StatementValidateWarning(warning_key, + gettext('account_statement' + '.msg_statement_paid_invoice_draft')) Line.write(common_lines, { 'invoice': None, }) @@ -537,15 +558,21 @@ class Statement(Workflow, ModelSQL, ModelView): @ModelView.button @Workflow.transition('posted') def post(cls, statements): - StatementLine = Pool().get('account.statement.line') + pool = Pool() + Lang = pool.get('ir.lang') + StatementLine = pool.get('account.statement.line') for statement in statements: for origin in statement.origins: if origin.pending_amount: - cls.raise_user_error('post_with_pending_amount', { - 'origin': origin.rec_name, - 'amount': origin.pending_amount, - 'statement': statement.rec_name, - }) + lang = Lang.get() + amount = lang.currency( + origin.pending_amount, statement.journal.currency) + raise StatementPostError( + gettext('account_statement' + '.msg_statement_post_pending_amount', + statement=statement.rec_name, + amount=amount, + origin=origin.rec_name)) lines = [l for s in statements for l in s.lines] StatementLine.post_move(lines) @@ -674,7 +701,7 @@ class Line( t = cls.__table__() cls._sql_constraints += [ ('check_statement_line_amount', Check(t, t.amount != 0), - 'Amount should be a positive or negative value.'), + 'account_statement.msg_line_amount_non_zero'), ] @staticmethod diff --git a/tests/scenario_account_statement.rst b/tests/scenario_account_statement.rst index 6e23ff3a85..adc23c1025 100644 --- a/tests/scenario_account_statement.rst +++ b/tests/scenario_account_statement.rst @@ -360,7 +360,7 @@ Testing the use of an invoice in multiple statements:: >>> statement1.click('validate_statement') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - UserWarning: ... + StatementValidateWarning: ... >>> statement2.reload() >>> Model.get('res.user.warning')(user=config.user, ... name=str(statement2.lines[0].id), always=True).save() @@ -396,7 +396,7 @@ Testing balance validation:: >>> statement.click('validate_statement') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - UserError: ... + StatementValidateError: ... >>> second_line = statement.lines.new() >>> second_line.date = today @@ -425,7 +425,7 @@ Testing amount validation:: >>> statement.click('validate_statement') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - UserError: ... + StatementValidateError: ... >>> second_line = statement.lines.new() >>> second_line.date = today @@ -454,7 +454,7 @@ Test number of lines validation:: >>> statement.click('validate_statement') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - UserError: ... + StatementValidateError: ... >>> second_line = statement.lines.new() >>> second_line.date = today diff --git a/tests/scenario_statement_origin.rst b/tests/scenario_statement_origin.rst index 7c1f9f72d3..59fddd0bca 100644 --- a/tests/scenario_statement_origin.rst +++ b/tests/scenario_statement_origin.rst @@ -86,7 +86,7 @@ Statement can not be posted until all origins are finished:: >>> statement.click('post') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... - UserError: ... + StatementPostError: ... >>> statement.click('draft') >>> origin, = statement.origins >>> line = origin.lines.new() diff --git a/tryton.cfg b/tryton.cfg index f992c8bfff..cade7dc6d7 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -10,3 +10,4 @@ depends: xml: statement.xml journal.xml + message.xml