Replace _constraints with validate in ModelStorage and improve user messages.

issue2616
review371002
This commit is contained in:
Albert Cervera i Areny committed 2013-03-07 16:53:42 +01:00
1 parent 5dcabe9a7f
commit 7f9c38ee89
8 files changed
+384 -211

No files matched your search

+34 -33
View File
@@ -47,12 +47,6 @@ class TypeTemplate(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(TypeTemplate, cls).__setup__()
cls._constraints += [
('check_recursion', 'recursive_types'),
]
cls._error_messages.update({
'recursive_types': 'You can not create recursive types!',
})
cls._order.insert(0, ('sequence', 'ASC'))
@classmethod
@@ -65,6 +59,11 @@ class TypeTemplate(ModelSQL, ModelView):
# Migration from 2.4: drop required on sequence
table.not_null_action('sequence', action='remove')
@classmethod
def validate(cls, records):
super(TypeTemplate, cls).validate(records)
cls.check_recursion(records, rec_name='name')
@staticmethod
def default_balance_sheet():
return False
@@ -187,12 +186,6 @@ class Type(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(Type, cls).__setup__()
cls._constraints += [
('check_recursion', 'recursive_types'),
]
cls._error_messages.update({
'recursive_types': 'You can not create recursive types!',
})
cls._order.insert(0, ('sequence', 'ASC'))
@classmethod
@@ -205,6 +198,11 @@ class Type(ModelSQL, ModelView):
# Migration from 2.4: drop required on sequence
table.not_null_action('sequence', action='remove')
@classmethod
def validate(cls, types):
super(Type, cls).validate(types)
cls.check_recursion(types, rec_name='name')
@staticmethod
def default_balance_sheet():
return False
@@ -364,15 +362,14 @@ class AccountTemplate(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(AccountTemplate, cls).__setup__()
cls._constraints += [
('check_recursion', 'recursive_accounts'),
]
cls._error_messages.update({
'recursive_accounts': 'You can not create recursive accounts!',
})
cls._order.insert(0, ('code', 'ASC'))
cls._order.insert(1, ('name', 'ASC'))
@classmethod
def validate(cls, templates):
super(AccountTemplate, cls).validate(templates)
cls.check_recursion(templates)
@staticmethod
def default_kind():
return 'view'
@@ -576,21 +573,22 @@ class Account(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(Account, cls).__setup__()
cls._constraints += [
('check_recursion', 'recursive_accounts'),
]
cls._error_messages.update({
'recursive_accounts': 'You can not create recursive accounts!',
'delete_account_containing_move_lines': ('You can not delete '
'accounts containing move lines!'),
})
'delete_account_containing_move_lines': ('You can not delete '
'account "%s" because it has move lines.'),
})
cls._sql_error_messages.update({
'parent_fkey': ('You can not delete accounts '
'that have children!'),
})
'parent_fkey': ('You can not delete accounts that have '
'children.'),
})
cls._order.insert(0, ('code', 'ASC'))
cls._order.insert(1, ('name', 'ASC'))
@classmethod
def validate(cls, accounts):
super(Account, cls).validate(accounts)
cls.check_recursion(accounts)
@staticmethod
def default_left():
return 0
@@ -870,10 +868,12 @@ class Account(ModelSQL, ModelView):
childs = cls.search([
('parent', 'child_of', [a.id for a in accounts]),
])
if MoveLine.search([
('account', 'in', [a.id for a in childs]),
]):
cls.raise_user_error('delete_account_containing_move_lines')
lines = MoveLine.search([
('account', 'in', [a.id for a in childs]),
])
if lines:
cls.raise_user_error('delete_account_containing_move_lines', (
lines[0].account.rec_name,))
super(Account, cls).delete(accounts)
def update_account(self, template2account=None, template2type=None):
@@ -2061,7 +2061,8 @@ class OpenAgedBalance(Wizard):
super(OpenAgedBalance, cls).__setup__()
cls._error_messages.update({
'warning': 'Warning',
'term_overlap_desc': 'You cannot define overlapping terms'})
'term_overlap_desc': 'You cannot define overlapping terms',
})
def do_print_(self, action):
if not (self.start.term1 < self.start.term2 < self.start.term3):
+36
View File
@@ -703,5 +703,41 @@ this repository contains the full copyright notices and license terms. -->
id="menu_aged_balance" icon="tryton-print"
name="Aged Balance"/>
<record model="ir.translation" id="account_type_template_recursion_error">
<field name="name">account.account.type.template</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">recursion_error</field>
<field name="value">Recursion error: Account Type Template "%(rec_name)s" with parent "%(parent_rec_name)s" was configured as ancestor of itself.</field>
<field name="module">account</field>
<field name="fuzzy" eval="False"/>
</record>
<record model="ir.translation" id="account_type_recursion_error">
<field name="name">account.account.type</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">recursion_error</field>
<field name="value">Recursion error: Account Type "%(rec_name)s" with parent "%(parent_rec_name)s" was configured as ancestor of itself.</field>
<field name="module">account</field>
<field name="fuzzy" eval="False"/>
</record>
<record model="ir.translation" id="account_template_recursion_error">
<field name="name">account.account.template</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">recursion_error</field>
<field name="value">Recursion error: Account Template "%(rec_name)s" with parent "%(parent_rec_name)s" was configured as ancestor of itself.</field>
<field name="module">account</field>
<field name="fuzzy" eval="False"/>
</record>
<record model="ir.translation" id="account_recursion_error">
<field name="name">account.account</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">recursion_error</field>
<field name="value">Recursion error: Account "%(rec_name)s" with parent "%(parent_rec_name)s" was configured as ancestor of itself.</field>
<field name="module">account</field>
<field name="fuzzy" eval="False"/>
</record>
</data>
</tryton>
+50 -31
View File
@@ -51,26 +51,22 @@ class FiscalYear(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(FiscalYear, cls).__setup__()
cls._constraints += [
('check_dates', 'fiscalyear_overlaps'),
('check_post_move_sequence', 'different_post_move_sequence'),
]
cls._order.insert(0, ('start_date', 'ASC'))
cls._error_messages.update({
'change_post_move_sequence': ('You can not change '
'the post move sequence'),
'no_fiscalyear_date': 'No fiscal year defined for this date!',
'fiscalyear_overlaps':
'You can not have 2 fiscal years that overlaps!',
'different_post_move_sequence':
'You must have different post move sequence per fiscal year!',
'account_balance_not_zero':
'The balance of the account "%s" must be zero!',
'close_error': ('You can not close a fiscal year until '
'there is older fiscal year opened!'),
'reopen_error': ('You can not reopen a fiscal year until '
'there is more recent fiscal year closed!'),
})
'change_post_move_sequence': ('You can not change the post '
'move sequence in fiscal year "%s".'),
'no_fiscalyear_date': 'No fiscal year defined for "%s".',
'fiscalyear_overlaps': ('Fiscal year "%(first)s" and '
'"%(second)s" overlap.'),
'different_post_move_sequence': ('Fiscal year "%(first)s" and '
'"%(second)s" have the same post move sequence.'),
'account_balance_not_zero': ('The balance of the account "%s" '
'must be zero.'),
'close_error': ('You can not close fiscal year "%s" until you '
'close all previous fiscal years.'),
'reopen_error': ('You can not reopen fiscal year "%s" until '
'you reopen all later fiscal years.'),
})
cls._buttons.update({
'create_period': {
'invisible': ((Eval('state') != 'open')
@@ -96,6 +92,13 @@ class FiscalYear(ModelSQL, ModelView):
def default_company():
return Transaction().context.get('company')
@classmethod
def validate(cls, years):
super(FiscalYear, cls).validate(years)
for year in years:
year.check_dates()
year.check_post_move_sequence()
def check_dates(self):
cursor = Transaction().cursor
cursor.execute('SELECT id '
@@ -109,17 +112,24 @@ class FiscalYear(ModelSQL, ModelView):
self.end_date, self.end_date,
self.start_date, self.end_date,
self.company.id, self.id))
if cursor.fetchone():
return False
return True
second_id = cursor.fetchone()
if second_id:
second = self.__class__(second_id[0])
self.raise_user_error('fiscalyear_overlaps', {
'first': self.rec_name,
'second': second.rec_name,
})
def check_post_move_sequence(self):
if self.search([
('post_move_sequence', '=', self.post_move_sequence.id),
('id', '!=', self.id),
]):
return False
return True
years = self.search([
('post_move_sequence', '=', self.post_move_sequence.id),
('id', '!=', self.id),
])
if years:
self.raise_user_error('different_post_move_sequence', {
'first': self.rec_name,
'second': years[0].rec_name,
})
@classmethod
def write(cls, fiscalyears, vals):
@@ -128,7 +138,8 @@ class FiscalYear(ModelSQL, ModelView):
if fiscalyear.post_move_sequence and \
fiscalyear.post_move_sequence.id != \
vals['post_move_sequence']:
cls.raise_user_error('change_post_move_sequence')
cls.raise_user_error('change_post_move_sequence', (
fiscalyear.rec_name,))
vals = vals.copy()
if 'periods' in vals:
operator = ['delete', 'unlink_all', 'unlink', 'create', 'write',
@@ -189,7 +200,9 @@ class FiscalYear(ModelSQL, ModelView):
If exception is set the function will raise an exception
if any fiscal year is found.
'''
Date = Pool().get('ir.date')
pool = Pool()
Lang = pool.get('ir.lang')
Date = pool.get('ir.date')
if not date:
date = Date.today()
@@ -200,7 +213,13 @@ class FiscalYear(ModelSQL, ModelView):
], order=[('start_date', 'DESC')], limit=1)
if not fiscalyears:
if exception:
cls.raise_user_error('no_fiscalyear_date')
language = Transaction().language
languages = Lang.search([('code', '=', language)])
if not languages:
languages = Lang.search([('code', '=', 'en_US')])
language, = languages
formatted = Lang.strftime(date, language.code, language.date)
cls.raise_user_error('no_fiscalyear_date', (formatted,))
else:
return None
return fiscalyears[0].id
@@ -242,7 +261,7 @@ class FiscalYear(ModelSQL, ModelView):
('state', '=', 'open'),
('company', '=', fiscalyear.company.id),
]):
cls.raise_user_error('close_error')
cls.raise_user_error('close_error', (fiscalyear.rec_name,))
#First close the fiscalyear to be sure
#it will not have new period created between.
+18 -12
View File
@@ -31,7 +31,7 @@ class JournalType(ModelSQL, ModelView):
def __setup__(cls):
super(JournalType, cls).__setup__()
cls._sql_constraints += [
('code_uniq', 'UNIQUE(code)', 'The code must be unique!'),
('code_uniq', 'UNIQUE(code)', 'The code must be unique.'),
]
cls._order.insert(0, ('code', 'ASC'))
@@ -199,17 +199,18 @@ class JournalPeriod(ModelSQL, ModelView):
super(JournalPeriod, cls).__setup__()
cls._sql_constraints += [
('journal_period_uniq', 'UNIQUE(journal, period)',
'You can only open one journal per period!'),
'You can only open one journal per period.'),
]
cls._order.insert(0, ('name', 'ASC'))
cls._error_messages.update({
'modify_del_journal_period': ('You can not modify/delete '
'a journal - period with moves!'),
'create_journal_period': ('You can not create '
'a journal - period on a closed period!'),
'open_journal_period': ('You can not open '
'a journal - period from a closed period!'),
})
'modify_del_journal_period': ('You can not modify/delete '
'journal - period "%s" because it has moves.'),
'create_journal_period': ('You can not create a '
'journal - period on closed period "%s".'),
'open_journal_period': ('You can not open '
'journal - period "%(journal_period)s" because period '
'"%(period)s" is closed.'),
})
@staticmethod
def default_active():
@@ -231,7 +232,8 @@ class JournalPeriod(ModelSQL, ModelView):
('period', '=', period.period.id),
], limit=1)
if moves:
cls.raise_user_error('modify_del_journal_period')
cls.raise_user_error('modify_del_journal_period', (
period.rec_name,))
@classmethod
def create(cls, vlist):
@@ -240,7 +242,8 @@ class JournalPeriod(ModelSQL, ModelView):
if vals.get('period'):
period = Period(vals['period'])
if period.state == 'close':
cls.raise_user_error('create_journal_period')
cls.raise_user_error('create_journal_period', (
period.rec_name,))
return super(JournalPeriod, cls).create(vlist)
@classmethod
@@ -251,7 +254,10 @@ class JournalPeriod(ModelSQL, ModelView):
if vals.get('state') == 'open':
for journal_period in periods:
if journal_period.period.state == 'close':
cls.raise_user_error('open_journal_period')
cls.raise_user_error('open_journal_period', {
'journal_period': journal_period.rec_name,
'period': journal_period.period.rec_name,
})
super(JournalPeriod, cls).write(periods, vals)
@classmethod
+138 -76
View File
@@ -68,31 +68,28 @@ class Move(ModelSQL, ModelView):
def __setup__(cls):
super(Move, cls).__setup__()
cls._check_modify_exclude = ['state']
cls._constraints += [
('check_centralisation', 'period_centralized_journal'),
('check_company', 'company_in_move'),
('check_date', 'date_outside_period'),
]
cls._order.insert(0, ('date', 'DESC'))
cls._order.insert(1, ('number', 'DESC'))
cls._error_messages.update({
'del_posted_move': 'You can not delete posted moves!',
'post_empty_move': 'You can not post an empty move!',
'post_unbalanced_move': 'You can not post an unbalanced move!',
'draft_posted_move_journal': ('You can not set a posted move '
'to draft in this journal!'),
'modify_posted_move': 'Move "%s" is already posted!\n'
'You can not modify a posted move.',
'period_centralized_journal': ('You can not create more than '
'one move per period\n'
'in a centralized journal!'),
'company_in_move': ('You can not create lines on accounts\n'
'of different companies in the same move!'),
'date_outside_period': ('You can not create move '
'with a date outside the period!'),
'draft_closed_period': ('You can not set to draft a move '
'from a closed period'),
})
'post_empty_move': ('You can not post move "%s" because it is '
'empty.'),
'post_unbalanced_move': ('You can not post move "%s" because '
'it is an unbalanced.'),
'draft_posted_move_journal': ('You can not set posted move '
'"%(move)s" to draft in journal "%(journal)s".'),
'modify_posted_move': ('You can not modify move "%s" because '
'it is already posted.'),
'period_centralized_journal': ('Move "%(move)s" cannot be '
'created because there is already a move in journal '
'"%(journal)s" and you cannot create more than one move '
'per period in a centralized journal.'),
'company_in_move': ('You can not create lines on accounts'
'of different companies in move "%s".'),
'date_outside_period': ('You can not create move "%(move)s" '
'because it\'s date is outside its period.'),
'draft_closed_period': ('You can not set to draft move '
'"%(move)s" because period "%(period)s" is closed.'),
})
cls._buttons.update({
'post': {
'invisible': Eval('state') == 'posted',
@@ -171,6 +168,14 @@ class Move(ModelSQL, ModelView):
])
return [('', '')] + [(m.model, m.name) for m in models]
@classmethod
def validate(cls, moves):
super(Move, cls).validate(moves)
for move in moves:
move.check_centralisation()
move.check_company()
move.check_date()
def check_centralisation(self):
if self.journal.centralised:
moves = self.search([
@@ -179,8 +184,10 @@ class Move(ModelSQL, ModelView):
('state', '!=', 'posted'),
], limit=2)
if len(moves) > 1:
return False
return True
self.raise_user_error('period_centralized_journal', {
'move': self.rec_name,
'journal': self.journal.rec_name,
})
def check_company(self):
company_id = -1
@@ -188,19 +195,19 @@ class Move(ModelSQL, ModelView):
if company_id < 0:
company_id = line.account.company.id
if line.account.company.id != company_id:
return False
return True
self.raise_user_error('company_in_move', (self.rec_name,))
def check_date(self):
return self.period.start_date <= self.date <= self.period.end_date
if (self.date < self.period.start_date
or self.date > self.period.end_date):
self.raise_user_error('date_outside_period', (self.rec_name,))
@classmethod
def check_modify(cls, moves):
'Check posted moves for modifications.'
for move in moves:
if move.state == 'posted':
cls.raise_user_error('modify_posted_move',
error_args=(move.name,))
cls.raise_user_error('modify_posted_move', (move.name,))
@classmethod
def search_rec_name(cls, name, clause):
@@ -219,7 +226,7 @@ class Move(ModelSQL, ModelView):
if len(keys):
cls.check_modify(moves)
super(Move, cls).write(moves, vals)
cls.validate(moves)
cls.validate_move(moves)
@classmethod
def create(cls, vlist):
@@ -247,7 +254,7 @@ class Move(ModelSQL, ModelView):
cls.write([move], {
'centralised_line': line.id,
})
cls.validate(moves)
cls.validate_move(moves)
return moves
@classmethod
@@ -280,7 +287,7 @@ class Move(ModelSQL, ModelView):
return new_moves
@classmethod
def validate(cls, moves):
def validate_move(cls, moves):
'''
Validate balanced move and centralise it if in centralised journal
'''
@@ -388,14 +395,14 @@ class Move(ModelSQL, ModelView):
for move in moves:
amount = Decimal('0.0')
if not move.lines:
cls.raise_user_error('post_empty_move')
cls.raise_user_error('post_empty_move', (move.rec_name,))
company = None
for line in move.lines:
amount += line.debit - line.credit
if not company:
company = line.account.company
if not company.currency.is_zero(amount):
cls.raise_user_error('post_unbalanced_move')
cls.raise_user_error('post_unbalanced_move', (move.rec_name,))
for move in moves:
values = {
'state': 'posted',
@@ -411,10 +418,16 @@ class Move(ModelSQL, ModelView):
def draft(cls, moves):
for move in moves:
if not move.journal.update_posted:
cls.raise_user_error('draft_posted_move_journal')
cls.raise_user_error('draft_posted_move_journal', {
'move': move.rec_name,
'journal': move.journal.rec_name,
})
if move.period.state == 'close':
cls.raise_user_error('draft_closed_period')
return cls.write(moves, {
cls.raise_user_error('draft_closed_period', {
'move': move.rec_name,
'journal': move.period.rec_name,
})
cls.write(moves, {
'state': 'draft',
})
@@ -429,16 +442,23 @@ class Reconciliation(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(Reconciliation, cls).__setup__()
cls._constraints += [
('check_lines', 'invalid_reconciliation'),
]
cls._error_messages.update({
'modify': 'You can not modify a reconciliation!',
'invalid_reconciliation': ('You can not create reconciliation '
'where lines are not balanced, nor valid, '
'nor in the same account, nor in account to reconcile, '
'nor from the same party!'),
})
'modify': 'You can not modify a reconciliation.',
'reconciliation_line_not_valid': ('You can not reconcile line '
'"%s" because it is not in valid state.'),
'reconciliation_different_accounts': ('You can not reconcile '
'line "%(line)s" because it\'s account "%(account1)s" is '
'different from "%(account2)s".'),
'reconciliation_account_no_reconcile': ('You can not reconcile '
'line "%(line)s" because it\'s account "%(account)s" is '
'configured as not reconcilable.'),
'reconciliation_different_parties': ('You can not reconcile '
'line "%(line)s" because it\'s party "%(party1)s" is '
'different from %(party2)s".'),
'reconciliation_unbalanced': ('You can not create a '
'reconciliation where debit "%(debit)s" and credit '
'"%(credit)s" differ.'),
})
@classmethod
def create(cls, vlist):
@@ -455,29 +475,59 @@ class Reconciliation(ModelSQL, ModelView):
def write(cls, moves, vals):
cls.raise_user_error('modify')
@classmethod
def validate(cls, reconciliations):
super(Reconciliation, cls).validate(reconciliations)
cls.check_lines(reconciliations)
@classmethod
def check_lines(cls, reconciliations):
for reconciliation in reconciliations:
amount = Decimal('0.0')
debit = Decimal('0.0')
credit = Decimal('0.0')
account = None
party = None
for line in reconciliation.lines:
if line.state != 'valid':
return False
amount += line.debit - line.credit
cls.raise_user_error('reconciliation_line_not_valid',
(line.rec_name,))
debit += line.debit
credit += line.credit
if not account:
account = line.account
elif account.id != line.account.id:
return False
cls.raise_user_error('reconciliation_different_accounts', {
'line': line.rec_name,
'account1': line.account.rec_name,
'account2': account.rec_name,
})
if not account.reconcile:
return False
cls.raise_user_error('reconciliation_account_no_reconcile',
{
'line': line.rec_name,
'account': line.account.rec_name,
})
if not party:
party = line.party
elif line.party and party.id != line.party.id:
return False
if not account.company.currency.is_zero(amount):
return False
return True
cls.raise_user_error('reconciliation_different_parties', {
'line': line.rec_name,
'party1': line.party.rec_name,
'party2': party.rec_name,
})
if not account.company.currency.is_zero(debit - credit):
language = Transaction().language
languages = Lang.search([('code', '=', language)])
if not languages:
languages = Lang.search([('code', '=', 'en_US')])
language = languages[0]
debit = Lang.currency(lang, debit, account.company.currency)
credit = Lang.currency(lang, credit, account.company.currency)
cls.raise_user_error('reconciliation_unbalanced', {
'debit': debit,
'credit': credit,
})
class Line(ModelSQL, ModelView):
@@ -553,10 +603,7 @@ class Line(ModelSQL, ModelView):
cls._sql_constraints += [
('credit_debit',
'CHECK(credit * debit = 0.0)',
'Wrong credit/debit values!'),
]
cls._constraints += [
('check_account', 'move_view_inactive_account'),
'Wrong credit/debit values.'),
]
cls.__rpc__.update({
'on_write': RPC(instantiate=0),
@@ -564,15 +611,20 @@ class Line(ModelSQL, ModelView):
})
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'add_modify_closed_journal_period': ('You can not '
'add/modify lines in a closed journal period!'),
'modify_posted_move': 'You can not modify lines of a posted move!',
'modify_reconciled': 'You can not modify reconciled lines!',
'no_journal': 'No journal defined!',
'move_view_inactive_account': ('You can not create move lines\n'
'on view/inactive accounts!'),
'already_reconciled': 'Line "%s" (%d) already reconciled!',
})
'add_modify_closed_journal_period': ('You can not '
'add/modify lines in closed journal period "%s".'),
'modify_posted_move': ('You can not modify lines of move "%s" '
'because it is already posted.'),
'modify_reconciled': ('You can not modify line "%s" because it '
'is reconciled.'),
'no_journal': ('Move line cannot be created because there is '
'no journal defined.'),
'move_view_account': ('You can not create a move line with '
'account "%s" because it is a view account.'),
'move_inactive_account': ('You can not create a move line with '
'account "%s" because it is inactive.'),
'already_reconciled': 'Line "%s" (%d) already reconciled.',
})
@classmethod
def __register__(cls, module_name):
@@ -1136,12 +1188,19 @@ class Line(ModelSQL, ModelView):
def on_write(cls, lines):
return list(set(l.id for line in lines for l in line.move.lines))
@classmethod
def validate(cls, lines):
super(Line, cls).validate(lines)
for line in lines:
line.check_account()
def check_account(self):
if self.account.kind in ('view',):
return False
self.raise_user_error('move_view_account', (
self.account.rec_name,))
if not self.account.active:
return False
return True
self.raise_user_error('move_inactive_account', (
self.account.rec_name,))
@classmethod
def check_journal_period_modify(cls, period, journal):
@@ -1157,7 +1216,8 @@ class Line(ModelSQL, ModelView):
if journal_periods:
journal_period, = journal_periods
if journal_period.state == 'close':
cls.raise_user_error('add_modify_closed_journal_period')
cls.raise_user_error('add_modify_closed_journal_period', (
journal_period.rec_name,))
else:
JournalPeriod.create([{
'name': journal.name + ' - ' + period.name,
@@ -1173,9 +1233,11 @@ class Line(ModelSQL, ModelView):
journal_period_done = []
for line in lines:
if line.move.state == 'posted':
cls.raise_user_error('modify_posted_move')
cls.raise_user_error('modify_posted_move', (
line.move.rec_name,))
if line.reconciliation:
cls.raise_user_error('modify_reconciled')
cls.raise_user_error('modify_reconciled', (
line.rec_name,))
journal_period = (line.journal.id, line.period.id)
if journal_period not in journal_period_done:
cls.check_journal_period_modify(line.period,
@@ -1188,7 +1250,7 @@ class Line(ModelSQL, ModelView):
cls.check_modify(lines)
moves = [x.move for x in lines]
super(Line, cls).delete(lines)
Move.validate(moves)
Move.validate_move(moves)
@classmethod
def write(cls, lines, vals):
@@ -1201,7 +1263,7 @@ class Line(ModelSQL, ModelView):
Transaction().timestamp = {}
Move.validate(list(set(l.move for l in lines) | set(moves)))
Move.validate_move(list(set(l.move for l in lines) | set(moves)))
@classmethod
def create(cls, vlist):
@@ -1240,7 +1302,7 @@ class Line(ModelSQL, ModelView):
for line in lines)
for period, journal in period_and_journals:
cls.check_journal_period_modify(period, journal)
Move.validate(list(set(line.move for line in lines)))
Move.validate_move(list(set(line.move for line in lines)))
return lines
@classmethod
+80 -45
View File
@@ -55,32 +55,31 @@ class Period(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(Period, cls).__setup__()
cls._constraints += [
('check_dates', 'periods_overlaps'),
('check_fiscalyear_dates', 'fiscalyear_dates'),
('check_post_move_sequence', 'check_move_sequence'),
]
cls._order.insert(0, ('start_date', 'ASC'))
cls._error_messages.update({
'no_period_date': 'No period defined for this date!',
'modify_del_period_moves': ('You can not modify/delete '
'a period with moves!'),
'create_period_closed_fiscalyear': ('You can not create '
'a period on a closed fiscal year!'),
'open_period_closed_fiscalyear': ('You can not open '
'a period from a closed fiscal year!'),
'change_post_move_sequence': ('You can not change '
'the post move sequence '
'if there is already posted moves in the period'),
'close_period_non_posted_move': ('You can not close '
'a period with non posted moves!'),
'periods_overlaps': 'You can not have two overlapping periods!',
'check_move_sequence': ('You must have different '
'post move sequences per fiscal year '
'and in the same company!'),
'fiscalyear_dates': ('The period dates must be in '
'the fiscal year dates'),
})
'no_period_date': 'No period defined for date "%s".',
'modify_del_period_moves': ('You can not modify/delete '
'period "%s" because it has moves.'),
'create_period_closed_fiscalyear': ('You can not create '
'a period on fiscal year "%s" because it is closed.'),
'open_period_closed_fiscalyear': ('You can not open period '
'"%(period)s" because its fiscal year "%(fiscalyear)s" is '
'closed.'),
'change_post_move_sequence': ('You can not change the post '
'move sequence of period "%s" because there are already '
'posted moves in the period.'),
'close_period_non_posted_move': ('You can not close period '
'"%s" because there are non posted moves in this period.'),
'periods_overlap': ('"%(first)s" and "%(second)s" periods '
'overlap.'),
'check_move_sequence': ('Period "%(first)s" and "%(second)s" '
'have the same sequence.'),
'check_move_sequence_company': ('Company of sequence '
'"%(sequence)s" does not match the company of period '
'"%(period)s" to which it is assigned to.'),
'fiscalyear_dates': ('Dates of period "%s" are outside '
'are outside it\'s fiscal year dates.'),
})
@staticmethod
def default_state():
@@ -97,6 +96,14 @@ class Period(ModelSQL, ModelView):
def search_company(cls, name, clause):
return [('fiscalyear.%s' % name,) + tuple(clause[1:])]
@classmethod
def validate(cls, periods):
super(Period, cls).validate(periods)
for period in periods:
period.check_dates()
period.check_fiscalyear_dates()
period.check_post_move_sequence()
def check_dates(self):
cursor = Transaction().cursor
if self.type != 'standard':
@@ -113,25 +120,37 @@ class Period(ModelSQL, ModelView):
self.end_date, self.end_date,
self.start_date, self.end_date,
self.fiscalyear.id, self.id))
return not cursor.fetchone()
period_id = cursor.fetchone()
if period_id:
overlapping_period = self.__class__(period_id[0])
self.raise_user_error('periods_overlap', {
'first': self.rec_name,
'second': overlapping_period.rec_name,
})
def check_fiscalyear_dates(self):
return not (self.start_date < self.fiscalyear.start_date
or self.end_date > self.fiscalyear.end_date)
if (self.start_date < self.fiscalyear.start_date
or self.end_date > self.fiscalyear.end_date):
self.raise_user_error('fiscalyear_dates', (self.rec_name,))
def check_post_move_sequence(self):
if not self.post_move_sequence:
return True
if self.search([
('post_move_sequence', '=', self.post_move_sequence.id),
('fiscalyear', '!=', self.fiscalyear.id),
]):
return False
if (self.post_move_sequence.company
and (self.post_move_sequence.company.id !=
self.fiscalyear.company.id)):
return False
return True
return
periods = self.search([
('post_move_sequence', '=', self.post_move_sequence.id),
('fiscalyear', '!=', self.fiscalyear.id),
])
if periods:
self.raise_user_error('check_move_sequence', {
'first': self.rec_name,
'second': periods[0].rec_name,
})
if (self.post_move_sequence.company and
self.post_move_sequence.company != self.fiscalyear.company):
self.raise_user_error('check_move_sequence_company', {
'sequence': self.post_move_sequence.rec_name,
'period': self.rec_name,
})
@classmethod
def find(cls, company_id, date=None, exception=True, test_state=True):
@@ -142,7 +161,9 @@ class Period(ModelSQL, ModelView):
if no period is found.
If test_state is true, it will search on non-closed periods
'''
Date = Pool().get('ir.date')
pool = Pool()
Date = pool.get('ir.date')
Lang = pool.get('ir.lang')
if not date:
date = Date.today()
@@ -157,7 +178,14 @@ class Period(ModelSQL, ModelView):
periods = cls.search(clause, order=[('start_date', 'DESC')], limit=1)
if not periods:
if exception:
cls.raise_user_error('no_period_date')
language = Transaction().language
languages = Lang.search([('code', '=', language)])
if not languages:
languages = Lang.search([('code', '=', 'en_US')])
language = languages[0]
formatted = Lang.strftime(date, language.code,
language.date)
cls.raise_user_error('no_period_date', (formatted,))
else:
return None
return periods[0].id
@@ -169,7 +197,8 @@ class Period(ModelSQL, ModelView):
('period', 'in', [p.id for p in periods]),
], limit=1)
if moves:
cls.raise_user_error('modify_del_period_moves')
cls.raise_user_error('modify_del_period_moves', (
moves[0].period.rec_name,))
@classmethod
def search(cls, args, offset=0, limit=None, order=None, count=False,
@@ -206,7 +235,8 @@ class Period(ModelSQL, ModelView):
if vals.get('fiscalyear'):
fiscalyear = FiscalYear(vals['fiscalyear'])
if fiscalyear.state == 'close':
cls.raise_user_error('create_period_closed_fiscalyear')
cls.raise_user_error('create_period_closed_fiscalyear',
(fiscalyear.rec_name,))
if not vals.get('post_move_sequence'):
vals['post_move_sequence'] = (
fiscalyear.post_move_sequence.id)
@@ -222,7 +252,10 @@ class Period(ModelSQL, ModelView):
if vals.get('state') == 'open':
for period in periods:
if period.fiscalyear.state == 'close':
cls.raise_user_error('open_period_closed_fiscalyear')
cls.raise_user_error('open_period_closed_fiscalyear', {
'period': period.rec_name,
'fiscalyear': period.fiscalyear.rec_name,
})
if vals.get('post_move_sequence'):
for period in periods:
if period.post_move_sequence and \
@@ -232,7 +265,8 @@ class Period(ModelSQL, ModelView):
('period', '=', period.id),
('state', '=', 'posted'),
]):
cls.raise_user_error('change_post_move_sequence')
cls.raise_user_error('change_post_move_sequence',
(period.rec_name,))
super(Period, cls).write(periods, vals)
@classmethod
@@ -250,7 +284,8 @@ class Period(ModelSQL, ModelView):
('period', 'in', [p.id for p in periods]),
('state', '!=', 'posted'),
]):
cls.raise_user_error('close_period_non_posted_move')
cls.raise_user_error('close_period_non_posted_move',
(period.rec_name,))
#First close the period to be sure
#it will not have new journal.period created between.
cls.write(periods, {
+10 -14
View File
@@ -58,16 +58,14 @@ class TaxCodeTemplate(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(TaxCodeTemplate, cls).__setup__()
cls._constraints += [
('check_recursion', 'recursive_tax_code'),
]
cls._error_messages.update({
'recursive_tax_code': (
'You can not create recursive tax codes!'),
})
cls._order.insert(0, ('code', 'ASC'))
cls._order.insert(0, ('account', 'ASC'))
@classmethod
def validate(cls, templates):
super(CodeTemplate, cls).validate(templates)
cls.check_recursion(templates)
def _get_tax_code_value(self, code=None):
'''
Set values for tax code creation.
@@ -159,15 +157,13 @@ class TaxCode(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(TaxCode, cls).__setup__()
cls._constraints += [
('check_recursion', 'recursive_tax_code'),
]
cls._error_messages.update({
'recursive_tax_code': (
'You can not create recursive tax codes!'),
})
cls._order.insert(0, ('code', 'ASC'))
@classmethod
def validate(cls, codes):
super(TaxCode, cls).validate(codes)
cls.check_recursion(codes)
@staticmethod
def default_active():
return True
+18
View File
@@ -506,5 +506,23 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.translation" id="tax_code_recursion_error">
<field name="name">account.tax.code</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">recursion_error</field>
<field name="value">Recursion error: Tax Code "%(rec_name)s" with parent "%(parent_rec_name)s" was configured as ancestor of itself.</field>
<field name="module">account</field>
<field name="fuzzy" eval="False"/>
</record>
<record model="ir.translation" id="tax_code_template_recursion_error">
<field name="name">account.tax.code.template</field>
<field name="lang">en_US</field>
<field name="type">error</field>
<field name="src">recursion_error</field>
<field name="value">Recursion error: Tax Code Template "%(rec_name)s" with parent "%(parent_rec_name)s" was configured as ancestor of itself.</field>
<field name="module">account</field>
<field name="fuzzy" eval="False"/>
</record>
</data>
</tryton>