Use SQL constraint to enforce unique usage of post move sequence

This commit is contained in:
Cédric Krier
2024-10-10 00:34:19 +02:00
parent 6f4fbb008a
commit 1e7dd3c351
4 changed files with 16 additions and 59 deletions
-12
View File
@@ -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
+5 -20
View File
@@ -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()
+4 -4
View File
@@ -24,8 +24,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_period_standard_overlap">
<field name="text">The dates of standard period of the same fiscal year can not overlap.</field>
</record>
<record model="ir.message" id="msg_period_same_sequence">
<field name="text">You cannot use the same post move sequence for the periods "%(first)s" and "%(second)s" because they are from different fiscal years.</field>
<record model="ir.message" id="msg_period_post_move_sequence_unique">
<field name="text">A post move sequence can be reused only by periods in the same fiscal year.</field>
</record>
<record model="ir.message" id="msg_period_fiscalyear_dates">
<field name="text">The dates for period "%(period)s" must be between the dates of its fiscal year "%(fiscalyear)s".</field>
@@ -69,8 +69,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_open_fiscalyear_earlier">
<field name="text">Open fiscal years can not be before closed fiscal years.</field>
</record>
<record model="ir.message" id="msg_fiscalyear_different_post_move_sequence">
<field name="text">The fiscal years "%(first)s" and "%(second)s" cannot have the same post move sequence, you must use different sequences.</field>
<record model="ir.message" id="msg_fiscalyear_post_move_sequence_unique">
<field name="text">The post move sequence of fiscal years must be unique.</field>
</record>
<record model="ir.message" id="msg_close_fiscalyear_account_balance_not_zero">
<field name="text">To close the fiscal year, the balance of account "%(account)s" must be zero.</field>
+7 -23
View File
@@ -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):
'''