From 2c37f834351090210ac57c29b974a636e9fea3a8 Mon Sep 17 00:00:00 2001 From: Christophe Combelles Date: Fri, 17 Apr 2015 17:10:17 +0300 Subject: [PATCH] [FIX] analytic: duplication of analytic lines When duplicating analytic accounts, child accounts are duplicated as well. The custom copy method removes the analytic lines but this applies only on the first copy. As the copy_data method recursively copies child accounts, these child accounts did not use the custom copy method but the basic copy_data. Move to copy_data Fixes #6368, lp:1149676 --- addons/account/__openerp__.py | 1 + addons/account/test/analytic_hierarchy.yml | 56 ++++++++++++++++++++++ addons/analytic/analytic.py | 12 ++++- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 addons/account/test/analytic_hierarchy.yml diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 18277dbb4dd..d236d2643b8 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -157,6 +157,7 @@ for a particular financial year and for preparation of vouchers there is a modul #'test/account_cash_statement.yml', 'test/test_edi_invoice.yml', 'test/account_report.yml', + 'test/analytic_hierarchy.yml', 'test/account_fiscalyear_close.yml', #last test, as it will definitively close the demo fiscalyear ], 'installable': True, diff --git a/addons/account/test/analytic_hierarchy.yml b/addons/account/test/analytic_hierarchy.yml new file mode 100644 index 00000000000..117d6506b21 --- /dev/null +++ b/addons/account/test/analytic_hierarchy.yml @@ -0,0 +1,56 @@ +- + We create a simple hierarchy like this + Toplevel view account + ├ Real analytic account 1 + └ Real analytic account 2 +- + !record {model: account.analytic.account, id: analytic_account_view1}: + name: 'Toplevel view account' + type: 'view' +- + !record {model: account.analytic.account, id: analytic_account1}: + name: 'Real analytic account 1' + type: 'normal' + parent_id: analytic_account_view1 +- + !record {model: account.analytic.account, id: analytic_account2}: + name: 'Real analytic account 2' + type: 'normal' + parent_id: analytic_account_view1 +- + We add analytic lines in real accounts and journal +- + !record {model: account.analytic.journal, id: analytic_journal1}: + name: 'Analytic journal' +- + !record {model: account.analytic.line, id: analytic_line1}: + name: 'Analytic line 1' + account_id: analytic_account1 + journal_id: analytic_journal1 + general_account_id: account.a_expense +- + !record {model: account.analytic.line, id: analytic_line2}: + name: 'Analytic line 2' + account_id: analytic_account2 + journal_id: analytic_journal1 + general_account_id: account.a_expense +- + Now we copy the toplevel account +- + !function {model: account.analytic.account, name: copy, id: analytic_account_view1}: + - eval: "ref('analytic_account_view1')" +- + !python {model: account.analytic.account}: | + # the toplevel account has been copied with the (copy) suffix + accounts = self.search(cr, uid, [('name', 'like', '%Toplevel view account%')]) + assert len(accounts) == 2, 'The toplevel account has not been copied' + accounts = self.search(cr, uid, [('name', '=', 'Toplevel view account')]) + assert len(accounts) == 1, 'The toplevel account copy has a bad name' + # the sub-accounts and sub-accounts have been copied without the (copy) suffix + accounts = self.search(cr, uid, [('name', '=', 'Real analytic account 1')]) + assert len(accounts) == 2, 'The sub-account has not been copied' + accounts = self.search(cr, uid, [('name', '=', 'Real analytic account 2')]) + assert len(accounts) == 2, 'The sub-account has not been copied' + # the analytic lines should not be duplicated + lines = self.pool.get('account.analytic.line').search(cr, uid, [('name', 'like', '%Analytic line %')]) + assert len(lines) == 2, "The analytic lines shouldn't have been copied" diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 5c91caad3a5..3e402f91cf8 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -261,13 +261,21 @@ class account_analytic_account(osv.osv): def name_create(self, cr, uid, name, context=None): raise osv.except_osv(_('Warning'), _("Quick account creation disallowed.")) + def copy_data(self, cr, uid, id, default=None, context=None): + """executed for all the objects down the hierarchy during copy""" + if not default: + default = {} + default.setdefault('code', False) + default.setdefault('line_ids', []) + return super(account_analytic_account, self).copy_data(cr, uid, id, default, context=context) + def copy(self, cr, uid, id, default=None, context=None): + """ executed only on the toplevel copied object of the hierarchy. + Subobject are actually copied with copy_data""" if not default: default = {} analytic = self.browse(cr, uid, id, context=context) default.update( - code=False, - line_ids=[], name=_("%s (copy)") % (analytic['name'])) return super(account_analytic_account, self).copy(cr, uid, id, default, context=context)