From a63a3ab477ba95c44063c51f4aa5432d595f4198 Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Wed, 18 Dec 2019 09:12:12 -0300 Subject: [PATCH 01/12] [NEW] Extraction erpbrasil.febraban from l10n_br_account_payment_cobranca --- cnab_erpbrasil_febraban/README.rst | 91 +++ cnab_erpbrasil_febraban/__init__.py | 1 + cnab_erpbrasil_febraban/__manifest__.py | 24 + cnab_erpbrasil_febraban/febraban/__init__.py | 6 + .../febraban/boleto/__init__.py | 6 + .../febraban/boleto/document.py | 350 +++++++++++ cnab_erpbrasil_febraban/febraban/cnab.py | 89 +++ .../febraban/cnab_240/__init__.py | 4 + .../febraban/cnab_240/bancos/__init__.py | 6 + .../febraban/cnab_240/bancos/bb.py | 65 ++ .../febraban/cnab_240/bancos/bradesco.py | 67 ++ .../febraban/cnab_240/bancos/bradesco.py.orig | 71 +++ .../febraban/cnab_240/bancos/cef.py | 92 +++ .../febraban/cnab_240/bancos/itau.py | 67 ++ .../febraban/cnab_240/bancos/santander.py | 42 ++ .../febraban/cnab_240/cnab_240.py | 574 ++++++++++++++++++ .../febraban/cnab_240/cnab_240.py.orig | 566 +++++++++++++++++ .../febraban/cnab_400/__init__.py | 6 + .../febraban/cnab_400/bancos/__init__.py | 4 + .../febraban/cnab_400/bancos/bradesco.py | 97 +++ .../febraban/cnab_400/bancos/itau.py | 176 ++++++ .../febraban/cnab_400/cnab_400.py | 401 ++++++++++++ .../febraban/pag_for/__init__.py | 8 + .../febraban/pag_for/bancos/__init__.py | 6 + .../febraban/pag_for/bancos/bradesco.py | 60 ++ .../febraban/pag_for/pag_for500.py | 573 +++++++++++++++++ cnab_erpbrasil_febraban/models/__init__.py | 5 + .../models/account_invoice.py | 139 +++++ .../models/account_move_line.py | 50 ++ .../models/account_payment_mode.py | 18 + .../models/account_payment_order.py | 36 ++ .../models/l10n_br_cnab.py | 152 +++++ .../static/description/icon.png | Bin 0 -> 9455 bytes .../views/account_invoice.xml | 18 + 34 files changed, 3870 insertions(+) create mode 100644 cnab_erpbrasil_febraban/README.rst create mode 100644 cnab_erpbrasil_febraban/__init__.py create mode 100644 cnab_erpbrasil_febraban/__manifest__.py create mode 100644 cnab_erpbrasil_febraban/febraban/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/boleto/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/boleto/document.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py create mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py create mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py create mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py create mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py create mode 100644 cnab_erpbrasil_febraban/models/__init__.py create mode 100644 cnab_erpbrasil_febraban/models/account_invoice.py create mode 100644 cnab_erpbrasil_febraban/models/account_move_line.py create mode 100644 cnab_erpbrasil_febraban/models/account_payment_mode.py create mode 100644 cnab_erpbrasil_febraban/models/account_payment_order.py create mode 100644 cnab_erpbrasil_febraban/models/l10n_br_cnab.py create mode 100644 cnab_erpbrasil_febraban/static/description/icon.png create mode 100644 cnab_erpbrasil_febraban/views/account_invoice.xml diff --git a/cnab_erpbrasil_febraban/README.rst b/cnab_erpbrasil_febraban/README.rst new file mode 100644 index 000000000000..9d445db03244 --- /dev/null +++ b/cnab_erpbrasil_febraban/README.rst @@ -0,0 +1,91 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================= +Cnab Erpbrasil Febraban +======================= + +Integração com CNAB através da biblioteca erpbrasil.febraban + +Installation +============ + +To install this module, you need to: + +#. Do this ... + +Configuration +============= + +To configure this module, you need to: + +#. Go to ... + +.. figure:: path/to/local/image.png + :alt: alternative description + :width: 600 px + +Usage +===== + +To use this module, you need to: + +#. Go to ... + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +Known issues / Roadmap +====================== + +* ... + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Firstname Lastname +* Second Person + +Funders +------- + +The development of this module has been financially supported by: + +* Company 1 name +* Company 2 name + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/cnab_erpbrasil_febraban/__init__.py b/cnab_erpbrasil_febraban/__init__.py new file mode 100644 index 000000000000..0650744f6bc6 --- /dev/null +++ b/cnab_erpbrasil_febraban/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/cnab_erpbrasil_febraban/__manifest__.py b/cnab_erpbrasil_febraban/__manifest__.py new file mode 100644 index 000000000000..821b4bfe2759 --- /dev/null +++ b/cnab_erpbrasil_febraban/__manifest__.py @@ -0,0 +1,24 @@ +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Cnab Erpbrasil Febraban', + 'summary': """ + Integração com CNAB através da biblioteca erpbrasil.febraban""", + 'version': '12.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'KMEE,Odoo Community Association (OCA)', + 'website': 'http://odoo-brasil.org', + 'depends': [ + 'l10n_br_account_payment_cobranca', + 'queue_job' + ], + 'data': [ + 'views/account_invoice.xml', + ], + 'demo': [ + ], + 'external_dependencies': { + 'python': ['erpbrasil.febraban'], + }, +} diff --git a/cnab_erpbrasil_febraban/febraban/__init__.py b/cnab_erpbrasil_febraban/febraban/__init__.py new file mode 100644 index 000000000000..2cfbd6d7e782 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/boleto/__init__.py b/cnab_erpbrasil_febraban/febraban/boleto/__init__.py new file mode 100644 index 000000000000..4338cb783c5d --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/boleto/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2012 KMEE +# @author Luis Felipe Miléo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import document diff --git a/cnab_erpbrasil_febraban/febraban/boleto/document.py b/cnab_erpbrasil_febraban/febraban/boleto/document.py new file mode 100644 index 000000000000..b33e1d61eae1 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/boleto/document.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA (Luis Felipe Mileo mileo@kmee.com.br) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import datetime, date +import logging + +_logger = logging.getLogger(__name__) + +try: + from pyboleto import bank +except ImportError as err: + _logger.debug = err + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +BoletoException = bank.BoletoException + + +class Boleto: + boleto = object + account_number = '' + account_digit = '' + + branch_number = '' + branch_digit = '' + + nosso_numero = '' + + @staticmethod + def getBoleto(move_line, nosso_numero): + boleto_type = move_line.payment_mode_id.boleto_type + if boleto_type: + return dict_boleto[boleto_type][0](move_line, nosso_numero) + raise BoletoException(u'Configure o tipo de boleto no modo de ' + u'pagamento') + + @staticmethod + def getBoletoClass(move_line): + bank_code = \ + move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bank_id.code_bc + return bank.get_class_for_codigo(bank_code) + + def __init__(self, move_line, nosso_numero): + self._cedente(move_line.company_id) + self._sacado(move_line.partner_id) + self._move_line(move_line) + self.nosso_numero = str(nosso_numero) + + def getAccountNumber(self): + if self.account_digit: + return str(self.account_number + '-' + + self.account_digit).encode('utf-8') + return self.account_number.encode('utf-8') + + def getBranchNumber(self): + if self.branch_digit: + return str(self.branch_number + '-' + + self.branch_digit).encode('utf-8') + return self.branch_number.encode('utf-8') + + def _move_line(self, move_line): + self._payment_mode(move_line.payment_mode_id) + self._instructions(move_line.instrucoes) + self.boleto.data_vencimento = datetime.date(datetime.strptime( + move_line.date_maturity, '%Y-%m-%d')) + self.boleto.data_documento = datetime.date(datetime.strptime( + move_line.invoice_id.date_invoice, '%Y-%m-%d')) + self.boleto.data_processamento = date.today() + self.boleto.valor = str("%.2f" % move_line.residual if + move_line.residual else + move_line.debit or move_line.credit) + self.boleto.valor_documento = str("%.2f" % move_line.residual if + move_line.residual else + move_line.debit or move_line.credit) + self.boleto.especie = \ + move_line.currency_id and move_line.currency_id.symbol or 'R$' + self.boleto.quantidade = '' # str("%.2f" % move_line.amount_currency) + self.boleto.numero_documento = move_line.numero_documento + + def _instructions(self, instrucoes): + """ + :param instrucoes: + :return: + """ + if instrucoes: + for instrucao in instrucoes.split('\n'): + self.boleto.instrucoes.append(instrucao) + + def _payment_mode(self, payment_mode_id): + """ + :param payment_mode: + :return: + """ + self.boleto.convenio = payment_mode_id.boleto_convenio + self.boleto.especie_documento = payment_mode_id.boleto_modalidade + self.boleto.aceite = payment_mode_id.boleto_aceite + self.boleto.carteira = str(payment_mode_id.boleto_carteira) + + def _cedente(self, company): + """ + :param company: + :return: + """ + self.boleto.cedente = company.partner_id.legal_name.encode('utf-8') + self.boleto.cedente_documento = company.cnpj_cpf.encode('utf-8') + self.boleto.cedente_bairro = company.district + self.boleto.cedente_cep = company.zip + self.boleto.cedente_cidade = company.l10n_br_city_id.name + self.boleto.cedente_logradouro = \ + company.street + ', ' + company.number + self.boleto.cedente_uf = company.state_id.code + self.boleto.agencia_cedente = self.getBranchNumber() + self.boleto.conta_cedente = self.getAccountNumber() + + def _sacado(self, partner): + """ + + :param partner: + :return: + """ + self.boleto.sacado_endereco = \ + partner.street + ', ' + partner.number + self.boleto.sacado_cidade = partner.l10n_br_city_id.name + self.boleto.sacado_bairro = partner.district or '' + self.boleto.sacado_uf = partner.state_id.code + self.boleto.sacado_cep = partner.zip + self.boleto.sacado_nome = partner.legal_name + self.boleto.sacado_documento = partner.cnpj_cpf + + @classmethod + def get_pdfs(cls, boleto_list): + """ + + :param boletoList: + :return: + """ + fbuffer = StringIO() + + fbuffer.reset() + from pyboleto.pdf import BoletoPDF + + boleto = BoletoPDF(fbuffer) + for i in range(len(boleto_list)): + boleto.drawBoleto(boleto_list[i]) + boleto.nextPage() + boleto.save() + boleto_file = fbuffer.getvalue() + + fbuffer.close() + return boleto_file + + +class BoletoBB(Boleto): + + def __init__(self, move_line, nosso_numero): + # TODO: size o convenio and nosso numero, replace (7,2) + # Size of convenio 4, 6, 7 or 8 + # Nosso Numero format. 1 or 2 + # Used only for convenio=6 + # 1: Nosso Numero with 5 positions + # 2: Nosso Numero with 17 positions + self.boleto = Boleto.getBoletoClass(move_line)(7, 2) + self.account_number = \ + move_line.payment_mode_id.fixed_journal_id. \ + bank_account_id.acc_number + self.branch_number = \ + move_line.payment_mode_id.fixed_journal_id. \ + bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoBarisul(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = \ + move_line.payment_mode_id.fixed_journal_id. \ + bank_account_id.acc_number + self.branch_number = \ + move_line.payment_mode_id.fixed_journal_id. \ + bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoBradesco(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = \ + move_line.payment_mode_id.fixed_journal_id. \ + bank_account_id.acc_number + self.branch_number = \ + move_line.payment_mode_id.fixed_journal_id. \ + bank_account_id.bra_number + # bank specific + self.account_digit = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number_dig + self.branch_digit = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number_dig + # end bank specific + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoCaixa(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + # bank specific + self.account_digit = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number_dig + # end bank specific + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoHsbc(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoItau157(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoItau(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoReal(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoSantander101(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.ios = '0' + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoStatander101201(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.ios = '0' + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoCaixaSigcb(Boleto): + + def __init__(self, move_line, nosso_numero): + from pyboleto.bank.caixa_sigcb import BoletoCaixaSigcb + self.boleto = BoletoCaixaSigcb() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + # bank specific + self.account_digit = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number_dig + # end bank specific + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +class BoletoSicredi(Boleto): + + def __init__(self, move_line, nosso_numero): + self.boleto = Boleto.getBoletoClass(move_line)() + self.account_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.acc_number + self.branch_number = move_line.payment_mode_id. \ + fixed_journal_id.bank_account_id.bra_number + Boleto.__init__(self, move_line, nosso_numero) + self.boleto.nosso_numero = self.nosso_numero + + +dict_boleto = { + '1': (BoletoBB, 'Banco do Brasil 18'), + '2': (BoletoBarisul, 'Barisul x'), + '3': (BoletoBradesco, 'Bradesco 06, 03'), + '4': (BoletoCaixa, 'Caixa Economica SR'), + '5': (BoletoHsbc, 'HSBC CNR CSB'), + '6': (BoletoItau157, 'Itau 157'), + '7': (BoletoItau, 'Itau 175, 174, 178, 104, 109'), + '8': (BoletoReal, 'Real 57'), + '9': (BoletoSantander101, 'Santander 102'), + '10': (BoletoStatander101201, 'Santander 101, 201'), + '11': (BoletoCaixaSigcb, 'Caixa Sigcb'), + '12': (BoletoSicredi, 'Sicredi'), +} + + +def getBoletoSelection(): + list = [] + for i in dict_boleto: + list.append((i, dict_boleto[i][1])) + return list diff --git a/cnab_erpbrasil_febraban/febraban/cnab.py b/cnab_erpbrasil_febraban/febraban/cnab.py new file mode 100644 index 000000000000..869d227a2b01 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from __future__ import division, print_function, unicode_literals + +import logging +import base64 +import codecs + +_logger = logging.getLogger(__name__) + + +try: + from cnab240.tipos import ArquivoCobranca400 +except ImportError as err: + _logger.debug = (err) + + +class Cnab(object): + + def __init__(self): + self.arquivo = False + self.cnab_type = False + + @staticmethod + def get_cnab(bank, cnab_type='240'): + if cnab_type == '240': + from .cnab_240.cnab_240 import Cnab240 + return Cnab240.get_bank(bank) + elif cnab_type == '400': + from .cnab_400.cnab_400 import Cnab400 + return Cnab400.get_bank(bank) + elif cnab_type == '500': + from .pag_for.pag_for500 import PagFor500 + return PagFor500.get_bank(bank) + else: + return False + + @staticmethod + def gerar_remessa(order): + cnab = Cnab.get_cnab( + order.company_partner_bank_id.bank_id.code_bc, + order.payment_mode_id.payment_method_id.code + )() + return cnab.remessa(order) + + @staticmethod + def detectar_retorno(cnab_file_object): + arquivo_retono = base64.b64decode(cnab_file_object) + f = open('/tmp/cnab_retorno.ret', 'wb') + f.write(arquivo_retono) + f.close() + arquivo_retorno = codecs.open( + '/tmp/cnab_retorno.ret', + encoding='ascii' + ) + header = arquivo_retorno.readline() + arquivo_retorno.seek(0) + + if 210 < len(header) < 410: + cnab_type = '400' + banco = header[76:79] + elif len(header) < 210: + cnab_type = '240' + banco = header[:3] + + cnab = Cnab.get_cnab(banco, cnab_type)() + return cnab_type, cnab.retorno(arquivo_retorno) + + def retorno(self, arquivo_retorno): + return ArquivoCobranca400( + self.classe_retorno, + arquivo=arquivo_retorno + ) + + def remessa(self, order): + pass + + def convert_int(self, campo): + if campo: + return int(campo) + # Retornamos de propósito vazio para que a cnab240 acuse o erro do + # registro em branco pois, se retornarmos ZERO o erro vai passar + # despercebido + return '' diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py new file mode 100644 index 000000000000..7813b32b4bc8 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py new file mode 100644 index 000000000000..2cfbd6d7e782 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py new file mode 100644 index 000000000000..5826a47b9484 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from __future__ import division, print_function, unicode_literals + +import re +import string + +from ..cnab_240 import Cnab240 + + +class BB240(Cnab240): + + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import bancodobrasil + self.bank = bancodobrasil + + def _prepare_header(self): + """ + Preparar header do arquivo. + Adicionar informações no header do arquivo do Banco do Brasil + """ + vals = super(BB240, self)._prepare_header() + # vals['servico_servico'] = 1 + return vals + + def _prepare_cobranca(self, line): + """ + Preparar o evento (segmentoA e segmentoB) apartir da payment.line + :param line - payment.line + :return: dict - Informações + """ + vals = super(BB240, self)._prepare_cobranca(line) + # vals['prazo_baixa'] = unicode(str( + # vals['prazo_baixa']), "utf-8") + # vals['desconto1_percentual'] = Decimal('0.00') + # vals['valor_iof'] = Decimal('0.00') + # # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + # vals['identificacao_titulo_banco'] = self.convert_int( + # vals['identificacao_titulo_banco']) + # vals['cedente_conta_dv'] = unicode(str( + # vals['cedente_conta_dv']), "utf-8") + # vals['cedente_agencia_dv'] = unicode(str( + # vals['cedente_agencia_dv']), "utf-8") + # vals['cedente_dv_ag_cc'] = unicode(str( + # vals['cedente_dv_ag_cc']), "utf-8") + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py new file mode 100644 index 000000000000..7f9d5eb282b5 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import re +import string +from decimal import Decimal + +from ..cnab_240 import Cnab240 + + +class Bradesco240(Cnab240): + + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import bradesco + self.bank = bradesco + + def _prepare_header(self): + """ + + :param order: + :return: + """ + + vals = super(Bradesco240, self)._prepare_header() + vals['servico_servico'] = 1 + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Bradesco240, self)._prepare_cobranca(line) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + vals['identificacao_titulo_banco'] = self.convert_int( + vals['identificacao_titulo_banco']) + vals['cedente_conta_dv'] = unicode(str( + vals['cedente_conta_dv']), "utf-8") + vals['cedente_agencia_dv'] = unicode(str( + vals['cedente_agencia_dv']), "utf-8") + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + +def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig new file mode 100644 index 000000000000..95d4537a20cb --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig @@ -0,0 +1,71 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +from ..cnab_240 import Cnab240 +import re +import string +from decimal import Decimal + + +class Bradesco240(Cnab240): +<<<<<<< HEAD +======= + +>>>>>>> [FIX] pep8 and merge clear + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import bradesco + self.bank = bradesco + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(Bradesco240, self)._prepare_header() + return vals + + def _prepare_segmento(self, line): + """ + + :param line: + :return: + """ + vals = super(Bradesco240, self)._prepare_segmento(line) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py new file mode 100644 index 000000000000..7e6e1c03ccd2 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import re +import string +from decimal import Decimal + +from ..cnab_240 import Cnab240 + + +class Cef240(Cnab240): + + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import cef + self.bank = cef + + def _prepare_header(self): + """ + + :return: + """ + vals = super(Cef240, self)._prepare_header() + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + vals['cedente_agencia_dv'] = unicode(str( + vals['cedente_agencia_dv']), "utf-8") + # TODO: adicionar campo para preencher o codigo do cedente no + # cadastro da conta bancária + vals['cedente_codigo_codCedente'] = 6088 + vals['nome_do_banco'] = u'CAIXA ECONOMICA FEDERAL' + # Não pode pegar comentário da payment_line. + vals['reservado_cedente_campo23'] = u'REMESSA TESTE' + # reservado_banco_campo22 não é required. Código atualizado na + # biblioteca cnab240 + vals['data_credito_hd_lote'] = 15052015 + + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Cef240, self)._prepare_cobranca(line) + + carteira, nosso_numero, digito = self.nosso_numero( + line.move_line_id.transaction_ref) + + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + # Informar o Número do Documento - Seu Número (mesmo das posições + # 63-73 do Segmento P) + vals['identificacao_titulo'] = unicode(str( + vals['numero_documento']), "utf-8") + # TODO: campo 27.3P CEF. Código do juros de mora + vals['juros_cod_mora'] = 3 + vals['carteira_numero'] = self.convert_int(carteira) + vals['nosso_numero'] = self.convert_int(nosso_numero) + vals['nosso_numero_dv'] = self.convert_int(digito) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + + # Precisam estar preenchidos + # Header lote + # vals['servico_operacao'] = u'R' + # vals['servico_servico'] = 1 + vals['cedente_conta_dv'] = unicode(str( + vals['cedente_conta_dv']), "utf-8") + vals['cedente_codigo_codCedente'] = 6088 + vals['data_credito_hd_lote'] = 15052015 + + vals['desconto1_cod'] = 3 + vals['desconto1_data'] = 0 + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = 14 + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py new file mode 100644 index 000000000000..0ebb6a40e564 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import re +import string + +from ..cnab_240 import Cnab240 + + +class Itau240(Cnab240): + """ + + """ + + def __init__(self): + """ + + :return: + """ + super(Cnab240, self).__init__() + from cnab240.bancos import itau + self.bank = itau + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(Itau240, self)._prepare_header() + # vals['cedente_dv_ag_cc'] = self.convert_int( + # vals['cedente_dv_ag_cc']) + # vals['cedente_agencia_dv'] = self.convert_int( + # vals['cedente_agencia_dv']), + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Itau240, self)._prepare_cobranca(line) + + carteira, nosso_numero, digito = self.nosso_numero( + line.move_line_id.transaction_ref) + + vals['cedente_dv_ag_cc'] = self.convert_int( + vals['cedente_dv_ag_cc']) + vals['carteira_numero'] = self.convert_int(carteira) + vals['nosso_numero'] = self.convert_int(nosso_numero) + vals['nosso_numero_dv'] = self.convert_int(digito) + + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py new file mode 100644 index 000000000000..e04fc80fb92c --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from ..cnab_240 import Cnab240 + + +class Santander240(Cnab240): + """ + + """ + + def __init__(self): + """ + + :return: + """ + super(Cnab240, self).__init__() + from cnab240.bancos import santander + self.bank = santander + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(Santander240, self)._prepare_header() + del vals['arquivo_hora_de_geracao'] + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Santander240, self)._prepare_cobranca(line) + return vals diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py new file mode 100644 index 000000000000..f38a96645d15 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py @@ -0,0 +1,574 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from __future__ import division, print_function, unicode_literals + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from odoo.addons.l10n_br_base.tools.misc import punctuation_rm + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: + from cnab240.tipos import Arquivo, Lote +except ImportError as err: + _logger.debug = err + + +class Cnab240(Cnab): + """ + CNAB240 + """ + + def __init__(self): + super(Cnab, self).__init__() + + @staticmethod + def get_bank(bank): + ''' + Função chamada na criação do CNAB que dado o código do banco, + instancia o objeto do banco e retorna o obj ao CNAB que sera criado. + :param bank: str - Código do banco + :return: + ''' + 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 == '001': + from .bancos.bb import BB240 + return BB240 + else: + return Cnab240 + + def get_inscricao_tipo(self, partner_id): + # TODO: Implementar codigo para PIS/PASEP + if partner_id.is_company: + return 2 + else: + return 1 + + def _prepare_header(self): + """ + Preparar o header do arquivo do CNAB + :return: dict - Header do arquivo + """ + header_arquivo = { + # CONTROLE + # 01.0 + 'controle_banco': self.convert_int( + self.order.company_partner_bank_id.bank_id.code_bc + ), + # 02.0 # Sequencia para o Arquivo + 'controle_lote': 1, + # 03.0 0- Header do Arquivo + 'controle_registro': 0, + # 04.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + + # EMPRESA + # 05.0 - 1 - CPF / 2 - CNPJ + 'cedente_inscricao_tipo': + self.get_inscricao_tipo(self.order.company_id.partner_id), + # 06.0 + 'cedente_inscricao_numero': + self.convert_int(punctuation_rm(self.order.company_id.cnpj_cpf)), + # 07.0 + 'cedente_convenio': '0001222130126', + # 08.0 + 'cedente_agencia': + self.convert_int(self.order.company_partner_bank_id.bra_number), + # 09.0 + 'cedente_agencia_dv': + self.order.company_partner_bank_id.bra_number_dig, + # 10.0 + 'cedente_conta': + self.convert_int(punctuation_rm( + self.order.company_partner_bank_id.acc_number)), + # 11.0 + 'cedente_conta_dv': + self.order.company_partner_bank_id.acc_number_dig[0], + # 12.0 + 'cedente_agencia_conta_dv': + self.order.company_partner_bank_id.acc_number_dig[1] + if len( + self.order.company_partner_bank_id.acc_number_dig + ) > 1 else '', + # 13.0 + 'cedente_nome': + self.order.company_partner_bank_id.partner_id.legal_name[:30] + if self.order.company_partner_bank_id.partner_id.legal_name + else self.order.company_partner_bank_id.partner_id.name[:30], + # 14.0 + 'nome_banco': self.order.company_partner_bank_id.bank_name, + # 15.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + + # ARQUIVO + # 16.0 Código Remessa = 1 / Retorno = 2 + 'arquivo_codigo': '1', + # 17.0 + 'arquivo_data_de_geracao': self.data_hoje(), + # 18.0 + 'arquivo_hora_de_geracao': self.hora_agora(), + # 19.0 TODO: Número sequencial de arquivo + 'arquivo_sequencia': self.convert_int(self.get_file_numeration()), + # 20.0 + 'arquivo_layout': 103, + # 21.0 + 'arquivo_densidade': 0, + # 22.0 + 'reservado_banco': '', + # 23.0 + 'reservado_empresa': 'EMPRESA 100', + # 24.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + } + + return header_arquivo + + def _prepare_header_lote(self): + """ + Preparar o header de LOTE para arquivo do CNAB + :return: dict - Header do arquivo + """ + empresa = self.order.company_partner_bank_id.partner_id + + header_arquivo_lote = { + + # CONTROLE + # 01.1 + 'controle_banco': self.convert_int(self.order.company_partner_bank_id.code_bc), + # 02.1 Sequencia para o Arquivo + 'controle_lote': 1, + # 03.1 0- Header do Arquivo + 'controle_registro': 1, + + # SERVICO + # 04.1 # Header do lote sempre 'C' + 'servico_operacao': 'C', + # 05.1 + 'servico_servico': self.order.tipo_servico, + # 06.1 + 'servico_forma_lancamento': 1, + # 07.1 + 'servico_layout': 20, + # 08.1 + # CNAB - Uso Exclusivo da FEBRABAN/CNAB + + # EMPRESA CEDENTE + # 09.1 + 'empresa_inscricao_tipo': 2, + # self.get_inscricao_tipo(self.order.company_id.partner_id), + # 10.1 + 'empresa_inscricao_numero': punctuation_rm(empresa.cnpj_cpf), + # 11.1 + 'cedente_convenio': self.order.codigo_convenio, + # 12.1 + 'cedente_agencia': + self.convert_int(self.order.company_partner_bank_id.bra_number), + # 13.1 + 'cedente_agencia_dv': + self.order.company_partner_bank_id.bra_number_dig, + # 14.1 + 'cedente_conta': + self.convert_int(punctuation_rm( + self.order.company_partner_bank_id.acc_number)), + # 15.1 + 'cedente_conta_dv': + self.order.company_partner_bank_id.acc_number_dig[0], + # 16.1 + 'cedente_agencia_conta_dv': + self.order.company_partner_bank_id.acc_number_dig[1] + if len( + self.order.company_partner_bank_id.acc_number_dig + ) > 1 else '', + # 17.1 + 'cedente_nome': + self.order.company_partner_bank_id.partner_id.legal_name[:30] + if self.order.company_partner_bank_id.partner_id.legal_name + else self.order.company_partner_bank_id.partner_id.name[:30], + # 18.1 + 'mensagem1': '', + + # ENDERECO + # 19.1 + 'empresa_logradouro': empresa.street, + # 20.1 + 'empresa_endereco_numero': empresa.number, + # 21.1 + 'empresa_endereco_complemento': empresa.street2, + # 22.1 + 'empresa_endereco_cidade': empresa.l10n_br_city_id.name, + # 23.1 + 'empresa_endereco_cep': self.get_cep('prefixo', empresa.zip), + # 24.1 + 'empresa_endereco_cep_complemento': + self.get_cep('sufixo', empresa.zip), + # 25.1 + 'empresa_endereco_estado': empresa.state_id.code, + + # 26.1 + 'indicativo_forma_pagamento': '', + # 27.1 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + # 28.1 + 'ocorrencias': '', + } + return header_arquivo_lote + + def get_file_numeration(self): + # Função para retornar a numeração sequencial do arquivo + return 1 + + def _prepare_cobranca(self, line): + """ + :param line: + :return: + """ + # prefixo, sufixo = self.cep(line.partner_id.zip) + + aceite = u'N' + 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': self.convert_int( + self.order.company_partner_bank_id.code_bc), + 'cedente_agencia': self.convert_int( + self.order.company_partner_bank_id.bra_number), + 'cedente_conta': self.convert_int( + self.order.company_partner_bank_id.acc_number), + 'cedente_conta_dv': + self.order.company_partner_bank_id.acc_number_dig, + 'cedente_agencia_dv': + self.order.company_partner_bank_id.bra_number_dig, + 'identificacao_titulo': u'0000000', # TODO + 'identificacao_titulo_banco': u'0000000', # TODO + 'identificacao_titulo_empresa': line.move_line_id.move_id.name, + 'numero_documento': line.name, + 'vencimento_titulo': self.format_date( + line.ml_maturity_date), + 'valor_titulo': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + # TODO: fépefwfwe + # TODO: Código adotado para identificar o título de cobrança. + # 8 é Nota de cŕedito comercial + 'especie_titulo': self.convert_int(self.order.payment_mode_id.boleto_especie), + 'aceite_titulo': aceite, + 'data_emissao_titulo': self.format_date( + line.ml_date_created), + # 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.ml_maturity_date), + 'juros_mora_taxa_dia': Decimal('0.00'), + 'valor_abatimento': Decimal('0.00'), + 'sacado_inscricao_tipo': self.convert_int( + self.get_inscricao_tipo(line.partner_id)), + 'sacado_inscricao_numero': line.partner_id.cnpj_cpf and self.convert_int( + punctuation_rm(line.partner_id.cnpj_cpf)) or '', + 'sacado_nome': line.partner_id.legal_name, + 'sacado_endereco': ( + line.partner_id.street + ' ' + line.partner_id.number), + 'sacado_bairro': line.partner_id.district or '', + 'sacado_cep': + self.get_cep('prefixo', line.partner_id.zip), + 'sacado_cep_sufixo': + self.get_cep('sufixo', line.partner_id.zip), + 'sacado_cidade': line.partner_id.l10n_br_city_id.name, + 'sacado_uf': line.partner_id.state_id.code, + 'codigo_protesto': + self.convert_int(self.order.payment_mode_id.boleto_protesto), + 'prazo_protesto': + self.convert_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': + self.convert_int(self.order.payment_mode_id.boleto_carteira), + } + + def _prepare_pagamento(self, line): + """ + Prepara um dict para preencher os valores do segmento A e B apartir de + uma linha da payment.order e insere informações que irão compor o + header do lote + :param line: payment.line - linha que sera base para evento + :return: dict - Dict contendo todas informações dos segmentos + """ + vals = { + + # SEGMENTO A + # CONTROLE + # 01.3A + 'controle_banco': + self.convert_int(self.order.company_partner_bank_id.code_bc), + # 02.3A + 'controle_lote': 1, + # 03.3A - 3-Registros Iniciais do Lote + 'controle_registro': 3, + + # SERVICO + # 04.3A - Nº Seqüencial do Registro - Inicia em 1 em cada novo lote + # TODO: Contador para o sequencial do lote + 'servico_numero_registro': 1, + # 05.3A + # Segmento Código de Segmento do Reg.Detalhe + # 06.3A + 'servico_tipo_movimento': self.order.tipo_movimento, + # 07.3A + 'servico_codigo_movimento': self.order.codigo_instrucao_movimento, + + # FAVORECIDO + # 08.3A - 018-TED 700-DOC + 'favorecido_camara': 0, + # 09.3A + 'favorecido_banco': self.convert_int(line.bank_id.code_bc), + # 10.3A + 'favorecido_agencia': self.convert_int(line.bank_id.bra_number), + # 11.3A + 'favorecido_agencia_dv': line.bank_id.bra_number_dig, + # 12.3A + 'favorecido_conta': punctuation_rm(line.bank_id.acc_number), + # 13.3A + 'favorecido_conta_dv': line.bank_id.acc_number_dig[0] + if line.bank_id.acc_number_dig else '', + # 14.3A + 'favorecido_dv': line.bank_id.acc_number_dig[1] + if len(line.bank_id.bra_number_dig or '') > 1 else '', + # 15.3A + 'favorecido_nome': line.partner_id.name, + + # CREDITO + # 16.3A - + 'credito_seu_numero': line.name, + # 17.3A + 'credito_data_pagamento': self.format_date(line.date), + # 18.3A + 'credito_moeda_tipo': line.currency.name, + # 19.3A + 'credito_moeda_quantidade': Decimal('0.00000'), + # 20.3A + 'credito_valor_pagamento': + Decimal(str(line.amount_currency)).quantize(Decimal('1.00')), + # 21.3A + # 'credito_nosLoteso_numero': '', + # 22.3A + # 'credito_data_real': '', + # 23.3A + # 'credito_valor_real': '', + + # INFORMAÇÔES + # 24.3A + # 'outras_informacoes': '', + # 25.3A + # 'codigo_finalidade_doc': line.codigo_finalidade_doc, + # 26.3A + 'codigo_finalidade_ted': line.codigo_finalidade_ted or '', + # 27.3A + 'codigo_finalidade_complementar': + line.codigo_finalidade_complementar or '', + # 28.3A + # CNAB - Uso Exclusivo FEBRABAN/CNAB + # 29.3A + # 'aviso_ao_favorecido': line.aviso_ao_favorecido, + 'aviso_ao_favorecido': 0, + # 'ocorrencias': '', + + # SEGMENTO B + # Preenchido no segmento A + # 01.3B + # 02.3B + # 03.3B + + # 04.3B + # 05.3B + # 06.3B + + # DADOS COMPLEMENTARES - FAVORECIDOS + # 07.3B + 'favorecido_tipo_inscricao': + self.get_inscricao_tipo(line.partner_id), + # 08.3B + 'favorecido_num_inscricao': line.partner_id.cnpj_cpf and + self.convert_int(punctuation_rm(line.partner_id.cnpj_cpf)) or '', + # 09.3B + 'favorecido_endereco_rua': line.partner_id.street or '', + # 10.3B + 'favorecido_endereco_num': self.convert_int(line.partner_id.number) or 0, + # 11.3B + 'favorecido_endereco_complemento': line.partner_id.street2 or '', + # 12.3B + 'favorecido_endereco_bairro': line.partner_id.district or '', + # 13.3B + 'favorecido_endereco_cidade': + line.partner_id.l10n_br_city_id.name or '', + # 14.3B + # 'favorecido_cep': self.convert_int(line.partner_id.zip[:5]) or 0, + 'favorecido_cep': self.get_cep('prefixo', line.partner_id.zip), + # 15.3B + 'favorecido_cep_complemento': + self.get_cep('sufixo', line.partner_id.zip), + # 16.3B + 'favorecido_estado': line.partner_id.state_id.code or '', + + # DADOS COMPLEMENTARES - PAGAMENTO + # 17.3B + 'pagamento_vencimento': 0, + # 18.3B + 'pagamento_valor_documento': Decimal('0.00'), + # 19.3B + 'pagamento_abatimento': Decimal('0.00'), + # 20.3B + 'pagamento_desconto': Decimal('0.00'), + # 21.3B + 'pagamento_mora': Decimal('0.00'), + # 22.3B + 'pagamento_multa': Decimal('0.00'), + # 23.3B + # TODO: Verificar se este campo é retornado no retorno + # 'cod_documento_favorecido': '', + # 24.3B - Informado No SegmentoA + # 'aviso_ao_favorecido': '0', + # 25.3B + # 'codigo_ug_centralizadora': '0', + # 26.3B + # 'codigo_ispb': '0', + } + return vals + + def _adicionar_evento(self, line): + """ + Adicionar o evento no arquivo de acordo com seu tipo + """ + # if self.order.payment_order_type == 'payment': + # incluir = self.arquivo.incluir_debito_pagamento + # prepare = self._prepare_pagamento + # else: + # incluir = self.arquivo.incluir_cobranca + # prepare = self._prepare_cobranca + pass + + def remessa(self, order): + """ + Cria a remessa de eventos que sera anexada ao arquivo + :param order: payment.order + :return: Arquivo Cnab pronto para download + """ + # cobrancasimples_valor_titulos = 0 + + self.order = order + + # Preparar Header do Arquivo + self.arquivo = Arquivo(self.bank, **self._prepare_header()) + + if order.payment_order_type == 'payment': + incluir = self.arquivo.incluir_debito_pagamento + prepare = self._prepare_pagamento + + header = self.bank.registros.HeaderLotePagamento( + **self._prepare_header_lote()) + + trailer = self.bank.registros.TrailerLotePagamento() + trailer.somatoria_valores = Decimal('0.00') + trailer.somatoria_quantidade_moedas = Decimal('0.00000') + + lote_pagamento = Lote(self.bank, header, trailer) + self.arquivo.adicionar_lote(lote_pagamento) + + else: + incluir = self.arquivo.incluir_cobranca + prepare = self._prepare_cobranca + + for line in order.bank_line_ids: + # para cada linha da payment order adicoinar como um novo evento + # self._adicionar_evento(line) + # try: + incluir(tipo_lote=30, **prepare(line)) + # except: + # from odoo import exceptions + # raise exceptions.ValidationError("Erro") + # self.arquivo.lotes[0].header.servico_servico = 30 + # TODO: tratar soma de tipos de cobranca + # cobrancasimples_valor_titulos += line.amount_currency + # 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 get_cep(self, tipo, value): + ''' + :param tipo: + :param value: + :return: + ''' + if not value: + if tipo == 'prefixo': + return 0 + else: + return '' + value = punctuation_rm(value) + sufixo = value[-3:] + prefixo = value[:5] + if tipo == 'sufixo': + return sufixo + else: + return prefixo + + def format_date(self, srt_date): + if not srt_date: + return 0 + return self.convert_int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%d%m%Y')) + + def data_hoje(self): + return (self.convert_int(time.strftime("%d%m%Y"))) + + def hora_agora(self): + return (self.convert_int(time.strftime("%H%M%S"))) + + def nosso_numero(self, format): + """ + Hook para ser sobrescrito e adicionar informação + :param format: + :return: + """ + pass diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig new file mode 100644 index 000000000000..1fabc0a2c0b9 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig @@ -0,0 +1,566 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from __future__ import division, print_function, unicode_literals + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from openerp.addons.l10n_br_base.tools.misc import punctuation_rm + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: +<<<<<<< HEAD + from cnab240.tipos import Arquivo + from cnab240.errors import (Cnab240Error) +======= + from cnab240.tipos import Arquivo, Lote +>>>>>>> fixup! [FIX] Flake8 +except ImportError as err: + _logger.debug = err + + +class Cnab240(Cnab): + """ + CNAB240 + """ + + def __init__(self): + super(Cnab, self).__init__() + + @staticmethod + def get_bank(bank): + ''' + Função chamada na criação do CNAB que dado o código do banco, + instancia o objeto do banco e retorna o obj ao CNAB que sera criado. + :param bank: str - Código do banco + :return: + ''' + 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 == '001': + from .bancos.bb import BB240 + return BB240 + else: + return Cnab240 + + def inscricao_tipo(self, partner_id): + # TODO: Implementar codigo para PIS/PASEP + if partner_id.is_company: + return 2 + else: + return 1 + + def _prepare_header(self): + """ + Preparar o header do arquivo do CNAB + :return: dict - Header do arquivo + """ + header_arquivo = { + # CONTROLE + # 01.0 + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.0 # Sequencia para o Arquivo + 'controle_lote': 1, + # 03.0 0- Header do Arquivo + 'controle_registro': 0, + # 04.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + + # EMPRESA + # 05.0 - 1 - CPF / 2 - CNPJ + 'cedente_inscricao_tipo': + self.get_inscricao_tipo(self.order.company_id.partner_id), + # 06.0 + 'cedente_inscricao_numero': + int(punctuation_rm(self.order.company_id.cnpj_cpf)), + # 07.0 + 'cedente_convenio': '0001222130126', + # 08.0 + 'cedente_agencia': + int(self.order.mode.bank_id.bra_number), + # 09.0 + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + # 10.0 + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + # 11.0 + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], + # 12.0 + 'cedente_agencia_conta_dv': + self.order.mode.bank_id.acc_number_dig[1] + if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', + # 13.0 + 'cedente_nome': + self.order.mode.bank_id.partner_id.legal_name[:30], + # 14.0 + 'nome_banco': self.order.mode.bank_id.bank_name, + # 15.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + + # ARQUIVO + # 16.0 Código Remessa = 1 / Retorno = 2 + 'arquivo_codigo': '1', + # 17.0 + 'arquivo_data_de_geracao': self.data_hoje(), + # 18.0 + 'arquivo_hora_de_geracao': self.hora_agora(), + # 19.0 TODO: Número sequencial de arquivo + 'arquivo_sequencia': int(self.get_file_numeration()), + # 20.0 + 'arquivo_layout': 103, + # 21.0 + 'arquivo_densidade': 0, + # 22.0 + 'reservado_banco': '', + # 23.0 + 'reservado_empresa': 'EMPRESA 100', + # 24.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + } + + return header_arquivo + + def _prepare_header_lote(self): + """ + Preparar o header de LOTE para arquivo do CNAB + :return: dict - Header do arquivo + """ + empresa = self.order.mode.bank_id.partner_id + + header_arquivo_lote = { + + # CONTROLE + # 01.1 + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.1 Sequencia para o Arquivo + 'controle_lote': 1, + # 03.1 0- Header do Arquivo + 'controle_registro': 1, + + # SERVICO + # 04.1 # Header do lote sempre 'C' + 'servico_operacao': 'C', + # 05.1 + 'servico_servico': self.order.tipo_servico, + # 06.1 + 'servico_forma_lancamento': 1, + # 07.1 + 'servico_layout': 20, + # 08.1 + # CNAB - Uso Exclusivo da FEBRABAN/CNAB + + # EMPRESA CEDENTE + # 09.1 + 'empresa_inscricao_tipo': 2, + # self.get_inscricao_tipo(self.order.company_id.partner_id), + # 10.1 + 'empresa_inscricao_numero': punctuation_rm(empresa.cnpj_cpf), + # 11.1 + 'cedente_convenio': self.order.codigo_convenio, + # 12.1 + 'cedente_agencia': + int(self.order.mode.bank_id.bra_number), + # 13.1 + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + # 14.1 + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + # 15.1 + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], + # 16.1 + 'cedente_agencia_conta_dv': + self.order.mode.bank_id.acc_number_dig[1] + if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', + # 17.1 + 'cedente_nome': + self.order.mode.bank_id.partner_id.legal_name[:30], + # 18.1 + 'mensagem1': '', + + # ENDERECO + # 19.1 + 'empresa_logradouro': empresa.street, + # 20.1 + 'empresa_endereco_numero': empresa.number, + # 21.1 + 'empresa_endereco_complemento': empresa.street2, + # 22.1 + 'empresa_endereco_cidade': empresa.l10n_br_city_id.name, + # 23.1 + 'empresa_endereco_cep': self.get_cep('prefixo', empresa.zip), + # 24.1 + 'empresa_endereco_cep_complemento': + self.get_cep('sufixo', empresa.zip), + # 25.1 + 'empresa_endereco_estado': empresa.state_id.code, + + # 26.1 + 'indicativo_forma_pagamento': '', + # 27.1 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + # 28.1 + 'ocorrencias': '', + } + return header_arquivo_lote + + def get_file_numeration(self): + # Função para retornar a numeração sequencial do arquivo + return 1 + + def sacado_inscricao_tipo(self, partner_id): + # TODO: Implementar codigo para PIS/PASEP + if partner_id.is_company: + return 2 + else: + return 1 + + def _prepare_cobranca(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 { + '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, + 'identificacao_titulo': u'0000000', # TODO + 'identificacao_titulo_banco': u'0000000', # TODO + 'identificacao_titulo_empresa': line.move_line_id.move_id.name, + 'numero_documento': line.name, + 'vencimento_titulo': self.format_date( + line.ml_maturity_date), + 'valor_titulo': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + # TODO: fépefwfwe + # 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), + # 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.ml_maturity_date), + '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 _prepare_pagamento(self, line): + """ + Prepara um dict para preencher os valores do segmento A e B apartir de + uma linha da payment.order e insere informações que irão compor o + header do lote + :param line: payment.line - linha que sera base para evento + :return: dict - Dict contendo todas informações dos segmentos + """ + vals = { + + # SEGMENTO A + # CONTROLE + # 01.3A + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.3A + 'controle_lote': 1, + # 03.3A - 3-Registros Iniciais do Lote + 'controle_registro': 3, + + # SERVICO + # 04.3A - Nº Seqüencial do Registro - Inicia em 1 em cada novo lote + # TODO: Contador para o sequencial do lote + 'servico_numero_registro': 1, + # 05.3A + # Segmento Código de Segmento do Reg.Detalhe + # 06.3A + 'servico_tipo_movimento': self.order.tipo_movimento, + # 07.3A + 'servico_codigo_movimento': self.order.codigo_instrucao_movimento, + + # FAVORECIDO + # 08.3A - 018-TED 700-DOC + 'favorecido_camara': 0, + # 09.3A + 'favorecido_banco': int(line.bank_id.bank_bic), + # 10.3A + 'favorecido_agencia': int(line.bank_id.bra_number), + # 11.3A + 'favorecido_agencia_dv': line.bank_id.bra_number_dig, + # 12.3A + 'favorecido_conta': punctuation_rm(line.bank_id.acc_number), + # 13.3A + 'favorecido_conta_dv': line.bank_id.acc_number_dig[0] + if line.bank_id.acc_number_dig else '', + # 14.3A + 'favorecido_dv': line.bank_id.acc_number_dig[1] + if len(line.bank_id.bra_number_dig or '') > 1 else '', + # 15.3A + 'favorecido_nome': line.partner_id.name, + + # CREDITO + # 16.3A - + 'credito_seu_numero': line.name, + # 17.3A + 'credito_data_pagamento': self.format_date(line.date), + # 18.3A + 'credito_moeda_tipo': line.currency.name, + # 19.3A + 'credito_moeda_quantidade': Decimal('0.00000'), + # 20.3A + 'credito_valor_pagamento': + Decimal(str(line.amount_currency)).quantize(Decimal('1.00')), + # 21.3A + # 'credito_nosLoteso_numero': '', + # 22.3A + # 'credito_data_real': '', + # 23.3A + # 'credito_valor_real': '', + + # INFORMAÇÔES + # 24.3A + # 'outras_informacoes': '', + # 25.3A + # 'codigo_finalidade_doc': line.codigo_finalidade_doc, + # 26.3A + 'codigo_finalidade_ted': line.codigo_finalidade_ted or '', + # 27.3A + 'codigo_finalidade_complementar': + line.codigo_finalidade_complementar or '', + # 28.3A + # CNAB - Uso Exclusivo FEBRABAN/CNAB + # 29.3A + # 'aviso_ao_favorecido': line.aviso_ao_favorecido, + 'aviso_ao_favorecido': 0, + # 'ocorrencias': '', + + # SEGMENTO B + # Preenchido no segmento A + # 01.3B + # 02.3B + # 03.3B + + # 04.3B + # 05.3B + # 06.3B + + # DADOS COMPLEMENTARES - FAVORECIDOS + # 07.3B + 'favorecido_tipo_inscricao': + self.get_inscricao_tipo(line.partner_id), + # 08.3B + 'favorecido_num_inscricao': + int(punctuation_rm(line.partner_id.cnpj_cpf)), + # 09.3B + 'favorecido_endereco_rua': line.partner_id.street or '', + # 10.3B + 'favorecido_endereco_num': int(line.partner_id.number) or 0, + # 11.3B + 'favorecido_endereco_complemento': line.partner_id.street2 or '', + # 12.3B + 'favorecido_endereco_bairro': line.partner_id.district or '', + # 13.3B + 'favorecido_endereco_cidade': + line.partner_id.l10n_br_city_id.name or '', + # 14.3B + # 'favorecido_cep': int(line.partner_id.zip[:5]) or 0, + 'favorecido_cep': self.get_cep('prefixo', line.partner_id.zip), + # 15.3B + 'favorecido_cep_complemento': + self.get_cep('sufixo', line.partner_id.zip), + # 16.3B + 'favorecido_estado': line.partner_id.state_id.code or '', + + # DADOS COMPLEMENTARES - PAGAMENTO + # 17.3B + 'pagamento_vencimento': 0, + # 18.3B + 'pagamento_valor_documento': Decimal('0.00'), + # 19.3B + 'pagamento_abatimento': Decimal('0.00'), + # 20.3B + 'pagamento_desconto': Decimal('0.00'), + # 21.3B + 'pagamento_mora': Decimal('0.00'), + # 22.3B + 'pagamento_multa': Decimal('0.00'), + # 23.3B + # TODO: Verificar se este campo é retornado no retorno + # 'cod_documento_favorecido': '', + # 24.3B - Informado No SegmentoA + # 'aviso_ao_favorecido': '0', + # 25.3B + # 'codigo_ug_centralizadora': '0', + # 26.3B + # 'codigo_ispb': '0', + } + return vals + + def _adicionar_evento(self, line): + """ + Adicionar o evento no arquivo de acordo com seu tipo + """ + # if self.order.payment_order_type == 'payment': + # incluir = self.arquivo.incluir_debito_pagamento + # prepare = self._prepare_pagamento + # else: + # incluir = self.arquivo.incluir_cobranca + # prepare = self._prepare_cobranca + pass + + def remessa(self, order): + """ + Cria a remessa de eventos que sera anexada ao arquivo + :param order: payment.order + :return: Arquivo Cnab pronto para download + """ + # cobrancasimples_valor_titulos = 0 + + self.order = order + + # Preparar Header do Arquivo + self.arquivo = Arquivo(self.bank, **self._prepare_header()) + + if order.payment_order_type == 'payment': + incluir = self.arquivo.incluir_debito_pagamento + prepare = self._prepare_pagamento + else: + incluir = self.arquivo.incluir_cobranca + prepare = self._prepare_cobranca + + for line in order.bank_line_ids: + # para cada linha da payment order adicoinar como um novo evento + # self._adicionar_evento(line) + # try: + incluir(**prepare(line)) + # except: + # from openerp import exceptions + # raise exceptions.ValidationError("Erro") + self.arquivo.lotes[0].header.servico_servico = 1 + # TODO: tratar soma de tipos de cobranca + # cobrancasimples_valor_titulos += line.amount_currency + # 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 get_cep(self, tipo, value): + ''' + :param tipo: + :param value: + :return: + ''' + if not value: + if tipo == 'prefixo': + return 0 + else: + return '' + value = punctuation_rm(value) + sulfixo = format[-3:] + prefixo = format[:5] + if tipo == 'sulfixo': + return sulfixo + else: + return prefixo + + def format_date(self, srt_date): + if not srt_date: + return 0 + return int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%d%m%Y')) + + def data_hoje(self): + return (int(time.strftime("%d%m%Y"))) + + def hora_agora(self): + return (int(time.strftime("%H%M%S"))) + + def rmchar(self, format): + return re.sub('[%s]' % re.escape(string.punctuation), '', + format or '') + + def nosso_numero(self, format): + """ + Hook para ser sobrescrito e adicionar informação + :param format: + :return: + """ + pass diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py new file mode 100644 index 000000000000..2cfbd6d7e782 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py new file mode 100644 index 000000000000..5d3fd105cafb --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py new file mode 100644 index 000000000000..373af4681665 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +import re +import string +from decimal import Decimal + +from ..cnab_400 import Cnab400 + + +class Bradesco400(Cnab400): + + def __init__(self): + super(Cnab400, self).__init__() + from cnab240.bancos import bradesco_cobranca_400 + self.bank = bradesco_cobranca_400 + self.controle_linha = 2 + + def _prepare_header(self): + """ + + :param order: + :return: + """ + + vals = super(Bradesco400, self)._prepare_header() + vals['servico_servico'] = 1 + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Bradesco400, self)._prepare_cobranca(line) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + vals['identificacao_titulo_banco'] = self.convert_int( + vals['identificacao_titulo_banco']) + vals['cedente_conta_dv'] = unicode(str( + vals['cedente_conta_dv']), "utf-8") + vals['cedente_agencia_dv'] = unicode(str( + vals['cedente_agencia_dv']), "utf-8") + # vals['cedente_dv_ag_cc'] = unicode(str( + # vals['cedente_dv_ag_cc']), "utf-8") + + vals['sacado_cc_dv'] = u'0' + vals['identificacao_empresa_beneficiaria_banco'] = \ + self.retorna_id_empr_benef() + vals['digito_conferencia_numero_bancario'] = u'0' + vals['condicao_emissao_papeleta'] = 1 + + vals['indicador_rateio_credito'] = u"" + self.controle_linha += 1 + + return vals + + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def retorna_id_empr_benef(self): + dig_cart = 3 + dig_ag = 5 + dig_conta = 7 + + carteira = self.adiciona_digitos( + self.order.payment_mode_id.boleto_carteira, dig_cart) + agencia = self.adiciona_digitos( + self.order.company_partner_bank_id.bra_number, dig_ag) + conta = self.adiciona_digitos( + self.order.company_partner_bank_id.acc_number, dig_conta) + + ident = u'0' + (carteira) + (agencia) + (conta) + \ + (self.order.company_partner_bank_id.acc_number_dig) + return ident + + def adiciona_digitos(self, campo, num_digitos): + chars_faltantes = num_digitos - len(campo) + return (u'0' * chars_faltantes) + campo + + +def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py new file mode 100644 index 000000000000..cfcf6a55a7b0 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# © 2019 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from __future__ import division, print_function, unicode_literals + +import re +import string +from decimal import Decimal +from odoo.addons.l10n_br_base.tools.misc import punctuation_rm + +from ..cnab_400 import Cnab400 + + +class Itau400(Cnab400): + + def __init__(self): + super(Cnab400, self).__init__() + self.controle_linha = 1 + + def remessa(self, order): + from cnab240.bancos import itau_cobranca_400 + self.classe_remessa = itau_cobranca_400 + return super(Itau400, self).remessa(order) + + def retorno(self, arquivo_retorno): + from cnab240.bancos import itau_cobranca_retorno_400 + self.classe_retorno = itau_cobranca_retorno_400 + return super(Itau400, self).retorno(arquivo_retorno) + + @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 order: + :return: + """ + vals = { + 'cedente_agencia': self.convert_int( + self.order.company_partner_bank_id.bra_number), + 'cedente_conta': self.convert_int( + self.order.company_partner_bank_id.acc_number), + 'cedente_conta_dv': self.convert_int( + self.order.company_partner_bank_id.acc_number_dig), + 'cedente_nome': unicode(self.order.company_id.legal_name), + 'arquivo_data_de_geracao': self.data_hoje(), + 'arquivo_hora_de_geracao': self.hora_agora(), + 'num_seq_registro': self.controle_linha, + } + self.controle_linha += 1 + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + sacado_endereco = self.retorna_endereco(line.partner_id.id) + + # TODO: Garantir que o account.move.line selecionado é o correto + move_line_id = line.payment_line_ids[:1].move_line_id + + # TODO: Guardar estrutura com códigos de ocorrências + identificacao_ocorrencia = 1 + if move_line_id.state_cnab == 'added_paid': + identificacao_ocorrencia = 34 + + vals = { + 'identificacao_titulo_empresa': line.identificacao_titulo_empresa, + 'nosso_numero': self.convert_int(line.nosso_numero), + 'numero_documento': self.adiciona_digitos_num_doc( + line.numero_documento), + 'cedente_inscricao_tipo': self.inscricao_tipo, + 'cedente_inscricao_numero': self.convert_int(punctuation_rm( + self.order.company_id.cnpj_cpf)), + 'cedente_agencia': self.convert_int( + self.order.company_partner_bank_id.bra_number), + 'cedente_conta': self.convert_int( + self.order.company_partner_bank_id.acc_number), + 'cedente_conta_dv': self.convert_int( + self.order.company_partner_bank_id.acc_number_dig + ), + 'instrucao': 0, # TODO VERIFICAR + 'quantidade_moeda': 0, + 'carteira_numero': self.convert_int( + self.order.payment_mode_id.boleto_carteira + ), + 'carteira_cod': self.order.payment_mode_id.boleto_modalidade, + 'identificacao_ocorrencia': identificacao_ocorrencia, + 'vencimento_titulo': self.format_date( + line.date), + 'valor_titulo': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + 'agencia_cobradora': 0, + 'especie_titulo': self.order.payment_mode_id.boleto_especie, + 'aceite_titulo': self.order.payment_mode_id.boleto_aceite, + 'data_emissao_titulo': self.format_date( + line.date), # FIXME + 'primeira_instrucao': self.convert_int( + self.order.payment_mode_id.boleto_protesto + ), + 'segunda_instrucao': self.convert_int( + self.order.payment_mode_id.boleto_protesto_prazo + + ), + 'juros_mora_taxa_dia': self.calcula_valor_juros_dia( + line.amount_currency, + self.order.payment_mode_id.cnab_percent_interest + ), + 'data_limite_desconto': 0, + 'valor_desconto': Decimal('0.00'), + 'valor_iof': Decimal('0.00'), + 'valor_abatimento': Decimal('0.00'), + 'sacado_inscricao_tipo': self.convert_int( + self.sacado_inscricao_tipo(line.partner_id)), + 'sacado_inscricao_numero': line.partner_id.cnpj_cpf and self.convert_int( + punctuation_rm(line.partner_id.cnpj_cpf)) or '', + 'sacado_nome': line.partner_id.legal_name, + 'sacado_endereco': sacado_endereco, + 'sacado_bairro': line.partner_id.district or '', + 'sacado_cep': ( + line.partner_id.zip and + self.convert_int(line.partner_id.zip.replace('-', '')) or '' + ), + 'sacado_cidade': line.partner_id.l10n_br_city_id.name, + 'sacado_uf': line.partner_id.state_id.code, + 'sacador_avalista': self.order.payment_mode_id.comunicacao_2, + 'juros_mora_data': 0, + # self.format_date( + # line.date), + 'prazo': 0, # De 5 a 120 dias. + # 'sacador_avalista': u'Protestar após 5 dias', + 'num_seq_registro': self.controle_linha, + } + return vals + + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def retorna_id_empr_benef(self): + dig_cart = 3 + dig_ag = 5 + dig_conta = 7 + + carteira = self.adiciona_digitos( + self.order.payment_mode_id.boleto_carteira, dig_cart) + agencia = self.adiciona_digitos( + self.order.company_partner_bank_id.bra_number, dig_ag) + conta = self.adiciona_digitos( + self.order.company_partner_bank_id.acc_number, dig_conta) + + ident = u'0' + (carteira) + (agencia) + (conta) + \ + (self.order.company_partner_bank_id.acc_number_dig) + return ident + + def adiciona_digitos(self, campo, num_digitos): + chars_faltantes = num_digitos - len(campo) + return (u'0' * chars_faltantes) + campo + + +def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py b/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py new file mode 100644 index 000000000000..92ace1c8071d --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py @@ -0,0 +1,401 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from odoo.addons.l10n_br_base.tools.misc import punctuation_rm + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: + from cnab240.tipos import ArquivoCobranca400 + from cnab240.errors import Cnab240Error +except ImportError as err: + _logger.debug = (err) + +IDENTIFICACAO_DA_OCORRENCIA = [ + ('01', u'Remessa'), + ('02', u'Pedido de baixa'), + ('03', u'Pedido de Protesto Falimentar'), + ('04', u'Concessão de abatimento'), + ('05', u'Cancelamento de abatimento concedido'), + ('06', u'Alteração de vencimento'), + ('07', u'Alteração do controle do participante'), + ('08', u'Alteração de seu número'), + ('09', u'Pedido de protesto'), + ('18', u'Sustar protesto e baixar Título'), + ('19', u'Sustar protesto e manter em carteira'), + ('22', u'Transferência Cessão crédito ID. Prod.10'), + ('23', u'Transferência entre Carteiras'), + ('24', u'Dev. Transferência entre Carteiras'), + ('31', u'Alteração de outros dados'), + ('45', u'Pedido de Negativação (NOVO)'), + ('46', u'Excluir Negativação com baixa (NOVO)'), + ('47', u'Excluir negativação e manter pendente (NOVO)'), + ('68', u'Acerto nos dados do rateio de Crédito'), + ('69', u'Cancelamento do rateio de crédito'), +] + +ESPECIE_DE_TITULO = [ + ('01', u'Duplicata'), + ('02', u'Nota Promissória'), + ('03', u'Nota de Seguro'), + ('04', u'Cobrança Seriada'), + ('05', u'Recibo'), + ('10', u'Letras de Câmbio'), + ('11', u'Nota de Débito'), + ('12', u'Duplicata de Serv'), + ('30', u'Boleto de Proposta'), + ('99', u'Outros'), +] + +# Essas instruções deverão ser enviadas no Arquivo-Remessa, quando da +# entrada, desde que código de ocorrência na posição 109 a 110 do registro +# de transação, seja “01”, para as instruções de protesto/negativação, o +# CNPJ / CPF e o endereço do Pagador deverão ser informados corretamente +LISTA_PRIMEIRA_INSTRUCAO = [ + ('05', u'Protesto Falimentar'), + ('06', u'Protestar'), + ('07', u'Negativar'), + ('18', u'Decurso de prazo'), + + ('08', u'Não cobrar juros de mora'), + ('09', u'Não receber após o vencimento'), + ('10', u'Multas de 10% após o 4o dia do Vencimento'), + ('11', u'Não receber após o 8o dia do vencimento.'), + ('12', u'Cobrar encargos após o 5o dia do vencimento'), + ('13', u'Cobrar encargos após o 10o dia do vencimento'), + ('14', u'Cobrar encargos após o 15o dia do vencimento'), + ('15', u'Conceder desconto mesmo se pago após o vencimento'), +] + + +class Cnab400(Cnab): + + def __init__(self): + super(Cnab, self).__init__() + + @staticmethod + def get_bank(bank): + if bank == '237': + from .bancos.bradesco import Bradesco400 + return Bradesco400 + elif bank == '341': + from .bancos.itau import Itau400 + return Itau400 + else: + return Cnab400 + + @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 { + 'controle_banco': self.convert_int( + self.order.company_partner_bank_id.bank_id.code_bc + ), + 'arquivo_data_de_geracao': self.data_hoje(), + 'arquivo_hora_de_geracao': self.hora_agora(), + # TODO: Número sequencial de arquivo + 'arquivo_sequencia': self.convert_int(self.get_file_numeration()), + 'cedente_inscricao_tipo': self.inscricao_tipo, + 'cedente_inscricao_numero': self.convert_int(punctuation_rm( + self.order.company_id.cnpj_cpf)), + 'cedente_agencia': self.convert_int( + self.order.company_partner_bank_id.bra_number), + 'cedente_conta': + self.convert_int(self.order.company_partner_bank_id.acc_number), + 'cedente_conta_dv': + self.order.company_partner_bank_id.acc_number_dig, + 'cedente_agencia_dv': + self.order.company_partner_bank_id.bra_number_dig, + 'cedente_nome': + self.order.company_id.legal_name, + 'arquivo_codigo': 1, # Remessa/Retorno + 'servico_operacao': u'R', + 'nome_banco': + unicode(self.order.company_partner_bank_id.bank_name), + 'codigo_empresa': + self.convert_int(self.order.payment_mode_id.boleto_convenio), + } + + def get_file_numeration(self): + # TODO: FIX ME + # numero = self.order.get_next_number() + # if not numero: + numero = 1 + return numero + + def format_date(self, srt_date): + return self.convert_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 codificar(self, texto): + return texto.encode('utf-8') + + def _prepare_cobranca(self, line): + """ + :param line: + :return: + """ + prefixo, sulfixo = self.cep(line.partner_id.zip) + + aceite = u'N' + if not self.order.payment_mode_id.boleto_aceite == 'S': + aceite = u'A' + + codigo_protesto = 0 + dias_protestar = 0 + if self.order.payment_mode_id.boleto_protesto == '3' \ + or self.order.payment_mode_id.boleto_protesto == '0': + codigo_protesto = 0 + dias_protestar = 0 + elif self.order.payment_mode_id.boleto_protesto == '1' \ + or self.order.payment_mode_id.boleto_protesto == '2': + codigo_protesto = 6 + if (self.convert_int(self.order.payment_mode_id.boleto_protesto_prazo)) < 5: + dias_protestar = 5 + else: + dias_protestar = self.convert_int( + self.order.payment_mode_id.boleto_protesto_prazo) + + sacado_endereco = self.retorna_endereco(line.partner_id.id) + + # 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 { + + 'percentual_multa': Decimal('0.00'), + 'valor_desconto': Decimal('0.00'), + 'valor_abatimento_concedido_cancelado': Decimal('0.00'), + 'primeira_instrucao': codigo_protesto, + 'segunda_instrucao': dias_protestar, + 'sacado_cep': self.convert_int(prefixo), + 'sacado_cep_sufixo': self.convert_int(sulfixo), + 'sacador_avalista': + self.order.payment_mode_id.comunicacao_2, + # 'sacador_avalista': u'Protestar após 5 dias', + 'num_seq_registro': + self.controle_linha, + + 'controle_banco': self.convert_int( + self.order.company_partner_bank_id.bank_id.code_bc + ), + 'cedente_agencia': self.convert_int( + self.order.company_partner_bank_id.bra_number), + 'cedente_conta': self.convert_int( + self.order.company_partner_bank_id.acc_number), + 'cedente_conta_dv': + self.order.company_partner_bank_id.acc_number_dig, + 'cedente_agencia_dv': + self.order.company_partner_bank_id.bra_number_dig, + 'identificacao_titulo': u'0000000', # TODO + 'identificacao_titulo_banco': u'0000000', # TODO + 'identificacao_titulo_empresa': line.name, # FIXME + + 'vencimento_titulo': self.format_date( + line.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': self.convert_int(self.order.payment_mode_id.boleto_especie), + 'aceite_titulo': aceite, + 'data_emissao_titulo': self.format_date( + line.date), # FIXME + # 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.date), + + # 'juros_mora_taxa_dia': Decimal('0.20'), + 'juros_mora_taxa_dia': self.calcula_valor_juros_dia( + line.amount_currency, 0), # line.percent_interest + + 'valor_abatimento': Decimal('0.00'), + 'sacado_inscricao_tipo': self.convert_int( + self.sacado_inscricao_tipo(line.partner_id)), + 'sacado_inscricao_numero': line.partner_id.cnpj_cpf and self.convert_int( + punctuation_rm(line.partner_id.cnpj_cpf)) or '', + 'sacado_nome': line.partner_id.legal_name, + + # 'sacado_endereco': ( + # line.partner_id.street + + # ' ' + str(line.partner_id.number) + # ), + + 'sacado_endereco': sacado_endereco, + + 'sacado_bairro': line.partner_id.district or '', + 'sacado_cidade': line.partner_id.l10n_br_city_id.name, + 'sacado_uf': line.partner_id.state_id.code, + 'codigo_baixa': 2, + 'prazo_baixa': 0, # De 5 a 120 dias. + 'controlecob_data_gravacao': self.data_hoje(), + 'cobranca_carteira': self.convert_int( + self.order.payment_mode_id.boleto_carteira + ), + 'primeira_mensagem': u'', + # Trazer da nova tela do payment_mode + 'identificacao_ocorrencia': 1, + + # numero fatura esta copiando para communication + 'numero_documento': self.adiciona_digitos_num_doc( + line.communication), + # 'numero_documento': str(line.move_line_id.invoice.number), + + } + + def remessa(self, order): + """ + + :param order: + :return: + """ + self.order = order + self.arquivo = ArquivoCobranca400( + self.classe_remessa, **self._prepare_header()) + for line in order.bank_line_ids: + try: + self.arquivo.incluir_cobranca(**self._prepare_cobranca(line)) + self.controle_linha += 1 + self.arquivo.trailer.num_seq_registro = self.controle_linha + line.is_erro_exportacao = False + line.mensagem_erro_exportacao = '' + + for payment_line in line.payment_line_ids: + payment_line.move_line_id.state_cnab = 'exported' + + except Cnab240Error as e: + mensagem = '' + if hasattr(e, 'campo'): + mensagem += u' Campo ' + e.campo.nome + mensagem += u' valor ' + str(e.campo.valor) + mensagem += u' inválido' + else: + mensagem += u' Erro desconhecido' + line.is_erro_exportacao = True + line.mensagem_erro_exportacao = mensagem + + for payment_line in line.payment_line_ids: + payment_line.move_line_id.state_cnab = 'exporting_error' + + continue + + remessa = unicode(self.arquivo) + return unicodedata.normalize( + 'NFKD', remessa).encode('ascii', 'ignore') + + def data_hoje(self): + return (self.convert_int(time.strftime("%d%m%y"))) + + def hora_agora(self): + return (self.convert_int(time.strftime("%H%M%S"))) + + def calcula_valor_juros_dia(self, total_titulo, percent_juros): + valor_juros = 0 + valor_juros = (total_titulo * (percent_juros / 100)) + return (Decimal(valor_juros).quantize(Decimal('1.00'))) + + def adiciona_digitos_num_doc(self, campo): + num_digitos = 10 + campo = str(campo) + chars_faltantes = num_digitos - len(campo) + return (u' ' * chars_faltantes) + campo + + # @api.multi + def retorna_endereco(self, id_parceiro): + # self.ensure_one() + # workaround to get env + res_partner_model = self.order.env['res.partner'] + res_partner_end_cobranca = res_partner_model.search( + [('parent_id', '=', id_parceiro), ('type', '=', 'cnab_cobranca')], + limit=1) + if res_partner_end_cobranca: + str_endereco = self.monta_endereco(res_partner_end_cobranca) + else: + res_partner_end_cobranca = res_partner_model.search( + [('id', '=', id_parceiro)] + ) + str_endereco = self.monta_endereco(res_partner_end_cobranca) + # Essa abordagem substitui caracteres especiais por '?' + # str_endereco = / + # unicode(str_endereco.encode("ascii", errors="replace")) + + # Substitui sinal de grau por espaço + if str_endereco: + str_endereco = str_endereco.replace(u"\xb0", u" ") + + return str_endereco + + def monta_endereco(self, partner_item): + + street = self.check_address_item_filled(partner_item.street) + number = self.check_address_item_filled(partner_item.number) + complemento = self.check_address_item_filled(partner_item.street2) + # distrito = self.check_address_item_filled(partner_item.district) + + str_endereco = ( + street + + ' ' + + number + + ' ' + + complemento + # + ' ' + + # partner_item.l10n_br_city_id.name + + # ' ' + partner_item.state_id.name + ) + return str_endereco + + def check_address_item_filled(self, item): + if not item: + return ('') + else: + return item diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/__init__.py b/cnab_erpbrasil_febraban/febraban/pag_for/__init__.py new file mode 100644 index 000000000000..32c397f2f690 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/pag_for/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import pag_for500 diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py b/cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py new file mode 100644 index 000000000000..2cfbd6d7e782 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Daniel Sadamo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py b/cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py new file mode 100644 index 000000000000..de45b9a00459 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +import re +import string + +from ..pag_for500 import PagFor500 + + +class BradescoPagFor(PagFor500): + + def __init__(self): + super(PagFor500, self).__init__() + from cnab240.bancos import bradescoPagFor + self.bank = bradescoPagFor + self.controle_linha = 2 + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(BradescoPagFor, self)._prepare_header() + vals['codigo_comunicacao'] = self.convert_int( + self.order.payment_mode_id.boleto_convenio) + return vals + + def _prepare_cobranca(self, line, vals): + """ + + :param line: + :return: + """ + vals = super(BradescoPagFor, self)._prepare_cobranca(line, vals) + + # TODO campo para informar a data do pagamento. + vals['data_para_efetivacao_pag'] = self.muda_campos_data( + vals['vencimento_titulo']) + self.controle_linha += 1 + + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos + # entre CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def muda_campos_data(self, campo): + campo = str(campo) + campo = campo[-4:] + campo[2:4] + campo[:2] + return self.convert_int(campo) diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py b/cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py new file mode 100644 index 000000000000..e84aa22f1503 --- /dev/null +++ b/cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py @@ -0,0 +1,573 @@ +# -*- coding: utf-8 -*- +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# @author Fernando Marcato +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from odoo import _ +from odoo.addons.l10n_br_base.tools.misc import punctuation_rm +from odoo.exceptions import Warning as UserError + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: + from cnab240.tipos import Arquivo +except ImportError as err: + _logger.debug = (err) +try: + from pyboleto.data import BoletoData +except ImportError as err: + _logger.debug = (err) + +TIPO_CONTA_FORNECEDOR = [ + ('1', u'Conta corrente'), + ('2', u'Conta Poupança'), +] + +TIPO_DOCUMENTO = [ + ('01', u'Nota Fiscal/Fatura'), + ('02', u'Fatura'), + ('03', u'Nota Fiscal'), + ('01', u'Duplicata'), + ('01', u'Outros'), +] + +MODALIDADE = [ + ('01', u'01 - Crédito em conta-corrente ou poupança Bradesco'), + ('02', u'02 - Cheque OP ( Ordem de Pagamento'), + ('03', u'03 - DOC COMPE'), + ('05', u'05 - Crédito em conta real time'), + ('08', u'08 - TED'), + ('30', u'30 - Rastreamento de Títulos'), + ('31', u'31 - Títulos de terceiros'), +] + +TIPO_MOVIMENTO = [ + ('0', u'Inclusão'), + ('5', u'Alteração'), + ('9', u'Exclusão'), +] + +CODIGO_MOVIMENTO = [ + ('00', u'Autoriza agendamento'), + ('25', u'Desautoriza Agendamento'), + ('50', u'Efetuar Alegçação'), +] + +TIPO_DOC = [ + ('C', u'Titularidade Diferente'), + ('D', u'Mesma Titularidade'), +] + +FINALIDADE_DOC_TED = [ + ('01', u'Crédito em Conta Corrente'), + ('02', u'Pagamento de Aluguel /Condomínios'), + ('03', u'Pagamento de Duplicatas/Títulos'), + ('04', u'Pagamento de Dividendos'), + ('05', u'Pagamento de Mensal. Escolares'), + ('06', u'Pagamento de Salário'), + ('07', u'Pagamento de Fornec/Honor.'), + ('08', u'Operações de Câmbio /Fundos /Bolsa de Valores'), + ('09', u'Repasse de Arrec./Pagto de Tributos'), + ('10', u'Transferência Internacional em Reais'), + ('11', u'DOC COMPE/TED para Poupança'), + ('12', u'DOC COMPE/TED para Depósito Judicial'), + ('13', u'Pensão Alimentícia'), + ('14', u'Restituição de Imposto de Renda'), + ('18', u'Operações Seguro Habit.', u'SFH'), + ('19', u'Operações do FDS', u'Caixa'), + ('20', u'Pagamento De Operação De Crédito'), + ('23', u'Taxa de Administração'), + ('27', u'Pagamento Acordo/Execução Judicial'), + ('28', u'Liquidação de Empréstimos Consignados'), + ('29', u'Pagamento de Bolsa Auxilio'), + ('30', u'Remuneração A Cooperado'), + ('31', u'Pagamento de Prebenda'), + ('33', u'Pagamento de Juros sobre Capital Próprio'), + ('34', u'Pagamento de Rendimentos ou Amortização s/ Cotas ' + u'e/ou Debêntures'), + ('35', u'Taxa De Serviço'), + ('37', u'Pagamento de Juros e/ou Amortização de Títulos ' + u'Depositados em Garantia.'), + ('38', u'Estorno Ou Restituição', u'Diversos'), + ('59', u'Restituição de Prêmios de Seguros'), + ('60', u'Pagamento de Indenização Sinistro Seguro'), + ('61', u'Pagamento de Premio de Co-Seguro'), + ('63', u'Pagamento de Indenização Sinistro Co-Seguro'), + ('64', u'Pagamento de Premio De Resseguro'), + ('65', u'Restituição de Premio De Resseguro'), + ('66', u'Pagamento de Indenização Sinistro Resseguro'), + ('67', u'Restituição Indenização Sinistro Resseguro'), + ('68', u'Pagamento de Despesas Com Sinistro'), + ('69', u'Pagamento de Inspeções/Vistorias Prévias'), + ('70', u'Pagamento de Resgate de Titulo de Capitalização'), + ('71', u'Pagamento de Sorteio de Titulo de Capitalização'), + ('72', u'Devolução Mensal de Titulo de Capitalização.'), + ('73', u'Restituição de Contribuição de Plano Previdenciário'), + ('74', u'Pagamento de Beneficio Previdenciário Pecúlio'), + ('75', u'Pagamento de Beneficio Previdenciário Pensão'), + ('76', u'Pagamento de Beneficio Previdenciário Aposentadoria'), + ('77', u'Pagamento de Resgate Previdenciário'), + ('78', u'Pagamento de Comissão de Corretagem'), + ('79', u'Pagamento de Transferências/Portabilidade de Reserva ' + u'Seguro/Previdência'), + ('80', u'Pagamento de Impostos'), + ('81', u'Pagamento de Serviços Públicos'), + ('82', u'Pagamento de Honorários'), + ('83', u'Pagamento de Corretoras'), + ('84', u'Repasse de Valores BNDES'), + ('85', u'Liquidação de Compromissos com BNDES'), + ('86', u'Compra e Venda de Ações'), + ('87', u'Contratos Referenciados em Ações ou Índices de Ações'), + ('88', u'Operação De Cambio'), + ('89', u'Pagamento de Boleto Bancário em Cartório'), + ('90', u'Pagamento de Tarifas pela Prestação de Serviços de Arrecadação' + u' de Convênios'), + ('91', u'Operações no Mercado de Renda Fixa e Variável com Utilização ' + u'de Intermediário'), + ('92', u'Operação de Câmbio Mercado Interbancário Instituições ' + u'sem Reservas Bancárias'), + ('93', u'Pagamento de Operações com Identificação de Destinatário Final'), + ('94', u'Ordem Bancaria do Tesouro - OBT'), + ('99', u'Outros'), +] + + +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': self.convert_int(self.get_file_numeration()), + 'cedente_inscricao_tipo': self.inscricao_tipo, + 'cnpj_cpf_base': self.convert_int(punctuation_rm( + self.order.company_id.cnpj_cpf)[0:8]), + 'cnpj_cpf_filial': self.convert_int(punctuation_rm( + self.order.company_id.cnpj_cpf)[9:12]), + 'sufixo_cnpj': self.convert_int(punctuation_rm( + self.order.company_id.cnpj_cpf)[12:14]), + 'cedente_agencia': + self.convert_int(self.order.company_partner_bank_id.bra_number), + 'cedente_conta': + self.convert_int(self.order.company_partner_bank_id.acc_number), + 'cedente_agencia_conta_dv': + self.order.company_partner_bank_id.bra_number_dig, + 'nome_empresa_pagadora': self.order.company_id.legal_name, + 'cedente_codigo_agencia_digito': + self.order.company_partner_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': self.convert_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 self.convert_int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%d%m%Y')) + + def format_date_ano_mes_dia(self, srt_date): + return self.convert_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 _prepare_cobranca(self, line, vals): + """ + + :param line: + :return: + """ + segmento = {} + + vals.update(segmento) + + # TODO this zip code + prefixo, sulfixo = self.cep(line.partner_id.zip) + + segmento = { + 'conta_complementar': + self.convert_int(self.order.company_partner_bank_id.acc_number), + # 'especie_titulo': 8, + + 'tipo_inscricao': self.convert_int( + self.sacado_inscricao_tipo(line.partner_id)), + 'cnpj_cpf_base_forn': line.partner_id.cnpj_cpf and self.convert_int( + punctuation_rm(line.partner_id.cnpj_cpf)[0:8]) or '', + 'cnpj_cpf_filial_forn': line.partner_id.cnpj_cpf and self.convert_int( + punctuation_rm(line.partner_id.cnpj_cpf)[9:12]) or '', + 'cnpj_cpf_forn_sufixo': line.partner_id.cnpj_cpf and self.convert_int( + punctuation_rm(line.partner_id.cnpj_cpf)[12:14]) or '', + 'nome_forn': line.partner_id.legal_name, + 'endereco_forn': ( + line.partner_id.street + ' ' + line.partner_id.number), + 'cep_forn': self.convert_int(prefixo), + 'cep_complemento_forn': self.convert_int(sulfixo), + + # TODO quando banco é 237, deve-se extrair da linha + # digitável. Do contrário, zeros. + # 'nosso_numero': 11, # FIXME + + # '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': self.convert_int(line.ml_inv_ref.internal_number), + + 'modalidade_pagamento': self.convert_int( + line.order_id.mode.type_purchase_payment), + + # Quando não informada o sistema assume a data constante do campo + # Vencimento + 'data_para_efetivacao_pag': 0, + + 'tipo_movimento': 0, + # TODO Tipo de Movimento. + # 0 - Inclusão. + # 5 - Alteração. + # 9 - Exclusão. + + 'codigo_movimento': 0, # Autoriza agendamento + + # Quando não informado consulta em todos processamentos + # 'horario_consulta_saldo': u'5', + + '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': self.convert_int(self.get_file_numeration()), + 'sequencial_transacao': self.controle_linha, + 'codigo_protesto': + self.convert_int(self.order.payment_mode_id.boleto_protesto), + 'prazo_protesto': + self.convert_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(), + + } + 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 (self.convert_int(time.strftime("%d%m%Y"))) + + def data_hoje_pag_for(self): + return (self.convert_int(time.strftime("%Y%m%d"))) + + def hora_agora(self): + return (self.convert_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(_(u'Operação não suportada')) + elif mode in ('03'): + return self.lancamento_doc(line) + elif mode in ('05'): + raise UserError(_(u'Operação não suportada')) + elif mode in ('08'): + return self.lancamento_ted(line) + elif mode in ('30'): + raise UserError(_(u'Operação não suportada')) + elif mode in ('31'): + # titulos de terceiros + return self.lancamento_titulos_terceiros(line) + raise UserError(_(u'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': self.convert_int(line.bank_id.bra_number), + 'digito_agencia_forn_transacao': line.bank_id.bra_number_dig, + 'conta_corrente_forn': self.convert_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': self.convert_int(self.order.payment_mode_id.boleto_carteira), + + 'nosso_numero': 0, + + 'vencimento_titulo': self.format_date_ano_mes_dia( + line.ml_maturity_date), + + 'informacoes_complementares': u'', + } + + return self._prepare_cobranca(line, vals) + + def lancamento_ted(self, line): + # TODO: + # modalidade 08. + + vals = { + 'conta_complementar': + self.convert_int(self.order.company_partner_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': + self.convert_int(line.bank_id.bank.bic), + 'codigo_agencia_forn': + self.convert_int(line.bank_id.bra_number), + 'digito_agencia_forn_transacao': + line.bank_id.bra_number_dig, + 'conta_corrente_forn': + self.convert_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': + # self.convert_int(self.order.payment_mode_id.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_cobranca(line, vals) + + def lancamento_doc(self): + # TODO: + + vals = {} + + return self._prepare_cobranca(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': + self.convert_int(self.order.company_partner_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_cobranca(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' + # pagamento duplicatas. Ou será 01? + finalidade_doc_compe = FINALIDADE_DOC_TED[2][0] + 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): + codigo_banco_fornecedor = linha_digitavel[:3] + res = {} + + # para banco = 237, bradesco + if (codigo_banco_fornecedor == '237'): + res = { + 'codigo_banco_forn': self.convert_int(codigo_banco_fornecedor), + 'codigo_agencia_forn': self.convert_int(linha_digitavel[4:8]), + # Calcular usando modulo 11 base 7 + 'digito_agencia_forn_transacao': u'', + 'conta_corrente_forn': self.convert_int(linha_digitavel[23:30]), + # Calcular usando modulo 11 base 7 + 'digito_conta_forn_transacao': u'', + + 'carteira': self.convert_int(linha_digitavel[8:10]), + + 'nosso_numero': self.convert_int(linha_digitavel[11:21]) + } + # para outros bancos + else: + res = { + 'codigo_banco_forn': self.convert_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 diff --git a/cnab_erpbrasil_febraban/models/__init__.py b/cnab_erpbrasil_febraban/models/__init__.py new file mode 100644 index 000000000000..ea8447c48a65 --- /dev/null +++ b/cnab_erpbrasil_febraban/models/__init__.py @@ -0,0 +1,5 @@ +from . import account_invoice +from . import account_move_line +from . import account_payment_mode +from . import account_payment_order +from . import l10n_br_cnab diff --git a/cnab_erpbrasil_febraban/models/account_invoice.py b/cnab_erpbrasil_febraban/models/account_invoice.py new file mode 100644 index 000000000000..552978a1c5a9 --- /dev/null +++ b/cnab_erpbrasil_febraban/models/account_invoice.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +import json +from datetime import datetime +from dateutil.relativedelta import relativedelta + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from odoo.addons.queue_job.job import job + +from pyboleto.bank_api.itau import ApiItau + +_logger = logging.getLogger(__name__) + + +class AccountInvoice(models.Model): + + _inherit = 'account.invoice' + + @job + @api.multi + def register_invoice_api(self): + for record in self: + receivable_ids = record.mapped('move_line_receivable_id') + if not receivable_ids: + return False + + boleto_list = receivable_ids.generate_boleto(validate=False) + if not boleto_list: + raise UserError(_( + u"Não foi possível registrar as faturas pela API" + )) + + company_id = record.partner_id.company_id.sudo() + + itau_key = company_id.itau_key + barcode_endpoint = company_id.raiz_endpoint + environment = company_id.environment + + token = record.obtain_token(company_id, environment) + + for boleto in boleto_list: + ApiItau.convert_to(boleto, tipo_ambiente=environment) + response = False + try: + response = boleto.post(token, itau_key, barcode_endpoint) + if response and response.ok: + # Remove Invoice from debit.orders + record._remove_payment_order_line(_raise=False) + + # Create new Debit Order for payment_order_line + try: + record.create_api_account_payment_line() + + except Exception as e: + _logger.debug(str(e)) + else: + receivable_ids.write({ + 'state_cnab': 'not_accepted' + }) + + except Exception as e: + raise UserError(_( + u"Erro ao registrar a fatura boleto. Verifique se as " + u"configurações da API estão corretas. %s" + ) % str(e)) + + finally: + if response and response.ok: + # ambiente = 1 --> HML + if boleto.tipo_ambiente == '1': + receivable_ids.write({ + 'state_cnab': 'accepted_hml' + }) + # PROD + else: + receivable_ids.write({ + 'state_cnab': 'accepted', + 'situacao_pagamento': 'aberta' + }) + + record.create_bank_api_operation( + response, + operation_type='invoice_register', + environment=environment, + ) + self.message_post(_( + "Comunicação com o banco via API concluída. Verifique a Aba " + "'Operações Bancárias' consultar o resultado do processamento." + )) + + def obtain_token(self, company_id, environment): + """ + Método para buscar ou atualizar o Token da empresa + :param company_id: Empresa + :param environment: Ambiente da operação + :return: O Token da empresa + """ + + token = company_id.api_itau_token + if not token or company_id.api_itau_token_due_datetime <= \ + fields.Datetime.now(): + + client_id = company_id.client_id + client_secret = company_id.client_secret + endpoint = company_id.api_endpoint + + token_request = False + try: + token_request = ApiItau.generate_api_key( + client_id, client_secret, endpoint) + token_request_dict = json.loads(token_request.content) + token = token_request_dict.get('access_token') + company_id.api_itau_token = token + company_id.api_itau_token_due_datetime = \ + fields.Datetime.context_timestamp( + self, datetime.now()) + relativedelta( + seconds=token_request_dict.get('expires_in')) + + except Exception as e: + company_id.api_itau_token = '' + company_id.api_itau_token_due_datetime = \ + fields.Datetime.now() + raise UserError(_( + u"Erro na obtenção do Token de acesso à Api. %s" + ) % str(e)) + finally: + self.create_bank_api_operation( + token_request, + operation_type='token_request', + environment=environment, + ) + self._cr.commit() + + return token diff --git a/cnab_erpbrasil_febraban/models/account_move_line.py b/cnab_erpbrasil_febraban/models/account_move_line.py new file mode 100644 index 000000000000..96b9fff9b94b --- /dev/null +++ b/cnab_erpbrasil_febraban/models/account_move_line.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + +from ..febraban.boleto.document import Boleto + + +class AccountMoveLine(models.Model): + + _inherit = 'account.move.line' + + @api.multi + def generate_boleto(self, validate=True): + boleto_list = [] + + for move_line in self: + + if validate and move_line.state_cnab not in \ + ['accepted', 'accepted_hml']: + if move_line.state_cnab == 'not_accepted': + raise UserError(_( + u'Essa fatura foi transmitida com erro ao banco, ' + u'é necessário corrigí-la e reenviá-la.' + )) + raise UserError(_( + u'Antes de imprimir o boleto é necessário transmitir a ' + u'fatura para registro no banco.' + )) + + boleto = Boleto.getBoleto( + move_line, move_line.nosso_numero + ) + + # Se a cobrança tiver sido emitida em homologação + if move_line.state_cnab == 'accepted_hml': + boleto.boleto.instrucoes.append(_( + u'Boleto emitido em homologacao! Sem valor fiscal!')) + + boleto_list.append(boleto.boleto) + + if not boleto_list: + raise UserError( + 'Error !', ('Não é possível gerar os boletos\n' + 'Certifique-se que a fatura esteja confirmada e o ' + 'forma de pagamento seja duplicatas')) + pdf_string = Boleto.get_pdfs(boleto_list) + return pdf_string \ No newline at end of file diff --git a/cnab_erpbrasil_febraban/models/account_payment_mode.py b/cnab_erpbrasil_febraban/models/account_payment_mode.py new file mode 100644 index 000000000000..d85d9e1554f7 --- /dev/null +++ b/cnab_erpbrasil_febraban/models/account_payment_mode.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ + +from ..febraban.boleto.document import getBoletoSelection + +boleto_selection = getBoletoSelection() + + +class AccountPaymentMode(models.Model): + + _inherit = 'account.payment.mode' + + boleto_type = fields.Selection( + selection_add=boleto_selection + ) diff --git a/cnab_erpbrasil_febraban/models/account_payment_order.py b/cnab_erpbrasil_febraban/models/account_payment_order.py new file mode 100644 index 000000000000..50721badbb2f --- /dev/null +++ b/cnab_erpbrasil_febraban/models/account_payment_order.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +import logging + +from odoo import api, models, fields +from ..febraban.cnab import Cnab + +_logger = logging.getLogger(__name__) + +try: + from cnab240.errors import (Cnab240Error) +except ImportError as err: + _logger.debug = err + + +class AccountPaymentOrder(models.Model): + + _inherit = 'account.payment.order' + + def _generate_payment_file(self): + try: + return Cnab.gerar_remessa(order=self), self.name + '.REM' + except Cnab240Error as e: + _logger.error("Erro ao gerar o arquivo: \n\n{0}".format(e)) + + @api.multi + def generate_payment_file(self): + """Returns (payment file as string, filename)""" + self.ensure_one() + if self.payment_method_id.code in ('240', '400', '500'): + return self._generate_payment_file() + return super(AccountPaymentOrder, self).generate_payment_file() \ No newline at end of file diff --git a/cnab_erpbrasil_febraban/models/l10n_br_cnab.py b/cnab_erpbrasil_febraban/models/l10n_br_cnab.py new file mode 100644 index 000000000000..07bd91386ad5 --- /dev/null +++ b/cnab_erpbrasil_febraban/models/l10n_br_cnab.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from datetime import datetime +from ..febraban.cnab import Cnab + +from odoo import api, models, fields + +_logger = logging.getLogger(__name__) + +class L10n_brCnab(models.Model): + + _inherit = 'l10n_br.cnab' + + @api.multi + def reprocessar_arquivo_retorno(self): + cnab_type, arquivo_parser = Cnab.detectar_retorno(self.arquivo_retorno) + data_arquivo = str(arquivo_parser.header.arquivo_data_de_geracao) + self.sequencial_arquivo = str(arquivo_parser.header.sequencial_arquivo) + self.data_arquivo = datetime.strptime(data_arquivo.zfill(6), "%d%m%y") + + self.bank_account_id = self._busca_conta( + arquivo_parser.header.codigo_do_banco, + arquivo_parser.header.cedente_agencia, + arquivo_parser.header.cedente_conta, + ) + + self.num_lotes = len(arquivo_parser.lotes) + self.num_eventos = arquivo_parser.trailer.totais_quantidade_registros + for lote in arquivo_parser.lotes: + + header = lote.header or arquivo_parser.header + trailer = lote.trailer or arquivo_parser.trailer + + lote_id = self.lote_id and self.lote_id[0] + bankless_line_id = \ + lote_id.evento_id.filtered( + lambda e: not e.bank_payment_line_id) + bankless_line_id.unlink() + + for evento in lote.eventos: + if not lote_id: + lote_id, lote_bank_account_id = self._cria_lote( + header, lote, evento, trailer) + + if cnab_type == '240': + self._reprocessa_lote_240(evento, lote_id) + else: + self._reprocessa_lote_400(evento, lote_id) + + #TODO: Verificar necessidade de atualizar dados do Account.Move + return self.write({'state': 'done'}) + + @api.multi + def processar_arquivo_retorno(self): + cnab_type, arquivo_parser = Cnab.detectar_retorno(self.arquivo_retorno) + # if not arquivo_parser.header.arquivo_codigo == u'2': + # raise exceptions.Warning( + # u"Este não é um arquivo de retorno!" + # ) + data_arquivo = str(arquivo_parser.header.arquivo_data_de_geracao) + self.sequencial_arquivo = str(arquivo_parser.header.sequencial_arquivo) + self.data_arquivo = datetime.strptime(data_arquivo.zfill(6), "%d%m%y") + + if self.search([ + ('data_arquivo', '=', self.data_arquivo), + ('sequencial_arquivo', '=', self.sequencial_arquivo), + ('id', '!=', self.id)]): + self.state = 'error' + self.motivo_erro = u"O arquivo %s, de %s - sequencial %s, " \ + u"ja se encontra importado." % \ + (self.filename, + datetime.strftime(fields.Datetime.from_string( + self.data_arquivo), "%d/%m/%Y"), + self.sequencial_arquivo) + return + + self.bank_account_id = self._busca_conta( + arquivo_parser.header.codigo_do_banco, + arquivo_parser.header.cedente_agencia, + arquivo_parser.header.cedente_conta, + ) + + self.num_lotes = len(arquivo_parser.lotes) + self.num_eventos = arquivo_parser.trailer.totais_quantidade_registros + for lote in arquivo_parser.lotes: + + header = lote.header or arquivo_parser.header + trailer = lote.trailer or arquivo_parser.trailer + + lote_id = False + total_amount = 0.0 + lines = [] + inv_list = [] + for evento in lote.eventos: + if not lote_id: + lote_id, lote_bank_account_id = self._cria_lote( + header, lote, evento, trailer) + + if cnab_type == '240': + self._lote_240(evento, lote_id) + else: + line_vals, line_amount, invoices = \ + self._lote_400(evento, lote_id) + for inv in invoices: + inv_list.append(inv) + if line_vals and line_amount: + for line in line_vals: + lines.append(line) + total_amount += line_amount + + if total_amount and lines: + counterpart_account_id = self.env['account.journal'].browse( + lines[0][2]['journal_id']).default_debit_account_id.id + + lines.append( + (0, 0, { + 'name': 'cobranca', + 'debit': total_amount, + 'account_id': counterpart_account_id, + 'journal_id': lines[0][2]['journal_id'], + 'date_maturity': False, + 'partner_id': False, + }) + ) + move = self.env['account.move'].create({ + 'name': 'RetornoCnab_' + fields.Datetime.now(), + 'ref': + 'Retorno Gerado em %s' % + datetime.strftime(datetime.strptime( + data_arquivo.zfill(6), "%d%m%y"), "%d/%m/%Y"), + 'date': str(datetime.now()), + 'line_ids': lines, + 'journal_id': lines[0][2]['journal_id'] + }) + move.post() + + for inv in inv_list: + if inv.state != 'open': + continue + inv_move_lines = inv.move_line_receivable_id + pay_move_lines = move.line_ids.filtered( + lambda x: x.account_id == inv_move_lines.account_id and + x.partner_id == inv_move_lines.partner_id and + x.name == inv_move_lines.transaction_ref + ) + move_lines = pay_move_lines | inv_move_lines + move_lines.reconcile() + + return self.write({'state': 'done'}) diff --git a/cnab_erpbrasil_febraban/static/description/icon.png b/cnab_erpbrasil_febraban/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/cnab_erpbrasil_febraban/views/account_invoice.xml b/cnab_erpbrasil_febraban/views/account_invoice.xml new file mode 100644 index 000000000000..b1faf915bd3e --- /dev/null +++ b/cnab_erpbrasil_febraban/views/account_invoice.xml @@ -0,0 +1,18 @@ + + + + + + + account.invoice.form (in cnab_erpbrasil_febraban) + account.invoice + + + + + + + + + From 50a7656bec17fd55953c38a66ede15ebfe47b981 Mon Sep 17 00:00:00 2001 From: Hugo Borges Date: Tue, 7 Jan 2020 14:55:01 -0300 Subject: [PATCH 02/12] [FIX] erpbrasil.febraban dependency --- cnab_erpbrasil_febraban/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cnab_erpbrasil_febraban/__manifest__.py b/cnab_erpbrasil_febraban/__manifest__.py index 821b4bfe2759..8de0d64fa771 100644 --- a/cnab_erpbrasil_febraban/__manifest__.py +++ b/cnab_erpbrasil_febraban/__manifest__.py @@ -19,6 +19,6 @@ 'demo': [ ], 'external_dependencies': { - 'python': ['erpbrasil.febraban'], + 'python': ['pyboleto'], }, } From 69c5cd7d3e5648a185284e9203da769d7d429d42 Mon Sep 17 00:00:00 2001 From: Hugo Borges Date: Tue, 7 Jan 2020 14:55:47 -0300 Subject: [PATCH 03/12] [FIX] python3 StringIO --- cnab_erpbrasil_febraban/febraban/boleto/document.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cnab_erpbrasil_febraban/febraban/boleto/document.py b/cnab_erpbrasil_febraban/febraban/boleto/document.py index b33e1d61eae1..3908963dd333 100644 --- a/cnab_erpbrasil_febraban/febraban/boleto/document.py +++ b/cnab_erpbrasil_febraban/febraban/boleto/document.py @@ -15,7 +15,7 @@ try: from cStringIO import StringIO except ImportError: - from StringIO import StringIO + from io import StringIO BoletoException = bank.BoletoException From c1ec55ec010995ddaea6f4c8052c073012ef5c92 Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Thu, 3 Sep 2020 10:35:08 -0300 Subject: [PATCH 04/12] [FIX][WIP] Exporting Erros Signed-off-by: Luis Felipe Mileo --- cnab_erpbrasil_febraban/__manifest__.py | 8 +-- .../febraban/boleto/document.py | 6 +-- .../febraban/cnab_240/cnab_240.py | 50 +++++++++++-------- .../febraban/cnab_400/cnab_400.py | 4 +- .../models/account_invoice.py | 6 +-- .../models/account_payment_order.py | 4 +- 6 files changed, 44 insertions(+), 34 deletions(-) diff --git a/cnab_erpbrasil_febraban/__manifest__.py b/cnab_erpbrasil_febraban/__manifest__.py index 8de0d64fa771..73b746d9ae66 100644 --- a/cnab_erpbrasil_febraban/__manifest__.py +++ b/cnab_erpbrasil_febraban/__manifest__.py @@ -10,15 +10,15 @@ 'author': 'KMEE,Odoo Community Association (OCA)', 'website': 'http://odoo-brasil.org', 'depends': [ - 'l10n_br_account_payment_cobranca', - 'queue_job' + 'l10n_br_account_payment_order', + # 'queue_job' ], 'data': [ - 'views/account_invoice.xml', + # 'views/account_invoice.xml', ], 'demo': [ ], 'external_dependencies': { - 'python': ['pyboleto'], + 'python': ['erpbrasil.febraban'], }, } diff --git a/cnab_erpbrasil_febraban/febraban/boleto/document.py b/cnab_erpbrasil_febraban/febraban/boleto/document.py index 3908963dd333..5e2862348a40 100644 --- a/cnab_erpbrasil_febraban/febraban/boleto/document.py +++ b/cnab_erpbrasil_febraban/febraban/boleto/document.py @@ -8,7 +8,8 @@ _logger = logging.getLogger(__name__) try: - from pyboleto import bank + from erpbrasil.febraban.boleto.banco import get_class_for_codigo + from erpbrasil.febraban.boleto.exceptions import BoletoException except ImportError as err: _logger.debug = err @@ -16,7 +17,6 @@ from cStringIO import StringIO except ImportError: from io import StringIO -BoletoException = bank.BoletoException class Boleto: @@ -42,7 +42,7 @@ def getBoletoClass(move_line): bank_code = \ move_line.payment_mode_id. \ fixed_journal_id.bank_account_id.bank_id.code_bc - return bank.get_class_for_codigo(bank_code) + return get_class_for_codigo(bank_code) def __init__(self, move_line, nosso_numero): self._cedente(move_line.company_id) diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py index f38a96645d15..1d3b4168aa42 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py +++ b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py @@ -15,13 +15,12 @@ import unicodedata from decimal import Decimal -from odoo.addons.l10n_br_base.tools.misc import punctuation_rm from ..cnab import Cnab _logger = logging.getLogger(__name__) try: - from cnab240.tipos import Arquivo, Lote + from erpbrasi.febraban.cnab.tipos import Arquivo, Lote except ImportError as err: _logger.debug = err @@ -42,23 +41,23 @@ def get_bank(bank): :param bank: str - Código do banco :return: ''' - 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 == '001': - from .bancos.bb import BB240 - return BB240 - else: - return Cnab240 + # 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 == '001': + # from .bancos.bb import BB240 + # return BB240 + # else: + return Cnab240 def get_inscricao_tipo(self, partner_id): # TODO: Implementar codigo para PIS/PASEP @@ -490,10 +489,19 @@ def remessa(self, order): :param order: payment.order :return: Arquivo Cnab pronto para download """ - # cobrancasimples_valor_titulos = 0 - self.order = order + if not (self.order.company_partner_bank_id and + self.order.company_partner_bank_id.bank_id + ): + raise NotImplementedError + + bank_id = self.order.company_partner_bank_id.bank_id + + + + # self.bank = + # Preparar Header do Arquivo self.arquivo = Arquivo(self.bank, **self._prepare_header()) diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py b/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py index 92ace1c8071d..c31b53e65807 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py +++ b/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py @@ -17,8 +17,8 @@ _logger = logging.getLogger(__name__) try: - from cnab240.tipos import ArquivoCobranca400 - from cnab240.errors import Cnab240Error + from erpbrasil.febraban.cnab.tipos import ArquivoCobranca400 + from erpbrasil.febraban.cnab.errors import Cnab240Error except ImportError as err: _logger.debug = (err) diff --git a/cnab_erpbrasil_febraban/models/account_invoice.py b/cnab_erpbrasil_febraban/models/account_invoice.py index 552978a1c5a9..80b46121abc0 100644 --- a/cnab_erpbrasil_febraban/models/account_invoice.py +++ b/cnab_erpbrasil_febraban/models/account_invoice.py @@ -10,9 +10,9 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.addons.queue_job.job import job +# from odoo.addons.queue_job.job import job -from pyboleto.bank_api.itau import ApiItau +# from pyboleto.bank_api.itau import ApiItau _logger = logging.getLogger(__name__) @@ -21,7 +21,7 @@ class AccountInvoice(models.Model): _inherit = 'account.invoice' - @job + # @job @api.multi def register_invoice_api(self): for record in self: diff --git a/cnab_erpbrasil_febraban/models/account_payment_order.py b/cnab_erpbrasil_febraban/models/account_payment_order.py index 50721badbb2f..1784e2c000eb 100644 --- a/cnab_erpbrasil_febraban/models/account_payment_order.py +++ b/cnab_erpbrasil_febraban/models/account_payment_order.py @@ -12,6 +12,8 @@ _logger = logging.getLogger(__name__) try: + from erpbrasi.febraban.cnab.tipos import Arquivo, Lote + from cnab240.errors import (Cnab240Error) except ImportError as err: _logger.debug = err @@ -33,4 +35,4 @@ def generate_payment_file(self): self.ensure_one() if self.payment_method_id.code in ('240', '400', '500'): return self._generate_payment_file() - return super(AccountPaymentOrder, self).generate_payment_file() \ No newline at end of file + return super(AccountPaymentOrder, self).generate_payment_file() From 1fe6a7b0a691165a3a4f609f89cb3eef5c6977f1 Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Thu, 3 Sep 2020 11:09:47 -0300 Subject: [PATCH 05/12] [WIP] Bank Transfer Signed-off-by: Luis Felipe Mileo --- cnab_erpbrasil_febraban/febraban/cnab.py | 88 +++++++++++++++++++++--- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/cnab_erpbrasil_febraban/febraban/cnab.py b/cnab_erpbrasil_febraban/febraban/cnab.py index 869d227a2b01..e9d87c51ed64 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab.py +++ b/cnab_erpbrasil_febraban/febraban/cnab.py @@ -27,27 +27,93 @@ def __init__(self): self.cnab_type = False @staticmethod - def get_cnab(bank, cnab_type='240'): + def gerar_remessa(order): + bank_code = order.company_partner_bank_id.bank_id.code_bc + cnab_type = order.payment_mode_id.payment_method_id.code + if cnab_type == '240': - from .cnab_240.cnab_240 import Cnab240 - return Cnab240.get_bank(bank) + from febraban.cnab240.itau.sispag import Transfer, File + from febraban.cnab240.itau.sispag.file.lot import Lot + from febraban.cnab240.user import User, UserAddress, UserBank + sender = User( + name="YOUR COMPANY NAME HERE", + identifier="12345678901234", + bank=UserBank( + bankId="341", + branchCode="4321", + accountNumber="12345678", + accountVerifier="9" + ), + address=UserAddress( + streetLine1="AV PAULISTA 1000", + city="SAO PAULO", + stateCode="SP", + zipCode="01310000" + ) + ) + + receiver1 = User( + name="RECEIVER NAME HERE", + identifier="01234567890", + bank=UserBank( + bankId="341", + branchCode="1234", + accountNumber="123456", + accountVerifier="9" + ) + ) + + receiver2 = User( + name="RECEIVER NAME HERE", + identifier="01234567890", + bank=UserBank( + bankId="341", + branchCode="1234", + accountNumber="123456", + accountVerifier="9" + ) + ) + + receivers = [receiver1, receiver2] + + file = File() + file.setSender(sender) + + lot = Lot() + sender.name = "SENDER NAME" + lot.setSender(sender) + lot.setHeaderLotType( + kind="20", # Tipo de pagamento - Fornecedores + method="01" # TED - Outra titularidade + ) + + for receiver in receivers: + payment = Transfer() + payment.setSender(sender) + payment.setReceiver(receiver) + payment.setAmountInCents("10000") + payment.setScheduleDate("06052020") + payment.setInfo( + reason="10" # Crédito em Conta Corrente + ) + payment.setIdentifier("ID1234567890") + lot.add(register=payment) + + file.addLot(lot) + return file.toString().encode() elif cnab_type == '400': + raise NotImplementedError + # Legacy Code from .cnab_400.cnab_400 import Cnab400 return Cnab400.get_bank(bank) elif cnab_type == '500': + raise NotImplementedError + # Legacy Code from .pag_for.pag_for500 import PagFor500 return PagFor500.get_bank(bank) else: return False - @staticmethod - def gerar_remessa(order): - cnab = Cnab.get_cnab( - order.company_partner_bank_id.bank_id.code_bc, - order.payment_mode_id.payment_method_id.code - )() - return cnab.remessa(order) - @staticmethod def detectar_retorno(cnab_file_object): arquivo_retono = base64.b64decode(cnab_file_object) From 39781a7c43d7d3609e05ab34e8a418a7556a2f52 Mon Sep 17 00:00:00 2001 From: Gabriel Cardoso de Faria Date: Thu, 10 Sep 2020 13:45:30 -0300 Subject: [PATCH 06/12] [ADD] Bank Transfer --- cnab_erpbrasil_febraban/febraban/cnab.py | 79 +++++++++++------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/cnab_erpbrasil_febraban/febraban/cnab.py b/cnab_erpbrasil_febraban/febraban/cnab.py index e9d87c51ed64..89658ad14aec 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab.py +++ b/cnab_erpbrasil_febraban/febraban/cnab.py @@ -10,6 +10,7 @@ import logging import base64 import codecs +from unidecode import unidecode _logger = logging.getLogger(__name__) @@ -28,7 +29,8 @@ def __init__(self): @staticmethod def gerar_remessa(order): - bank_code = order.company_partner_bank_id.bank_id.code_bc + bank_id = order.company_partner_bank_id.bank_id + bank_code = bank_id.code_bc cnab_type = order.payment_mode_id.payment_method_id.code if cnab_type == '240': @@ -36,67 +38,60 @@ def gerar_remessa(order): from febraban.cnab240.itau.sispag.file.lot import Lot from febraban.cnab240.user import User, UserAddress, UserBank sender = User( - name="YOUR COMPANY NAME HERE", - identifier="12345678901234", + name=order.company_id.legal_name.upper(), + identifier=order.company_id.cnpj_cpf.replace( + '.', '').replace('/', '').replace('-', ''), bank=UserBank( - bankId="341", - branchCode="4321", - accountNumber="12345678", - accountVerifier="9" + bankId=bank_code, + branchCode=order.company_partner_bank_id.bra_number, + accountNumber=order.company_partner_bank_id.acc_number, + accountVerifier= + order.company_partner_bank_id.acc_number_dig ), address=UserAddress( - streetLine1="AV PAULISTA 1000", - city="SAO PAULO", - stateCode="SP", - zipCode="01310000" + streetLine1=(order.company_id.partner_id.street + ' ' + + (order.company_id.partner_id.street_number + or '')).upper(), + city=unidecode(order.company_id.city_id.name).upper(), + stateCode=order.company_id.state_id.code, + zipCode=order.company_id.zip.replace('-', '') ) ) - receiver1 = User( - name="RECEIVER NAME HERE", - identifier="01234567890", - bank=UserBank( - bankId="341", - branchCode="1234", - accountNumber="123456", - accountVerifier="9" - ) - ) - - receiver2 = User( - name="RECEIVER NAME HERE", - identifier="01234567890", - bank=UserBank( - bankId="341", - branchCode="1234", - accountNumber="123456", - accountVerifier="9" - ) - ) - - receivers = [receiver1, receiver2] - file = File() file.setSender(sender) lot = Lot() - sender.name = "SENDER NAME" + sender.name = order.company_id.legal_name.upper() lot.setSender(sender) lot.setHeaderLotType( - kind="20", # Tipo de pagamento - Fornecedores - method="01" # TED - Outra titularidade + kind=order.service_type, # Tipo de pagamento - Fornecedores + method=order.release_form # TED - Outra titularidade ) - for receiver in receivers: + for line in order.bank_line_ids: + receiver = User( + name=line.partner_id.name.upper(), + identifier=(line.partner_id.cnpj_cpf or '' + ).replace('-', '').replace('.', '' + ).replace('/', ''), + bank=UserBank( + bankId=line.partner_bank_id.bank_id.code_bc, + branchCode=line.partner_bank_id.bra_number, + accountNumber=line.partner_bank_id.acc_number, + accountVerifier=line.partner_bank_id.acc_number_dig + ) + ) + payment = Transfer() payment.setSender(sender) payment.setReceiver(receiver) - payment.setAmountInCents("10000") - payment.setScheduleDate("06052020") + payment.setAmountInCents(str(int(line.amount_currency * 100))) + payment.setScheduleDate(line.date.strftime('%d%m%Y')) payment.setInfo( reason="10" # Crédito em Conta Corrente ) - payment.setIdentifier("ID1234567890") + payment.setIdentifier("ID%s" % line.own_number) lot.add(register=payment) file.addLot(lot) From 583cb576b1d549fc0b7e634cea8b742a59e5cdd5 Mon Sep 17 00:00:00 2001 From: Gabriel Cardoso de Faria Date: Fri, 11 Sep 2020 17:07:22 -0300 Subject: [PATCH 07/12] [ADD] DAS, ISS and Utility Payment --- cnab_erpbrasil_febraban/febraban/cnab.py | 55 ++++++++++++++++++------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/cnab_erpbrasil_febraban/febraban/cnab.py b/cnab_erpbrasil_febraban/febraban/cnab.py index 89658ad14aec..00bc124e5ea4 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab.py +++ b/cnab_erpbrasil_febraban/febraban/cnab.py @@ -12,6 +12,12 @@ import codecs from unidecode import unidecode +from febraban.cnab240.itau.sispag import \ + Transfer, DasPayment, IssPayment, UtilityPayment, File +from febraban.cnab240.itau.sispag.file.lot import Lot +from febraban.cnab240.libs.barCode import LineNumberO +from febraban.cnab240.user import User, UserAddress, UserBank + _logger = logging.getLogger(__name__) @@ -34,9 +40,6 @@ def gerar_remessa(order): cnab_type = order.payment_mode_id.payment_method_id.code if cnab_type == '240': - from febraban.cnab240.itau.sispag import Transfer, File - from febraban.cnab240.itau.sispag.file.lot import Lot - from febraban.cnab240.user import User, UserAddress, UserBank sender = User( name=order.company_id.legal_name.upper(), identifier=order.company_id.cnpj_cpf.replace( @@ -66,7 +69,8 @@ def gerar_remessa(order): lot.setSender(sender) lot.setHeaderLotType( kind=order.service_type, # Tipo de pagamento - Fornecedores - method=order.release_form # TED - Outra titularidade + method=order.release_form_itau or + order.release_form # TED - Outra titularidade ) for line in order.bank_line_ids: @@ -83,15 +87,40 @@ def gerar_remessa(order): ) ) - payment = Transfer() - payment.setSender(sender) - payment.setReceiver(receiver) - payment.setAmountInCents(str(int(line.amount_currency * 100))) - payment.setScheduleDate(line.date.strftime('%d%m%Y')) - payment.setInfo( - reason="10" # Crédito em Conta Corrente - ) - payment.setIdentifier("ID%s" % line.own_number) + if order.release_form_itau == "41": + payment = Transfer() + payment.setSender(sender) + payment.setReceiver(receiver) + payment.setAmountInCents(str(int(line.amount_currency * 100))) + payment.setScheduleDate(line.date.strftime('%d%m%Y')) + payment.setInfo( + reason="10" # Crédito em Conta Corrente + ) + payment.setIdentifier("ID%s" % line.own_number) + elif order.release_form_itau == "91": + payment = DasPayment() + payment.setPayment( + sender=sender, + scheduleDate=line.date.strftime('%d%m%Y'), + identifier="ID%s" % line.own_number, + lineNumber=LineNumberO(line.communication) + ) + elif order.release_form_itau == "19": + payment = IssPayment() + payment.setPayment( + sender=sender, + scheduleDate=line.date.strftime('%d%m%Y'), + identifier="ID%s" % line.own_number, + lineNumber=LineNumberO(line.communication) + ) + elif order.release_form_itau == "13": + payment = UtilityPayment() + payment.setPayment( + sender=sender, + scheduleDate=line.date.strftime('%d%m%Y'), + identifier="ID%s" % line.own_number, + lineNumber=LineNumberO(line.communication) + ) lot.add(register=payment) file.addLot(lot) From f9bd2e0e8a0ec4482a76a693b7d14f442431fb99 Mon Sep 17 00:00:00 2001 From: Gabriel Cardoso de Faria Date: Fri, 18 Sep 2020 13:24:02 -0300 Subject: [PATCH 08/12] [ADD] Generate multiple cnab payment types in same cnab240 file --- cnab_erpbrasil_febraban/febraban/cnab.py | 122 ++++++++++++----------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/cnab_erpbrasil_febraban/febraban/cnab.py b/cnab_erpbrasil_febraban/febraban/cnab.py index 00bc124e5ea4..9ccc7db97e17 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab.py +++ b/cnab_erpbrasil_febraban/febraban/cnab.py @@ -61,69 +61,79 @@ def gerar_remessa(order): ) ) + bank_line_obj = order.env['bank.payment.line'] + option_obj = order.env['l10n_br.cnab.option'] + file = File() file.setSender(sender) - lot = Lot() - sender.name = order.company_id.legal_name.upper() - lot.setSender(sender) - lot.setHeaderLotType( - kind=order.service_type, # Tipo de pagamento - Fornecedores - method=order.release_form_itau or - order.release_form # TED - Outra titularidade - ) - - for line in order.bank_line_ids: - receiver = User( - name=line.partner_id.name.upper(), - identifier=(line.partner_id.cnpj_cpf or '' - ).replace('-', '').replace('.', '' - ).replace('/', ''), - bank=UserBank( - bankId=line.partner_bank_id.bank_id.code_bc, - branchCode=line.partner_bank_id.bra_number, - accountNumber=line.partner_bank_id.acc_number, - accountVerifier=line.partner_bank_id.acc_number_dig - ) + for group in bank_line_obj.read_group( + [('id', 'in', order.bank_line_ids.ids)], + [], ['release_form_id', 'service_type_id'], lazy=False + ): + lot = Lot() + sender.name = order.company_id.legal_name.upper() + lot.setSender(sender) + lot.setHeaderLotType( + kind=option_obj.browse(group['service_type_id'][0]).code, + method=option_obj.browse(group['release_form_id'][0]).code, ) - if order.release_form_itau == "41": - payment = Transfer() - payment.setSender(sender) - payment.setReceiver(receiver) - payment.setAmountInCents(str(int(line.amount_currency * 100))) - payment.setScheduleDate(line.date.strftime('%d%m%Y')) - payment.setInfo( - reason="10" # Crédito em Conta Corrente + for line in bank_line_obj.search(group['__domain']): + receiver = User( + name=line.partner_id.name.upper(), + identifier=(line.partner_id.cnpj_cpf or '' + ).replace('-', '').replace( + '.', '').replace('/', ''), + bank=UserBank( + bankId=line.partner_bank_id.bank_id.code_bc, + branchCode=line.partner_bank_id.bra_number, + accountNumber=line.partner_bank_id.acc_number, + accountVerifier= + line.partner_bank_id.acc_number_dig + ) ) - payment.setIdentifier("ID%s" % line.own_number) - elif order.release_form_itau == "91": - payment = DasPayment() - payment.setPayment( - sender=sender, - scheduleDate=line.date.strftime('%d%m%Y'), - identifier="ID%s" % line.own_number, - lineNumber=LineNumberO(line.communication) - ) - elif order.release_form_itau == "19": - payment = IssPayment() - payment.setPayment( - sender=sender, - scheduleDate=line.date.strftime('%d%m%Y'), - identifier="ID%s" % line.own_number, - lineNumber=LineNumberO(line.communication) - ) - elif order.release_form_itau == "13": - payment = UtilityPayment() - payment.setPayment( - sender=sender, - scheduleDate=line.date.strftime('%d%m%Y'), - identifier="ID%s" % line.own_number, - lineNumber=LineNumberO(line.communication) - ) - lot.add(register=payment) - file.addLot(lot) + if line.release_form_id.code == "41": + payment = Transfer() + payment.setSender(sender) + payment.setReceiver(receiver) + payment.setAmountInCents(str(int(line.amount_currency * 100))) + payment.setScheduleDate(line.date.strftime('%d%m%Y')) + payment.setInfo( + reason="10" # Crédito em Conta Corrente + ) + payment.setIdentifier("ID%s" % line.own_number) + elif line.release_form_id.code == "91": + payment = DasPayment() + payment.setPayment( + sender=sender, + scheduleDate=line.date.strftime('%d%m%Y'), + identifier="ID%s" % line.own_number, + lineNumber=LineNumberO(line.communication) + ) + elif line.release_form_id.code == "19": + payment = IssPayment() + payment.setPayment( + sender=sender, + scheduleDate=line.date.strftime('%d%m%Y'), + identifier="ID%s" % line.own_number, + lineNumber=LineNumberO(line.communication) + ) + elif line.release_form_id.code == "13": + payment = UtilityPayment() + payment.setPayment( + sender=sender, + scheduleDate=line.date.strftime('%d%m%Y'), + identifier="ID%s" % line.own_number, + lineNumber=LineNumberO(line.communication) + ) + else: + continue + lot.add(register=payment) + + file.addLot(lot) + return file.toString().encode() elif cnab_type == '400': raise NotImplementedError From ebe915f684854d86e3cc796d4079b3d25b05cc9d Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Wed, 30 Sep 2020 07:49:20 -0300 Subject: [PATCH 09/12] [REM] Legacy Code Signed-off-by: Luis Felipe Mileo Signed-off-by: Luis Felipe Mileo --- cnab_erpbrasil_febraban/README.rst | 91 --- .../febraban/boleto/__init__.py | 6 - .../febraban/boleto/document.py | 350 ----------- .../febraban/cnab_240/__init__.py | 4 - .../febraban/cnab_240/bancos/__init__.py | 6 - .../febraban/cnab_240/bancos/bb.py | 65 -- .../febraban/cnab_240/bancos/bradesco.py | 67 -- .../febraban/cnab_240/bancos/bradesco.py.orig | 71 --- .../febraban/cnab_240/bancos/cef.py | 92 --- .../febraban/cnab_240/bancos/itau.py | 67 -- .../febraban/cnab_240/bancos/santander.py | 42 -- .../febraban/cnab_240/cnab_240.py | 582 ------------------ .../febraban/cnab_240/cnab_240.py.orig | 566 ----------------- .../febraban/cnab_400/__init__.py | 6 - .../febraban/cnab_400/bancos/__init__.py | 4 - .../febraban/cnab_400/bancos/bradesco.py | 97 --- .../febraban/cnab_400/bancos/itau.py | 176 ------ .../febraban/cnab_400/cnab_400.py | 401 ------------ .../febraban/pag_for/__init__.py | 8 - .../febraban/pag_for/bancos/__init__.py | 6 - .../febraban/pag_for/bancos/bradesco.py | 60 -- .../febraban/pag_for/pag_for500.py | 573 ----------------- cnab_erpbrasil_febraban/models/__init__.py | 6 +- .../models/account_invoice.py | 139 ----- .../models/account_move_line.py | 50 -- .../models/account_payment_mode.py | 18 - .../views/account_invoice.xml | 18 - 27 files changed, 3 insertions(+), 3568 deletions(-) delete mode 100644 cnab_erpbrasil_febraban/README.rst delete mode 100644 cnab_erpbrasil_febraban/febraban/boleto/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/boleto/document.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py delete mode 100644 cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py delete mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py delete mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py delete mode 100644 cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py delete mode 100644 cnab_erpbrasil_febraban/models/account_invoice.py delete mode 100644 cnab_erpbrasil_febraban/models/account_move_line.py delete mode 100644 cnab_erpbrasil_febraban/models/account_payment_mode.py delete mode 100644 cnab_erpbrasil_febraban/views/account_invoice.xml diff --git a/cnab_erpbrasil_febraban/README.rst b/cnab_erpbrasil_febraban/README.rst deleted file mode 100644 index 9d445db03244..000000000000 --- a/cnab_erpbrasil_febraban/README.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html - :alt: License: AGPL-3 - -======================= -Cnab Erpbrasil Febraban -======================= - -Integração com CNAB através da biblioteca erpbrasil.febraban - -Installation -============ - -To install this module, you need to: - -#. Do this ... - -Configuration -============= - -To configure this module, you need to: - -#. Go to ... - -.. figure:: path/to/local/image.png - :alt: alternative description - :width: 600 px - -Usage -===== - -To use this module, you need to: - -#. Go to ... - -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} - -.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt -.. branch is "8.0" for example - -Known issues / Roadmap -====================== - -* ... - -Bug Tracker -=========== - -Bugs are tracked on `GitHub Issues -`_. In case of trouble, please -check there if your issue has already been reported. If you spotted it first, -help us smash it by providing detailed and welcomed feedback. - -Credits -======= - -Images ------- - -* Odoo Community Association: `Icon `_. - -Contributors ------------- - -* Firstname Lastname -* Second Person - -Funders -------- - -The development of this module has been financially supported by: - -* Company 1 name -* Company 2 name - -Maintainer ----------- - -.. image:: https://odoo-community.org/logo.png - :alt: Odoo Community Association - :target: https://odoo-community.org - -This module is maintained by the OCA. - -OCA, or the Odoo Community Association, is a nonprofit organization whose -mission is to support the collaborative development of Odoo features and -promote its widespread use. - -To contribute to this module, please visit https://odoo-community.org. diff --git a/cnab_erpbrasil_febraban/febraban/boleto/__init__.py b/cnab_erpbrasil_febraban/febraban/boleto/__init__.py deleted file mode 100644 index 4338cb783c5d..000000000000 --- a/cnab_erpbrasil_febraban/febraban/boleto/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2012 KMEE -# @author Luis Felipe Miléo -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from . import document diff --git a/cnab_erpbrasil_febraban/febraban/boleto/document.py b/cnab_erpbrasil_febraban/febraban/boleto/document.py deleted file mode 100644 index 5e2862348a40..000000000000 --- a/cnab_erpbrasil_febraban/febraban/boleto/document.py +++ /dev/null @@ -1,350 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA (Luis Felipe Mileo mileo@kmee.com.br) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from datetime import datetime, date -import logging - -_logger = logging.getLogger(__name__) - -try: - from erpbrasil.febraban.boleto.banco import get_class_for_codigo - from erpbrasil.febraban.boleto.exceptions import BoletoException -except ImportError as err: - _logger.debug = err - -try: - from cStringIO import StringIO -except ImportError: - from io import StringIO - - -class Boleto: - boleto = object - account_number = '' - account_digit = '' - - branch_number = '' - branch_digit = '' - - nosso_numero = '' - - @staticmethod - def getBoleto(move_line, nosso_numero): - boleto_type = move_line.payment_mode_id.boleto_type - if boleto_type: - return dict_boleto[boleto_type][0](move_line, nosso_numero) - raise BoletoException(u'Configure o tipo de boleto no modo de ' - u'pagamento') - - @staticmethod - def getBoletoClass(move_line): - bank_code = \ - move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bank_id.code_bc - return get_class_for_codigo(bank_code) - - def __init__(self, move_line, nosso_numero): - self._cedente(move_line.company_id) - self._sacado(move_line.partner_id) - self._move_line(move_line) - self.nosso_numero = str(nosso_numero) - - def getAccountNumber(self): - if self.account_digit: - return str(self.account_number + '-' + - self.account_digit).encode('utf-8') - return self.account_number.encode('utf-8') - - def getBranchNumber(self): - if self.branch_digit: - return str(self.branch_number + '-' + - self.branch_digit).encode('utf-8') - return self.branch_number.encode('utf-8') - - def _move_line(self, move_line): - self._payment_mode(move_line.payment_mode_id) - self._instructions(move_line.instrucoes) - self.boleto.data_vencimento = datetime.date(datetime.strptime( - move_line.date_maturity, '%Y-%m-%d')) - self.boleto.data_documento = datetime.date(datetime.strptime( - move_line.invoice_id.date_invoice, '%Y-%m-%d')) - self.boleto.data_processamento = date.today() - self.boleto.valor = str("%.2f" % move_line.residual if - move_line.residual else - move_line.debit or move_line.credit) - self.boleto.valor_documento = str("%.2f" % move_line.residual if - move_line.residual else - move_line.debit or move_line.credit) - self.boleto.especie = \ - move_line.currency_id and move_line.currency_id.symbol or 'R$' - self.boleto.quantidade = '' # str("%.2f" % move_line.amount_currency) - self.boleto.numero_documento = move_line.numero_documento - - def _instructions(self, instrucoes): - """ - :param instrucoes: - :return: - """ - if instrucoes: - for instrucao in instrucoes.split('\n'): - self.boleto.instrucoes.append(instrucao) - - def _payment_mode(self, payment_mode_id): - """ - :param payment_mode: - :return: - """ - self.boleto.convenio = payment_mode_id.boleto_convenio - self.boleto.especie_documento = payment_mode_id.boleto_modalidade - self.boleto.aceite = payment_mode_id.boleto_aceite - self.boleto.carteira = str(payment_mode_id.boleto_carteira) - - def _cedente(self, company): - """ - :param company: - :return: - """ - self.boleto.cedente = company.partner_id.legal_name.encode('utf-8') - self.boleto.cedente_documento = company.cnpj_cpf.encode('utf-8') - self.boleto.cedente_bairro = company.district - self.boleto.cedente_cep = company.zip - self.boleto.cedente_cidade = company.l10n_br_city_id.name - self.boleto.cedente_logradouro = \ - company.street + ', ' + company.number - self.boleto.cedente_uf = company.state_id.code - self.boleto.agencia_cedente = self.getBranchNumber() - self.boleto.conta_cedente = self.getAccountNumber() - - def _sacado(self, partner): - """ - - :param partner: - :return: - """ - self.boleto.sacado_endereco = \ - partner.street + ', ' + partner.number - self.boleto.sacado_cidade = partner.l10n_br_city_id.name - self.boleto.sacado_bairro = partner.district or '' - self.boleto.sacado_uf = partner.state_id.code - self.boleto.sacado_cep = partner.zip - self.boleto.sacado_nome = partner.legal_name - self.boleto.sacado_documento = partner.cnpj_cpf - - @classmethod - def get_pdfs(cls, boleto_list): - """ - - :param boletoList: - :return: - """ - fbuffer = StringIO() - - fbuffer.reset() - from pyboleto.pdf import BoletoPDF - - boleto = BoletoPDF(fbuffer) - for i in range(len(boleto_list)): - boleto.drawBoleto(boleto_list[i]) - boleto.nextPage() - boleto.save() - boleto_file = fbuffer.getvalue() - - fbuffer.close() - return boleto_file - - -class BoletoBB(Boleto): - - def __init__(self, move_line, nosso_numero): - # TODO: size o convenio and nosso numero, replace (7,2) - # Size of convenio 4, 6, 7 or 8 - # Nosso Numero format. 1 or 2 - # Used only for convenio=6 - # 1: Nosso Numero with 5 positions - # 2: Nosso Numero with 17 positions - self.boleto = Boleto.getBoletoClass(move_line)(7, 2) - self.account_number = \ - move_line.payment_mode_id.fixed_journal_id. \ - bank_account_id.acc_number - self.branch_number = \ - move_line.payment_mode_id.fixed_journal_id. \ - bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoBarisul(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = \ - move_line.payment_mode_id.fixed_journal_id. \ - bank_account_id.acc_number - self.branch_number = \ - move_line.payment_mode_id.fixed_journal_id. \ - bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoBradesco(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = \ - move_line.payment_mode_id.fixed_journal_id. \ - bank_account_id.acc_number - self.branch_number = \ - move_line.payment_mode_id.fixed_journal_id. \ - bank_account_id.bra_number - # bank specific - self.account_digit = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number_dig - self.branch_digit = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number_dig - # end bank specific - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoCaixa(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - # bank specific - self.account_digit = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number_dig - # end bank specific - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoHsbc(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoItau157(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoItau(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoReal(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoSantander101(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.ios = '0' - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoStatander101201(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.ios = '0' - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoCaixaSigcb(Boleto): - - def __init__(self, move_line, nosso_numero): - from pyboleto.bank.caixa_sigcb import BoletoCaixaSigcb - self.boleto = BoletoCaixaSigcb() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - # bank specific - self.account_digit = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number_dig - # end bank specific - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -class BoletoSicredi(Boleto): - - def __init__(self, move_line, nosso_numero): - self.boleto = Boleto.getBoletoClass(move_line)() - self.account_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.acc_number - self.branch_number = move_line.payment_mode_id. \ - fixed_journal_id.bank_account_id.bra_number - Boleto.__init__(self, move_line, nosso_numero) - self.boleto.nosso_numero = self.nosso_numero - - -dict_boleto = { - '1': (BoletoBB, 'Banco do Brasil 18'), - '2': (BoletoBarisul, 'Barisul x'), - '3': (BoletoBradesco, 'Bradesco 06, 03'), - '4': (BoletoCaixa, 'Caixa Economica SR'), - '5': (BoletoHsbc, 'HSBC CNR CSB'), - '6': (BoletoItau157, 'Itau 157'), - '7': (BoletoItau, 'Itau 175, 174, 178, 104, 109'), - '8': (BoletoReal, 'Real 57'), - '9': (BoletoSantander101, 'Santander 102'), - '10': (BoletoStatander101201, 'Santander 101, 201'), - '11': (BoletoCaixaSigcb, 'Caixa Sigcb'), - '12': (BoletoSicredi, 'Sicredi'), -} - - -def getBoletoSelection(): - list = [] - for i in dict_boleto: - list.append((i, dict_boleto[i][1])) - return list diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py deleted file mode 100644 index 7813b32b4bc8..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py deleted file mode 100644 index 2cfbd6d7e782..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py deleted file mode 100644 index 5826a47b9484..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bb.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from __future__ import division, print_function, unicode_literals - -import re -import string - -from ..cnab_240 import Cnab240 - - -class BB240(Cnab240): - - def __init__(self): - super(Cnab240, self).__init__() - from cnab240.bancos import bancodobrasil - self.bank = bancodobrasil - - def _prepare_header(self): - """ - Preparar header do arquivo. - Adicionar informações no header do arquivo do Banco do Brasil - """ - vals = super(BB240, self)._prepare_header() - # vals['servico_servico'] = 1 - return vals - - def _prepare_cobranca(self, line): - """ - Preparar o evento (segmentoA e segmentoB) apartir da payment.line - :param line - payment.line - :return: dict - Informações - """ - vals = super(BB240, self)._prepare_cobranca(line) - # vals['prazo_baixa'] = unicode(str( - # vals['prazo_baixa']), "utf-8") - # vals['desconto1_percentual'] = Decimal('0.00') - # vals['valor_iof'] = Decimal('0.00') - # # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') - # vals['identificacao_titulo_banco'] = self.convert_int( - # vals['identificacao_titulo_banco']) - # vals['cedente_conta_dv'] = unicode(str( - # vals['cedente_conta_dv']), "utf-8") - # vals['cedente_agencia_dv'] = unicode(str( - # vals['cedente_agencia_dv']), "utf-8") - # vals['cedente_dv_ag_cc'] = unicode(str( - # vals['cedente_dv_ag_cc']), "utf-8") - return vals - - # Override cnab_240.nosso_numero. Diferentes números de dígitos entre - # CEF e Itau - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito - - def str_to_unicode(inp_str): - inp_str = unicode(inp_str, "utf-8") - return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py deleted file mode 100644 index 7f9d5eb282b5..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import re -import string -from decimal import Decimal - -from ..cnab_240 import Cnab240 - - -class Bradesco240(Cnab240): - - def __init__(self): - super(Cnab240, self).__init__() - from cnab240.bancos import bradesco - self.bank = bradesco - - def _prepare_header(self): - """ - - :param order: - :return: - """ - - vals = super(Bradesco240, self)._prepare_header() - vals['servico_servico'] = 1 - return vals - - def _prepare_cobranca(self, line): - """ - - :param line: - :return: - """ - vals = super(Bradesco240, self)._prepare_cobranca(line) - vals['prazo_baixa'] = unicode(str( - vals['prazo_baixa']), "utf-8") - vals['desconto1_percentual'] = Decimal('0.00') - vals['valor_iof'] = Decimal('0.00') - # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') - vals['identificacao_titulo_banco'] = self.convert_int( - vals['identificacao_titulo_banco']) - vals['cedente_conta_dv'] = unicode(str( - vals['cedente_conta_dv']), "utf-8") - vals['cedente_agencia_dv'] = unicode(str( - vals['cedente_agencia_dv']), "utf-8") - vals['cedente_dv_ag_cc'] = unicode(str( - vals['cedente_dv_ag_cc']), "utf-8") - return vals - - # Override cnab_240.nosso_numero. Diferentes números de dígitos entre - # CEF e Itau - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito - - -def str_to_unicode(inp_str): - inp_str = unicode(inp_str, "utf-8") - return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig deleted file mode 100644 index 95d4537a20cb..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/bradesco.py.orig +++ /dev/null @@ -1,71 +0,0 @@ -# coding: utf-8 -# ########################################################################### -# -# Author: Luis Felipe Mileo -# Fernando Marcato Rodrigues -# Daniel Sadamo Hirayama -# Copyright 2015 KMEE - www.kmee.com.br -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - - -from ..cnab_240 import Cnab240 -import re -import string -from decimal import Decimal - - -class Bradesco240(Cnab240): -<<<<<<< HEAD -======= - ->>>>>>> [FIX] pep8 and merge clear - def __init__(self): - super(Cnab240, self).__init__() - from cnab240.bancos import bradesco - self.bank = bradesco - - def _prepare_header(self): - """ - - :param order: - :return: - """ - vals = super(Bradesco240, self)._prepare_header() - return vals - - def _prepare_segmento(self, line): - """ - - :param line: - :return: - """ - vals = super(Bradesco240, self)._prepare_segmento(line) - vals['prazo_baixa'] = unicode(str( - vals['prazo_baixa']), "utf-8") - vals['desconto1_percentual'] = Decimal('0.00') - vals['valor_iof'] = Decimal('0.00') - vals['cobrancasimples_valor_titulos'] = Decimal('02.00') - return vals - - # Override cnab_240.nosso_numero. Diferentes números de dígitos entre - # CEF e Itau - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py deleted file mode 100644 index 7e6e1c03ccd2..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/cef.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import re -import string -from decimal import Decimal - -from ..cnab_240 import Cnab240 - - -class Cef240(Cnab240): - - def __init__(self): - super(Cnab240, self).__init__() - from cnab240.bancos import cef - self.bank = cef - - def _prepare_header(self): - """ - - :return: - """ - vals = super(Cef240, self)._prepare_header() - vals['cedente_dv_ag_cc'] = unicode(str( - vals['cedente_dv_ag_cc']), "utf-8") - vals['cedente_agencia_dv'] = unicode(str( - vals['cedente_agencia_dv']), "utf-8") - # TODO: adicionar campo para preencher o codigo do cedente no - # cadastro da conta bancária - vals['cedente_codigo_codCedente'] = 6088 - vals['nome_do_banco'] = u'CAIXA ECONOMICA FEDERAL' - # Não pode pegar comentário da payment_line. - vals['reservado_cedente_campo23'] = u'REMESSA TESTE' - # reservado_banco_campo22 não é required. Código atualizado na - # biblioteca cnab240 - vals['data_credito_hd_lote'] = 15052015 - - return vals - - def _prepare_cobranca(self, line): - """ - - :param line: - :return: - """ - vals = super(Cef240, self)._prepare_cobranca(line) - - carteira, nosso_numero, digito = self.nosso_numero( - line.move_line_id.transaction_ref) - - vals['cedente_dv_ag_cc'] = unicode(str( - vals['cedente_dv_ag_cc']), "utf-8") - # Informar o Número do Documento - Seu Número (mesmo das posições - # 63-73 do Segmento P) - vals['identificacao_titulo'] = unicode(str( - vals['numero_documento']), "utf-8") - # TODO: campo 27.3P CEF. Código do juros de mora - vals['juros_cod_mora'] = 3 - vals['carteira_numero'] = self.convert_int(carteira) - vals['nosso_numero'] = self.convert_int(nosso_numero) - vals['nosso_numero_dv'] = self.convert_int(digito) - vals['prazo_baixa'] = unicode(str( - vals['prazo_baixa']), "utf-8") - - # Precisam estar preenchidos - # Header lote - # vals['servico_operacao'] = u'R' - # vals['servico_servico'] = 1 - vals['cedente_conta_dv'] = unicode(str( - vals['cedente_conta_dv']), "utf-8") - vals['cedente_codigo_codCedente'] = 6088 - vals['data_credito_hd_lote'] = 15052015 - - vals['desconto1_cod'] = 3 - vals['desconto1_data'] = 0 - vals['desconto1_percentual'] = Decimal('0.00') - vals['valor_iof'] = Decimal('0.00') - - return vals - - # Override cnab_240.nosso_numero. Diferentes números de dígitos entre - # CEF e Itau - def nosso_numero(self, format): - digito = format[-1:] - carteira = 14 - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py deleted file mode 100644 index 0ebb6a40e564..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/itau.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import re -import string - -from ..cnab_240 import Cnab240 - - -class Itau240(Cnab240): - """ - - """ - - def __init__(self): - """ - - :return: - """ - super(Cnab240, self).__init__() - from cnab240.bancos import itau - self.bank = itau - - def _prepare_header(self): - """ - - :param order: - :return: - """ - vals = super(Itau240, self)._prepare_header() - # vals['cedente_dv_ag_cc'] = self.convert_int( - # vals['cedente_dv_ag_cc']) - # vals['cedente_agencia_dv'] = self.convert_int( - # vals['cedente_agencia_dv']), - return vals - - def _prepare_cobranca(self, line): - """ - - :param line: - :return: - """ - vals = super(Itau240, self)._prepare_cobranca(line) - - carteira, nosso_numero, digito = self.nosso_numero( - line.move_line_id.transaction_ref) - - vals['cedente_dv_ag_cc'] = self.convert_int( - vals['cedente_dv_ag_cc']) - vals['carteira_numero'] = self.convert_int(carteira) - vals['nosso_numero'] = self.convert_int(nosso_numero) - vals['nosso_numero_dv'] = self.convert_int(digito) - - return vals - - # Override cnab_240.nosso_numero. Diferentes números de dígitos entre - # CEF e Itau - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py b/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py deleted file mode 100644 index e04fc80fb92c..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/bancos/santander.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from ..cnab_240 import Cnab240 - - -class Santander240(Cnab240): - """ - - """ - - def __init__(self): - """ - - :return: - """ - super(Cnab240, self).__init__() - from cnab240.bancos import santander - self.bank = santander - - def _prepare_header(self): - """ - - :param order: - :return: - """ - vals = super(Santander240, self)._prepare_header() - del vals['arquivo_hora_de_geracao'] - return vals - - def _prepare_cobranca(self, line): - """ - - :param line: - :return: - """ - vals = super(Santander240, self)._prepare_cobranca(line) - return vals diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py deleted file mode 100644 index 1d3b4168aa42..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py +++ /dev/null @@ -1,582 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from __future__ import division, print_function, unicode_literals - -import datetime -import logging -import re -import string -import time -import unicodedata -from decimal import Decimal - - -from ..cnab import Cnab - -_logger = logging.getLogger(__name__) -try: - from erpbrasi.febraban.cnab.tipos import Arquivo, Lote -except ImportError as err: - _logger.debug = err - - -class Cnab240(Cnab): - """ - CNAB240 - """ - - def __init__(self): - super(Cnab, self).__init__() - - @staticmethod - def get_bank(bank): - ''' - Função chamada na criação do CNAB que dado o código do banco, - instancia o objeto do banco e retorna o obj ao CNAB que sera criado. - :param bank: str - Código do banco - :return: - ''' - # 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 == '001': - # from .bancos.bb import BB240 - # return BB240 - # else: - return Cnab240 - - def get_inscricao_tipo(self, partner_id): - # TODO: Implementar codigo para PIS/PASEP - if partner_id.is_company: - return 2 - else: - return 1 - - def _prepare_header(self): - """ - Preparar o header do arquivo do CNAB - :return: dict - Header do arquivo - """ - header_arquivo = { - # CONTROLE - # 01.0 - 'controle_banco': self.convert_int( - self.order.company_partner_bank_id.bank_id.code_bc - ), - # 02.0 # Sequencia para o Arquivo - 'controle_lote': 1, - # 03.0 0- Header do Arquivo - 'controle_registro': 0, - # 04.0 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - - # EMPRESA - # 05.0 - 1 - CPF / 2 - CNPJ - 'cedente_inscricao_tipo': - self.get_inscricao_tipo(self.order.company_id.partner_id), - # 06.0 - 'cedente_inscricao_numero': - self.convert_int(punctuation_rm(self.order.company_id.cnpj_cpf)), - # 07.0 - 'cedente_convenio': '0001222130126', - # 08.0 - 'cedente_agencia': - self.convert_int(self.order.company_partner_bank_id.bra_number), - # 09.0 - 'cedente_agencia_dv': - self.order.company_partner_bank_id.bra_number_dig, - # 10.0 - 'cedente_conta': - self.convert_int(punctuation_rm( - self.order.company_partner_bank_id.acc_number)), - # 11.0 - 'cedente_conta_dv': - self.order.company_partner_bank_id.acc_number_dig[0], - # 12.0 - 'cedente_agencia_conta_dv': - self.order.company_partner_bank_id.acc_number_dig[1] - if len( - self.order.company_partner_bank_id.acc_number_dig - ) > 1 else '', - # 13.0 - 'cedente_nome': - self.order.company_partner_bank_id.partner_id.legal_name[:30] - if self.order.company_partner_bank_id.partner_id.legal_name - else self.order.company_partner_bank_id.partner_id.name[:30], - # 14.0 - 'nome_banco': self.order.company_partner_bank_id.bank_name, - # 15.0 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - - # ARQUIVO - # 16.0 Código Remessa = 1 / Retorno = 2 - 'arquivo_codigo': '1', - # 17.0 - 'arquivo_data_de_geracao': self.data_hoje(), - # 18.0 - 'arquivo_hora_de_geracao': self.hora_agora(), - # 19.0 TODO: Número sequencial de arquivo - 'arquivo_sequencia': self.convert_int(self.get_file_numeration()), - # 20.0 - 'arquivo_layout': 103, - # 21.0 - 'arquivo_densidade': 0, - # 22.0 - 'reservado_banco': '', - # 23.0 - 'reservado_empresa': 'EMPRESA 100', - # 24.0 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - } - - return header_arquivo - - def _prepare_header_lote(self): - """ - Preparar o header de LOTE para arquivo do CNAB - :return: dict - Header do arquivo - """ - empresa = self.order.company_partner_bank_id.partner_id - - header_arquivo_lote = { - - # CONTROLE - # 01.1 - 'controle_banco': self.convert_int(self.order.company_partner_bank_id.code_bc), - # 02.1 Sequencia para o Arquivo - 'controle_lote': 1, - # 03.1 0- Header do Arquivo - 'controle_registro': 1, - - # SERVICO - # 04.1 # Header do lote sempre 'C' - 'servico_operacao': 'C', - # 05.1 - 'servico_servico': self.order.tipo_servico, - # 06.1 - 'servico_forma_lancamento': 1, - # 07.1 - 'servico_layout': 20, - # 08.1 - # CNAB - Uso Exclusivo da FEBRABAN/CNAB - - # EMPRESA CEDENTE - # 09.1 - 'empresa_inscricao_tipo': 2, - # self.get_inscricao_tipo(self.order.company_id.partner_id), - # 10.1 - 'empresa_inscricao_numero': punctuation_rm(empresa.cnpj_cpf), - # 11.1 - 'cedente_convenio': self.order.codigo_convenio, - # 12.1 - 'cedente_agencia': - self.convert_int(self.order.company_partner_bank_id.bra_number), - # 13.1 - 'cedente_agencia_dv': - self.order.company_partner_bank_id.bra_number_dig, - # 14.1 - 'cedente_conta': - self.convert_int(punctuation_rm( - self.order.company_partner_bank_id.acc_number)), - # 15.1 - 'cedente_conta_dv': - self.order.company_partner_bank_id.acc_number_dig[0], - # 16.1 - 'cedente_agencia_conta_dv': - self.order.company_partner_bank_id.acc_number_dig[1] - if len( - self.order.company_partner_bank_id.acc_number_dig - ) > 1 else '', - # 17.1 - 'cedente_nome': - self.order.company_partner_bank_id.partner_id.legal_name[:30] - if self.order.company_partner_bank_id.partner_id.legal_name - else self.order.company_partner_bank_id.partner_id.name[:30], - # 18.1 - 'mensagem1': '', - - # ENDERECO - # 19.1 - 'empresa_logradouro': empresa.street, - # 20.1 - 'empresa_endereco_numero': empresa.number, - # 21.1 - 'empresa_endereco_complemento': empresa.street2, - # 22.1 - 'empresa_endereco_cidade': empresa.l10n_br_city_id.name, - # 23.1 - 'empresa_endereco_cep': self.get_cep('prefixo', empresa.zip), - # 24.1 - 'empresa_endereco_cep_complemento': - self.get_cep('sufixo', empresa.zip), - # 25.1 - 'empresa_endereco_estado': empresa.state_id.code, - - # 26.1 - 'indicativo_forma_pagamento': '', - # 27.1 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - # 28.1 - 'ocorrencias': '', - } - return header_arquivo_lote - - def get_file_numeration(self): - # Função para retornar a numeração sequencial do arquivo - return 1 - - def _prepare_cobranca(self, line): - """ - :param line: - :return: - """ - # prefixo, sufixo = self.cep(line.partner_id.zip) - - aceite = u'N' - 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': self.convert_int( - self.order.company_partner_bank_id.code_bc), - 'cedente_agencia': self.convert_int( - self.order.company_partner_bank_id.bra_number), - 'cedente_conta': self.convert_int( - self.order.company_partner_bank_id.acc_number), - 'cedente_conta_dv': - self.order.company_partner_bank_id.acc_number_dig, - 'cedente_agencia_dv': - self.order.company_partner_bank_id.bra_number_dig, - 'identificacao_titulo': u'0000000', # TODO - 'identificacao_titulo_banco': u'0000000', # TODO - 'identificacao_titulo_empresa': line.move_line_id.move_id.name, - 'numero_documento': line.name, - 'vencimento_titulo': self.format_date( - line.ml_maturity_date), - 'valor_titulo': Decimal(str(line.amount_currency)).quantize( - Decimal('1.00')), - # TODO: fépefwfwe - # TODO: Código adotado para identificar o título de cobrança. - # 8 é Nota de cŕedito comercial - 'especie_titulo': self.convert_int(self.order.payment_mode_id.boleto_especie), - 'aceite_titulo': aceite, - 'data_emissao_titulo': self.format_date( - line.ml_date_created), - # 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.ml_maturity_date), - 'juros_mora_taxa_dia': Decimal('0.00'), - 'valor_abatimento': Decimal('0.00'), - 'sacado_inscricao_tipo': self.convert_int( - self.get_inscricao_tipo(line.partner_id)), - 'sacado_inscricao_numero': line.partner_id.cnpj_cpf and self.convert_int( - punctuation_rm(line.partner_id.cnpj_cpf)) or '', - 'sacado_nome': line.partner_id.legal_name, - 'sacado_endereco': ( - line.partner_id.street + ' ' + line.partner_id.number), - 'sacado_bairro': line.partner_id.district or '', - 'sacado_cep': - self.get_cep('prefixo', line.partner_id.zip), - 'sacado_cep_sufixo': - self.get_cep('sufixo', line.partner_id.zip), - 'sacado_cidade': line.partner_id.l10n_br_city_id.name, - 'sacado_uf': line.partner_id.state_id.code, - 'codigo_protesto': - self.convert_int(self.order.payment_mode_id.boleto_protesto), - 'prazo_protesto': - self.convert_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': - self.convert_int(self.order.payment_mode_id.boleto_carteira), - } - - def _prepare_pagamento(self, line): - """ - Prepara um dict para preencher os valores do segmento A e B apartir de - uma linha da payment.order e insere informações que irão compor o - header do lote - :param line: payment.line - linha que sera base para evento - :return: dict - Dict contendo todas informações dos segmentos - """ - vals = { - - # SEGMENTO A - # CONTROLE - # 01.3A - 'controle_banco': - self.convert_int(self.order.company_partner_bank_id.code_bc), - # 02.3A - 'controle_lote': 1, - # 03.3A - 3-Registros Iniciais do Lote - 'controle_registro': 3, - - # SERVICO - # 04.3A - Nº Seqüencial do Registro - Inicia em 1 em cada novo lote - # TODO: Contador para o sequencial do lote - 'servico_numero_registro': 1, - # 05.3A - # Segmento Código de Segmento do Reg.Detalhe - # 06.3A - 'servico_tipo_movimento': self.order.tipo_movimento, - # 07.3A - 'servico_codigo_movimento': self.order.codigo_instrucao_movimento, - - # FAVORECIDO - # 08.3A - 018-TED 700-DOC - 'favorecido_camara': 0, - # 09.3A - 'favorecido_banco': self.convert_int(line.bank_id.code_bc), - # 10.3A - 'favorecido_agencia': self.convert_int(line.bank_id.bra_number), - # 11.3A - 'favorecido_agencia_dv': line.bank_id.bra_number_dig, - # 12.3A - 'favorecido_conta': punctuation_rm(line.bank_id.acc_number), - # 13.3A - 'favorecido_conta_dv': line.bank_id.acc_number_dig[0] - if line.bank_id.acc_number_dig else '', - # 14.3A - 'favorecido_dv': line.bank_id.acc_number_dig[1] - if len(line.bank_id.bra_number_dig or '') > 1 else '', - # 15.3A - 'favorecido_nome': line.partner_id.name, - - # CREDITO - # 16.3A - - 'credito_seu_numero': line.name, - # 17.3A - 'credito_data_pagamento': self.format_date(line.date), - # 18.3A - 'credito_moeda_tipo': line.currency.name, - # 19.3A - 'credito_moeda_quantidade': Decimal('0.00000'), - # 20.3A - 'credito_valor_pagamento': - Decimal(str(line.amount_currency)).quantize(Decimal('1.00')), - # 21.3A - # 'credito_nosLoteso_numero': '', - # 22.3A - # 'credito_data_real': '', - # 23.3A - # 'credito_valor_real': '', - - # INFORMAÇÔES - # 24.3A - # 'outras_informacoes': '', - # 25.3A - # 'codigo_finalidade_doc': line.codigo_finalidade_doc, - # 26.3A - 'codigo_finalidade_ted': line.codigo_finalidade_ted or '', - # 27.3A - 'codigo_finalidade_complementar': - line.codigo_finalidade_complementar or '', - # 28.3A - # CNAB - Uso Exclusivo FEBRABAN/CNAB - # 29.3A - # 'aviso_ao_favorecido': line.aviso_ao_favorecido, - 'aviso_ao_favorecido': 0, - # 'ocorrencias': '', - - # SEGMENTO B - # Preenchido no segmento A - # 01.3B - # 02.3B - # 03.3B - - # 04.3B - # 05.3B - # 06.3B - - # DADOS COMPLEMENTARES - FAVORECIDOS - # 07.3B - 'favorecido_tipo_inscricao': - self.get_inscricao_tipo(line.partner_id), - # 08.3B - 'favorecido_num_inscricao': line.partner_id.cnpj_cpf and - self.convert_int(punctuation_rm(line.partner_id.cnpj_cpf)) or '', - # 09.3B - 'favorecido_endereco_rua': line.partner_id.street or '', - # 10.3B - 'favorecido_endereco_num': self.convert_int(line.partner_id.number) or 0, - # 11.3B - 'favorecido_endereco_complemento': line.partner_id.street2 or '', - # 12.3B - 'favorecido_endereco_bairro': line.partner_id.district or '', - # 13.3B - 'favorecido_endereco_cidade': - line.partner_id.l10n_br_city_id.name or '', - # 14.3B - # 'favorecido_cep': self.convert_int(line.partner_id.zip[:5]) or 0, - 'favorecido_cep': self.get_cep('prefixo', line.partner_id.zip), - # 15.3B - 'favorecido_cep_complemento': - self.get_cep('sufixo', line.partner_id.zip), - # 16.3B - 'favorecido_estado': line.partner_id.state_id.code or '', - - # DADOS COMPLEMENTARES - PAGAMENTO - # 17.3B - 'pagamento_vencimento': 0, - # 18.3B - 'pagamento_valor_documento': Decimal('0.00'), - # 19.3B - 'pagamento_abatimento': Decimal('0.00'), - # 20.3B - 'pagamento_desconto': Decimal('0.00'), - # 21.3B - 'pagamento_mora': Decimal('0.00'), - # 22.3B - 'pagamento_multa': Decimal('0.00'), - # 23.3B - # TODO: Verificar se este campo é retornado no retorno - # 'cod_documento_favorecido': '', - # 24.3B - Informado No SegmentoA - # 'aviso_ao_favorecido': '0', - # 25.3B - # 'codigo_ug_centralizadora': '0', - # 26.3B - # 'codigo_ispb': '0', - } - return vals - - def _adicionar_evento(self, line): - """ - Adicionar o evento no arquivo de acordo com seu tipo - """ - # if self.order.payment_order_type == 'payment': - # incluir = self.arquivo.incluir_debito_pagamento - # prepare = self._prepare_pagamento - # else: - # incluir = self.arquivo.incluir_cobranca - # prepare = self._prepare_cobranca - pass - - def remessa(self, order): - """ - Cria a remessa de eventos que sera anexada ao arquivo - :param order: payment.order - :return: Arquivo Cnab pronto para download - """ - self.order = order - - if not (self.order.company_partner_bank_id and - self.order.company_partner_bank_id.bank_id - ): - raise NotImplementedError - - bank_id = self.order.company_partner_bank_id.bank_id - - - - # self.bank = - - # Preparar Header do Arquivo - self.arquivo = Arquivo(self.bank, **self._prepare_header()) - - if order.payment_order_type == 'payment': - incluir = self.arquivo.incluir_debito_pagamento - prepare = self._prepare_pagamento - - header = self.bank.registros.HeaderLotePagamento( - **self._prepare_header_lote()) - - trailer = self.bank.registros.TrailerLotePagamento() - trailer.somatoria_valores = Decimal('0.00') - trailer.somatoria_quantidade_moedas = Decimal('0.00000') - - lote_pagamento = Lote(self.bank, header, trailer) - self.arquivo.adicionar_lote(lote_pagamento) - - else: - incluir = self.arquivo.incluir_cobranca - prepare = self._prepare_cobranca - - for line in order.bank_line_ids: - # para cada linha da payment order adicoinar como um novo evento - # self._adicionar_evento(line) - # try: - incluir(tipo_lote=30, **prepare(line)) - # except: - # from odoo import exceptions - # raise exceptions.ValidationError("Erro") - # self.arquivo.lotes[0].header.servico_servico = 30 - # TODO: tratar soma de tipos de cobranca - # cobrancasimples_valor_titulos += line.amount_currency - # 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 get_cep(self, tipo, value): - ''' - :param tipo: - :param value: - :return: - ''' - if not value: - if tipo == 'prefixo': - return 0 - else: - return '' - value = punctuation_rm(value) - sufixo = value[-3:] - prefixo = value[:5] - if tipo == 'sufixo': - return sufixo - else: - return prefixo - - def format_date(self, srt_date): - if not srt_date: - return 0 - return self.convert_int(datetime.datetime.strptime( - srt_date, '%Y-%m-%d').strftime('%d%m%Y')) - - def data_hoje(self): - return (self.convert_int(time.strftime("%d%m%Y"))) - - def hora_agora(self): - return (self.convert_int(time.strftime("%H%M%S"))) - - def nosso_numero(self, format): - """ - Hook para ser sobrescrito e adicionar informação - :param format: - :return: - """ - pass diff --git a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig b/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig deleted file mode 100644 index 1fabc0a2c0b9..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_240/cnab_240.py.orig +++ /dev/null @@ -1,566 +0,0 @@ -# coding: utf-8 -# ########################################################################### -# -# Author: Luis Felipe Mileo -# Fernando Marcato Rodrigues -# Daniel Sadamo Hirayama -# Copyright 2015 KMEE - www.kmee.com.br -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from __future__ import division, print_function, unicode_literals - -import datetime -import logging -import re -import string -import time -import unicodedata -from decimal import Decimal - -from openerp.addons.l10n_br_base.tools.misc import punctuation_rm - -from ..cnab import Cnab - -_logger = logging.getLogger(__name__) -try: -<<<<<<< HEAD - from cnab240.tipos import Arquivo - from cnab240.errors import (Cnab240Error) -======= - from cnab240.tipos import Arquivo, Lote ->>>>>>> fixup! [FIX] Flake8 -except ImportError as err: - _logger.debug = err - - -class Cnab240(Cnab): - """ - CNAB240 - """ - - def __init__(self): - super(Cnab, self).__init__() - - @staticmethod - def get_bank(bank): - ''' - Função chamada na criação do CNAB que dado o código do banco, - instancia o objeto do banco e retorna o obj ao CNAB que sera criado. - :param bank: str - Código do banco - :return: - ''' - 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 == '001': - from .bancos.bb import BB240 - return BB240 - else: - return Cnab240 - - def inscricao_tipo(self, partner_id): - # TODO: Implementar codigo para PIS/PASEP - if partner_id.is_company: - return 2 - else: - return 1 - - def _prepare_header(self): - """ - Preparar o header do arquivo do CNAB - :return: dict - Header do arquivo - """ - header_arquivo = { - # CONTROLE - # 01.0 - 'controle_banco': int(self.order.mode.bank_id.bank_bic), - # 02.0 # Sequencia para o Arquivo - 'controle_lote': 1, - # 03.0 0- Header do Arquivo - 'controle_registro': 0, - # 04.0 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - - # EMPRESA - # 05.0 - 1 - CPF / 2 - CNPJ - 'cedente_inscricao_tipo': - self.get_inscricao_tipo(self.order.company_id.partner_id), - # 06.0 - 'cedente_inscricao_numero': - int(punctuation_rm(self.order.company_id.cnpj_cpf)), - # 07.0 - 'cedente_convenio': '0001222130126', - # 08.0 - 'cedente_agencia': - int(self.order.mode.bank_id.bra_number), - # 09.0 - 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, - # 10.0 - 'cedente_conta': int(self.order.mode.bank_id.acc_number), - # 11.0 - 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], - # 12.0 - 'cedente_agencia_conta_dv': - self.order.mode.bank_id.acc_number_dig[1] - if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', - # 13.0 - 'cedente_nome': - self.order.mode.bank_id.partner_id.legal_name[:30], - # 14.0 - 'nome_banco': self.order.mode.bank_id.bank_name, - # 15.0 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - - # ARQUIVO - # 16.0 Código Remessa = 1 / Retorno = 2 - 'arquivo_codigo': '1', - # 17.0 - 'arquivo_data_de_geracao': self.data_hoje(), - # 18.0 - 'arquivo_hora_de_geracao': self.hora_agora(), - # 19.0 TODO: Número sequencial de arquivo - 'arquivo_sequencia': int(self.get_file_numeration()), - # 20.0 - 'arquivo_layout': 103, - # 21.0 - 'arquivo_densidade': 0, - # 22.0 - 'reservado_banco': '', - # 23.0 - 'reservado_empresa': 'EMPRESA 100', - # 24.0 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - } - - return header_arquivo - - def _prepare_header_lote(self): - """ - Preparar o header de LOTE para arquivo do CNAB - :return: dict - Header do arquivo - """ - empresa = self.order.mode.bank_id.partner_id - - header_arquivo_lote = { - - # CONTROLE - # 01.1 - 'controle_banco': int(self.order.mode.bank_id.bank_bic), - # 02.1 Sequencia para o Arquivo - 'controle_lote': 1, - # 03.1 0- Header do Arquivo - 'controle_registro': 1, - - # SERVICO - # 04.1 # Header do lote sempre 'C' - 'servico_operacao': 'C', - # 05.1 - 'servico_servico': self.order.tipo_servico, - # 06.1 - 'servico_forma_lancamento': 1, - # 07.1 - 'servico_layout': 20, - # 08.1 - # CNAB - Uso Exclusivo da FEBRABAN/CNAB - - # EMPRESA CEDENTE - # 09.1 - 'empresa_inscricao_tipo': 2, - # self.get_inscricao_tipo(self.order.company_id.partner_id), - # 10.1 - 'empresa_inscricao_numero': punctuation_rm(empresa.cnpj_cpf), - # 11.1 - 'cedente_convenio': self.order.codigo_convenio, - # 12.1 - 'cedente_agencia': - int(self.order.mode.bank_id.bra_number), - # 13.1 - 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, - # 14.1 - 'cedente_conta': int(self.order.mode.bank_id.acc_number), - # 15.1 - 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], - # 16.1 - 'cedente_agencia_conta_dv': - self.order.mode.bank_id.acc_number_dig[1] - if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', - # 17.1 - 'cedente_nome': - self.order.mode.bank_id.partner_id.legal_name[:30], - # 18.1 - 'mensagem1': '', - - # ENDERECO - # 19.1 - 'empresa_logradouro': empresa.street, - # 20.1 - 'empresa_endereco_numero': empresa.number, - # 21.1 - 'empresa_endereco_complemento': empresa.street2, - # 22.1 - 'empresa_endereco_cidade': empresa.l10n_br_city_id.name, - # 23.1 - 'empresa_endereco_cep': self.get_cep('prefixo', empresa.zip), - # 24.1 - 'empresa_endereco_cep_complemento': - self.get_cep('sufixo', empresa.zip), - # 25.1 - 'empresa_endereco_estado': empresa.state_id.code, - - # 26.1 - 'indicativo_forma_pagamento': '', - # 27.1 - # CNAB - Uso Exclusivo FEBRABAN / CNAB - # 28.1 - 'ocorrencias': '', - } - return header_arquivo_lote - - def get_file_numeration(self): - # Função para retornar a numeração sequencial do arquivo - return 1 - - def sacado_inscricao_tipo(self, partner_id): - # TODO: Implementar codigo para PIS/PASEP - if partner_id.is_company: - return 2 - else: - return 1 - - def _prepare_cobranca(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 { - '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, - 'identificacao_titulo': u'0000000', # TODO - 'identificacao_titulo_banco': u'0000000', # TODO - 'identificacao_titulo_empresa': line.move_line_id.move_id.name, - 'numero_documento': line.name, - 'vencimento_titulo': self.format_date( - line.ml_maturity_date), - 'valor_titulo': Decimal(str(line.amount_currency)).quantize( - Decimal('1.00')), - # TODO: fépefwfwe - # 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), - # 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.ml_maturity_date), - '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 _prepare_pagamento(self, line): - """ - Prepara um dict para preencher os valores do segmento A e B apartir de - uma linha da payment.order e insere informações que irão compor o - header do lote - :param line: payment.line - linha que sera base para evento - :return: dict - Dict contendo todas informações dos segmentos - """ - vals = { - - # SEGMENTO A - # CONTROLE - # 01.3A - 'controle_banco': int(self.order.mode.bank_id.bank_bic), - # 02.3A - 'controle_lote': 1, - # 03.3A - 3-Registros Iniciais do Lote - 'controle_registro': 3, - - # SERVICO - # 04.3A - Nº Seqüencial do Registro - Inicia em 1 em cada novo lote - # TODO: Contador para o sequencial do lote - 'servico_numero_registro': 1, - # 05.3A - # Segmento Código de Segmento do Reg.Detalhe - # 06.3A - 'servico_tipo_movimento': self.order.tipo_movimento, - # 07.3A - 'servico_codigo_movimento': self.order.codigo_instrucao_movimento, - - # FAVORECIDO - # 08.3A - 018-TED 700-DOC - 'favorecido_camara': 0, - # 09.3A - 'favorecido_banco': int(line.bank_id.bank_bic), - # 10.3A - 'favorecido_agencia': int(line.bank_id.bra_number), - # 11.3A - 'favorecido_agencia_dv': line.bank_id.bra_number_dig, - # 12.3A - 'favorecido_conta': punctuation_rm(line.bank_id.acc_number), - # 13.3A - 'favorecido_conta_dv': line.bank_id.acc_number_dig[0] - if line.bank_id.acc_number_dig else '', - # 14.3A - 'favorecido_dv': line.bank_id.acc_number_dig[1] - if len(line.bank_id.bra_number_dig or '') > 1 else '', - # 15.3A - 'favorecido_nome': line.partner_id.name, - - # CREDITO - # 16.3A - - 'credito_seu_numero': line.name, - # 17.3A - 'credito_data_pagamento': self.format_date(line.date), - # 18.3A - 'credito_moeda_tipo': line.currency.name, - # 19.3A - 'credito_moeda_quantidade': Decimal('0.00000'), - # 20.3A - 'credito_valor_pagamento': - Decimal(str(line.amount_currency)).quantize(Decimal('1.00')), - # 21.3A - # 'credito_nosLoteso_numero': '', - # 22.3A - # 'credito_data_real': '', - # 23.3A - # 'credito_valor_real': '', - - # INFORMAÇÔES - # 24.3A - # 'outras_informacoes': '', - # 25.3A - # 'codigo_finalidade_doc': line.codigo_finalidade_doc, - # 26.3A - 'codigo_finalidade_ted': line.codigo_finalidade_ted or '', - # 27.3A - 'codigo_finalidade_complementar': - line.codigo_finalidade_complementar or '', - # 28.3A - # CNAB - Uso Exclusivo FEBRABAN/CNAB - # 29.3A - # 'aviso_ao_favorecido': line.aviso_ao_favorecido, - 'aviso_ao_favorecido': 0, - # 'ocorrencias': '', - - # SEGMENTO B - # Preenchido no segmento A - # 01.3B - # 02.3B - # 03.3B - - # 04.3B - # 05.3B - # 06.3B - - # DADOS COMPLEMENTARES - FAVORECIDOS - # 07.3B - 'favorecido_tipo_inscricao': - self.get_inscricao_tipo(line.partner_id), - # 08.3B - 'favorecido_num_inscricao': - int(punctuation_rm(line.partner_id.cnpj_cpf)), - # 09.3B - 'favorecido_endereco_rua': line.partner_id.street or '', - # 10.3B - 'favorecido_endereco_num': int(line.partner_id.number) or 0, - # 11.3B - 'favorecido_endereco_complemento': line.partner_id.street2 or '', - # 12.3B - 'favorecido_endereco_bairro': line.partner_id.district or '', - # 13.3B - 'favorecido_endereco_cidade': - line.partner_id.l10n_br_city_id.name or '', - # 14.3B - # 'favorecido_cep': int(line.partner_id.zip[:5]) or 0, - 'favorecido_cep': self.get_cep('prefixo', line.partner_id.zip), - # 15.3B - 'favorecido_cep_complemento': - self.get_cep('sufixo', line.partner_id.zip), - # 16.3B - 'favorecido_estado': line.partner_id.state_id.code or '', - - # DADOS COMPLEMENTARES - PAGAMENTO - # 17.3B - 'pagamento_vencimento': 0, - # 18.3B - 'pagamento_valor_documento': Decimal('0.00'), - # 19.3B - 'pagamento_abatimento': Decimal('0.00'), - # 20.3B - 'pagamento_desconto': Decimal('0.00'), - # 21.3B - 'pagamento_mora': Decimal('0.00'), - # 22.3B - 'pagamento_multa': Decimal('0.00'), - # 23.3B - # TODO: Verificar se este campo é retornado no retorno - # 'cod_documento_favorecido': '', - # 24.3B - Informado No SegmentoA - # 'aviso_ao_favorecido': '0', - # 25.3B - # 'codigo_ug_centralizadora': '0', - # 26.3B - # 'codigo_ispb': '0', - } - return vals - - def _adicionar_evento(self, line): - """ - Adicionar o evento no arquivo de acordo com seu tipo - """ - # if self.order.payment_order_type == 'payment': - # incluir = self.arquivo.incluir_debito_pagamento - # prepare = self._prepare_pagamento - # else: - # incluir = self.arquivo.incluir_cobranca - # prepare = self._prepare_cobranca - pass - - def remessa(self, order): - """ - Cria a remessa de eventos que sera anexada ao arquivo - :param order: payment.order - :return: Arquivo Cnab pronto para download - """ - # cobrancasimples_valor_titulos = 0 - - self.order = order - - # Preparar Header do Arquivo - self.arquivo = Arquivo(self.bank, **self._prepare_header()) - - if order.payment_order_type == 'payment': - incluir = self.arquivo.incluir_debito_pagamento - prepare = self._prepare_pagamento - else: - incluir = self.arquivo.incluir_cobranca - prepare = self._prepare_cobranca - - for line in order.bank_line_ids: - # para cada linha da payment order adicoinar como um novo evento - # self._adicionar_evento(line) - # try: - incluir(**prepare(line)) - # except: - # from openerp import exceptions - # raise exceptions.ValidationError("Erro") - self.arquivo.lotes[0].header.servico_servico = 1 - # TODO: tratar soma de tipos de cobranca - # cobrancasimples_valor_titulos += line.amount_currency - # 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 get_cep(self, tipo, value): - ''' - :param tipo: - :param value: - :return: - ''' - if not value: - if tipo == 'prefixo': - return 0 - else: - return '' - value = punctuation_rm(value) - sulfixo = format[-3:] - prefixo = format[:5] - if tipo == 'sulfixo': - return sulfixo - else: - return prefixo - - def format_date(self, srt_date): - if not srt_date: - return 0 - return int(datetime.datetime.strptime( - srt_date, '%Y-%m-%d').strftime('%d%m%Y')) - - def data_hoje(self): - return (int(time.strftime("%d%m%Y"))) - - def hora_agora(self): - return (int(time.strftime("%H%M%S"))) - - def rmchar(self, format): - return re.sub('[%s]' % re.escape(string.punctuation), '', - format or '') - - def nosso_numero(self, format): - """ - Hook para ser sobrescrito e adicionar informação - :param format: - :return: - """ - pass diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py deleted file mode 100644 index 2cfbd6d7e782..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_400/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py deleted file mode 100644 index 5d3fd105cafb..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py deleted file mode 100644 index 373af4681665..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/bradesco.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - -import re -import string -from decimal import Decimal - -from ..cnab_400 import Cnab400 - - -class Bradesco400(Cnab400): - - def __init__(self): - super(Cnab400, self).__init__() - from cnab240.bancos import bradesco_cobranca_400 - self.bank = bradesco_cobranca_400 - self.controle_linha = 2 - - def _prepare_header(self): - """ - - :param order: - :return: - """ - - vals = super(Bradesco400, self)._prepare_header() - vals['servico_servico'] = 1 - return vals - - def _prepare_cobranca(self, line): - """ - - :param line: - :return: - """ - vals = super(Bradesco400, self)._prepare_cobranca(line) - vals['prazo_baixa'] = unicode(str( - vals['prazo_baixa']), "utf-8") - vals['desconto1_percentual'] = Decimal('0.00') - vals['valor_iof'] = Decimal('0.00') - # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') - vals['identificacao_titulo_banco'] = self.convert_int( - vals['identificacao_titulo_banco']) - vals['cedente_conta_dv'] = unicode(str( - vals['cedente_conta_dv']), "utf-8") - vals['cedente_agencia_dv'] = unicode(str( - vals['cedente_agencia_dv']), "utf-8") - # vals['cedente_dv_ag_cc'] = unicode(str( - # vals['cedente_dv_ag_cc']), "utf-8") - - vals['sacado_cc_dv'] = u'0' - vals['identificacao_empresa_beneficiaria_banco'] = \ - self.retorna_id_empr_benef() - vals['digito_conferencia_numero_bancario'] = u'0' - vals['condicao_emissao_papeleta'] = 1 - - vals['indicador_rateio_credito'] = u"" - self.controle_linha += 1 - - return vals - - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito - - def retorna_id_empr_benef(self): - dig_cart = 3 - dig_ag = 5 - dig_conta = 7 - - carteira = self.adiciona_digitos( - self.order.payment_mode_id.boleto_carteira, dig_cart) - agencia = self.adiciona_digitos( - self.order.company_partner_bank_id.bra_number, dig_ag) - conta = self.adiciona_digitos( - self.order.company_partner_bank_id.acc_number, dig_conta) - - ident = u'0' + (carteira) + (agencia) + (conta) + \ - (self.order.company_partner_bank_id.acc_number_dig) - return ident - - def adiciona_digitos(self, campo, num_digitos): - chars_faltantes = num_digitos - len(campo) - return (u'0' * chars_faltantes) + campo - - -def str_to_unicode(inp_str): - inp_str = unicode(inp_str, "utf-8") - return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py b/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py deleted file mode 100644 index cfcf6a55a7b0..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_400/bancos/itau.py +++ /dev/null @@ -1,176 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2019 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from __future__ import division, print_function, unicode_literals - -import re -import string -from decimal import Decimal -from odoo.addons.l10n_br_base.tools.misc import punctuation_rm - -from ..cnab_400 import Cnab400 - - -class Itau400(Cnab400): - - def __init__(self): - super(Cnab400, self).__init__() - self.controle_linha = 1 - - def remessa(self, order): - from cnab240.bancos import itau_cobranca_400 - self.classe_remessa = itau_cobranca_400 - return super(Itau400, self).remessa(order) - - def retorno(self, arquivo_retorno): - from cnab240.bancos import itau_cobranca_retorno_400 - self.classe_retorno = itau_cobranca_retorno_400 - return super(Itau400, self).retorno(arquivo_retorno) - - @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 order: - :return: - """ - vals = { - 'cedente_agencia': self.convert_int( - self.order.company_partner_bank_id.bra_number), - 'cedente_conta': self.convert_int( - self.order.company_partner_bank_id.acc_number), - 'cedente_conta_dv': self.convert_int( - self.order.company_partner_bank_id.acc_number_dig), - 'cedente_nome': unicode(self.order.company_id.legal_name), - 'arquivo_data_de_geracao': self.data_hoje(), - 'arquivo_hora_de_geracao': self.hora_agora(), - 'num_seq_registro': self.controle_linha, - } - self.controle_linha += 1 - return vals - - def _prepare_cobranca(self, line): - """ - - :param line: - :return: - """ - sacado_endereco = self.retorna_endereco(line.partner_id.id) - - # TODO: Garantir que o account.move.line selecionado é o correto - move_line_id = line.payment_line_ids[:1].move_line_id - - # TODO: Guardar estrutura com códigos de ocorrências - identificacao_ocorrencia = 1 - if move_line_id.state_cnab == 'added_paid': - identificacao_ocorrencia = 34 - - vals = { - 'identificacao_titulo_empresa': line.identificacao_titulo_empresa, - 'nosso_numero': self.convert_int(line.nosso_numero), - 'numero_documento': self.adiciona_digitos_num_doc( - line.numero_documento), - 'cedente_inscricao_tipo': self.inscricao_tipo, - 'cedente_inscricao_numero': self.convert_int(punctuation_rm( - self.order.company_id.cnpj_cpf)), - 'cedente_agencia': self.convert_int( - self.order.company_partner_bank_id.bra_number), - 'cedente_conta': self.convert_int( - self.order.company_partner_bank_id.acc_number), - 'cedente_conta_dv': self.convert_int( - self.order.company_partner_bank_id.acc_number_dig - ), - 'instrucao': 0, # TODO VERIFICAR - 'quantidade_moeda': 0, - 'carteira_numero': self.convert_int( - self.order.payment_mode_id.boleto_carteira - ), - 'carteira_cod': self.order.payment_mode_id.boleto_modalidade, - 'identificacao_ocorrencia': identificacao_ocorrencia, - 'vencimento_titulo': self.format_date( - line.date), - 'valor_titulo': Decimal(str(line.amount_currency)).quantize( - Decimal('1.00')), - 'agencia_cobradora': 0, - 'especie_titulo': self.order.payment_mode_id.boleto_especie, - 'aceite_titulo': self.order.payment_mode_id.boleto_aceite, - 'data_emissao_titulo': self.format_date( - line.date), # FIXME - 'primeira_instrucao': self.convert_int( - self.order.payment_mode_id.boleto_protesto - ), - 'segunda_instrucao': self.convert_int( - self.order.payment_mode_id.boleto_protesto_prazo - - ), - 'juros_mora_taxa_dia': self.calcula_valor_juros_dia( - line.amount_currency, - self.order.payment_mode_id.cnab_percent_interest - ), - 'data_limite_desconto': 0, - 'valor_desconto': Decimal('0.00'), - 'valor_iof': Decimal('0.00'), - 'valor_abatimento': Decimal('0.00'), - 'sacado_inscricao_tipo': self.convert_int( - self.sacado_inscricao_tipo(line.partner_id)), - 'sacado_inscricao_numero': line.partner_id.cnpj_cpf and self.convert_int( - punctuation_rm(line.partner_id.cnpj_cpf)) or '', - 'sacado_nome': line.partner_id.legal_name, - 'sacado_endereco': sacado_endereco, - 'sacado_bairro': line.partner_id.district or '', - 'sacado_cep': ( - line.partner_id.zip and - self.convert_int(line.partner_id.zip.replace('-', '')) or '' - ), - 'sacado_cidade': line.partner_id.l10n_br_city_id.name, - 'sacado_uf': line.partner_id.state_id.code, - 'sacador_avalista': self.order.payment_mode_id.comunicacao_2, - 'juros_mora_data': 0, - # self.format_date( - # line.date), - 'prazo': 0, # De 5 a 120 dias. - # 'sacador_avalista': u'Protestar após 5 dias', - 'num_seq_registro': self.controle_linha, - } - return vals - - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito - - def retorna_id_empr_benef(self): - dig_cart = 3 - dig_ag = 5 - dig_conta = 7 - - carteira = self.adiciona_digitos( - self.order.payment_mode_id.boleto_carteira, dig_cart) - agencia = self.adiciona_digitos( - self.order.company_partner_bank_id.bra_number, dig_ag) - conta = self.adiciona_digitos( - self.order.company_partner_bank_id.acc_number, dig_conta) - - ident = u'0' + (carteira) + (agencia) + (conta) + \ - (self.order.company_partner_bank_id.acc_number_dig) - return ident - - def adiciona_digitos(self, campo, num_digitos): - chars_faltantes = num_digitos - len(campo) - return (u'0' * chars_faltantes) + campo - - -def str_to_unicode(inp_str): - inp_str = unicode(inp_str, "utf-8") - return inp_str diff --git a/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py b/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py deleted file mode 100644 index c31b53e65807..000000000000 --- a/cnab_erpbrasil_febraban/febraban/cnab_400/cnab_400.py +++ /dev/null @@ -1,401 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import datetime -import logging -import re -import string -import time -import unicodedata -from decimal import Decimal - -from odoo.addons.l10n_br_base.tools.misc import punctuation_rm - -from ..cnab import Cnab - -_logger = logging.getLogger(__name__) -try: - from erpbrasil.febraban.cnab.tipos import ArquivoCobranca400 - from erpbrasil.febraban.cnab.errors import Cnab240Error -except ImportError as err: - _logger.debug = (err) - -IDENTIFICACAO_DA_OCORRENCIA = [ - ('01', u'Remessa'), - ('02', u'Pedido de baixa'), - ('03', u'Pedido de Protesto Falimentar'), - ('04', u'Concessão de abatimento'), - ('05', u'Cancelamento de abatimento concedido'), - ('06', u'Alteração de vencimento'), - ('07', u'Alteração do controle do participante'), - ('08', u'Alteração de seu número'), - ('09', u'Pedido de protesto'), - ('18', u'Sustar protesto e baixar Título'), - ('19', u'Sustar protesto e manter em carteira'), - ('22', u'Transferência Cessão crédito ID. Prod.10'), - ('23', u'Transferência entre Carteiras'), - ('24', u'Dev. Transferência entre Carteiras'), - ('31', u'Alteração de outros dados'), - ('45', u'Pedido de Negativação (NOVO)'), - ('46', u'Excluir Negativação com baixa (NOVO)'), - ('47', u'Excluir negativação e manter pendente (NOVO)'), - ('68', u'Acerto nos dados do rateio de Crédito'), - ('69', u'Cancelamento do rateio de crédito'), -] - -ESPECIE_DE_TITULO = [ - ('01', u'Duplicata'), - ('02', u'Nota Promissória'), - ('03', u'Nota de Seguro'), - ('04', u'Cobrança Seriada'), - ('05', u'Recibo'), - ('10', u'Letras de Câmbio'), - ('11', u'Nota de Débito'), - ('12', u'Duplicata de Serv'), - ('30', u'Boleto de Proposta'), - ('99', u'Outros'), -] - -# Essas instruções deverão ser enviadas no Arquivo-Remessa, quando da -# entrada, desde que código de ocorrência na posição 109 a 110 do registro -# de transação, seja “01”, para as instruções de protesto/negativação, o -# CNPJ / CPF e o endereço do Pagador deverão ser informados corretamente -LISTA_PRIMEIRA_INSTRUCAO = [ - ('05', u'Protesto Falimentar'), - ('06', u'Protestar'), - ('07', u'Negativar'), - ('18', u'Decurso de prazo'), - - ('08', u'Não cobrar juros de mora'), - ('09', u'Não receber após o vencimento'), - ('10', u'Multas de 10% após o 4o dia do Vencimento'), - ('11', u'Não receber após o 8o dia do vencimento.'), - ('12', u'Cobrar encargos após o 5o dia do vencimento'), - ('13', u'Cobrar encargos após o 10o dia do vencimento'), - ('14', u'Cobrar encargos após o 15o dia do vencimento'), - ('15', u'Conceder desconto mesmo se pago após o vencimento'), -] - - -class Cnab400(Cnab): - - def __init__(self): - super(Cnab, self).__init__() - - @staticmethod - def get_bank(bank): - if bank == '237': - from .bancos.bradesco import Bradesco400 - return Bradesco400 - elif bank == '341': - from .bancos.itau import Itau400 - return Itau400 - else: - return Cnab400 - - @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 { - 'controle_banco': self.convert_int( - self.order.company_partner_bank_id.bank_id.code_bc - ), - 'arquivo_data_de_geracao': self.data_hoje(), - 'arquivo_hora_de_geracao': self.hora_agora(), - # TODO: Número sequencial de arquivo - 'arquivo_sequencia': self.convert_int(self.get_file_numeration()), - 'cedente_inscricao_tipo': self.inscricao_tipo, - 'cedente_inscricao_numero': self.convert_int(punctuation_rm( - self.order.company_id.cnpj_cpf)), - 'cedente_agencia': self.convert_int( - self.order.company_partner_bank_id.bra_number), - 'cedente_conta': - self.convert_int(self.order.company_partner_bank_id.acc_number), - 'cedente_conta_dv': - self.order.company_partner_bank_id.acc_number_dig, - 'cedente_agencia_dv': - self.order.company_partner_bank_id.bra_number_dig, - 'cedente_nome': - self.order.company_id.legal_name, - 'arquivo_codigo': 1, # Remessa/Retorno - 'servico_operacao': u'R', - 'nome_banco': - unicode(self.order.company_partner_bank_id.bank_name), - 'codigo_empresa': - self.convert_int(self.order.payment_mode_id.boleto_convenio), - } - - def get_file_numeration(self): - # TODO: FIX ME - # numero = self.order.get_next_number() - # if not numero: - numero = 1 - return numero - - def format_date(self, srt_date): - return self.convert_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 codificar(self, texto): - return texto.encode('utf-8') - - def _prepare_cobranca(self, line): - """ - :param line: - :return: - """ - prefixo, sulfixo = self.cep(line.partner_id.zip) - - aceite = u'N' - if not self.order.payment_mode_id.boleto_aceite == 'S': - aceite = u'A' - - codigo_protesto = 0 - dias_protestar = 0 - if self.order.payment_mode_id.boleto_protesto == '3' \ - or self.order.payment_mode_id.boleto_protesto == '0': - codigo_protesto = 0 - dias_protestar = 0 - elif self.order.payment_mode_id.boleto_protesto == '1' \ - or self.order.payment_mode_id.boleto_protesto == '2': - codigo_protesto = 6 - if (self.convert_int(self.order.payment_mode_id.boleto_protesto_prazo)) < 5: - dias_protestar = 5 - else: - dias_protestar = self.convert_int( - self.order.payment_mode_id.boleto_protesto_prazo) - - sacado_endereco = self.retorna_endereco(line.partner_id.id) - - # 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 { - - 'percentual_multa': Decimal('0.00'), - 'valor_desconto': Decimal('0.00'), - 'valor_abatimento_concedido_cancelado': Decimal('0.00'), - 'primeira_instrucao': codigo_protesto, - 'segunda_instrucao': dias_protestar, - 'sacado_cep': self.convert_int(prefixo), - 'sacado_cep_sufixo': self.convert_int(sulfixo), - 'sacador_avalista': - self.order.payment_mode_id.comunicacao_2, - # 'sacador_avalista': u'Protestar após 5 dias', - 'num_seq_registro': - self.controle_linha, - - 'controle_banco': self.convert_int( - self.order.company_partner_bank_id.bank_id.code_bc - ), - 'cedente_agencia': self.convert_int( - self.order.company_partner_bank_id.bra_number), - 'cedente_conta': self.convert_int( - self.order.company_partner_bank_id.acc_number), - 'cedente_conta_dv': - self.order.company_partner_bank_id.acc_number_dig, - 'cedente_agencia_dv': - self.order.company_partner_bank_id.bra_number_dig, - 'identificacao_titulo': u'0000000', # TODO - 'identificacao_titulo_banco': u'0000000', # TODO - 'identificacao_titulo_empresa': line.name, # FIXME - - 'vencimento_titulo': self.format_date( - line.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': self.convert_int(self.order.payment_mode_id.boleto_especie), - 'aceite_titulo': aceite, - 'data_emissao_titulo': self.format_date( - line.date), # FIXME - # 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.date), - - # 'juros_mora_taxa_dia': Decimal('0.20'), - 'juros_mora_taxa_dia': self.calcula_valor_juros_dia( - line.amount_currency, 0), # line.percent_interest - - 'valor_abatimento': Decimal('0.00'), - 'sacado_inscricao_tipo': self.convert_int( - self.sacado_inscricao_tipo(line.partner_id)), - 'sacado_inscricao_numero': line.partner_id.cnpj_cpf and self.convert_int( - punctuation_rm(line.partner_id.cnpj_cpf)) or '', - 'sacado_nome': line.partner_id.legal_name, - - # 'sacado_endereco': ( - # line.partner_id.street + - # ' ' + str(line.partner_id.number) - # ), - - 'sacado_endereco': sacado_endereco, - - 'sacado_bairro': line.partner_id.district or '', - 'sacado_cidade': line.partner_id.l10n_br_city_id.name, - 'sacado_uf': line.partner_id.state_id.code, - 'codigo_baixa': 2, - 'prazo_baixa': 0, # De 5 a 120 dias. - 'controlecob_data_gravacao': self.data_hoje(), - 'cobranca_carteira': self.convert_int( - self.order.payment_mode_id.boleto_carteira - ), - 'primeira_mensagem': u'', - # Trazer da nova tela do payment_mode - 'identificacao_ocorrencia': 1, - - # numero fatura esta copiando para communication - 'numero_documento': self.adiciona_digitos_num_doc( - line.communication), - # 'numero_documento': str(line.move_line_id.invoice.number), - - } - - def remessa(self, order): - """ - - :param order: - :return: - """ - self.order = order - self.arquivo = ArquivoCobranca400( - self.classe_remessa, **self._prepare_header()) - for line in order.bank_line_ids: - try: - self.arquivo.incluir_cobranca(**self._prepare_cobranca(line)) - self.controle_linha += 1 - self.arquivo.trailer.num_seq_registro = self.controle_linha - line.is_erro_exportacao = False - line.mensagem_erro_exportacao = '' - - for payment_line in line.payment_line_ids: - payment_line.move_line_id.state_cnab = 'exported' - - except Cnab240Error as e: - mensagem = '' - if hasattr(e, 'campo'): - mensagem += u' Campo ' + e.campo.nome - mensagem += u' valor ' + str(e.campo.valor) - mensagem += u' inválido' - else: - mensagem += u' Erro desconhecido' - line.is_erro_exportacao = True - line.mensagem_erro_exportacao = mensagem - - for payment_line in line.payment_line_ids: - payment_line.move_line_id.state_cnab = 'exporting_error' - - continue - - remessa = unicode(self.arquivo) - return unicodedata.normalize( - 'NFKD', remessa).encode('ascii', 'ignore') - - def data_hoje(self): - return (self.convert_int(time.strftime("%d%m%y"))) - - def hora_agora(self): - return (self.convert_int(time.strftime("%H%M%S"))) - - def calcula_valor_juros_dia(self, total_titulo, percent_juros): - valor_juros = 0 - valor_juros = (total_titulo * (percent_juros / 100)) - return (Decimal(valor_juros).quantize(Decimal('1.00'))) - - def adiciona_digitos_num_doc(self, campo): - num_digitos = 10 - campo = str(campo) - chars_faltantes = num_digitos - len(campo) - return (u' ' * chars_faltantes) + campo - - # @api.multi - def retorna_endereco(self, id_parceiro): - # self.ensure_one() - # workaround to get env - res_partner_model = self.order.env['res.partner'] - res_partner_end_cobranca = res_partner_model.search( - [('parent_id', '=', id_parceiro), ('type', '=', 'cnab_cobranca')], - limit=1) - if res_partner_end_cobranca: - str_endereco = self.monta_endereco(res_partner_end_cobranca) - else: - res_partner_end_cobranca = res_partner_model.search( - [('id', '=', id_parceiro)] - ) - str_endereco = self.monta_endereco(res_partner_end_cobranca) - # Essa abordagem substitui caracteres especiais por '?' - # str_endereco = / - # unicode(str_endereco.encode("ascii", errors="replace")) - - # Substitui sinal de grau por espaço - if str_endereco: - str_endereco = str_endereco.replace(u"\xb0", u" ") - - return str_endereco - - def monta_endereco(self, partner_item): - - street = self.check_address_item_filled(partner_item.street) - number = self.check_address_item_filled(partner_item.number) - complemento = self.check_address_item_filled(partner_item.street2) - # distrito = self.check_address_item_filled(partner_item.district) - - str_endereco = ( - street + - ' ' + - number + - ' ' + - complemento - # + ' ' + - # partner_item.l10n_br_city_id.name + - # ' ' + partner_item.state_id.name - ) - return str_endereco - - def check_address_item_filled(self, item): - if not item: - return ('') - else: - return item diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/__init__.py b/cnab_erpbrasil_febraban/febraban/pag_for/__init__.py deleted file mode 100644 index 32c397f2f690..000000000000 --- a/cnab_erpbrasil_febraban/febraban/pag_for/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from . import pag_for500 diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py b/cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py deleted file mode 100644 index 2cfbd6d7e782..000000000000 --- a/cnab_erpbrasil_febraban/febraban/pag_for/bancos/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Daniel Sadamo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py b/cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py deleted file mode 100644 index de45b9a00459..000000000000 --- a/cnab_erpbrasil_febraban/febraban/pag_for/bancos/bradesco.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - - -import re -import string - -from ..pag_for500 import PagFor500 - - -class BradescoPagFor(PagFor500): - - def __init__(self): - super(PagFor500, self).__init__() - from cnab240.bancos import bradescoPagFor - self.bank = bradescoPagFor - self.controle_linha = 2 - - def _prepare_header(self): - """ - - :param order: - :return: - """ - vals = super(BradescoPagFor, self)._prepare_header() - vals['codigo_comunicacao'] = self.convert_int( - self.order.payment_mode_id.boleto_convenio) - return vals - - def _prepare_cobranca(self, line, vals): - """ - - :param line: - :return: - """ - vals = super(BradescoPagFor, self)._prepare_cobranca(line, vals) - - # TODO campo para informar a data do pagamento. - vals['data_para_efetivacao_pag'] = self.muda_campos_data( - vals['vencimento_titulo']) - self.controle_linha += 1 - - return vals - - # Override cnab_240.nosso_numero. Diferentes números de dígitos - # entre CEF e Itau - def nosso_numero(self, format): - digito = format[-1:] - carteira = format[:3] - nosso_numero = re.sub( - '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') - return carteira, nosso_numero, digito - - def muda_campos_data(self, campo): - campo = str(campo) - campo = campo[-4:] + campo[2:4] + campo[:2] - return self.convert_int(campo) diff --git a/cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py b/cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py deleted file mode 100644 index e84aa22f1503..000000000000 --- a/cnab_erpbrasil_febraban/febraban/pag_for/pag_for500.py +++ /dev/null @@ -1,573 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2012 KMEE INFORMATICA LTDA -# @author Luis Felipe Mileo -# @author Fernando Marcato -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -import datetime -import logging -import re -import string -import time -import unicodedata -from decimal import Decimal - -from odoo import _ -from odoo.addons.l10n_br_base.tools.misc import punctuation_rm -from odoo.exceptions import Warning as UserError - -from ..cnab import Cnab - -_logger = logging.getLogger(__name__) -try: - from cnab240.tipos import Arquivo -except ImportError as err: - _logger.debug = (err) -try: - from pyboleto.data import BoletoData -except ImportError as err: - _logger.debug = (err) - -TIPO_CONTA_FORNECEDOR = [ - ('1', u'Conta corrente'), - ('2', u'Conta Poupança'), -] - -TIPO_DOCUMENTO = [ - ('01', u'Nota Fiscal/Fatura'), - ('02', u'Fatura'), - ('03', u'Nota Fiscal'), - ('01', u'Duplicata'), - ('01', u'Outros'), -] - -MODALIDADE = [ - ('01', u'01 - Crédito em conta-corrente ou poupança Bradesco'), - ('02', u'02 - Cheque OP ( Ordem de Pagamento'), - ('03', u'03 - DOC COMPE'), - ('05', u'05 - Crédito em conta real time'), - ('08', u'08 - TED'), - ('30', u'30 - Rastreamento de Títulos'), - ('31', u'31 - Títulos de terceiros'), -] - -TIPO_MOVIMENTO = [ - ('0', u'Inclusão'), - ('5', u'Alteração'), - ('9', u'Exclusão'), -] - -CODIGO_MOVIMENTO = [ - ('00', u'Autoriza agendamento'), - ('25', u'Desautoriza Agendamento'), - ('50', u'Efetuar Alegçação'), -] - -TIPO_DOC = [ - ('C', u'Titularidade Diferente'), - ('D', u'Mesma Titularidade'), -] - -FINALIDADE_DOC_TED = [ - ('01', u'Crédito em Conta Corrente'), - ('02', u'Pagamento de Aluguel /Condomínios'), - ('03', u'Pagamento de Duplicatas/Títulos'), - ('04', u'Pagamento de Dividendos'), - ('05', u'Pagamento de Mensal. Escolares'), - ('06', u'Pagamento de Salário'), - ('07', u'Pagamento de Fornec/Honor.'), - ('08', u'Operações de Câmbio /Fundos /Bolsa de Valores'), - ('09', u'Repasse de Arrec./Pagto de Tributos'), - ('10', u'Transferência Internacional em Reais'), - ('11', u'DOC COMPE/TED para Poupança'), - ('12', u'DOC COMPE/TED para Depósito Judicial'), - ('13', u'Pensão Alimentícia'), - ('14', u'Restituição de Imposto de Renda'), - ('18', u'Operações Seguro Habit.', u'SFH'), - ('19', u'Operações do FDS', u'Caixa'), - ('20', u'Pagamento De Operação De Crédito'), - ('23', u'Taxa de Administração'), - ('27', u'Pagamento Acordo/Execução Judicial'), - ('28', u'Liquidação de Empréstimos Consignados'), - ('29', u'Pagamento de Bolsa Auxilio'), - ('30', u'Remuneração A Cooperado'), - ('31', u'Pagamento de Prebenda'), - ('33', u'Pagamento de Juros sobre Capital Próprio'), - ('34', u'Pagamento de Rendimentos ou Amortização s/ Cotas ' - u'e/ou Debêntures'), - ('35', u'Taxa De Serviço'), - ('37', u'Pagamento de Juros e/ou Amortização de Títulos ' - u'Depositados em Garantia.'), - ('38', u'Estorno Ou Restituição', u'Diversos'), - ('59', u'Restituição de Prêmios de Seguros'), - ('60', u'Pagamento de Indenização Sinistro Seguro'), - ('61', u'Pagamento de Premio de Co-Seguro'), - ('63', u'Pagamento de Indenização Sinistro Co-Seguro'), - ('64', u'Pagamento de Premio De Resseguro'), - ('65', u'Restituição de Premio De Resseguro'), - ('66', u'Pagamento de Indenização Sinistro Resseguro'), - ('67', u'Restituição Indenização Sinistro Resseguro'), - ('68', u'Pagamento de Despesas Com Sinistro'), - ('69', u'Pagamento de Inspeções/Vistorias Prévias'), - ('70', u'Pagamento de Resgate de Titulo de Capitalização'), - ('71', u'Pagamento de Sorteio de Titulo de Capitalização'), - ('72', u'Devolução Mensal de Titulo de Capitalização.'), - ('73', u'Restituição de Contribuição de Plano Previdenciário'), - ('74', u'Pagamento de Beneficio Previdenciário Pecúlio'), - ('75', u'Pagamento de Beneficio Previdenciário Pensão'), - ('76', u'Pagamento de Beneficio Previdenciário Aposentadoria'), - ('77', u'Pagamento de Resgate Previdenciário'), - ('78', u'Pagamento de Comissão de Corretagem'), - ('79', u'Pagamento de Transferências/Portabilidade de Reserva ' - u'Seguro/Previdência'), - ('80', u'Pagamento de Impostos'), - ('81', u'Pagamento de Serviços Públicos'), - ('82', u'Pagamento de Honorários'), - ('83', u'Pagamento de Corretoras'), - ('84', u'Repasse de Valores BNDES'), - ('85', u'Liquidação de Compromissos com BNDES'), - ('86', u'Compra e Venda de Ações'), - ('87', u'Contratos Referenciados em Ações ou Índices de Ações'), - ('88', u'Operação De Cambio'), - ('89', u'Pagamento de Boleto Bancário em Cartório'), - ('90', u'Pagamento de Tarifas pela Prestação de Serviços de Arrecadação' - u' de Convênios'), - ('91', u'Operações no Mercado de Renda Fixa e Variável com Utilização ' - u'de Intermediário'), - ('92', u'Operação de Câmbio Mercado Interbancário Instituições ' - u'sem Reservas Bancárias'), - ('93', u'Pagamento de Operações com Identificação de Destinatário Final'), - ('94', u'Ordem Bancaria do Tesouro - OBT'), - ('99', u'Outros'), -] - - -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': self.convert_int(self.get_file_numeration()), - 'cedente_inscricao_tipo': self.inscricao_tipo, - 'cnpj_cpf_base': self.convert_int(punctuation_rm( - self.order.company_id.cnpj_cpf)[0:8]), - 'cnpj_cpf_filial': self.convert_int(punctuation_rm( - self.order.company_id.cnpj_cpf)[9:12]), - 'sufixo_cnpj': self.convert_int(punctuation_rm( - self.order.company_id.cnpj_cpf)[12:14]), - 'cedente_agencia': - self.convert_int(self.order.company_partner_bank_id.bra_number), - 'cedente_conta': - self.convert_int(self.order.company_partner_bank_id.acc_number), - 'cedente_agencia_conta_dv': - self.order.company_partner_bank_id.bra_number_dig, - 'nome_empresa_pagadora': self.order.company_id.legal_name, - 'cedente_codigo_agencia_digito': - self.order.company_partner_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': self.convert_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 self.convert_int(datetime.datetime.strptime( - srt_date, '%Y-%m-%d').strftime('%d%m%Y')) - - def format_date_ano_mes_dia(self, srt_date): - return self.convert_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 _prepare_cobranca(self, line, vals): - """ - - :param line: - :return: - """ - segmento = {} - - vals.update(segmento) - - # TODO this zip code - prefixo, sulfixo = self.cep(line.partner_id.zip) - - segmento = { - 'conta_complementar': - self.convert_int(self.order.company_partner_bank_id.acc_number), - # 'especie_titulo': 8, - - 'tipo_inscricao': self.convert_int( - self.sacado_inscricao_tipo(line.partner_id)), - 'cnpj_cpf_base_forn': line.partner_id.cnpj_cpf and self.convert_int( - punctuation_rm(line.partner_id.cnpj_cpf)[0:8]) or '', - 'cnpj_cpf_filial_forn': line.partner_id.cnpj_cpf and self.convert_int( - punctuation_rm(line.partner_id.cnpj_cpf)[9:12]) or '', - 'cnpj_cpf_forn_sufixo': line.partner_id.cnpj_cpf and self.convert_int( - punctuation_rm(line.partner_id.cnpj_cpf)[12:14]) or '', - 'nome_forn': line.partner_id.legal_name, - 'endereco_forn': ( - line.partner_id.street + ' ' + line.partner_id.number), - 'cep_forn': self.convert_int(prefixo), - 'cep_complemento_forn': self.convert_int(sulfixo), - - # TODO quando banco é 237, deve-se extrair da linha - # digitável. Do contrário, zeros. - # 'nosso_numero': 11, # FIXME - - # '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': self.convert_int(line.ml_inv_ref.internal_number), - - 'modalidade_pagamento': self.convert_int( - line.order_id.mode.type_purchase_payment), - - # Quando não informada o sistema assume a data constante do campo - # Vencimento - 'data_para_efetivacao_pag': 0, - - 'tipo_movimento': 0, - # TODO Tipo de Movimento. - # 0 - Inclusão. - # 5 - Alteração. - # 9 - Exclusão. - - 'codigo_movimento': 0, # Autoriza agendamento - - # Quando não informado consulta em todos processamentos - # 'horario_consulta_saldo': u'5', - - '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': self.convert_int(self.get_file_numeration()), - 'sequencial_transacao': self.controle_linha, - 'codigo_protesto': - self.convert_int(self.order.payment_mode_id.boleto_protesto), - 'prazo_protesto': - self.convert_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(), - - } - 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 (self.convert_int(time.strftime("%d%m%Y"))) - - def data_hoje_pag_for(self): - return (self.convert_int(time.strftime("%Y%m%d"))) - - def hora_agora(self): - return (self.convert_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(_(u'Operação não suportada')) - elif mode in ('03'): - return self.lancamento_doc(line) - elif mode in ('05'): - raise UserError(_(u'Operação não suportada')) - elif mode in ('08'): - return self.lancamento_ted(line) - elif mode in ('30'): - raise UserError(_(u'Operação não suportada')) - elif mode in ('31'): - # titulos de terceiros - return self.lancamento_titulos_terceiros(line) - raise UserError(_(u'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': self.convert_int(line.bank_id.bra_number), - 'digito_agencia_forn_transacao': line.bank_id.bra_number_dig, - 'conta_corrente_forn': self.convert_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': self.convert_int(self.order.payment_mode_id.boleto_carteira), - - 'nosso_numero': 0, - - 'vencimento_titulo': self.format_date_ano_mes_dia( - line.ml_maturity_date), - - 'informacoes_complementares': u'', - } - - return self._prepare_cobranca(line, vals) - - def lancamento_ted(self, line): - # TODO: - # modalidade 08. - - vals = { - 'conta_complementar': - self.convert_int(self.order.company_partner_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': - self.convert_int(line.bank_id.bank.bic), - 'codigo_agencia_forn': - self.convert_int(line.bank_id.bra_number), - 'digito_agencia_forn_transacao': - line.bank_id.bra_number_dig, - 'conta_corrente_forn': - self.convert_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': - # self.convert_int(self.order.payment_mode_id.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_cobranca(line, vals) - - def lancamento_doc(self): - # TODO: - - vals = {} - - return self._prepare_cobranca(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': - self.convert_int(self.order.company_partner_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_cobranca(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' - # pagamento duplicatas. Ou será 01? - finalidade_doc_compe = FINALIDADE_DOC_TED[2][0] - 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): - codigo_banco_fornecedor = linha_digitavel[:3] - res = {} - - # para banco = 237, bradesco - if (codigo_banco_fornecedor == '237'): - res = { - 'codigo_banco_forn': self.convert_int(codigo_banco_fornecedor), - 'codigo_agencia_forn': self.convert_int(linha_digitavel[4:8]), - # Calcular usando modulo 11 base 7 - 'digito_agencia_forn_transacao': u'', - 'conta_corrente_forn': self.convert_int(linha_digitavel[23:30]), - # Calcular usando modulo 11 base 7 - 'digito_conta_forn_transacao': u'', - - 'carteira': self.convert_int(linha_digitavel[8:10]), - - 'nosso_numero': self.convert_int(linha_digitavel[11:21]) - } - # para outros bancos - else: - res = { - 'codigo_banco_forn': self.convert_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 diff --git a/cnab_erpbrasil_febraban/models/__init__.py b/cnab_erpbrasil_febraban/models/__init__.py index ea8447c48a65..2750539336d1 100644 --- a/cnab_erpbrasil_febraban/models/__init__.py +++ b/cnab_erpbrasil_febraban/models/__init__.py @@ -1,5 +1,5 @@ -from . import account_invoice -from . import account_move_line -from . import account_payment_mode +# Copyright 2019 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + from . import account_payment_order from . import l10n_br_cnab diff --git a/cnab_erpbrasil_febraban/models/account_invoice.py b/cnab_erpbrasil_febraban/models/account_invoice.py deleted file mode 100644 index 80b46121abc0..000000000000 --- a/cnab_erpbrasil_febraban/models/account_invoice.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2019 KMEE -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -import logging - -import json -from datetime import datetime -from dateutil.relativedelta import relativedelta - -from odoo import api, fields, models, _ -from odoo.exceptions import UserError -# from odoo.addons.queue_job.job import job - -# from pyboleto.bank_api.itau import ApiItau - -_logger = logging.getLogger(__name__) - - -class AccountInvoice(models.Model): - - _inherit = 'account.invoice' - - # @job - @api.multi - def register_invoice_api(self): - for record in self: - receivable_ids = record.mapped('move_line_receivable_id') - if not receivable_ids: - return False - - boleto_list = receivable_ids.generate_boleto(validate=False) - if not boleto_list: - raise UserError(_( - u"Não foi possível registrar as faturas pela API" - )) - - company_id = record.partner_id.company_id.sudo() - - itau_key = company_id.itau_key - barcode_endpoint = company_id.raiz_endpoint - environment = company_id.environment - - token = record.obtain_token(company_id, environment) - - for boleto in boleto_list: - ApiItau.convert_to(boleto, tipo_ambiente=environment) - response = False - try: - response = boleto.post(token, itau_key, barcode_endpoint) - if response and response.ok: - # Remove Invoice from debit.orders - record._remove_payment_order_line(_raise=False) - - # Create new Debit Order for payment_order_line - try: - record.create_api_account_payment_line() - - except Exception as e: - _logger.debug(str(e)) - else: - receivable_ids.write({ - 'state_cnab': 'not_accepted' - }) - - except Exception as e: - raise UserError(_( - u"Erro ao registrar a fatura boleto. Verifique se as " - u"configurações da API estão corretas. %s" - ) % str(e)) - - finally: - if response and response.ok: - # ambiente = 1 --> HML - if boleto.tipo_ambiente == '1': - receivable_ids.write({ - 'state_cnab': 'accepted_hml' - }) - # PROD - else: - receivable_ids.write({ - 'state_cnab': 'accepted', - 'situacao_pagamento': 'aberta' - }) - - record.create_bank_api_operation( - response, - operation_type='invoice_register', - environment=environment, - ) - self.message_post(_( - "Comunicação com o banco via API concluída. Verifique a Aba " - "'Operações Bancárias' consultar o resultado do processamento." - )) - - def obtain_token(self, company_id, environment): - """ - Método para buscar ou atualizar o Token da empresa - :param company_id: Empresa - :param environment: Ambiente da operação - :return: O Token da empresa - """ - - token = company_id.api_itau_token - if not token or company_id.api_itau_token_due_datetime <= \ - fields.Datetime.now(): - - client_id = company_id.client_id - client_secret = company_id.client_secret - endpoint = company_id.api_endpoint - - token_request = False - try: - token_request = ApiItau.generate_api_key( - client_id, client_secret, endpoint) - token_request_dict = json.loads(token_request.content) - token = token_request_dict.get('access_token') - company_id.api_itau_token = token - company_id.api_itau_token_due_datetime = \ - fields.Datetime.context_timestamp( - self, datetime.now()) + relativedelta( - seconds=token_request_dict.get('expires_in')) - - except Exception as e: - company_id.api_itau_token = '' - company_id.api_itau_token_due_datetime = \ - fields.Datetime.now() - raise UserError(_( - u"Erro na obtenção do Token de acesso à Api. %s" - ) % str(e)) - finally: - self.create_bank_api_operation( - token_request, - operation_type='token_request', - environment=environment, - ) - self._cr.commit() - - return token diff --git a/cnab_erpbrasil_febraban/models/account_move_line.py b/cnab_erpbrasil_febraban/models/account_move_line.py deleted file mode 100644 index 96b9fff9b94b..000000000000 --- a/cnab_erpbrasil_febraban/models/account_move_line.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2019 KMEE -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api, fields, models, _ -from odoo.exceptions import UserError - -from ..febraban.boleto.document import Boleto - - -class AccountMoveLine(models.Model): - - _inherit = 'account.move.line' - - @api.multi - def generate_boleto(self, validate=True): - boleto_list = [] - - for move_line in self: - - if validate and move_line.state_cnab not in \ - ['accepted', 'accepted_hml']: - if move_line.state_cnab == 'not_accepted': - raise UserError(_( - u'Essa fatura foi transmitida com erro ao banco, ' - u'é necessário corrigí-la e reenviá-la.' - )) - raise UserError(_( - u'Antes de imprimir o boleto é necessário transmitir a ' - u'fatura para registro no banco.' - )) - - boleto = Boleto.getBoleto( - move_line, move_line.nosso_numero - ) - - # Se a cobrança tiver sido emitida em homologação - if move_line.state_cnab == 'accepted_hml': - boleto.boleto.instrucoes.append(_( - u'Boleto emitido em homologacao! Sem valor fiscal!')) - - boleto_list.append(boleto.boleto) - - if not boleto_list: - raise UserError( - 'Error !', ('Não é possível gerar os boletos\n' - 'Certifique-se que a fatura esteja confirmada e o ' - 'forma de pagamento seja duplicatas')) - pdf_string = Boleto.get_pdfs(boleto_list) - return pdf_string \ No newline at end of file diff --git a/cnab_erpbrasil_febraban/models/account_payment_mode.py b/cnab_erpbrasil_febraban/models/account_payment_mode.py deleted file mode 100644 index d85d9e1554f7..000000000000 --- a/cnab_erpbrasil_febraban/models/account_payment_mode.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2019 KMEE -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api, fields, models, _ - -from ..febraban.boleto.document import getBoletoSelection - -boleto_selection = getBoletoSelection() - - -class AccountPaymentMode(models.Model): - - _inherit = 'account.payment.mode' - - boleto_type = fields.Selection( - selection_add=boleto_selection - ) diff --git a/cnab_erpbrasil_febraban/views/account_invoice.xml b/cnab_erpbrasil_febraban/views/account_invoice.xml deleted file mode 100644 index b1faf915bd3e..000000000000 --- a/cnab_erpbrasil_febraban/views/account_invoice.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - account.invoice.form (in cnab_erpbrasil_febraban) - account.invoice - - - - - - - - - From d4bbb35d198973f55845da35754cd2a61eb4c9f1 Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Wed, 30 Sep 2020 07:51:04 -0300 Subject: [PATCH 10/12] [REF] Only cnab 240 Signed-off-by: Luis Felipe Mileo --- cnab_erpbrasil_febraban/__manifest__.py | 8 +-- cnab_erpbrasil_febraban/febraban/cnab.py | 51 ++++--------------- .../models/account_payment_order.py | 13 +---- .../models/l10n_br_cnab.py | 9 ++-- 4 files changed, 20 insertions(+), 61 deletions(-) diff --git a/cnab_erpbrasil_febraban/__manifest__.py b/cnab_erpbrasil_febraban/__manifest__.py index 73b746d9ae66..93c1d84519b2 100644 --- a/cnab_erpbrasil_febraban/__manifest__.py +++ b/cnab_erpbrasil_febraban/__manifest__.py @@ -7,18 +7,18 @@ Integração com CNAB através da biblioteca erpbrasil.febraban""", 'version': '12.0.1.0.0', 'license': 'AGPL-3', - 'author': 'KMEE,Odoo Community Association (OCA)', + 'author': 'KMEE, Odoo Community Association (OCA)', 'website': 'http://odoo-brasil.org', 'depends': [ 'l10n_br_account_payment_order', - # 'queue_job' ], 'data': [ - # 'views/account_invoice.xml', ], 'demo': [ ], 'external_dependencies': { - 'python': ['erpbrasil.febraban'], + 'python': [ + 'febraban', + ], }, } diff --git a/cnab_erpbrasil_febraban/febraban/cnab.py b/cnab_erpbrasil_febraban/febraban/cnab.py index 9ccc7db97e17..0e4a18d30d08 100644 --- a/cnab_erpbrasil_febraban/febraban/cnab.py +++ b/cnab_erpbrasil_febraban/febraban/cnab.py @@ -1,28 +1,22 @@ -# -*- coding: utf-8 -*- # © 2012 KMEE INFORMATICA LTDA # @author Luis Felipe Mileo # @author Daniel Sadamo # @author Fernando Marcato # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from __future__ import division, print_function, unicode_literals - import logging import base64 import codecs from unidecode import unidecode -from febraban.cnab240.itau.sispag import \ - Transfer, DasPayment, IssPayment, UtilityPayment, File -from febraban.cnab240.itau.sispag.file.lot import Lot -from febraban.cnab240.libs.barCode import LineNumberO -from febraban.cnab240.user import User, UserAddress, UserBank - _logger = logging.getLogger(__name__) - try: - from cnab240.tipos import ArquivoCobranca400 + from febraban.cnab240.itau.sispag import \ + Transfer, DasPayment, IssPayment, UtilityPayment, File + from febraban.cnab240.itau.sispag.file.lot import Lot + from febraban.cnab240.libs.barCode import LineNumberO + from febraban.cnab240.user import User, UserAddress, UserBank except ImportError as err: _logger.debug = (err) @@ -135,18 +129,6 @@ def gerar_remessa(order): file.addLot(lot) return file.toString().encode() - elif cnab_type == '400': - raise NotImplementedError - # Legacy Code - from .cnab_400.cnab_400 import Cnab400 - return Cnab400.get_bank(bank) - elif cnab_type == '500': - raise NotImplementedError - # Legacy Code - from .pag_for.pag_for500 import PagFor500 - return PagFor500.get_bank(bank) - else: - return False @staticmethod def detectar_retorno(cnab_file_object): @@ -170,20 +152,9 @@ def detectar_retorno(cnab_file_object): cnab = Cnab.get_cnab(banco, cnab_type)() return cnab_type, cnab.retorno(arquivo_retorno) - - def retorno(self, arquivo_retorno): - return ArquivoCobranca400( - self.classe_retorno, - arquivo=arquivo_retorno - ) - - def remessa(self, order): - pass - - def convert_int(self, campo): - if campo: - return int(campo) - # Retornamos de propósito vazio para que a cnab240 acuse o erro do - # registro em branco pois, se retornarmos ZERO o erro vai passar - # despercebido - return '' + # + # def retorno(self, arquivo_retorno): + # return ArquivoCobranca400( + # self.classe_retorno, + # arquivo=arquivo_retorno + # ) diff --git a/cnab_erpbrasil_febraban/models/account_payment_order.py b/cnab_erpbrasil_febraban/models/account_payment_order.py index 1784e2c000eb..49aa966156a8 100644 --- a/cnab_erpbrasil_febraban/models/account_payment_order.py +++ b/cnab_erpbrasil_febraban/models/account_payment_order.py @@ -1,9 +1,6 @@ -# -*- coding: utf-8 -*- # Copyright 2019 KMEE # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from __future__ import division, print_function, unicode_literals - import logging from odoo import api, models, fields @@ -11,22 +8,14 @@ _logger = logging.getLogger(__name__) -try: - from erpbrasi.febraban.cnab.tipos import Arquivo, Lote - - from cnab240.errors import (Cnab240Error) -except ImportError as err: - _logger.debug = err - class AccountPaymentOrder(models.Model): - _inherit = 'account.payment.order' def _generate_payment_file(self): try: return Cnab.gerar_remessa(order=self), self.name + '.REM' - except Cnab240Error as e: + except Exception as e: _logger.error("Erro ao gerar o arquivo: \n\n{0}".format(e)) @api.multi diff --git a/cnab_erpbrasil_febraban/models/l10n_br_cnab.py b/cnab_erpbrasil_febraban/models/l10n_br_cnab.py index 07bd91386ad5..33ac947b068e 100644 --- a/cnab_erpbrasil_febraban/models/l10n_br_cnab.py +++ b/cnab_erpbrasil_febraban/models/l10n_br_cnab.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2019 KMEE # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -10,8 +9,8 @@ _logger = logging.getLogger(__name__) -class L10n_brCnab(models.Model): +class L10n_brCnab(models.Model): _inherit = 'l10n_br.cnab' @api.multi @@ -50,7 +49,7 @@ def reprocessar_arquivo_retorno(self): else: self._reprocessa_lote_400(evento, lote_id) - #TODO: Verificar necessidade de atualizar dados do Account.Move + # TODO: Verificar necessidade de atualizar dados do Account.Move return self.write({'state': 'done'}) @api.multi @@ -143,8 +142,8 @@ def processar_arquivo_retorno(self): inv_move_lines = inv.move_line_receivable_id pay_move_lines = move.line_ids.filtered( lambda x: x.account_id == inv_move_lines.account_id and - x.partner_id == inv_move_lines.partner_id and - x.name == inv_move_lines.transaction_ref + x.partner_id == inv_move_lines.partner_id and + x.name == inv_move_lines.transaction_ref ) move_lines = pay_move_lines | inv_move_lines move_lines.reconcile() From fdd7508555a758072bf6ff7a46cde8a0e2bed13c Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Wed, 30 Sep 2020 07:51:30 -0300 Subject: [PATCH 11/12] [NEW] Demo data Signed-off-by: Luis Felipe Mileo --- cnab_erpbrasil_febraban/__manifest__.py | 1 + cnab_erpbrasil_febraban/demo/account_payment_order.xml | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 cnab_erpbrasil_febraban/demo/account_payment_order.xml diff --git a/cnab_erpbrasil_febraban/__manifest__.py b/cnab_erpbrasil_febraban/__manifest__.py index 93c1d84519b2..7b17e960d728 100644 --- a/cnab_erpbrasil_febraban/__manifest__.py +++ b/cnab_erpbrasil_febraban/__manifest__.py @@ -15,6 +15,7 @@ 'data': [ ], 'demo': [ + 'demo/account_payment_order.xml', ], 'external_dependencies': { 'python': [ diff --git a/cnab_erpbrasil_febraban/demo/account_payment_order.xml b/cnab_erpbrasil_febraban/demo/account_payment_order.xml new file mode 100644 index 000000000000..85d7684bda38 --- /dev/null +++ b/cnab_erpbrasil_febraban/demo/account_payment_order.xml @@ -0,0 +1,7 @@ + + + + + + + From 83a783ae85dfa6849fbce405678b6d718bf43d8c Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Wed, 30 Sep 2020 07:58:34 -0300 Subject: [PATCH 12/12] [NEW] Readme Files Signed-off-by: Luis Felipe Mileo --- cnab_erpbrasil_febraban/README.rst | 127 +++++ cnab_erpbrasil_febraban/readme/CONFIGURE.rst | 0 .../readme/CONTRIBUTORS.rst | 2 + cnab_erpbrasil_febraban/readme/CREDITS.rst | 4 + .../readme/DESCRIPTION.rst | 13 + cnab_erpbrasil_febraban/readme/HISTORY.rst | 0 cnab_erpbrasil_febraban/readme/INSTALL.rst | 5 + cnab_erpbrasil_febraban/readme/ROADMAP.rst | 5 + cnab_erpbrasil_febraban/readme/USAGE.rst | 11 + .../readme/newsfragments/.gitkeep | 0 .../static/description/index.html | 488 ++++++++++++++++++ 11 files changed, 655 insertions(+) create mode 100644 cnab_erpbrasil_febraban/README.rst create mode 100644 cnab_erpbrasil_febraban/readme/CONFIGURE.rst create mode 100644 cnab_erpbrasil_febraban/readme/CONTRIBUTORS.rst create mode 100644 cnab_erpbrasil_febraban/readme/CREDITS.rst create mode 100644 cnab_erpbrasil_febraban/readme/DESCRIPTION.rst create mode 100644 cnab_erpbrasil_febraban/readme/HISTORY.rst create mode 100644 cnab_erpbrasil_febraban/readme/INSTALL.rst create mode 100644 cnab_erpbrasil_febraban/readme/ROADMAP.rst create mode 100644 cnab_erpbrasil_febraban/readme/USAGE.rst create mode 100644 cnab_erpbrasil_febraban/readme/newsfragments/.gitkeep create mode 100644 cnab_erpbrasil_febraban/static/description/index.html diff --git a/cnab_erpbrasil_febraban/README.rst b/cnab_erpbrasil_febraban/README.rst new file mode 100644 index 000000000000..19fb7719c5d0 --- /dev/null +++ b/cnab_erpbrasil_febraban/README.rst @@ -0,0 +1,127 @@ +======================= +Cnab Erpbrasil Febraban +======================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--brazil-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-brazil/tree/12.0/cnab_erpbrasil_febraban + :alt: OCA/l10n-brazil +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-brazil-12-0/l10n-brazil-12-0-cnab_erpbrasil_febraban + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/124/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Este módulo permite a exportação e importação de arquivos bancários no formato CNAB 240, +permitindo as seguintes operações: + +- Pagamento de Boletos; +- TED; +- DOC; +- Transferência entre contas do mesmo Banco; +- Pagamento de Impostos: + - DAS; + - ISS; + - DARF; + - GPS; + - Guias sem código de barras; + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +[ This file must only be present if there are very specific + installation instructions, such as installing non-python + dependencies. The audience is systems administrators. ] + +* Este módulo tem uma depedencia do pacote python https://github.com/starkbank/febraban-python/ + +Usage +===== + +[ This file must be present and contains the usage instructions + for end-users. As all other rst files included in the README, + it MUST NOT contain reStructuredText sections + only body text (paragraphs, lists, tables, etc). Should you need + a more elaborate structure to explain the addon, please create a + Sphinx documentation (which may include this file as a "quick start" + section). ] + +To use this module, you need to: + +#. Go to ... + +Known issues / Roadmap +====================== + +[ Enumerate known caveats and future potential improvements. + It is mostly intended for end-users, and can also help + potential new contributors discovering new features to implement. ] + +* ... + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* KMEE + +Contributors +~~~~~~~~~~~~ + +* Luis Felipe Mileo +* Gabriel Cardoso + +Other credits +~~~~~~~~~~~~~ + +O desenvolvimento deste módulo foi apoiado financeiramente por: + +* KMEE + + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/l10n-brazil `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/cnab_erpbrasil_febraban/readme/CONFIGURE.rst b/cnab_erpbrasil_febraban/readme/CONFIGURE.rst new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cnab_erpbrasil_febraban/readme/CONTRIBUTORS.rst b/cnab_erpbrasil_febraban/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000000..ecbb4aae4db5 --- /dev/null +++ b/cnab_erpbrasil_febraban/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Luis Felipe Mileo +* Gabriel Cardoso diff --git a/cnab_erpbrasil_febraban/readme/CREDITS.rst b/cnab_erpbrasil_febraban/readme/CREDITS.rst new file mode 100644 index 000000000000..74066855453e --- /dev/null +++ b/cnab_erpbrasil_febraban/readme/CREDITS.rst @@ -0,0 +1,4 @@ +O desenvolvimento deste módulo foi apoiado financeiramente por: + +* KMEE + diff --git a/cnab_erpbrasil_febraban/readme/DESCRIPTION.rst b/cnab_erpbrasil_febraban/readme/DESCRIPTION.rst new file mode 100644 index 000000000000..270343750f9b --- /dev/null +++ b/cnab_erpbrasil_febraban/readme/DESCRIPTION.rst @@ -0,0 +1,13 @@ +Este módulo permite a exportação e importação de arquivos bancários no formato CNAB 240, +permitindo as seguintes operações: + +- Pagamento de Boletos; +- TED; +- DOC; +- Transferência entre contas do mesmo Banco; +- Pagamento de Impostos: + - DAS; + - ISS; + - DARF; + - GPS; + - Guias sem código de barras; diff --git a/cnab_erpbrasil_febraban/readme/HISTORY.rst b/cnab_erpbrasil_febraban/readme/HISTORY.rst new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cnab_erpbrasil_febraban/readme/INSTALL.rst b/cnab_erpbrasil_febraban/readme/INSTALL.rst new file mode 100644 index 000000000000..620c3d6417ef --- /dev/null +++ b/cnab_erpbrasil_febraban/readme/INSTALL.rst @@ -0,0 +1,5 @@ +[ This file must only be present if there are very specific + installation instructions, such as installing non-python + dependencies. The audience is systems administrators. ] + +* Este módulo tem uma depedencia do pacote python https://github.com/starkbank/febraban-python/ diff --git a/cnab_erpbrasil_febraban/readme/ROADMAP.rst b/cnab_erpbrasil_febraban/readme/ROADMAP.rst new file mode 100644 index 000000000000..207233013b40 --- /dev/null +++ b/cnab_erpbrasil_febraban/readme/ROADMAP.rst @@ -0,0 +1,5 @@ +[ Enumerate known caveats and future potential improvements. + It is mostly intended for end-users, and can also help + potential new contributors discovering new features to implement. ] + +* ... diff --git a/cnab_erpbrasil_febraban/readme/USAGE.rst b/cnab_erpbrasil_febraban/readme/USAGE.rst new file mode 100644 index 000000000000..f4629c3d548a --- /dev/null +++ b/cnab_erpbrasil_febraban/readme/USAGE.rst @@ -0,0 +1,11 @@ +[ This file must be present and contains the usage instructions + for end-users. As all other rst files included in the README, + it MUST NOT contain reStructuredText sections + only body text (paragraphs, lists, tables, etc). Should you need + a more elaborate structure to explain the addon, please create a + Sphinx documentation (which may include this file as a "quick start" + section). ] + +To use this module, you need to: + +#. Go to ... diff --git a/cnab_erpbrasil_febraban/readme/newsfragments/.gitkeep b/cnab_erpbrasil_febraban/readme/newsfragments/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cnab_erpbrasil_febraban/static/description/index.html b/cnab_erpbrasil_febraban/static/description/index.html new file mode 100644 index 000000000000..e49589a5d7d1 --- /dev/null +++ b/cnab_erpbrasil_febraban/static/description/index.html @@ -0,0 +1,488 @@ + + + + + + +Cnab Erpbrasil Febraban + + + +
+

