Trust-Code/odoo-brasil

View on GitHub
br_bank_statement_import/models/account_bank_statement_import.py

Summary

Maintainability
A
1 hr
Test Coverage
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import uuid
import logging
import StringIO

from odoo import fields, models
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)

try:
    from ofxparse import OfxParser
except ImportError:
    _logger.debug('Cannot import ofxparse dependencies.')


class AccountBankStatementImport(models.TransientModel):
    _inherit = 'account.bank.statement.import'

    unique_transaction = fields.Boolean(
        string=u'Gerar ID Único', default=False,
        help=u'Apenas marque esta opção em caso do arquivo OFX conter \
        registros duplicados (campo FITID), alguns bancos exportam \
        o arquivo OFX com dois registros diferentes com mesmo número \
        de transação (o que não deveria). O comportamento padrão do Odoo \
        caso exista duplicados é ignorar os duplicados (mesmo FITID) \
        e se forem todos duplicados dizer que o arquivo já foi importado. \
        Se alguma dessas situações estiver ocorrendo ao importar o arquivo \
        talvez você precise marcar esta opção.'
    )
    force_journal_account = fields.Boolean(string=u"Forçar conta bancária?")
    journal_id = fields.Many2one('account.journal', string=u"Conta Bancária",
                                 domain=[('type', '=', 'bank')])

    def _parse_file(self, data_file):
        if self._check_ofx:
            return self._parse_ofx(data_file)
        return super(AccountBankStatementImport, self)._parse_file(data_file)

    def _check_ofx(self, data_file, raise_error=False):
        try:
            data_file = data_file.replace('\r\n', '\n').replace('\r', '\n')
            OfxParser.parse(StringIO.StringIO(data_file))
            return True
        except Exception as e:
            if raise_error:
                raise UserError(u"Arquivo formato inválido:\n%s" % str(e))
            return False

    def _parse_ofx(self, data_file):
        data_file = data_file.replace('\r\n', '\n').replace('\r', '\n')
        ofx = OfxParser.parse(StringIO.StringIO(data_file))
        transacoes = []
        total = 0.0
        index = 1  # Some banks don't use a unique transaction id, we make one
        for account in ofx.accounts:
            for transacao in account.statement.transactions:
                unique_id = transacao.id
                if self.unique_transaction:
                    unique_id = str(uuid.uuid4())
                transacoes.append({
                    'date': transacao.date,
                    'name': transacao.payee + (
                        transacao.memo and ': ' + transacao.memo or ''),
                    'ref': transacao.id,
                    'amount': transacao.amount,
                    'unique_import_id': unique_id
                })
                total += float(transacao.amount)
                index += 1
        # Really? Still using Brazilian Cruzeiros :/
        if ofx.account.statement.currency.upper() == "BRC":
            ofx.account.statement.currency = "BRL"

        journal = self.journal_id
        if not self.force_journal_account:
            dummy, journal = self._find_additional_data(
                ofx.account.statement.currency, ofx.account.number)

        name = u"%s - %s até %s" % (
            journal.name,
            ofx.account.statement.start_date.strftime('%d/%m/%Y'),
            ofx.account.statement.end_date.strftime('%d/%m/%Y')
        )
        vals_bank_statement = {
            'name': name,
            'transactions': transacoes,
            'balance_start': ofx.account.statement.balance,
            'balance_end_real': float(ofx.account.statement.balance) + total,
        }

        account_number = ofx.account.number
        if self.force_journal_account:
            account_number = self.journal_id.bank_acc_number
        return (
            ofx.account.statement.currency,
            account_number,
            [vals_bank_statement]
        )