# -*- coding: utf-8 -*- # noqa: This is a backport from Odoo. OCA has no control over style here. # flake8: noqa import dateutil.parser import StringIO from openerp.tools.translate import _ from openerp.osv import osv, fields from openerp.exceptions import Warning class account_bank_statement_import(osv.TransientModel): _inherit = "account.bank.statement.import" _columns = { 'journal_id': fields.many2one('account.journal', string='Journal', help='Accounting journal related to the bank statement you\'re importing. It has be be manually chosen for statement formats which doesn\'t allow automatic journal detection (QIF for example).'), 'hide_journal_field': fields.boolean('Hide the journal field in the view'), } def _get_hide_journal_field(self, cr, uid, context=None): return context and 'journal_id' in context or False _defaults = { 'hide_journal_field': _get_hide_journal_field, } def _get_journal(self, cr, uid, currency_id, bank_account_id, account_number, context=None): """ As .QIF format does not allow us to detect the journal, we need to let the user choose it. We set it in context before to call super so it's the same as calling the widget from a journal """ if context is None: context = {} if context.get('active_id'): record = self.browse(cr, uid, context.get('active_id'), context=context) if record.journal_id: context['journal_id'] = record.journal_id.id return super(account_bank_statement_import, self)._get_journal(cr, uid, currency_id, bank_account_id, account_number, context=context) def _check_qif(self, cr, uid, data_file, context=None): return data_file.strip().startswith('!Type:') def _parse_file(self, cr, uid, data_file, context=None): if not self._check_qif(cr, uid, data_file, context=context): return super(account_bank_statement_import, self)._parse_file(cr, uid, data_file, context=context) try: file_data = "" for line in StringIO.StringIO(data_file).readlines(): file_data += line if '\r' in file_data: data_list = file_data.split('\r') else: data_list = file_data.split('\n') header = data_list[0].strip() header = header.split(":")[1] except: raise Warning(_('Could not decipher the QIF file.')) transactions = [] vals_line = {} total = 0 if header == "Bank": vals_bank_statement = {} for line in data_list: line = line.strip() if not line: continue if line[0] == 'D': # date of transaction vals_line['date'] = dateutil.parser.parse(line[1:], fuzzy=True).date() elif line[0] == 'T': # Total amount total += float(line[1:].replace(',', '')) vals_line['amount'] = float(line[1:].replace(',', '')) elif line[0] == 'N': # Check number vals_line['ref'] = line[1:] elif line[0] == 'P': # Payee vals_line['name'] = 'name' in vals_line and line[1:] + ': ' + vals_line['name'] or line[1:] # Since QIF doesn't provide account numbers, we'll have to find res.partner and res.partner.bank here # (normal behavious is to provide 'account_number', which the generic module uses to find partner/bank) ids = self.pool.get('res.partner.bank').search(cr, uid, [('owner_name', '=', line[1:])], context=context) if ids: vals_line['bank_account_id'] = bank_account_id = ids[0] vals_line['partner_id'] = self.pool.get('res.partner.bank').browse(cr, uid, bank_account_id, context=context).partner_id.id elif line[0] == 'M': # Memo vals_line['name'] = 'name' in vals_line and vals_line['name'] + ': ' + line[1:] or line[1:] elif line[0] == '^': # end of item transactions.append(vals_line) vals_line = {} elif line[0] == '\n': transactions = [] else: pass else: raise Warning(_('This file is either not a bank statement or is not correctly formed.')) vals_bank_statement.update({ 'balance_end_real': total, 'transactions': transactions }) return None, None, [vals_bank_statement]