Cnab Erpbrasil Febraban

+ + +

Beta License: AGPL-3 OCA/l10n-brazil Translate me on Weblate Try me on Runbot

+

Este módulo permite a exportação e importação de arquivos bancários no formato CNAB 240, +permitindo as seguintes operações:

+
    +
  • Pagamento de Boletos;
  • +
  • TED;
  • +
  • DOC;
  • +
  • Transferência entre contas do mesmo Banco;
  • +
  • +
    Pagamento de Impostos:
    +
      +
    • DAS;
    • +
    • ISS;
    • +
    • DARF;
    • +
    • GPS;
    • +
    • Guias sem código de barras;
    • +
    +
    +
    +
  • +
+

Table of contents

+ +
+

Installation

+
+
[ This file must only be present if there are very specific
+
installation instructions, such as installing non-python +dependencies. The audience is systems administrators. ]
+
+ +
+
+

Usage

+
+
[ This file must be present and contains the usage instructions
+
for end-users. As all other rst files included in the README, +it MUST NOT contain reStructuredText sections +only body text (paragraphs, lists, tables, etc). Should you need +a more elaborate structure to explain the addon, please create a +Sphinx documentation (which may include this file as a “quick start” +section). ]
+
+

To use this module, you need to:

+
    +
  1. Go to …
  2. +
+
+
+

Known issues / Roadmap

+
+
[ Enumerate known caveats and future potential improvements.
+
It is mostly intended for end-users, and can also help +potential new contributors discovering new features to implement. ]
+
+
    +
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • KMEE
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

O desenvolvimento deste módulo foi apoiado financeiramente por:

+
    +
  • KMEE
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/l10n-brazil project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ +