Exemplo n.º 1
0
class TestCnab240(unittest.TestCase):
    
    def __init__(self, *args, **kwargs):
        super(TestCnab240, self).__init__(*args, **kwargs)
        self.maxDiff = None 

    def setUp(self):
        self.itau_data = get_itau_data_from_dict()
        self.arquivo = Arquivo(itau, **self.itau_data['arquivo'])

    def test_unicode(self):
        self.arquivo.incluir_cobranca(**self.itau_data['cobranca'])
        self.assertEqual(str(self.arquivo), get_itau_file_remessa())

    def test_empty_data(self):
        arquivo = Arquivo(itau)
        self.assertRaises(errors.ArquivoVazioError, str, arquivo)

    def test_leitura(self):
        return_file_path = os.path.join(ARQS_DIRPATH, 'cobranca.itau.ret')
        ret_file = codecs.open(return_file_path, encoding='ascii')
        arquivo = Arquivo(itau, arquivo=ret_file)
        ret_file.seek(0)
        self.assertEqual(ret_file.read(), str(arquivo))
        ret_file.close()
Exemplo n.º 2
0
    def remessa(self, order):
        """

        :param order:
        :return:
        """
        cobrancasimples_valor_titulos = 0

        self.order = order
        header = self._prepare_header()
        self.arquivo = Arquivo(self.bank, **header)
        for line in order.line_ids:
            if line.payment_mode_id.bank_account_id.bank_id.bic  == '755':
                self.nosso_numero_with_dv = line.nosso_numero + line.nosso_numero_dv
            else:
                self.nosso_numero_with_dv = line.nosso_numero
                
            print self.nosso_numero
            print self.nosso_numero_with_dv
 
            seg = self._prepare_segmento(line.move_line_id)
            print seg
            self.arquivo.incluir_cobranca(header, **seg)
            self.arquivo.lotes[0].header.servico_servico = 1
            # TODO: tratar soma de tipos de cobranca
            cobrancasimples_valor_titulos += line.move_line_id.amount_currency
            self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                Decimal(cobrancasimples_valor_titulos).quantize(
                    Decimal('1.00'))

        return unicode(self.arquivo)
Exemplo n.º 3
0
    def montarArquivoNC_IDS(self, cr, uid, ids, context=None):
        # str = unicode(arquivo)
        # f = open('/tmp/arquivo_remessa.rem','w')
        # f.write(str) # python will convert \n to os.linesep
        # f.close()

        res = {}
        cnab_data = dict()

        # Header values
        dict_arquivo = self.get_header_data(cr, uid, ids, context)
        dict_salvar = dict_arquivo
        cnab_data['arquivo'] = dict_arquivo
        arquivo = Arquivo(cef, **cnab_data['arquivo'])

        # Segmentos
        nossa_classe_pool = self.pool.get('l10n_br_account.payment_receivable')
        segmento_pool = self.pool.get('cnab240export.segmentos')
        nossa_classe_ids = []
        arquivo.lotes[0].header.servico_servico = 1
        for nc_ids in nossa_classe_ids:
            # Para os dados de cada "nossa_classe_line" e correspondente
            # "move_line", inclua os segmentos P e Q.
            id_segmento = segmento_pool.create(cr, uid, context=None)
            segmento_cobranca = segmento_pool.write_segmentos(cr, uid, id_segmento, nc_ids, context)
            cnab_data['cobranca'] = segmento_cobranca
            arquivo.incluir_cobranca(**cnab_data['cobranca'])

        self.salva_dados(cr, uid, ids, dict_salvar, context)

        return res
