From bc33b8dd04aea344a1e92a3cf2e06e849a9e5ff8 Mon Sep 17 00:00:00 2001 From: Arthur Maniet Date: Fri, 27 Mar 2015 12:55:23 +0100 Subject: [PATCH] [IMP] account_bank_statement_import: ask for confirmation before creating a journal In previous versions the system would simply refuse to import a bank statement if the corresponding journal/account did not exist. As of 9.0 the system can create them automatically, but should not do that without asking for confirmation first, to avoid user mistakes with dangerous consequences. Closes #6023 --- .../account_bank_statement_import/__init__.py | 2 + .../__openerp__.py | 3 +- .../account_bank_statement_import.py | 72 ++++++++++--------- .../wizard/__init__.py | 1 + .../wizard/journal_creation.py | 42 +++++++++++ .../wizard/journal_creation.xml | 27 +++++++ .../tests/test_import_bank_statement.py | 11 ++- 7 files changed, 122 insertions(+), 36 deletions(-) create mode 100644 addons/account_bank_statement_import/wizard/__init__.py create mode 100644 addons/account_bank_statement_import/wizard/journal_creation.py create mode 100644 addons/account_bank_statement_import/wizard/journal_creation.xml diff --git a/addons/account_bank_statement_import/__init__.py b/addons/account_bank_statement_import/__init__.py index 0882f8a9139..a72befb7117 100644 --- a/addons/account_bank_statement_import/__init__.py +++ b/addons/account_bank_statement_import/__init__.py @@ -1,3 +1,5 @@ # -*- encoding: utf-8 -*- import account_bank_statement_import + +import wizard diff --git a/addons/account_bank_statement_import/__openerp__.py b/addons/account_bank_statement_import/__openerp__.py index d074ea16901..e40afbdc484 100644 --- a/addons/account_bank_statement_import/__openerp__.py +++ b/addons/account_bank_statement_import/__openerp__.py @@ -9,7 +9,8 @@ 'description' : """Generic Wizard to Import Bank Statements. Includes the import of files in .OFX format""", 'data' : [ 'account_bank_statement_import_view.xml', - 'account_import_tip_data.xml' + 'account_import_tip_data.xml', + 'wizard/journal_creation.xml', ], 'demo': [ 'demo/fiscalyear_period.xml', diff --git a/addons/account_bank_statement_import/account_bank_statement_import.py b/addons/account_bank_statement_import/account_bank_statement_import.py index 6a39a6a2920..67818766e17 100644 --- a/addons/account_bank_statement_import/account_bank_statement_import.py +++ b/addons/account_bank_statement_import/account_bank_statement_import.py @@ -37,21 +37,47 @@ class account_bank_statement_import(osv.TransientModel): context = {} #set the active_id in the context, so that any extension module could #reuse the fields chosen in the wizard if needed (see .QIF for example) - context.update({'active_id': ids[0]}) + ctx = dict(context) + ctx['active_id'] = ids[0] - data_file = self.browse(cr, uid, ids[0], context=context).data_file + data_file = self.browse(cr, uid, ids[0], context=ctx).data_file # The appropriate implementation module returns the required data - currency_code, account_number, stmts_vals = self._parse_file(cr, uid, base64.b64decode(data_file), context=context) + currency_code, account_number, stmts_vals = self._parse_file(cr, uid, base64.b64decode(data_file), context=ctx) # Check raw data - self._check_parsed_data(cr, uid, stmts_vals, context=context) + self._check_parsed_data(cr, uid, stmts_vals, context=ctx) # Try to find the bank account and currency in odoo - currency_id, bank_account_id = self._find_additional_data(cr, uid, currency_code, account_number, context=context) - # Find or create the bank journal - journal_id = self._get_journal(cr, uid, currency_id, bank_account_id, account_number, context=context) - # Create the bank account if not already existing - if not bank_account_id and account_number: - self._create_bank_account(cr, uid, account_number, journal_id=journal_id, partner_id=uid, context=context) + currency_id, bank_account_id = self._find_additional_data(cr, uid, currency_code, account_number, context=ctx) + # Try to find the journal + journal_id = self._get_journal(cr, uid, currency_id, bank_account_id, account_number, context=ctx) + # If no journal found, ask the user about creating one + if not journal_id: + return self._journal_creation_wizard(cr, uid, currency_id, account_number, bank_account_id, context=ctx) + # Or directly finish the import + return self._finalize_import(cr, uid, bank_account_id, account_number, journal_id, stmts_vals, context=ctx) + + def _journal_creation_wizard(self, cr, uid, currency_id, account_number, bank_account_id, context=None): + """ Calls a wizard that allows the user to accept/refuse journal creation """ + return { + 'name': _('Journal Creation'), + 'type': 'ir.actions.act_window', + 'res_model': 'account.bank.statement.import.journal.creation', + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'new', + 'context': { + 'statement_import_transient_id': context['active_id'], + 'default_currency_id': currency_id, + 'default_account_number': account_number, + 'bank_account_id': bank_account_id, + 'default_name': _('Bank') + ' ' + account_number, + } + } + + def _finalize_import(self, cr, uid, bank_account_id, account_number, journal_id, stmts_vals, context=None): + """ This part is separated from import_file so it can be called via the joutnal creation wizard + No CUD can happen before this method is called, so not calling it is like aborting the import. + """ # Prepare statement data to be used for bank statements creation stmts_vals = self._complete_stmts_vals(cr, uid, stmts_vals, journal_id, account_number, context=context) # Create the bank statements @@ -153,31 +179,12 @@ class account_bank_statement_import(osv.TransientModel): if currency_id and currency_id != journal_currency_id: raise UserError(_('The currency of the bank statement is not the same as the currency of the journal !')) - # If there is no journal, create one (and its account) - if not journal_id and account_number: - journal_id = self._create_journal(cr, uid, currency_id, account_number, context=context) - if bank_account_id: - bank_pool.write(cr, uid, [bank_account_id], {'journal_id': journal_id}, context=context) - - # If we couldn't find/create a journal, everything is lost - if not journal_id: + # If we couldn't find a journal and can't create one, everything is lost + if not journal_id and not account_number: raise UserError(_('Cannot find in which journal import this statement. Please manually select a journal.')) return journal_id - def _create_journal(self, cr, uid, currency_id, account_number, context=None): - """ Create a journal and its account """ - wmca_pool = self.pool.get('wizard.multi.charts.accounts') - company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id - - vals_account = {'currency_id': currency_id, 'acc_name': account_number, 'account_type': 'bank', 'currency_id': currency_id} - vals_account = wmca_pool._prepare_bank_account(cr, uid, company, vals_account, context=context) - account_id = self.pool.get('account.account').create(cr, uid, vals_account, context=context) - - vals_journal = {'currency_id': currency_id, 'acc_name': _('Bank') + ' ' + account_number, 'account_type': 'bank'} - vals_journal = wmca_pool._prepare_bank_journal(cr, uid, company, vals_journal, account_id, context=context) - return self.pool.get('account.journal').create(cr, uid, vals_journal, context=context) - def _create_bank_account(self, cr, uid, account_number, journal_id=False, partner_id=False, context=None): try: type_model, type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'bank_normal') @@ -245,7 +252,7 @@ class account_bank_statement_import(osv.TransientModel): else: ignored_statement_lines_import_ids.append(line_vals['unique_import_id']) if len(filtered_st_lines) > 0: - # Remove values that won't be used to create records + # Remove values that won't be used to create records st_vals.pop('transactions', None) for line_vals in filtered_st_lines: line_vals.pop('account_number', None) @@ -270,4 +277,3 @@ class account_bank_statement_import(osv.TransientModel): }] return statement_ids, notifications - diff --git a/addons/account_bank_statement_import/wizard/__init__.py b/addons/account_bank_statement_import/wizard/__init__.py new file mode 100644 index 00000000000..a92b373b470 --- /dev/null +++ b/addons/account_bank_statement_import/wizard/__init__.py @@ -0,0 +1 @@ +import journal_creation diff --git a/addons/account_bank_statement_import/wizard/journal_creation.py b/addons/account_bank_statement_import/wizard/journal_creation.py new file mode 100644 index 00000000000..547afda2395 --- /dev/null +++ b/addons/account_bank_statement_import/wizard/journal_creation.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import fields, osv +from openerp.tools.translate import _ + +class account_bank_statement_import_journal_creation(osv.TransientModel): + _name = 'account.bank.statement.import.journal.creation' + _description = 'Import Bank Statement Journal Creation Wizard' + _columns = { + 'name': fields.char('Journal Name', required=True), + 'currency_id': fields.many2one('res.currency', 'Currency', readonly=True), + 'account_number': fields.char('Account Number', readonly=True), + } + + def create_journal(self, cr, uid, ids, context=None): + bank_account_id = context['bank_account_id'] + + wmca_pool = self.pool.get('wizard.multi.charts.accounts') + import_wiz_obj = self.pool['account.bank.statement.import'] + company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id + wiz = self.browse(cr, uid, ids, context=context)[0] + currency_id = wiz.currency_id.id + account_number = wiz.account_number + + # Create the account.account + vals_account = {'currency_id': currency_id, 'acc_name': account_number, 'account_type': 'bank', 'currency_id': currency_id} + vals_account = wmca_pool._prepare_bank_account(cr, uid, company, vals_account, context=context) + account_id = self.pool.get('account.account').create(cr, uid, vals_account, context=context) + + # Create the account.journal + name = wiz.name + vals_journal = {'currency_id': currency_id, 'acc_name': name, 'account_type': 'bank'} + vals_journal = wmca_pool._prepare_bank_journal(cr, uid, company, vals_journal, account_id, context=context) + journal_id = self.pool.get('account.journal').create(cr, uid, vals_journal, context=context) + if bank_account_id: + self.pool.get('res.partner.bank').write(cr, uid, [bank_account_id], {'journal_id': journal_id}, context=context) + # Create the bank account if not already existing + elif not bank_account_id and account_number: + import_wiz_obj._create_bank_account(cr, uid, account_number, journal_id=journal_id, partner_id=uid, context=context) + # Finish the statement import + statement_import_transient = import_wiz_obj.browse(cr, uid, context['statement_import_transient_id'], context=context) + return statement_import_transient.import_file() diff --git a/addons/account_bank_statement_import/wizard/journal_creation.xml b/addons/account_bank_statement_import/wizard/journal_creation.xml new file mode 100644 index 00000000000..a834327e8ed --- /dev/null +++ b/addons/account_bank_statement_import/wizard/journal_creation.xml @@ -0,0 +1,27 @@ + + + + + + Journal Creation + account.bank.statement.import.journal.creation + +
+

