diff --git a/modules/account/exceptions.py b/modules/account/exceptions.py
index ec51d4526e..0be7e42aba 100644
--- a/modules/account/exceptions.py
+++ b/modules/account/exceptions.py
@@ -21,22 +21,10 @@ class PeriodDatesError(PeriodValidationError):
pass
-class PeriodSequenceError(PeriodValidationError):
- pass
-
-
class FiscalYearNotFoundError(UserError):
pass
-class FiscalYearValidationError(ValidationError):
- pass
-
-
-class FiscalYearSequenceError(FiscalYearValidationError):
- pass
-
-
class FiscalYearCloseError(UserError):
pass
diff --git a/modules/account/fiscalyear.py b/modules/account/fiscalyear.py
index 6c948540b1..21c2393064 100644
--- a/modules/account/fiscalyear.py
+++ b/modules/account/fiscalyear.py
@@ -8,7 +8,8 @@ from sql.operators import Equal, NotEqual
from trytond.cache import Cache
from trytond.i18n import gettext
-from trytond.model import Exclude, ModelSQL, ModelView, Workflow, fields
+from trytond.model import (
+ Exclude, ModelSQL, ModelView, Unique, Workflow, fields)
from trytond.model.exceptions import AccessError
from trytond.pool import Pool
from trytond.pyson import Eval, Id
@@ -20,8 +21,7 @@ from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
from .exceptions import (
- FiscalYearCloseError, FiscalYearNotFoundError, FiscalYearReOpenError,
- FiscalYearSequenceError)
+ FiscalYearCloseError, FiscalYearNotFoundError, FiscalYearReOpenError)
STATES = {
'readonly': Eval('state') != 'open',
@@ -79,6 +79,8 @@ class FiscalYear(Workflow, ModelSQL, ModelView):
t.end_date), RangeOverlap),
(Case((t.state == 'open', t.id), else_=-1), NotEqual)),
'account.msg_open_fiscalyear_earlier'),
+ ('post_move_sequence_unique', Unique(t, t.post_move_sequence),
+ 'account.msg_fiscalyear_post_move_unique'),
]
cls._order.insert(0, ('start_date', 'DESC'))
cls._transitions |= set((
@@ -136,25 +138,8 @@ class FiscalYear(Workflow, ModelSQL, ModelView):
@classmethod
def validate_fields(cls, fiscalyears, field_names):
super().validate_fields(fiscalyears, field_names)
- cls.check_post_move_sequence(fiscalyears, field_names)
cls.check_period_dates(fiscalyears, field_names)
- @classmethod
- def check_post_move_sequence(cls, fiscalyears, field_names=None):
- if field_names and 'post_move_sequence' not in field_names:
- return
- for fiscalyear in fiscalyears:
- sequence = fiscalyear.post_move_sequence
- years = cls.search([
- ('post_move_sequence', '=', sequence.id),
- ('id', '!=', fiscalyear.id),
- ], limit=1)
- if years:
- raise FiscalYearSequenceError(gettext(
- 'account.msg_fiscalyear_different_post_move_sequence',
- first=fiscalyear.rec_name,
- second=years[0].rec_name))
-
@classmethod
def check_period_dates(cls, fiscalyears, field_names=None):
pool = Pool()
diff --git a/modules/account/message.xml b/modules/account/message.xml
index cf80cc7926..0670a47893 100644
--- a/modules/account/message.xml
+++ b/modules/account/message.xml
@@ -24,8 +24,8 @@ this repository contains the full copyright notices and license terms. -->
The dates of standard period of the same fiscal year can not overlap.
-
- You cannot use the same post move sequence for the periods "%(first)s" and "%(second)s" because they are from different fiscal years.
+
+ A post move sequence can be reused only by periods in the same fiscal year.
The dates for period "%(period)s" must be between the dates of its fiscal year "%(fiscalyear)s".
@@ -69,8 +69,8 @@ this repository contains the full copyright notices and license terms. -->
Open fiscal years can not be before closed fiscal years.
-
- The fiscal years "%(first)s" and "%(second)s" cannot have the same post move sequence, you must use different sequences.
+
+ The post move sequence of fiscal years must be unique.
To close the fiscal year, the balance of account "%(account)s" must be zero.
diff --git a/modules/account/period.py b/modules/account/period.py
index 95e10791bc..71068e1617 100644
--- a/modules/account/period.py
+++ b/modules/account/period.py
@@ -1,7 +1,7 @@
# 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 sql.operators import Equal
+from sql.operators import Equal, NotEqual
from trytond.cache import Cache
from trytond.const import OPERATORS
@@ -15,9 +15,7 @@ from trytond.sql.operators import RangeOverlap
from trytond.tools import grouped_slice
from trytond.transaction import Transaction
-from .exceptions import (
- ClosePeriodError, PeriodDatesError, PeriodNotFoundError,
- PeriodSequenceError)
+from .exceptions import ClosePeriodError, PeriodDatesError, PeriodNotFoundError
_STATES = {
'readonly': Eval('state') != 'open',
@@ -70,6 +68,11 @@ class Period(Workflow, ModelSQL, ModelView):
(DateRange(t.start_date, t.end_date, '[]'), RangeOverlap),
where=t.type == 'standard'),
'account.msg_period_standard_overlap'),
+ ('post_move_sequence_unique',
+ Exclude(t,
+ (t.post_move_sequence, Equal),
+ (t.fiscalyear, NotEqual)),
+ 'account.msg_period_post_move_sequence_unique'),
]
cls._sql_indexes.add(
Index(
@@ -135,7 +138,6 @@ class Period(Workflow, ModelSQL, ModelView):
super().validate_fields(periods, field_names)
cls.check_fiscalyear_dates(periods, field_names)
cls.check_move_dates(periods, field_names)
- cls.check_post_move_sequence(periods, field_names)
@classmethod
def check_fiscalyear_dates(cls, periods, field_names=None):
@@ -180,24 +182,6 @@ class Period(Workflow, ModelSQL, ModelView):
move=move.rec_name,
move_date=lang.strftime(move.date)))
- @classmethod
- def check_post_move_sequence(cls, periods, field_names=None):
- if field_names and not (
- field_names & {'post_move_sequence', 'fiscalyear'}):
- return
- for period in periods:
- if not period.post_move_sequence:
- continue
- periods = cls.search([
- ('post_move_sequence', '=', period.post_move_sequence.id),
- ('fiscalyear', '!=', period.fiscalyear.id),
- ])
- if periods:
- raise PeriodSequenceError(
- gettext('account.msg_period_same_sequence',
- first=period.rec_name,
- second=periods[0].rec_name))
-
@classmethod
def find(cls, company, date=None, test_state=True):
'''