Exemplo n.º 4
0
class TestCnab240(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super(TestCnab240, self).__init__(*args, **kwargs)
        self.maxDiff = None

    def setUp(self):
        self.itau_data = get_itau_data_from_dict()
        self.arquivo = Arquivo(itau, **self.itau_data['arquivo'])

    def test_unicode(self):
        self.arquivo.incluir_cobranca(**self.itau_data['cobranca'])
        self.assertEqual(str(self.arquivo), get_itau_file_remessa())

    def test_empty_data(self):
        arquivo = Arquivo(itau)
        self.assertRaises(errors.ArquivoVazioError, str, arquivo)

    def test_leitura_itau(self):
        return_file_path = os.path.join(ARQS_DIRPATH, 'cobranca.itau.ret')
        ret_file = codecs.open(return_file_path, encoding='ascii')
        arquivo = Arquivo(itau, arquivo=ret_file)

        ret_file.seek(0)
        self.assertEqual(ret_file.read(), str(arquivo))
        ret_file.close()
Exemplo n.º 5
0
    def remessa(self, order):
        """

        :param order:
        :return:
        """
        cobrancasimples_valor_titulos = 0

        self.order = order
        header = self._prepare_header()
        self.arquivo = Arquivo(self.bank, **header)
        #
        for line in order.line_ids:

            if line.validate_line_to_export():
                seg = self._prepare_segmento(line.move_line_id)
                self.arquivo.incluir_cobranca(header, **seg)
                self.arquivo.lotes[0].header.servico_servico = 1
                # TODO: tratar soma de tipos de cobranca
                cobrancasimples_valor_titulos += line.value
                self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                    Decimal(cobrancasimples_valor_titulos).quantize(
                        Decimal('1.00'))
                year = str(datetime.datetime.now().year)[2:]
                # add year in nosso_numero because we pass it to bank
                # and this is used to loacate payment order line while
                # importing bank return
                if line.nosso_numero[:2] != year:
                    line.nosso_numero = year + str(line.nosso_numero)
                line.state = 'ag'

        return unicode(self.arquivo)
Exemplo n.º 6
0
    def montarArquivoNC_IDS(self, cr, uid, ids, context=None):
        # str = unicode(arquivo)
        # f = open('/tmp/arquivo_remessa.rem','w')
        # f.write(str) # python will convert \n to os.linesep
        # f.close()

        res = {}
        cnab_data = dict()

        # Header values
        dict_arquivo = self.get_header_data(cr, uid, ids, context)
        dict_salvar = dict_arquivo
        cnab_data['arquivo'] = dict_arquivo
        arquivo = Arquivo(cef, **cnab_data['arquivo'])

        # Segmentos
        nossa_classe_pool = self.pool.get('l10n_br_account.payment_receivable')
        segmento_pool = self.pool.get('cnab240export.segmentos')
        nossa_classe_ids = []
        arquivo.lotes[0].header.servico_servico = 1
        for nc_ids in nossa_classe_ids:
            # Para os dados de cada "nossa_classe_line" e correspondente
            # "move_line", inclua os segmentos P e Q.
            id_segmento = segmento_pool.create(cr, uid, context=None)
            segmento_cobranca = segmento_pool.write_segmentos(
                cr, uid, id_segmento, nc_ids, context)
            cnab_data['cobranca'] = segmento_cobranca
            arquivo.incluir_cobranca(**cnab_data['cobranca'])

        self.salva_dados(cr, uid, ids, dict_salvar, context)

        return res
Exemplo n.º 7
0
def processa_pagamentos(data):
    arquivo = Arquivo(banco_brasil, **data)
    pagamentos = data.get('pagamentos')
    valor_total = Decimal(0.0)
    # "arquivo_data_de_geracao": "01041990",
    # "arquivo_hora_de_geracao": "235959",

    for pagamento in pagamentos:
        arquivo.incluir_pagamentos_diversos(**data, **pagamento)
        valor_total += Decimal(pagamento.get('valor', 0.0))

    arquivo.lotes[0].trailer.somatorio_valor = valor_total
    return str(arquivo)
Exemplo n.º 8
0
 def remessa(self, order):
     cobrancasimples_valor_titulos = 0
     self.order = order
     header = self._prepare_header()
     self.arquivo = Arquivo(self.bank, **header)
     for line in order.line_ids:
         seg = self._prepare_segmento(line.move_line_id)
         self.arquivo.incluir_cobranca(header, **seg)
         self.arquivo.lotes[0].header.servico_servico = 1
         # TODO: tratar soma de tipos de cobranca
         cobrancasimples_valor_titulos += line.move_line_id.amount_currency
         self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
             Decimal(cobrancasimples_valor_titulos).quantize(
                 Decimal('1.00'))
     return str(self.arquivo)
Exemplo n.º 9
0
 def test_leitura(self):
     return_file_path = os.path.join(ARQS_DIRPATH, 'cobranca.itau.ret')
     ret_file = codecs.open(return_file_path, encoding='ascii')
     arquivo = Arquivo(itau, arquivo=ret_file)
     ret_file.seek(0)
     self.assertEqual(ret_file.read(), str(arquivo))
     ret_file.close()
Exemplo n.º 10
0
    def _parse(self, *args, **kwargs):
        """Launch the parsing itself."""
        cnab240_file = tempfile.NamedTemporaryFile()
        cnab240_file.seek(0)
        cnab240_file.write(self.filebuffer)
        cnab240_file.flush()

        ret_file = codecs.open(cnab240_file.name, encoding='ascii')
        arquivo = Arquivo(cef, arquivo=ret_file)

        cnab240_file.close()

        res = []
        for lote in arquivo.lotes:
            for evento in lote.eventos:
                res.append({
                    'name': evento.sacado_nome,
                    'date': datetime.datetime.strptime(
                        str(evento.vencimento_titulo), '%d%m%Y'),
                    'amount': evento.valor_titulo,
                    'ref': evento.numero_documento,
                    'label': evento.sacado_inscricao_numero,  # cnpj
                    'transaction_id': evento.nosso_numero_identificacao,
                    # nosso numero
                    'commission_amount': evento.valor_tarifas,
                })

        self.result_row_list = res
        return True
Exemplo n.º 11
0
    def _get_account(self, cnab_file):
        if self.cnab_type != 'receivable':
            return super(L10nBrPaymentCnabImport, self)._get_account(cnab_file)

        stream = StringIO(cnab_file.decode('ascii'))
        bank = get_bank(self.journal_id.bank_id.bic)
        cnab = Arquivo(bank, arquivo=stream)
        return cnab.header.cedente_conta, cnab.header.cedente_agencia
 def _check_cnab(self, data_file, raise_error=False):
     try:
         cnab240_file = tempfile.NamedTemporaryFile()
         cnab240_file.write(data_file)
         cnab240_file.flush()
         Arquivo(sicoob, arquivo=open(cnab240_file.name, 'r'))
         return True
     except Exception as e:
         if raise_error:
             raise UserError(u"Arquivo formato inválido:\n%s" % str(e))
         return False
Exemplo n.º 13
0
    def remessa(self, order):
        """
        :param order:
        :return:
        """
        cobrancasimples_valor_titulos = 0

        self.order = order
        self.arquivo = Arquivo(self.bank, **self._prepare_header())
        for line in order.line_ids:
            self.arquivo.incluir_cobranca(**self._prepare_segmento(line))
            self.arquivo.lotes[0].header.servico_servico = 1
            # TODO: tratar soma de tipos de cobranca
            cobrancasimples_valor_titulos += line.amount_currency
            # fixed 'quantidade_registros'  in trailer to 000001
            self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                Decimal(cobrancasimples_valor_titulos).quantize(
                    Decimal('1.00'))

        remessa = unicode(self.arquivo)
        return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore')
Exemplo n.º 14
0
    def remessa(self, header, lista_boletos):
        """

        :param order:

        :return:
        """
        cobrancasimples_valor_titulos = Decimal(0.00)

        self.arquivo = Arquivo(self.bank, **self._prepare_header(**header))
        for line in lista_boletos:
            self.arquivo.incluir_cobranca(**self._prepare_segmento(line))
            self.arquivo.lotes[0].header.servico_servico = 1
            # TODO: tratar soma de tipos de cobranca
            # TODO: Verificar se é o valor do documento ou o valor
            cobrancasimples_valor_titulos += Decimal(line.valor_documento)
            self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                Decimal(cobrancasimples_valor_titulos).quantize(
                    Decimal('1.00'))

        remessa = unicode(self.arquivo)
        return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore')
    def _parse_cnab(self, data_file, raise_error=False):
        cnab240_file = tempfile.NamedTemporaryFile()
        cnab240_file.write(data_file)
        cnab240_file.flush()

        arquivo = Arquivo(sicoob, arquivo=open(cnab240_file.name, 'r'))
        transacoes = []
        for lote in arquivo.lotes:
            for evento in lote.eventos:
                valor = evento.valor_lancamento
                if evento.tipo_lancamento == 'D':
                    valor *= -1
                transacoes.append({
                    'name':
                    evento.descricao_historico,
                    'date':
                    datetime.strptime(str(evento.data_lancamento), '%d%m%Y'),
                    'amount':
                    valor,
                    'partner_name':
                    evento.cedente_nome,
                    'ref':
                    evento.numero_documento,
                    'unique_import_id':
                    str(evento.servico_numero_registro),
                })
        header = arquivo.lotes[0].header
        trailer = arquivo.lotes[0].trailer

        inicio = datetime.strptime(str(header.data_saldo_inicial), '%d%m%Y')
        final = datetime.strptime(str(trailer.data_saldo_final), '%d%m%Y')

        vals_bank_statement = {
            'name':
            u"%s - %s até %s" %
            (arquivo.header.nome_do_banco, inicio.strftime('%d/%m/%Y'),
             final.strftime('%d/%m/%Y')),
            'date':
            inicio,
            'balance_start':
            arquivo.lotes[0].header.valor_saldo_inicial,
            'balance_end_real':
            arquivo.lotes[0].trailer.valor_saldo_final,
            'transactions':
            transacoes
        }
        account_number = str(arquivo.header.cedente_conta)
        if self.force_journal_account:
            account_number = self.journal_id.bank_acc_number
        return (arquivo.lotes[0].header.moeda, account_number,
                [vals_bank_statement])
Exemplo n.º 16
0
    def remessa(self, order):
        """

        :param order:
        :return:
        """

        pag_valor_titulos = 0

        self.order = order
        self.arquivo = Arquivo(self.bank, **self._prepare_header())
        cont_lote = 0

        for line in order.line_ids:
            self.arquivo.incluir_pagamento(**self.incluir_pagamento_for(line))
            pag_valor_titulos += line.amount_currency
            self.arquivo.trailer.total_valor_arq = Decimal(
                pag_valor_titulos).quantize(Decimal('1.00'))
            self.arquivo.trailer.sequencial_transacao = self.controle_linha

            cont_lote += 1
        remessa = unicode(self.arquivo)
        return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore')
    def parse(self, data, banco_impt):
        """Launch the parsing itself."""
        cnab240_file = tempfile.NamedTemporaryFile()
        cnab240_file.seek(0)
        cnab240_file.write(data)
        cnab240_file.flush()
        ret_file = codecs.open(cnab240_file.name, encoding='ascii')
        # Nome_modo_impt é o nome da pasta do json. Código do banco é inválido
        # nessa situação
        arquivo = Arquivo((self.determine_bank(banco_impt)), arquivo=ret_file)

        cnab240_file.close()
        transacoes = []
        total_amt = Decimal(0.00)
        for lote in arquivo.lotes:
            for evento in lote.eventos:
                vals = {
                    'name': evento.sacado_nome,
                    'amount': evento.valor_titulo,
                    'ref': evento.numero_documento,
                    'label': evento.sacado_inscricao_numero,  # cnpj
                    'transaction_id': evento.numero_documento,
                    # nosso numero, Alfanumérico
                    'unique_import_id': evento.nosso_numero,
                }
                if evento.vencimento_titulo:
                    vals['date'] = datetime.datetime.strptime(
                        str(evento.vencimento_titulo), '%d%m%Y')
                transacoes.append(vals)
                total_amt += evento.valor_titulo

        vals_bank_statement = {
            'name':
            '%s - %s' % (arquivo.header.nome_do_banco,
                         arquivo.header.arquivo_data_de_geracao),
            'date':
            datetime.datetime.strptime(
                str(arquivo.header.arquivo_data_de_geracao), '%d%m%Y'),
            'balance_start':
            0.00,
            'balance_end_real':
            total_amt,
            'currency_code':
            u'BRL',  # Código da moeda
            'account_number':
            arquivo.header.cedente_conta,
            'transactions':
            transacoes
        }
        return [vals_bank_statement]
Exemplo n.º 18
0
 def _check_cnab(self, data_file, raise_error=False):
     try:
         cnab240_file = tempfile.NamedTemporaryFile()
         cnab240_file.write(data_file)
         cnab240_file.flush()
         arquivo = open(cnab240_file.name, 'r')
         # read 1st 3 chars of 1st line from file
         bank_code = arquivo.readline()[0:3]
         bank = self.determine_bank(bank_code)
         Arquivo(bank, arquivo=open(cnab240_file.name, 'r'))
         return True
     except Exception as e:
         if raise_error:
             raise UserError(u"Arquivo formato inválido:\n%s" % str(e))
     return False
Exemplo n.º 19
0
    def _check_cnab(self, data_file, raise_error=False):
        try:
            cnab240_file = tempfile.NamedTemporaryFile()
            cnab240_file.write(data_file)
            cnab240_file.flush()

            journal_id = self.env.context['journal_id']
            if self.force_journal_account:
                journal_id = self.journal_id.id

            bank = self.get_bank(journal_id)
            Arquivo(bank, arquivo=open(cnab240_file.name, 'r'))
            return True
        except Exception as e:
            if raise_error:
                raise UserError(u"Arquivo formato inválido:\n%s" % str(e))
            return False
Exemplo n.º 20
0
 def setUp(self):
     self.itau_data = get_itau_data_from_dict()
     self.arquivo = Arquivo(itau, **self.itau_data['arquivo'])
Exemplo n.º 21
0
class TestCnab240(unittest.TestCase):

    """ All tests related to file handling. """

    def setUp(self):
        self.itau_data = get_itau_data_from_dict()
        self.arquivo = Arquivo(itau, **self.itau_data['arquivo'])

    def test_unicode(self):
        self.arquivo.incluir_cobranca(**self.itau_data['cobranca'])
        self.arquivo.incluir_cobranca(**self.itau_data['cobranca2'])

        _file = unicode(self.arquivo).splitlines()
        _itau = get_itau_file_remessa().splitlines()

        for ix, l in enumerate(_file):
            assert l == _itau[ix], "Error on line {}\n{}\n{}".format(
                ix, l, _itau[ix]
            )

    def test_to_file_is_unicode(self):
        """ We check that what we write is what we are testing.

        Just to avoid regressions or being blind with bugs.
        Also, UTF-8 sanitization happens on dumping to file,
        so we have a special test below
        """
        self.arquivo.incluir_cobranca(**self.itau_data['cobranca'])
        self.arquivo.incluir_cobranca(**self.itau_data['cobranca2'])

        strio = StringIO()
        self.arquivo.escrever(strio)

        _file = strio.getvalue().splitlines()
        _unicode = unicode(self.arquivo).splitlines()

        strio.close()

        for ix, l in enumerate(_file):
            assert l == _unicode[ix], u"Error on line {}\n{}\n{}".format(
                ix, l, _unicode[ix]
            )

    def test_nonascii(self):
        """ Test if we can handle nonascii chars. """
        nonascii = get_nonascii_data()
        self.arquivo.incluir_cobranca(**nonascii['cobranca'])
        self.arquivo.incluir_cobranca(**nonascii['cobranca2'])

        strio = StringIO()
        self.arquivo.escrever(strio)

        _file = strio.getvalue().splitlines()
        _itau = get_itau_file_remessa().splitlines()
        strio.close()

        for ix, l in enumerate(_file):
            assert l == _itau[ix], u"Error on line {}\n{}\n{}".format(
                ix, l, _itau[ix]
            )

    # def test_record_limit(self):
    #     """ Check that we limit the file to 178 records."""
    #     #self.assertEqual(len(self.arquivo), 0)
    #
    #     import ipdb; ipdb.set_trace()
    #     _add = self.arquivo.incluir_cobranca
    #     data = self.itau_data['cobranca']
    #
    #     try:
    #         i = 0
    #         for _ in xrange(88):
    #             _add(**data)
    #             i += 1
    #     except errors.ArquivoCheioError:
    #         #assert False, 'Should fit, at {}'.format(i)
    #         pass
    #     else:
    #         self.assertRaises(errors.ArquivoCheioError, _add, **data)

    # def test_assure_len(self):
    #     """ Len of a record should be 2 and growth should be 2. """
    #     self.arquivo.c
    #     self.assertEqual(len(self.arquivo), 0)
    #     self.arquivo.incluir_cobranca(**self.itau_data['cobranca'])
    #     # header + seg_p + seg_q
    #     self.assertEqual(len(self.arquivo), 3)
    #     self.arquivo.incluir_cobranca(**self.itau_data['cobranca'])
    #     self.assertEqual(len(self.arquivo), 5)

    def test_empty_data(self):
        arquivo = Arquivo(itau)
        self.assertRaises(errors.ArquivoVazioError, unicode, arquivo)

    def test_leitura(self):
        return_file_path = os.path.join(ARQS_DIRPATH, 'cobranca.itau.ret')
        with codecs.open(return_file_path, encoding='ascii') as ret_file:
            arquivo = Arquivo(itau, arquivo=ret_file)
            ret_file.seek(0)
            self.assertEqual(ret_file.read(), unicode(arquivo))
Exemplo n.º 22
0
 def test_empty_data(self):
     arquivo = Arquivo(bancodobrasil)
     self.assertRaises(errors.ArquivoVazioError, str, arquivo)
Exemplo n.º 23
0
 def setUp(self):
     self.bancodobrasil_data = get_bancodobrasil_data_from_dict()
     self.arquivo = Arquivo(bancodobrasil,
                            **self.bancodobrasil_data['arquivo'])
Exemplo n.º 24
0
class Cnab240(Cnab):
    def __init__(self):
        super(Cnab, self).__init__()

    @staticmethod
    def get_bank(bank):
        if bank == '237':
            from .bancos.bradesco import Bradesco240
            return Bradesco240
        elif bank == '756':
            from .bancos.sicoob import Sicoob240
            return Sicoob240
        elif bank == '001':
            from .bancos.banco_brasil import BancoBrasil240
            return BancoBrasil240
        elif bank == '0851':
            from .bancos.cecred import Cecred240
            return Cecred240
        elif bank == '341':
            from .bancos.itau import Itau240
            return Itau240
        elif bank == '033':
            from .bancos.santander import Santander240
            return Santander240
        elif bank == '104':
            from .bancos.cef import Cef240
            return Cef240
        elif bank == '748':
            from .bancos.sicredi import Sicredi240
            return Sicredi240
        else:
            return Cnab240

    @property
    def inscricao_tipo(self):
        if self.order.company_id.partner_id.is_company:
            return 2
        else:
            return 1

    def _prepare_header(self):
        cnpj_cpf = re.sub('[^0-9]', '', self.order.company_id.cnpj_cpf)
        cedente_conta_dv = self.order.src_bank_account_id.acc_number_dig
        cedente_conta_dv = str(cedente_conta_dv)
        return {
            'controle_banco': int(self.order.src_bank_account_id.bank_bic),
            'arquivo_data_de_geracao': self.data_hoje(),
            'arquivo_hora_de_geracao': self.hora_agora(),
            'arquivo_sequencia': self.order.file_number,
            'cedente_inscricao_tipo': self.inscricao_tipo,
            'cedente_inscricao_numero': int(cnpj_cpf),
            'cedente_agencia': int(self.order.src_bank_account_id.bra_number),
            'cedente_conta': int(self.order.src_bank_account_id.acc_number),
            'cedente_conta_dv': cedente_conta_dv,
            'cedente_convenio': self.order.src_bank_account_id.codigo_convenio,
            'cedente_agencia_dv':
            self.order.src_bank_account_id.bra_number_dig,
            'cedente_nome': self.order.company_id.legal_name,
            # DV ag e conta
            'cedente_dv_ag_cc': self.order.src_bank_account_id.bra_number_dig,
            'arquivo_codigo': 1,  # Remessa/Retorno
            'servico_operacao': u'R',
            'nome_banco': self.order.src_bank_account_id.bank_name
        }

    def get_file_numeration(self):
        numero = False  # self.order.get_next_number()
        if not numero:
            numero = 1
        return numero

    def format_date(self, srt_date):
        return int(
            datetime.datetime.strptime(srt_date,
                                       '%Y-%m-%d').strftime('%d%m%Y'))

    def nosso_numero(self, format):
        pass

    def cep(self, format):
        sulfixo = format[-3:]
        prefixo = format[:5]
        return prefixo, sulfixo

    def sacado_inscricao_tipo(self, partner_id):
        # TODO: Implementar codigo para PIS/PASEP
        if partner_id.is_company:
            return 2
        else:
            return 1

    def rmchar(self, format):
        return re.sub('[%s]' % re.escape(string.punctuation), '', format or '')

    def _prepare_segmento(self, line):
        prefixo, sulfixo = self.cep(line.partner_id.zip)

        # if not self.order.payment_mode_id.boleto_aceite == 'S':
        #    aceite = u'A'

        # Código agencia do cedente
        # cedente_agencia = cedente_agencia

        # Dígito verificador da agência do cedente
        # cedente_agencia_conta_dv = cedente_agencia_dv

        # Código da conta corrente do cedente
        # cedente_conta = cedente_conta

        # Dígito verificador da conta corrente do cedente
        # cedente_conta_dv = cedente_conta_dv

        # Dígito verificador de agencia e conta
        # Era cedente_agencia_conta_dv agora é cedente_dv_ag_cc

        return {
            'controle_banco':
            int(self.order.src_bank_account_id.bank_bic),
            'cedente_agencia':
            int(self.order.src_bank_account_id.bra_number),
            'cedente_conta':
            int(self.order.src_bank_account_id.acc_number),
            'cedente_conta_dv':
            self.order.src_bank_account_id.acc_number_dig,
            'cedente_convenio':
            self.order.src_bank_account_id.codigo_convenio,
            'cedente_agencia_dv':
            self.order.src_bank_account_id.bra_number_dig,
            'cedente_nome':
            self.order.company_id.legal_name,
            # DV ag e cc
            'cedente_dv_ag_cc':
            self.order.src_bank_account_id.bra_number_dig,
            'identificacao_titulo':
            u'0000000',  # TODO
            'identificacao_titulo_banco':
            u'0000000',  # TODO
            'identificacao_titulo_empresa': (' ' * 25),
            'numero_documento':
            line.identifier,
            'vencimento_titulo':
            self.format_date(line.date_maturity),
            'valor_titulo':
            Decimal(str(line.amount_total)).quantize(Decimal('1.00')),
            # TODO: Código adotado para identificar o título de cobrança.
            # 8 é Nota de cŕedito comercial
            'especie_titulo':
            int(self.order.payment_mode_id.boleto_especie),
            'aceite_titulo':
            self.order.payment_mode_id.boleto_aceite,
            'data_emissao_titulo':
            self.format_date(line.emission_date),
            # Taxa de juros do Odoo padrão mensal: 2. Campo 27.3P
            # CEF/FEBRABAN e Itaú não tem.
            'codigo_juros':
            2,
            'juros_mora_data':
            self.format_date(line.date_maturity),
            'juros_mora_taxa':
            Decimal(str(
                self.order.payment_mode_id.late_payment_interest)).quantize(
                    Decimal('1.00')),
            # Multa padrão em percentual no Odoo, valor '2'
            'codigo_multa':
            '2',
            'data_multa':
            self.format_date(line.date_maturity),
            'juros_multa':
            Decimal(str(self.order.payment_mode_id.late_payment_fee)).quantize(
                Decimal('1.00')),
            'valor_abatimento':
            Decimal('0.00'),
            'sacado_inscricao_tipo':
            int(self.sacado_inscricao_tipo(line.partner_id)),
            'sacado_inscricao_numero':
            int(self.rmchar(line.partner_id.cnpj_cpf)),
            'sacado_nome':
            line.partner_id.legal_name or line.partner_id.name,
            'sacado_endereco':
            (line.partner_id.street + ' ' + line.partner_id.number),
            'sacado_bairro':
            line.partner_id.district,
            'sacado_cep':
            int(prefixo),
            'sacado_cep_sufixo':
            int(sulfixo),
            'sacado_cidade':
            line.partner_id.city_id.name,
            'sacado_uf':
            line.partner_id.state_id.code,
            'codigo_protesto':
            int(self.order.payment_mode_id.boleto_protesto),
            'prazo_protesto':
            int(self.order.payment_mode_id.boleto_protesto_prazo),
            'codigo_baixa':
            2,
            'prazo_baixa':
            0,  # De 5 a 120 dias.
            'controlecob_data_gravacao':
            self.data_hoje(),
            'cobranca_carteira':
            int(self.order.payment_mode_id.boleto_carteira[:2]),
        }

    def remessa(self, order):
        cobrancasimples_valor_titulos = 0
        self.order = order

        self._hook_validation()

        header = self._prepare_header()
        self.arquivo = Arquivo(self.bank, **header)
        for line in order.line_ids:
            seg = self._prepare_segmento(line)
            self.arquivo.incluir_cobranca(header, **seg)
            self.arquivo.lotes[0].header.servico_servico = 1
            # TODO: tratar soma de tipos de cobranca
            cobrancasimples_valor_titulos += line.amount_total
            self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                Decimal(cobrancasimples_valor_titulos).quantize(
                    Decimal('1.00'))
        return str(self.arquivo)

    def data_hoje(self):
        return (int(time.strftime("%d%m%Y")))

    def hora_agora(self):
        return (int(time.strftime("%H%M%S")))

    def _hook_validation(self):
        pass
Exemplo n.º 25
0
 def test_empty_data(self):
     arquivo = Arquivo(itau)
     self.assertRaises(errors.ArquivoVazioError, str, arquivo)
Exemplo n.º 26
0
class Cnab240(Cnab):
    """

    """
    def __init__(self):
        super(Cnab, self).__init__()

    @staticmethod
    def get_bank(bank):
        if bank == '341':
            from .bancos.itau import Itau240
            return Itau240
        elif bank == '237':
            from .bancos.bradesco import Bradesco240
            return Bradesco240
        elif bank == '104':
            from .bancos.cef import Cef240
            return Cef240
        elif bank == '033':
            from .bancos.santander import Santander240
            return Santander240
        else:
            return Cnab240

    def nosso_numero(self, format):
        return format

    def _prepare_header(self,
                        arquivo_codigo,
                        controle_banco,
                        cedente_agencia,
                        cedente_agencia_dv,
                        cedente_conta,
                        cedente_conta_dv,
                        cedente_dv_ag_cc,
                        cedente_inscricao_numero,
                        cedente_inscricao_tipo,
                        cedente_nome,
                        nome_banco,
                        servico_operacao,
                        arquivo_sequencia,
                        arquivo_data_de_geracao=False,
                        arquivo_hora_de_geracao=False,
                        **kwargs):
        """

        :param:
        :return:
        """
        return {
            'controle_banco':
            controle_banco,
            'arquivo_data_de_geracao':
            arquivo_data_de_geracao or self.data_hoje(),
            'arquivo_hora_de_geracao':
            arquivo_hora_de_geracao or self.hora_agora(),
            # TODO: Número sequencial de arquivo
            'arquivo_sequencia':
            int(arquivo_sequencia),
            'cedente_inscricao_tipo':
            int(self.inscricao_tipo(cedente_inscricao_numero)),
            'cedente_inscricao_numero':
            int(self.punctuation_rm(cedente_inscricao_numero)),
            'cedente_agencia':
            int(cedente_agencia),
            'cedente_conta':
            int(cedente_conta),
            'cedente_conta_dv':
            cedente_conta_dv,
            'cedente_agencia_dv':
            cedente_agencia_dv,
            'cedente_nome':
            cedente_nome,
            # DV ag e conta
            'cedente_dv_ag_cc':
            cedente_dv_ag_cc,
            'arquivo_codigo':
            1,  # Remessa/Retorno
            'servico_operacao':
            unicode(servico_operacao),
            'nome_banco':
            unicode(nome_banco),
        }

    def _prepare_segmento(self, line):
        """
        :param line:
        :return:
        """
        prefixo, sulfixo = self.cep(line.sacado_cep)

        aceite = u'N'
        if not line.aceite == 'S':
            aceite = u'A'

        # Código agencia do cedente
        # cedente_agencia = cedente_agencia

        # Dígito verificador da agência do cedente
        # cedente_agencia_conta_dv = cedente_agencia_dv

        # Código da conta corrente do cedente
        # cedente_conta = cedente_conta

        # Dígito verificador da conta corrente do cedente
        # cedente_conta_dv = cedente_conta_dv

        # Dígito verificador de agencia e conta
        # Era cedente_agencia_conta_dv agora é cedente_dv_ag_cc

        return {
            # TODO: Esses dados podem ser de outras filiais e contas
            # provavelmente, então pode ser que teremos que refazer este
            # trecho.
            'controle_banco':
            self.arquivo.header.controle_banco,
            'cedente_agencia':
            self.arquivo.header.cedente_agencia,
            'cedente_conta':
            self.arquivo.header.cedente_conta,
            'cedente_conta_dv':
            self.arquivo.header.cedente_conta_dv,
            'cedente_agencia_dv':
            self.arquivo.header.cedente_agencia_dv,
            'cedente_dv_ag_cc':
            self.arquivo.header.cedente_dv_ag_cc,
            'identificacao_titulo':
            u'0000000',  # TODO
            'identificacao_titulo_banco':
            u'0000000',  # TODO
            'identificacao_titulo_empresa':
            line.nosso_numero,
            'numero_documento':
            line.numero_documento,
            'vencimento_titulo':
            self.format_date(line.data_vencimento),
            'valor_titulo':
            Decimal(line.valor_documento).quantize(Decimal('1.00')),
            # TODO: Código adotado para identificar o título de cobrança.
            # 8 é Nota de cŕedito comercial
            'especie_titulo':
            8,  # FIXME
            #int(self.order.mode.boleto_especie),
            'aceite_titulo':
            aceite,
            'data_emissao_titulo':
            self.format_date(line.data_documento),
            # TODO: trazer taxa de juros do Odoo. Depende do valor do 27.3P
            # CEF/FEBRABAN e Itaú não tem.
            'juros_mora_data':
            self.format_date(line.data_vencimento),  # FIXME
            'juros_mora_taxa_dia':
            Decimal('0.00'),  # FIXME
            'valor_abatimento':
            Decimal('0.00'),  # FIXME
            'sacado_inscricao_tipo':
            int(self.inscricao_tipo(line.sacado_documento)),
            'sacado_inscricao_numero':
            int(self.punctuation_rm(line.sacado_documento)),
            'sacado_nome':
            line.sacado_nome,
            'sacado_endereco':
            line.sacado_endereco,
            'sacado_bairro':
            line.sacado_bairro,
            'sacado_cep':
            int(prefixo),
            'sacado_cep_sufixo':
            int(sulfixo),
            'sacado_cidade':
            line.sacado_cidade,
            'sacado_uf':
            line.sacado_uf,
            'codigo_protesto':
            1,
            #int(self.order.mode.boleto_protesto),
            'prazo_protesto':
            1,
            #int(self.order.mode.boleto_protesto_prazo),
            'codigo_baixa':
            2,
            'prazo_baixa':
            0,  # De 5 a 120 dias.
            'controlecob_data_gravacao':
            self.data_hoje(),
            'cobranca_carteira':
            int(line.carteira),
        }

    def remessa(self, header, lista_boletos):
        """

        :param order:

        :return:
        """
        cobrancasimples_valor_titulos = Decimal(0.00)

        self.arquivo = Arquivo(self.bank, **self._prepare_header(**header))
        for line in lista_boletos:
            self.arquivo.incluir_cobranca(**self._prepare_segmento(line))
            self.arquivo.lotes[0].header.servico_servico = 1
            # TODO: tratar soma de tipos de cobranca
            # TODO: Verificar se é o valor do documento ou o valor
            cobrancasimples_valor_titulos += Decimal(line.valor_documento)
            self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                Decimal(cobrancasimples_valor_titulos).quantize(
                    Decimal('1.00'))

        remessa = unicode(self.arquivo)
        return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore')
Exemplo n.º 27
0
class Cnab240(Cnab):
    """

    """
    def __init__(self):
        super(Cnab, self).__init__()

    @staticmethod
    def get_bank(bank):
        if bank == '341':
            from .bancos.itau import Itau240
            return Itau240
        elif bank == '237':
            from .bancos.bradesco import Bradesco240
            return Bradesco240
        elif bank == '104':
            from .bancos.cef import Cef240
            return Cef240
        elif bank == '033':
            from .bancos.santander import Santander240
            return Santander240
        elif bank == '756':
            from .bancos.sicoob import Sicoob240
            return Sicoob240
        else:
            return Cnab240

    @property
    def inscricao_tipo(self):
        # TODO: Implementar codigo para PIS/PASEP
        if self.order.company_id.partner_id.is_company:
            return 2
        else:
            return 1

    def _prepare_header(self):
        """

        :param:
        :return:
        """
        return {
            'cedente_agencia_conta_dv':
            int(self.order.mode.bank_id.acc_number_dig),
            'controle_banco':
            int(self.order.mode.bank_id.bank_bic),
            'arquivo_data_de_geracao':
            self.data_hoje(),
            'arquivo_hora_de_geracao':
            self.hora_agora(),
            # TODO: Número sequencial de arquivo
            'arquivo_sequencia':
            int(self.get_file_numeration()),
            'cedente_inscricao_tipo':
            self.inscricao_tipo,
            'cedente_inscricao_numero':
            int(punctuation_rm(self.order.company_id.cnpj_cpf)),
            'cedente_agencia':
            int(self.order.mode.bank_id.bra_number),
            'cedente_conta':
            int(self.order.mode.bank_id.acc_number),
            'cedente_conta_dv': (self.order.mode.bank_id.acc_number_dig),
            'cedente_agencia_dv':
            self.order.mode.bank_id.bra_number_dig,
            'cedente_nome':
            self.order.company_id.legal_name,
            # DV ag e conta
            'cedente_dv_ag_cc': (self.order.mode.bank_id.bra_acc_dig),
            'arquivo_codigo':
            1,  # Remessa/Retorno
            'servico_operacao':
            u'R',
            'nome_banco':
            unicode(self.order.mode.bank_id.bank_name),
        }

    def get_file_numeration(self):
        numero = self.order.get_next_number()
        if not numero:
            numero = 1
        return numero

    def format_date(self, srt_date):
        return int(
            datetime.datetime.strptime(srt_date,
                                       '%Y-%m-%d').strftime('%d%m%Y'))

    def nosso_numero(self, format):
        pass

    def cep(self, format):
        sulfixo = format[-3:]
        prefixo = format[:5]
        return prefixo, sulfixo

    def sacado_inscricao_tipo(self, partner_id):
        # TODO: Implementar codigo para PIS/PASEP
        if partner_id.is_company:
            return 2
        else:
            return 1

    def rmchar(self, format):
        return re.sub('[%s]' % re.escape(string.punctuation), '', format or '')

    def _prepare_segmento(self, line):
        """
        :param line:
        :return:
        """
        prefixo, sulfixo = self.cep(line.partner_id.zip)

        aceite = u'N'
        if not self.order.mode.boleto_aceite == 'S':
            aceite = u'A'

        # Código agencia do cedente
        # cedente_agencia = cedente_agencia

        # Dígito verificador da agência do cedente
        # cedente_agencia_conta_dv = cedente_agencia_dv

        # Código da conta corrente do cedente
        # cedente_conta = cedente_conta

        # Dígito verificador da conta corrente do cedente
        # cedente_conta_dv = cedente_conta_dv

        # Dígito verificador de agencia e conta
        # Era cedente_agencia_conta_dv agora é cedente_dv_ag_cc

        return {
            'cedente_agencia_conta_dv':
            int(self.order.mode.bank_id.acc_number_dig),
            'controle_banco':
            int(self.order.mode.bank_id.bank_bic),
            'cedente_agencia':
            int(self.order.mode.bank_id.bra_number),
            'cedente_conta':
            int(self.order.mode.bank_id.acc_number),
            'cedente_conta_dv':
            self.order.mode.bank_id.acc_number_dig,
            'cedente_agencia_dv':
            self.order.mode.bank_id.bra_number_dig,
            'cedente_nome':
            self.order.company_id.legal_name,
            # DV ag e cc
            'cedente_dv_ag_cc': (self.order.mode.bank_id.acc_number_dig),
            'identificacao_titulo':
            line.move_line_id.name,  # 25 chars limit
            'identificacao_titulo_banco':
            u'0000000',  # TODO
            'identificacao_titulo_empresa':
            line.move_line_id.move_id.name,
            'numero_documento':
            line.move_line_id.transaction_ref,  # 10 chars limit
            'vencimento_titulo':
            self.format_date(line.ml_maturity_date),
            'valor_titulo':
            Decimal(str(line.amount_currency)).quantize(Decimal('1.00')),
            # TODO: Código adotado para identificar o título de cobrança.
            # 8 é Nota de cŕedito comercial
            'especie_titulo':
            int(self.order.mode.boleto_especie),
            'aceite_titulo':
            aceite,
            'data_emissao_titulo':
            self.format_date(line.ml_date_created),
            # Taxa de juros do Odoo padrão mensal: 2. Campo 27.3P
            # CEF/FEBRABAN e Itaú não tem.
            'codigo_juros':
            2,
            'juros_mora_data':
            self.format_date(line.ml_maturity_date),
            'juros_mora_taxa':
            Decimal(str(self.order.mode.late_payment_interest)).quantize(
                Decimal('1.00')),
            # Multa padrão em percentual no Odoo, valor '2'
            'codigo_multa':
            '2',
            'data_multa':
            self.format_date(line.ml_maturity_date),
            'juros_multa':
            Decimal(str(self.order.mode.late_payment_fee)).quantize(
                Decimal('1.00')),
            # TODO Remover taxa dia - deixar apenas taxa normal
            'juros_mora_taxa_dia':
            Decimal('0.00'),
            'valor_abatimento':
            Decimal('0.00'),
            'sacado_inscricao_tipo':
            int(self.sacado_inscricao_tipo(line.partner_id)),
            'sacado_inscricao_numero':
            int(self.rmchar(line.partner_id.cnpj_cpf)),
            'sacado_nome':
            line.partner_id.legal_name,
            'sacado_endereco':
            (line.partner_id.street + ' ' + line.partner_id.number),
            'sacado_bairro':
            line.partner_id.district,
            'sacado_cep':
            int(prefixo),
            'sacado_cep_sufixo':
            int(sulfixo),
            'sacado_cidade':
            line.partner_id.l10n_br_city_id.name,
            'sacado_uf':
            line.partner_id.state_id.code,
            'codigo_protesto':
            int(self.order.mode.boleto_protesto),
            'prazo_protesto':
            int(self.order.mode.boleto_protesto_prazo),
            'codigo_baixa':
            2,
            'prazo_baixa':
            0,  # De 5 a 120 dias.
            'controlecob_data_gravacao':
            self.data_hoje(),
            'cobranca_carteira':
            int(self.order.mode.boleto_carteira),
        }

    def remessa(self, order):
        """
        :param order:
        :return:
        """
        cobrancasimples_valor_titulos = 0

        self.order = order
        self.arquivo = Arquivo(self.bank, **self._prepare_header())
        for line in order.line_ids:
            self.arquivo.incluir_cobranca(**self._prepare_segmento(line))
            self.arquivo.lotes[0].header.servico_servico = 1
            # TODO: tratar soma de tipos de cobranca
            cobrancasimples_valor_titulos += line.amount_currency
            # fixed 'quantidade_registros'  in trailer to 000001
            self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \
                Decimal(cobrancasimples_valor_titulos).quantize(
                    Decimal('1.00'))

        remessa = unicode(self.arquivo)
        return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore')

    def data_hoje(self):
        return (int(time.strftime("%d%m%Y")))

    def hora_agora(self):
        return (int(time.strftime("%H%M%S")))
Exemplo n.º 28
0
    def _parse_cnab(self, data_file, raise_error=False):
        """
        LEIO os dados aqui mas o tipo 9 nao vem
        res = super(AccountBankStatementImport, self)._parse_cnab(data_file, raise_error)
        x,y,z = res
        tr = z[0]['transactions']
        for ln in tr:
            print ln['name']
            print ln['partner_name']
            print ln['ref']
        """

        cnab240_file = tempfile.NamedTemporaryFile()
        cnab240_file.write(data_file)
        cnab240_file.flush()

        #arquivo = Arquivo(sicoob, arquivo=open(cnab240_file.name, 'r'))
        arquivo = Arquivo(itau, arquivo=open(cnab240_file.name, 'r'))
        transacoes = []

        inicio = datetime.strptime(str(arquivo.header.arquivo_data_de_geracao),
                                   '%d%m%Y')
        final = datetime.strptime(str(arquivo.header.arquivo_data_de_geracao),
                                  '%d%m%Y')
        #import pudb;pu.db
        cod_arquivo = str(arquivo.header.arquivo_sequencia +
                          arquivo.header.cedente_conta)
        n_arq = '%s - %s - %s' % (arquivo.header.cedente_conta,
                                  inicio.strftime('%d/%m/%Y'),
                                  final.strftime('%d/%m/%Y'))

        company_id = 1
        if self.force_journal_account:
            if not self.journal_id.company_id:
                raise UserError(u"Informe a Empresa na Conta Selecionada")
            company_id = str(self.journal_id.company_id.id)
        else:
            raise UserError(u"Informe a Conta")
        len_company = len(company_id)
        for lote in arquivo.lotes:
            for evento in lote.eventos:
                if evento.servico_codigo_movimento not in (6, 8, 9, 10):
                    continue
                n_doc = '0'
                if evento.numero_documento:
                    c_doc = len(evento.numero_documento)
                    if c_doc > 7:
                        try:
                            pos_doc = evento.numero_documento.index('/')
                            n_doc = evento.numero_documento[:pos_doc]
                            # coloquei aqui pois os titulos velhos nao tem a empresa na frente
                            if company_id != n_doc[:len_company]:
                                continue
                        except:
                            n_doc = evento.numero_documento
                    else:
                        n_doc = evento.numero_documento

                    prt = self.env['account.invoice'].search(
                        [('number', 'ilike', evento.numero_documento)],
                        limit=1)
                    prt_id = 0
                    if prt:
                        sacado = prt.partner_id.name
                        prt_id = prt.partner_id.id
                    else:
                        sacado = evento.sacado_nome

                    if evento.servico_codigo_movimento == 9:
                        self._alterar_status_fatura(prt.id, n_arq)
                        continue

                #valor = evento.valor_lancamento
                valor = evento.valor_titulo
                #if evento.tipo_lancamento == 'D':
                #    valor *= -1
                if evento.data_credito == 0:
                    dta_credito = evento.data_ocorrencia
                else:
                    dta_credito = evento.data_credito
                cod_arquivo += n_doc
                transacoes.append({
                    'name':
                    n_doc,
                    'date':
                    datetime.strptime(str(dta_credito), '%d%m%Y'),
                    'amount':
                    valor,
                    'partner_name':
                    sacado,
                    'ref':
                    n_doc,
                    'unique_import_id':
                    str(cod_arquivo),
                })
        header = arquivo.lotes[0].header
        trailer = arquivo.lotes[0].trailer

        vals_bank_statement = {
            'name':
            u"%s - %s até %s" %
            (arquivo.header.nome_do_banco, inicio.strftime('%d/%m/%Y'),
             final.strftime('%d/%m/%Y')),
            'date':
            inicio,
            'balance_start':
            0.0,  # arquivo.lotes[0].header.valor_saldo_inicial,
            'balance_end_real':
            0.0,  #arquivo.lotes[0].trailer.valor_saldo_final,
            'transactions':
            transacoes
        }
        account_number = str(arquivo.header.cedente_conta)
        if self.force_journal_account:
            account_number = self.journal_id.bank_acc_number
        return (
            'BRL',  #arquivo.lotes[0].header.moeda,
            account_number,
            [vals_bank_statement])

        return res
Exemplo n.º 29
0
class PagFor500(Cnab):
    """

    """
    def __init__(self):
        super(Cnab, self).__init__()

    @staticmethod
    def get_bank(bank):
        if bank == '237':
            from .bancos.bradesco import BradescoPagFor
            return BradescoPagFor
        else:
            return PagFor500

    @property
    def inscricao_tipo(self):
        # TODO: Implementar codigo para PIS/PASEP
        if self.order.company_id.partner_id.is_company:
            return 2
        else:
            return 1

    def _prepare_header(self):
        """

        :param:
        :return:
        """
        return {
            'arquivo_data_de_geracao':
            self.data_hoje_pag_for(),
            'arquivo_hora_de_geracao':
            self.hora_agora(),
            # TODO: Número sequencial de arquivo
            'numero_remessa':
            int(self.get_file_numeration()),
            'cedente_inscricao_tipo':
            self.inscricao_tipo,
            'cnpj_cpf_base':
            int(punctuation_rm(self.order.company_id.cnpj_cpf)[0:8]),
            'cnpj_cpf_filial':
            int(punctuation_rm(self.order.company_id.cnpj_cpf)[9:12]),
            'sufixo_cnpj':
            int(punctuation_rm(self.order.company_id.cnpj_cpf)[12:14]),
            'cedente_agencia':
            int(self.order.mode.bank_id.bra_number),
            'cedente_conta':
            int(self.order.mode.bank_id.acc_number),
            'cedente_agencia_conta_dv':
            self.order.mode.bank_id.bra_number_dig,
            'nome_empresa_pagadora':
            self.order.company_id.legal_name,
            'cedente_codigo_agencia_digito':
            self.order.mode.bank_id.bra_number_dig,
            'arquivo_codigo':
            1,  # Remessa/Retorno
            'servico_operacao':
            u'R',
            'reservado_empresa':
            u'BRADESCO PAG FOR',
            # Sequencial crescente e nunca pode ser repetido
            'numero_lista_debito':
            int(self.get_file_numeration()),
            # TODO: Sequencial crescente de 1 a 1 no arquivo. O primeiro header
            #  será sempre 000001
            'sequencial':
            1
        }

    def get_file_numeration(self):
        numero = self.order.get_next_number()
        if not numero:
            numero = 1
        return numero

    def format_date(self, srt_date):
        return int(
            datetime.datetime.strptime(srt_date,
                                       '%Y-%m-%d').strftime('%d%m%Y'))

    def format_date_ano_mes_dia(self, srt_date):
        return int(
            datetime.datetime.strptime(srt_date,
                                       '%Y-%m-%d').strftime('%Y%m%d'))

    def nosso_numero(self, format):
        pass

    def cep(self, format):
        sulfixo = format[-3:]
        prefixo = format[:5]
        return prefixo, sulfixo

    def sacado_inscricao_tipo(self, partner_id):
        # TODO: Implementar codigo para PIS/PASEP
        if partner_id.is_company:
            return 2
        else:
            return 1

    def rmchar(self, format):
        return re.sub('[%s]' % re.escape(string.punctuation), '', format or '')

    def _prepare_segmento(self, line, vals):
        """

        :param line:
        :return:
        """
        segmento = {}

        vals.update(segmento)

        # TODO this zip code
        prefixo, sulfixo = self.cep(line.partner_id.zip)

        aceite = u'N'
        if not self.order.mode.boleto_aceite == 'S':
            aceite = u'A'

        segmento = {
            'conta_complementar':
            int(self.order.mode.bank_id.acc_number),
            # 'especie_titulo': 8,
            'tipo_inscricao':
            int(self.sacado_inscricao_tipo(line.partner_id)),
            'cnpj_cpf_base_forn':
            int(self.rmchar(line.partner_id.cnpj_cpf)[0:8]),
            'cnpj_cpf_filial_forn':
            int(self.rmchar(line.partner_id.cnpj_cpf)[9:12]),
            'cnpj_cpf_forn_sufixo':
            int(self.rmchar(line.partner_id.cnpj_cpf)[12:14]),
            'nome_forn':
            line.partner_id.legal_name,
            'endereco_forn':
            (line.partner_id.street + ' ' + line.partner_id.number),
            'cep_forn':
            int(prefixo),
            'cep_complemento_forn':
            int(sulfixo),

            # 'nosso_numero': 11,  # FIXME # TODO quando banco é 237, deve-se extrair da linha digitável. Do contrário, zeros.

            # 'numero_documento': line.name,
            # 'vencimento_titulo': self.format_date_ano_mes_dia(
            #     line.ml_maturity_date),
            'data_emissao_titulo':
            self.format_date_ano_mes_dia(line.ml_date_created),
            'desconto1_data':
            0,
            'fator_vencimento':
            0,  # FIXME
            'valor_titulo':
            Decimal(str(line.amount_currency)).quantize(Decimal('1.00')),
            'valor_pagto':
            Decimal(str(line.amount_currency)).quantize(Decimal('1.00')),
            'valor_desconto':
            Decimal('0.00'),
            'valor_acrescimo':
            Decimal('0.00'),

            # FIXME
            'tipo_documento':
            2,  # NF, Fatura, Duplicata...
            # NF_Fatura_01/Fatura_02/NF_03/Duplicata_04/Outros_05
            'numero_nf':
            int(line.ml_inv_ref.internal_number),
            'modalidade_pagamento':
            int(line.order_id.mode.type_purchase_payment),
            'data_para_efetivacao_pag':
            0,  # Quando não informada o sistema assume a data constante do campo Vencimento
            'tipo_movimento':
            0,
            # TODO Tipo de Movimento.
            # 0 - Inclusão.
            # 5 - Alteração.
            # 9 - Exclusão.
            'codigo_movimento':
            0,  # Autoriza agendamento

            # 'horario_consulta_saldo': u'5',  # Quando não informado consulta em todos processamentos
            'codigo_area_empresa':
            0,
            'codigo_lancamento':
            0,  # FIXME
            'tipo_conta_fornecedor':
            1,  # FIXME

            # O Primeiro registro de transação sempre será o registro
            # “000002”, e assim sucessivamente.
            'sequencial':
            3,  # FIXME

            # Trailer
            'totais_quantidade_registros':
            0,
            'total_valor_arq':
            Decimal('0.00'),
            # FIXME: lib nao reconhece campo
            'sequencial_trailer':
            int(self.get_file_numeration()),
            'sequencial_transacao':
            self.controle_linha,
            'codigo_protesto':
            int(self.order.mode.boleto_protesto),
            'prazo_protesto':
            int(self.order.mode.boleto_protesto_prazo),
            'codigo_baixa':
            2,
            'prazo_baixa':
            0,  # De 5 a 120 dias.
            'controlecob_data_gravacao':
            self.data_hoje(),
        }
        segmento.update(vals)
        return segmento

    def remessa(self, order):
        """

        :param order:
        :return:
        """

        pag_valor_titulos = 0

        self.order = order
        self.arquivo = Arquivo(self.bank, **self._prepare_header())
        cont_lote = 0

        for line in order.line_ids:
            self.arquivo.incluir_pagamento(**self.incluir_pagamento_for(line))
            pag_valor_titulos += line.amount_currency
            self.arquivo.trailer.total_valor_arq = Decimal(
                pag_valor_titulos).quantize(Decimal('1.00'))
            self.arquivo.trailer.sequencial_transacao = self.controle_linha

            cont_lote += 1
        remessa = unicode(self.arquivo)
        return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore')

    def data_hoje(self):
        return (int(time.strftime("%d%m%Y")))

    def data_hoje_pag_for(self):
        return (int(time.strftime("%Y%m%d")))

    def hora_agora(self):
        return (int(time.strftime("%H%M%S")))

    @staticmethod
    def modulo11(num, base, r):
        return BoletoData.modulo11(num, base=9, r=0)

    def incluir_pagamento_for(self, line):
        mode = line.order_id.mode.type_purchase_payment
        if mode in ('01'):
            return self.lancamento_credito_bradesco(line)
        elif mode in ('02'):
            raise UserError('Operação não suportada')
        elif mode in ('03'):
            return self.lancamento_doc(line)
        elif mode in ('05'):
            raise UserError('Operação não suportada')
        elif mode in ('08'):
            return self.lancamento_ted(line)
        elif mode in ('30'):
            raise UserError('Operação não suportada')
        elif mode in ('31'):
            # titulos de terceiros
            return self.lancamento_titulos_terceiros(line)
        raise UserError('Operação não suportada')

    def lancamento_credito_bradesco(self, line):
        # TODO:
        # modalidade 01.

        vals = {
            'especie_titulo':
            line.order_id.mode.type_purchase_payment,
            'codigo_banco_forn':
            237,
            'codigo_agencia_forn':
            int(line.bank_id.bra_number),
            'digito_agencia_forn_transacao':
            line.bank_id.bra_number_dig,
            'conta_corrente_forn':
            int(line.bank_id.acc_number),
            'digito_conta_forn_transacao':
            line.bank_id.acc_number_dig,
            'numero_pagamento':
            self.adiciona_digitos_num_pag(line.communication),
            'carteira':
            int(self.order.mode.boleto_carteira),
            'nosso_numero':
            0,
            'vencimento_titulo':
            self.format_date_ano_mes_dia(line.ml_maturity_date),
            'informacoes_complementares':
            u'',
        }

        return self._prepare_segmento(line, vals)

    def lancamento_ted(self, line):
        # TODO:
        # modalidade 08.

        vals = {
            'conta_complementar':
            int(self.order.mode.bank_id.acc_number),
            'especie_titulo':
            line.order_id.mode.type_purchase_payment,

            # TODO: código do banco. Para a Modalidade de Pagamento valor
            # pode variar
            'codigo_banco_forn':
            int(line.bank_id.bank.bic),
            'codigo_agencia_forn':
            int(line.bank_id.bra_number),
            'digito_agencia_forn_transacao':
            line.bank_id.bra_number_dig,
            'conta_corrente_forn':
            int(line.bank_id.acc_number),
            'digito_conta_forn_transacao':
            line.bank_id.acc_number_dig,
            # TODO Gerado pelo cliente pagador quando do agendamento de
            # pagamento por parte desse, exceto para a modalidade 30 -
            # Títulos em Cobrança Bradesco
            # communication
            'numero_pagamento':
            self.adiciona_digitos_num_pag(line.communication),
            'carteira':
            0,
            'nosso_numero':
            0,
            'vencimento_titulo':
            self.format_date_ano_mes_dia(line.ml_maturity_date),
            'fator_vencimento':
            0,  # FIXME

            # 'modalidade_pagamento': int(self.order.mode.boleto_especie),
            'tipo_movimento':
            0,
            # TODO Tipo de Movimento.
            # 0 - Inclusão.
            # 5 - Alteração.
            # 9 - Exclusão. Wkf Odoo.
            'codigo_movimento':
            0,  # FIXME
            # 'horario_consulta_saldo': u'5',  # FIXME

            # 'informacoes_complementares': self.montar_info_comple_ted(),
            'informacoes_complementares':
            u'',
            'codigo_lancamento':
            0,  # FIXME
            'tipo_conta_fornecedor':
            1,  # FIXME
        }

        return self._prepare_segmento(line, vals)

    def lancamento_doc(self):
        # TODO:

        vals = {}

        return self._prepare_segmento(vals)

    def lancamento_titulos_terceiros(self, line):
        # TODO:

        res_cods_ag_cc = \
            self.ler_linha_digitavel_codigos_ag_cc(line.linha_digitavel)

        vals = {
            'conta_complementar':
            int(self.order.mode.bank_id.acc_number),
            'especie_titulo':
            line.order_id.mode.type_purchase_payment,

            # extrair do código de barras
            'codigo_banco_forn':
            res_cods_ag_cc['codigo_banco_forn'],
            'codigo_agencia_forn':
            res_cods_ag_cc['codigo_agencia_forn'],
            'digito_agencia_forn_transacao':
            res_cods_ag_cc['digito_agencia_forn_transacao'],
            'conta_corrente_forn':
            res_cods_ag_cc['conta_corrente_forn'],
            'digito_conta_forn_transacao':
            res_cods_ag_cc['digito_conta_forn_transacao'],
            'carteira':
            res_cods_ag_cc['carteira']
        }

        return self._prepare_segmento(vals)

    def adiciona_digitos_num_pag(self, campo):
        num_digitos = 16
        campo = str(campo)
        chars_faltantes = num_digitos - len(campo)
        return (u' ' * chars_faltantes) + campo

    def montar_info_comple_ted(self):
        tipo_doc_compe = TIPO_DOC[0][0]
        num_doc_ted = '000000'
        finalidade_doc_compe = FINALIDADE_DOC_TED[2][
            0]  # pagamento duplicatas. Ou será 01?
        tipo_conta_doc_ted = '01'
        codigo_identif_transf = '0000000000000000000000000'
        fim_do_campo = '    '
        info_comple = tipo_doc_compe + num_doc_ted + finalidade_doc_compe + \
                      tipo_conta_doc_ted + codigo_identif_transf + fim_do_campo
        return (info_comple.encode('utf-8'))

    def ler_linha_digitavel_codigos_ag_cc(self, linha_digitavel):
        linha_completa = linha_digitavel

        codigo_banco_fornecedor = linha_digitavel[:3]
        res = {}

        # para banco = 237, bradesco
        if (codigo_banco_fornecedor == '237'):
            res = {
                'codigo_banco_forn': int(codigo_banco_fornecedor),
                'codigo_agencia_forn': int(linha_digitavel[4:8]),
                'digito_agencia_forn_transacao':
                u'',  # Calcular usando modulo 11 base 7
                'conta_corrente_forn': int(linha_digitavel[23:30]),
                'digito_conta_forn_transacao':
                u'',  # Calcular usando modulo 11 base 7
                'carteira': int(linha_digitavel[8:10]),
                'nosso_numero': int(linha_digitavel[11:21])
            }
        # para outros bancos
        else:
            res = {
                'codigo_banco_forn': int(codigo_banco_fornecedor),
                'codigo_agencia_forn': 0,
                'digito_agencia_forn_transacao': u'',
                'conta_corrente_forn': 0,
                'digito_conta_forn_transacao': u'',
                'carteira': 0,
                'nosso_numero': 0,
            }
        return res
Exemplo n.º 30
0
    def montarArquivo(self, cr, uid, ids, context=None):
        res = {}
        cnab_data = dict()
        for obj_id in self.browse(cr, uid, ids, context):
            # exportation_bank = obj_id.codigo_banco
            exportation_bank = u'341'

        segmento_pool = self.pool.get('cnab240export.segmentos')

        ids_segmentos = segmento_pool.search(
            cr, uid,
            [('arquivo_id', 'in', ids)])

        #itau_data = dict()


        #itau_data['arquivo'] = dict_arquivo
        #itau_data['cobranca'] = dict_cobranca
        #arquivo = Arquivo(itau, **itau_data['arquivo'])
        #arquivo.incluir_cobranca(**itau_data['cobranca'])
        #arquivo.lotes[0].header.servico_servico = 1

        # Header
        dict_arquivo = self.get_cnab_header_data(cr, uid, ids, context)
        cnab_data['arquivo'] = dict_arquivo
        if exportation_bank == u'104':
            arquivo = Arquivo(itau, **cnab_data['arquivo'])
        elif exportation_bank == u'341':
            arquivo = Arquivo(itau, **cnab_data['arquivo'])

        #cnab_data['cobranca'] = dict_cobranca
        #arquivo.incluir_cobranca(**cnab_data['cobranca'])
        for seg in ids_segmentos:
            #pdb.set_trace()
            segmento_cobranca = self.get_cnab_segmento_data(cr, uid, seg, context)
            #cedente_nome = obj_id.cedente_nome
            #cedente_inscricao_numero = obj_id.cedente_inscricao_numero
            #cedente_inscricao_tipo = obj_id.cedente_inscricao_tipo
            #cedente_agencia = obj_id.cedente_agencia
            #cedente_conta = obj_id.cedente_conta
            #cedente_agencia_conta_dv = obj_id.cedente_agencia_digito
            #cedente_codigo_codCedente = obj_id.cedente_codCedente
            #nome_do_banco = obj_id.nome_do_banco
            #arquivo_sequencia = int(obj_id.arquivo_sequencia)
            segmento_cobranca['cedente_nome'] = dict_arquivo.get('cedente_nome')
            segmento_cobranca['cedente_inscricao_numero'] = dict_arquivo.get('cedente_inscricao_numero')
            segmento_cobranca['cedente_inscricao_tipo'] = dict_arquivo.get('cedente_inscricao_tipo')
            segmento_cobranca['cedente_agencia'] = dict_arquivo.get('cedente_agencia')
            segmento_cobranca['cedente_conta'] = dict_arquivo.get('cedente_conta')
            segmento_cobranca['cedente_agencia_conta_dv'] = dict_arquivo.get('cedente_agencia_conta_dv')
            #segmento_cobranca['dente_codCedente'] = dict_arquivo.get('cedente_codCedente')
            #segmento_cobranca['nome_do_banco'] = dict_arquivo.get('nome_do_banco')
            #segmento_cobranca[''] = dict_arquivo.get('')
            
            cnab_data['cobranca'] = segmento_cobranca
            arquivo.incluir_cobranca(**cnab_data['cobranca'])
            arquivo.lotes[0].header.servico_servico = 1

        str = unicode(arquivo)
        f = open('/tmp/arquivo_remessa.rem','w')
        f.write(str) # python will convert \n to os.linesep
        f.close()

        return True
Exemplo n.º 31
0
 def setUp(self):
     self.santander_data = get_santander_data_from_dict()
     self.arquivo = Arquivo(santander, **self.santander_data['arquivo'])
Exemplo n.º 32
0
 def setUp(self):
     self.itau_data = get_itau_data_from_dict()
     self.arquivo = Arquivo(itau, **self.itau_data['arquivo'])
Exemplo n.º 33
0
 def setUp(self):
     self.bancoob_data = get_bancoob_data_from_dict()
     self.arquivo = Arquivo(bancoob, **self.bancoob_data['arquivo'])
Exemplo n.º 34
0
    def _parse_cnab(self, data_file, raise_error=False):
        cnab240_file = tempfile.NamedTemporaryFile()
        cnab240_file.write(data_file)
        cnab240_file.flush()

        journal_id = self.env.context['journal_id']
        if self.force_journal_account:
            journal_id = self.journal_id.id

        bank = self.get_bank(journal_id)
        arquivo = Arquivo(bank, arquivo=open(cnab240_file.name, 'r'))
        transacoes = []
        valor_total = Decimal('0.0')
        for lote in arquivo.lotes:
            for evento in lote.eventos:
                valor = evento.titulo_pago
                # Apenas liquidação  (Sicoob:6)
                # Liquidação Banco do Brasil (6, 17)
                # Liquidação Bradesco (6, 177)
                # Liquidação Santander ('06', '17')
                if evento.servico_codigo_movimento in (6, 17, '06', '17',):
                    valor_total += valor

                    nosso_numero = self._get_nosso_numero(
                        journal_id, evento.nosso_numero)

                    move_line = self.env['account.move.line'].search(
                        [('nosso_numero', '=', nosso_numero)])

                    transacoes.append({
                        'name': "%s : %s" % (
                            move_line.partner_id.name or evento.sacado_nome,
                            evento.numero_documento or "%s: %s" % (
                                move_line.move_id.name, move_line.name)),
                        'date': datetime.strptime(
                            str(evento.data_ocorrencia), '%d%m%Y'),
                        'amount': valor,
                        'partner_name':
                        move_line.partner_id.name or evento.sacado_nome,
                        'partner_id': move_line.partner_id.id,
                        'ref': evento.numero_documento,
                        'unique_import_id': str(evento.nosso_numero),
                        'nosso_numero': nosso_numero,
                    })

        inicio = final = datetime.now()
        if len(transacoes):
            primeira_transacao = min(transacoes, key=lambda x: x["date"])
            ultima_transacao = max(transacoes, key=lambda x: x["date"])
            inicio = primeira_transacao["date"]
            final = ultima_transacao["date"]

        last_bank_stmt = self.env['account.bank.statement'].search(
            [('journal_id', '=', journal_id)],
            order="date desc, id desc", limit=1)
        last_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0.0

        vals_bank_statement = {
            'name': u"%s - %s até %s" % (
                arquivo.header.nome_do_banco,
                inicio.strftime('%d/%m/%Y'),
                final.strftime('%d/%m/%Y')),
            'date': inicio,
            'balance_start': last_balance,
            'balance_end_real': Decimal(last_balance) + valor_total,
            'transactions': transacoes
        }
        account_number = ''  # str(arquivo.header.cedente_conta)
        if self.force_journal_account:
            account_number = self.journal_id.bank_acc_number
        return (
            'BRL',
            account_number,
            [vals_bank_statement]
        )
Exemplo n.º 35
0
    def do_import(self, cnab_file):
        if self.cnab_type != 'receivable':
            return super(L10nBrPaymentCnabImport, self).do_import(cnab_file)

        stream = StringIO(cnab_file.decode('ascii'))
        bank = get_bank(self.journal_id.bank_id.bic)
        arquivo = Arquivo(bank, arquivo=stream)
        sequence = self.journal_id.l10n_br_sequence_statements
        statement = None

        for lote in arquivo.lotes:
            for evento in lote.eventos:

                if not statement:
                    statement = self.env['l10n_br.payment.statement'].create({
                        'journal_id':
                        self.journal_id.id,
                        'date':
                        date.today(),
                        'company_id':
                        self.journal_id.company_id.id,
                        'name':
                        sequence.next_by_id(),
                        'type':
                        'receivable',
                    })

                code, message = parse_cnab_code(
                    self.journal_id.bank_id.bic,
                    evento.servico_codigo_movimento)

                payment_line = self.env['payment.order.line'].search([
                    ('nosso_numero', '=', int(evento.nosso_numero)),
                    ('src_bank_account_id', '=',
                     self.journal_id.bank_account_id.id)
                ])

                due_date = date.today()
                effective_date = None
                if evento.vencimento_titulo:
                    due_date = datetime.strptime(
                        "{:08}".format(evento.vencimento_titulo), "%d%m%Y")
                if evento.data_ocorrencia:
                    effective_date = datetime.strptime(
                        "{:08}".format(evento.data_ocorrencia), "%d%m%Y")

                vals = {
                    'nosso_numero': evento.nosso_numero,
                    'numero_documento': evento.numero_documento,
                    'sacado_nome': evento.sacado_nome,
                    'valor_titulo': evento.valor_titulo,
                    'titulo_acrescimos': evento.titulo_acrescimos,
                    'titulo_desconto': evento.titulo_desconto,
                    'titulo_abatimento': evento.titulo_abatimento,
                    'titulo_pago': evento.titulo_pago,
                    'valor_tarifas': evento.valor_tarifas,
                    'titulo_liquido': evento.titulo_liquido,
                    'vencimento_titulo': due_date,
                    'data_ocorrencia': effective_date,
                    'cnab_code': code,
                    'cnab_message': message,
                }

                IMMUTABLE_STATES = ('paid', 'rejected', 'cancelled')
                if payment_line and payment_line.state in IMMUTABLE_STATES:
                    vals['cnab_message'] = 'Importado previamente'
                    self._create_ignored_line(statement, vals, payment_line)
                    continue

                if not payment_line:
                    self._create_ignored_line(statement, vals)
                    continue

                # Process the line
                payment_line.process_receivable_line(statement, vals)

        if not statement:
            raise UserError(_('Nenhum registro localizado nesse extrato!'))
        action = self.env.ref(
            'br_account_payment.action_payment_statement_tree')
        return action.read()[0]