From 21c76b21ca3f2369db72e47aa79ef3cf8a4cf517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 26 Sep 2012 19:43:02 +0200 Subject: [PATCH] Add cumulate option for Debit/Credit on Account issue1893 review455001 --- CHANGELOG | 1 + account.py | 71 ++++++++------- fiscalyear.py | 2 +- tests/test_account.py | 205 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 34 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5071dcb760..ee4d629ad1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add cumulate option for Debit/Credit on Account * Allow to open accounts from balance sheet * Add start/end balance to Trial balance diff --git a/account.py b/account.py index 92b6bbe7a5..977becd763 100644 --- a/account.py +++ b/account.py @@ -723,6 +723,8 @@ class Account(ModelSQL, ModelView): def get_credit_debit(cls, accounts, names): ''' Function to compute debit, credit for accounts. + If cumulate is set in the context, it is the cumulate amount over all + previous fiscal year. ''' res = {} pool = Pool() @@ -771,43 +773,46 @@ class Account(ModelSQL, ModelView): for name in names: res[name].setdefault(account.id, Decimal('0.0')) - youngest_fiscalyear = None - for fiscalyear in FiscalYear.browse(fiscalyear_ids): - if not youngest_fiscalyear \ - or youngest_fiscalyear.start_date > fiscalyear.start_date: - youngest_fiscalyear = fiscalyear + if Transaction().context.get('cumulate'): + youngest_fiscalyear = None + for fiscalyear in FiscalYear.browse(fiscalyear_ids): + if (not youngest_fiscalyear + or (youngest_fiscalyear.start_date + > fiscalyear.start_date)): + youngest_fiscalyear = fiscalyear - fiscalyear = None - if youngest_fiscalyear: - fiscalyears = FiscalYear.search([ - ('end_date', '<=', youngest_fiscalyear.start_date), - ('company', '=', youngest_fiscalyear.company), - ], order=[('end_date', 'DESC')], limit=1) - if fiscalyears: - fiscalyear, = fiscalyears + fiscalyear = None + if youngest_fiscalyear: + fiscalyears = FiscalYear.search([ + ('end_date', '<=', youngest_fiscalyear.start_date), + ('company', '=', youngest_fiscalyear.company), + ], order=[('end_date', 'DESC')], limit=1) + if fiscalyears: + fiscalyear, = fiscalyears - if fiscalyear: - if fiscalyear.state == 'close': - deferrals = Deferral.search([ - ('fiscalyear', '=', fiscalyear.id), - ('account', 'in', ids), - ]) - id2deferral = {} - for deferral in deferrals: - id2deferral[deferral.account.id] = deferral + if fiscalyear: + if fiscalyear.state == 'close': + deferrals = Deferral.search([ + ('fiscalyear', '=', fiscalyear.id), + ('account', 'in', ids), + ]) + id2deferral = {} + for deferral in deferrals: + id2deferral[deferral.account.id] = deferral - for account in accounts: - if account.id in id2deferral: - deferral = id2deferral[account.id] + for account in accounts: + if account.id in id2deferral: + deferral = id2deferral[account.id] + for name in names: + res[name][account.id] += getattr(deferral, + name) + else: + with Transaction().set_context(fiscalyear=fiscalyear.id, + date=None, dates=None): + res2 = cls.get_credit_debit(accounts, names) + for account in accounts: for name in names: - res[name][account.id] += getattr(deferral, name) - else: - with Transaction().set_context(fiscalyear=fiscalyear.id, - date=None, dates=None): - res2 = cls.get_credit_debit(accounts, names) - for account in accounts: - for name in names: - res[name][account.id] += res2[name][account.id] + res[name][account.id] += res2[name][account.id] for account in accounts: company_id = account2company[account.id] diff --git a/fiscalyear.py b/fiscalyear.py index fa43161816..683c8529e4 100644 --- a/fiscalyear.py +++ b/fiscalyear.py @@ -253,7 +253,7 @@ class FiscalYear(ModelSQL, ModelView): Period.close(periods) with Transaction().set_context(fiscalyear=fiscalyear.id, - date=None): + date=None, cumulate=True): accounts = Account.search([ ('company', '=', fiscalyear.company.id), ]) diff --git a/tests/test_account.py b/tests/test_account.py index 072feb0905..19b61a6338 100644 --- a/tests/test_account.py +++ b/tests/test_account.py @@ -11,6 +11,7 @@ if os.path.isdir(DIR): import unittest import datetime +from decimal import Decimal import trytond.tests.test_tryton from trytond.tests.test_tryton import test_view, test_depends from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT @@ -32,6 +33,9 @@ class AccountTestCase(unittest.TestCase): self.user = POOL.get('res.user') self.fiscalyear = POOL.get('account.fiscalyear') self.sequence = POOL.get('ir.sequence') + self.move = POOL.get('account.move') + self.journal = POOL.get('account.journal') + self.account_type = POOL.get('account.account.type') def test0005views(self): ''' @@ -102,6 +106,207 @@ class AccountTestCase(unittest.TestCase): self.assertEqual(len(fiscalyear.periods), 12) transaction.cursor.commit() + def test0030account_debit_credit(self): + ''' + Test account debit/credit. + ''' + with Transaction().start(DB_NAME, USER, + context=CONTEXT) as transaction: + fiscalyear, = self.fiscalyear.search([]) + period = fiscalyear.periods[0] + journal_revenue, = self.journal.search([ + ('code', '=', 'REV'), + ]) + journal_expense, = self.journal.search([ + ('code', '=', 'EXP'), + ]) + revenue, = self.account.search([ + ('kind', '=', 'revenue'), + ]) + receivable, = self.account.search([ + ('kind', '=', 'receivable'), + ]) + expense, = self.account.search([ + ('kind', '=', 'expense'), + ]) + payable, = self.account.search([ + ('kind', '=', 'payable'), + ]) + # Create some moves + values = [ + { + 'name': 'Test 1', + 'period': period.id, + 'journal': journal_revenue.id, + 'date': period.start_date, + 'lines': [ + ('create', { + 'name': 'Test 1', + 'account': revenue.id, + 'credit': Decimal(100), + }), + ('create', { + 'name': 'Test 1', + 'account': receivable.id, + 'debit': Decimal(100), + }), + ], + }, + { + 'name': 'Test 2', + 'period': period.id, + 'journal': journal_expense.id, + 'date': period.start_date, + 'lines': [ + ('create', { + 'name': 'Test 2', + 'account': expense.id, + 'debit': Decimal(30), + }), + ('create', { + 'name': 'Test 2', + 'account': payable.id, + 'credit': Decimal(30), + }), + ], + }, + ] + for value in values: + self.move.create(value) + + # Test debit/credit + self.assertEqual((revenue.debit, revenue.credit), + (Decimal(0), Decimal(100))) + self.assertEqual(revenue.balance, Decimal(-100)) + + # Use next fiscalyear + next_sequence = self.sequence.create({ + 'name': 'Next Year', + 'code': 'account.move', + 'company': fiscalyear.company.id, + }) + next_fiscalyear, = self.fiscalyear.copy([fiscalyear], + default={ + 'start_date': fiscalyear.end_date + datetime.timedelta(1), + 'end_date': fiscalyear.end_date + datetime.timedelta(360), + 'post_move_sequence': next_sequence.id, + 'periods': None, + }) + self.fiscalyear.create_period([next_fiscalyear]) + + # Test debit/credit for next year + with Transaction().set_context(fiscalyear=next_fiscalyear.id): + revenue = self.account(revenue.id) + self.assertEqual((revenue.debit, revenue.credit), + (Decimal(0), Decimal(0))) + self.assertEqual(revenue.balance, Decimal(-100)) + + # Test debit/credit cumulate for next year + with Transaction().set_context(fiscalyear=next_fiscalyear.id, + cumulate=True): + revenue = self.account(revenue.id) + self.assertEqual((revenue.debit, revenue.credit), + (Decimal(0), Decimal(100))) + self.assertEqual(revenue.balance, Decimal(-100)) + + # Close fiscalyear + journal_sequence, = self.sequence.search([ + ('code', '=', 'account.journal'), + ]) + journal_closing = self.journal.create({ + 'name': 'Closing', + 'code': 'CLO', + 'type': 'situation', + 'sequence': journal_sequence.id, + }) + type_equity, = self.account_type.search([ + ('name', '=', 'Equity'), + ]) + account_pl = self.account.create({ + 'name': 'P&L', + 'type': type_equity.id, + 'deferral': True, + 'parent': revenue.parent.id, + 'kind': 'other', + }) + self.move.create({ + 'name': 'Closing', + 'period': fiscalyear.periods[-1].id, + 'journal': journal_closing.id, + 'date': fiscalyear.periods[-1].end_date, + 'lines': [ + ('create', { + 'name': 'Closing', + 'account': revenue.id, + 'debit': Decimal(100), + }), + ('create', { + 'name': 'Closing', + 'account': expense.id, + 'credit': Decimal(30), + }), + ('create', { + 'name': 'Closing', + 'account': account_pl.id, + 'credit': Decimal('70'), + }), + ], + }) + moves = self.move.search([ + ('state', '=', 'draft'), + ('period.fiscalyear', '=', fiscalyear.id), + ]) + self.move.post(moves) + self.fiscalyear.close([fiscalyear]) + + # Check deferral + self.assertEqual(revenue.deferrals, ()) + + deferral_receivable, = receivable.deferrals + self.assertEqual( + (deferral_receivable.debit, deferral_receivable.credit), + (Decimal(100), Decimal(0))) + self.assertEqual(deferral_receivable.fiscalyear, fiscalyear) + + # Test debit/credit + with Transaction().set_context(fiscalyear=fiscalyear.id): + revenue = self.account(revenue.id) + self.assertEqual((revenue.debit, revenue.credit), + (Decimal(100), Decimal(100))) + self.assertEqual(revenue.balance, Decimal(0)) + + receivable = self.account(receivable.id) + self.assertEqual((receivable.debit, receivable.credit), + (Decimal(100), Decimal(0))) + self.assertEqual(receivable.balance, Decimal(100)) + + # Test debit/credit for next year + with Transaction().set_context(fiscalyear=next_fiscalyear.id): + revenue = self.account(revenue.id) + self.assertEqual((revenue.debit, revenue.credit), + (Decimal(0), Decimal(0))) + self.assertEqual(revenue.balance, Decimal(0)) + + receivable = self.account(receivable.id) + self.assertEqual((receivable.debit, receivable.credit), + (Decimal(0), Decimal(0))) + self.assertEqual(receivable.balance, Decimal(100)) + + # Test debit/credit cumulate for next year + with Transaction().set_context(fiscalyear=next_fiscalyear.id, + cumulate=True): + revenue = self.account(revenue.id) + self.assertEqual((revenue.debit, revenue.credit), + (Decimal(0), Decimal(0))) + self.assertEqual(revenue.balance, Decimal(0)) + + receivable = self.account(receivable.id) + self.assertEqual((receivable.debit, receivable.credit), + (Decimal(100), Decimal(0))) + self.assertEqual(receivable.balance, Decimal(100)) + + transaction.cursor.rollback() + def suite(): suite = trytond.tests.test_tryton.suite()