The account of the statement you are importing is not yet recorded in Odoo. In order to proceed with the import, you need to create a bank account and journal using this form.

+

Just click OK to create the account/journal and finish the import. If this was a mistake, hit cancel to abort the import.

+ + + + + + +
+
+
+ +
+
diff --git a/addons/account_bank_statement_import_ofx/tests/test_import_bank_statement.py b/addons/account_bank_statement_import_ofx/tests/test_import_bank_statement.py index 6a6215fa6df..3a2c080a173 100644 --- a/addons/account_bank_statement_import_ofx/tests/test_import_bank_statement.py +++ b/addons/account_bank_statement_import_ofx/tests/test_import_bank_statement.py @@ -17,13 +17,20 @@ class TestOfxFile(TransactionCase): #the Python library isn't installed on the server, the OFX import is unavailable and the test cannot be run return True cr, uid = self.cr, self.uid + creation_wiz_obj = self.registry('account.bank.statement.import.journal.creation') ofx_file_path = get_module_resource('account_bank_statement_import_ofx', 'test_ofx_file', 'test_ofx.ofx') ofx_file = open(ofx_file_path, 'rb').read().encode('base64') bank_statement_id = self.statement_import_model.create(cr, uid, dict( data_file=ofx_file, )) - self.statement_import_model.import_file(cr, uid, [bank_statement_id]) - statement_id = self.bank_statement_model.search(cr, uid, [('name', '=', '000000123')])[0] + res = self.statement_import_model.import_file(cr, uid, [bank_statement_id]) + self.assertEquals(res['res_model'], 'account.bank.statement.import.journal.creation', 'boom') + ctx = res.get('context', {}).copy() + wiz_id = creation_wiz_obj.create(cr, uid, {}, context=ctx) + wiz = creation_wiz_obj.browse(cr, uid, [wiz_id], context=ctx) + wiz.create_journal() + + statement_id = self.bank_statement_model.search(cr, uid, [('name', '=', '000000123')]) bank_st_record = self.bank_statement_model.browse(cr, uid, statement_id) self.assertEquals(bank_st_record.balance_start, 2516.56) self.assertEquals(bank_st_record.balance_end_real, 2156.56)