diff --git a/.isort.cfg b/.isort.cfg index 08469fcdb7ab..6bd177f35c7a 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,2 +1,2 @@ [settings] -known_third_party = OpenSSL,dateutil,erpbrasil,lxml,odoo,openupgradelib,requests,setuptools +known_third_party = OpenSSL,dateutil,erpbrasil,lxml,odoo,openerp,openupgradelib,pytz,requests,setuptools,workalendar diff --git a/README.md b/README.md index c12b4edb11db..47bf2710b861 100644 --- a/README.md +++ b/README.md @@ -76,23 +76,27 @@ Available addons ---------------- addon | version | summary --- | --- | --- -[l10n_br_account](l10n_br_account/) | 12.0.2.0.0 | Brazilian Localization Account +[l10n_br_account](l10n_br_account/) | 12.0.2.1.1 | Brazilian Localization Account [l10n_br_account_payment_order](l10n_br_account_payment_order/) | 12.0.1.0.0 | Brazilian Payment Order [l10n_br_base](l10n_br_base/) | 12.0.1.0.1 | Customization of base module for implementations in Brazil. -[l10n_br_coa](l10n_br_coa/) | 12.0.2.0.0 | Base Brasilian Localization of Chart of Account -[l10n_br_coa_generic](l10n_br_coa_generic/) | 12.0.2.0.0 | Plano de Contas para empresas do Regime normal (Micro e pequenas empresas) -[l10n_br_coa_simple](l10n_br_coa_simple/) | 12.0.2.0.0 | Brazilian Simple Chart of Account +[l10n_br_coa](l10n_br_coa/) | 12.0.2.1.0 | Base Brasilian Localization for the Chart of Accounts +[l10n_br_coa_generic](l10n_br_coa_generic/) | 12.0.2.1.0 | Plano de Contas para empresas do Regime normal (Micro e pequenas empresas) +[l10n_br_coa_simple](l10n_br_coa_simple/) | 12.0.2.1.0 | Brazilian Simple Chart of Account [l10n_br_crm](l10n_br_crm/) | 12.0.1.0.0 | Brazilian Localization CRM [l10n_br_currency_rate_update](l10n_br_currency_rate_update/) | 12.0.1.0.0 | Update exchange rates using OCA modules for Brazil -[l10n_br_fiscal](l10n_br_fiscal/) | 12.0.3.5.1 | Brazilian fiscal core module. +[l10n_br_fiscal](l10n_br_fiscal/) | 12.0.4.0.0 | Brazilian fiscal core module. [l10n_br_hr](l10n_br_hr/) | 12.0.1.0.0 | Brazilian Localization HR [l10n_br_hr_contract](l10n_br_hr_contract/) | 12.0.1.0.0 | Brazilian Localization HR Contract -[l10n_br_nfse](l10n_br_nfse/) | 12.0.1.3.0 | NFS-e +[l10n_br_mis_report](l10n_br_mis_report/) | 12.0.1.1.0 | Templates de relatórios contábeis brasileiros: Balanço Patrimonial e DRE +[l10n_br_nfse](l10n_br_nfse/) | 12.0.1.4.0 | NFS-e [l10n_br_portal](l10n_br_portal/) | 12.0.1.0.0 | Campos Brasileiros no Portal [l10n_br_resource](l10n_br_resource/) | 12.0.1.0.0 | This module extend core resource to create important brazilian informations. Define a Brazilian calendar and some tools to compute dates used in financial and payroll modules [l10n_br_sale](l10n_br_sale/) | 12.0.1.0.0 | Brazilian Localization Sale [l10n_br_stock](l10n_br_stock/) | 12.0.1.0.0 | Brazilian Localization Warehouse +[l10n_br_stock_account](l10n_br_stock_account/) | 12.0.1.0.0 | Brazilian Localization WMS Accounting +[l10n_br_website_sale](l10n_br_website_sale/) | 12.0.1.0.1 | Website sale localização brasileira. [l10n_br_zip](l10n_br_zip/) | 12.0.2.0.0 | Brazilian Localisation ZIP Codes +[payment_cielo](payment_cielo/) | 12.0.3.2.0 | Payment Acquirer: Cielo Implementation Unported addons diff --git a/l10n_br_account/__manifest__.py b/l10n_br_account/__manifest__.py index 8f3574973500..92d0cd5d69c4 100644 --- a/l10n_br_account/__manifest__.py +++ b/l10n_br_account/__manifest__.py @@ -7,7 +7,7 @@ "license": "AGPL-3", "author": "Akretion, Odoo Community Association (OCA)", "website": "http://github.com/OCA/l10n-brazil", - "version": "12.0.2.0.0", + "version": "12.0.2.1.1", "depends": ["account_cancel", "l10n_br_coa", "l10n_br_fiscal"], "data": [ # security diff --git a/l10n_br_account/data/account_tax_group.xml b/l10n_br_account/data/account_tax_group.xml index 1dd96f9b3c43..1bb2dbe5f416 100644 --- a/l10n_br_account/data/account_tax_group.xml +++ b/l10n_br_account/data/account_tax_group.xml @@ -1,5 +1,5 @@ - + diff --git a/l10n_br_account/i18n/pt_BR.po b/l10n_br_account/i18n/pt_BR.po index 9e223e2b47d7..df070c6c1145 100644 --- a/l10n_br_account/i18n/pt_BR.po +++ b/l10n_br_account/i18n/pt_BR.po @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-04-07 09:02+0000\n" -"PO-Revision-Date: 2020-06-13 17:19+0000\n" -"Last-Translator: Maurício Liell \n" +"PO-Revision-Date: 2020-11-05 07:08+0000\n" +"Last-Translator: Eder Brito \n" "Language-Team: \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" @@ -25,7 +25,7 @@ msgstr "Conta" #. module: l10n_br_account #: model:ir.model,name:l10n_br_account.model_l10n_br_account_document_line_mixin msgid "Account Document Line Mixin" -msgstr "" +msgstr "Mixin de Linha de Documento da Conta" #. module: l10n_br_account #: model:ir.model.fields,field_description:l10n_br_account.field_l10n_br_fiscal_operation__journal_id @@ -69,7 +69,7 @@ msgstr "Anotação de crédito" #. module: l10n_br_account #: model:ir.model.fields,field_description:l10n_br_account.field_l10n_br_account_document_line_mixin__display_name msgid "Display Name" -msgstr "" +msgstr "Nome de Exibição" #. module: l10n_br_account #: code:addons/l10n_br_account/wizards/account_invoice_refund.py:68 @@ -143,7 +143,7 @@ msgstr "Forçar Operação Fiscal" #. module: l10n_br_account #: model:ir.model.fields,field_description:l10n_br_account.field_l10n_br_account_document_line_mixin__id msgid "ID" -msgstr "" +msgstr "ID" #. module: l10n_br_account #: model:ir.model,name:l10n_br_account.model_account_invoice @@ -163,22 +163,22 @@ msgstr "Item de Diário" #. module: l10n_br_account #: model:ir.model.fields,field_description:l10n_br_account.field_l10n_br_account_document_line_mixin____last_update msgid "Last Modified on" -msgstr "" +msgstr "Última Modificação em" #. module: l10n_br_account #: model_terms:ir.ui.view,arch_db:l10n_br_account.invoice_search msgid "Legal Name" -msgstr "" +msgstr "Razão Social" #. module: l10n_br_account #: model_terms:ir.ui.view,arch_db:l10n_br_account.invoice_line_form msgid "Outros Custos" -msgstr "" +msgstr "Outros Custos" #. module: l10n_br_account #: model_terms:ir.ui.view,arch_db:l10n_br_account.invoice_search msgid "State Tax Number" -msgstr "" +msgstr "Número de Imposto Estadual" #. module: l10n_br_account #: model:ir.model,name:l10n_br_account.model_account_tax @@ -194,7 +194,7 @@ msgstr "Grupo de Imposto" #. module: l10n_br_account #: model_terms:ir.ui.view,arch_db:l10n_br_account.invoice_line_form msgid "Taxes" -msgstr "" +msgstr "Impostos" #. module: l10n_br_account #: model:ir.model,name:l10n_br_account.model_account_tax_template @@ -211,6 +211,8 @@ msgstr "Usado nos documentos fiscais" #, python-format msgid "You cannot delete a fiscal document which is not draft state." msgstr "" +"Você não pode excluir um documento fiscal que não esteja no estado de " +"rascunho." #~ msgid "Tax Account" #~ msgstr "Conta de imposto" diff --git a/l10n_br_account/models/account_invoice_line.py b/l10n_br_account/models/account_invoice_line.py index 7f7e021be748..df60fccfb7fc 100644 --- a/l10n_br_account/models/account_invoice_line.py +++ b/l10n_br_account/models/account_invoice_line.py @@ -143,6 +143,9 @@ def create(self, values): def write(self, values): dummy_doc_line = self.env.ref( 'l10n_br_fiscal.fiscal_document_line_dummy') + if values.get('invoice_id'): + values['document_id'] = self.env[ + "account.invoice"].browse(values['invoice_id']).fiscal_document_id.id result = super().write(values) for line in self: if line.fiscal_document_line_id != dummy_doc_line: diff --git a/l10n_br_account/tests/test_customer_invoice_dummy.py b/l10n_br_account/tests/test_customer_invoice_dummy.py index c4ef60d267cc..362a64b9593c 100644 --- a/l10n_br_account/tests/test_customer_invoice_dummy.py +++ b/l10n_br_account/tests/test_customer_invoice_dummy.py @@ -228,3 +228,11 @@ def test_invoice_other_currency(self): assert self.invoice_3.move_id, "Move Receivable not created for open invoice" self.assertEquals( self.invoice_3.state, "open", "Invoice should be in state Open") + + def test_invoice_line_ids_write(self): + self.invoice_3.invoice_line_ids.write({'invoice_id': self.invoice_3.id}) + for line in self.invoice_3.invoice_line_ids: + self.assertEquals( + line.document_id.id, + self.invoice_3.fiscal_document_id.id, + "line.document_id should be equal account.fiscal_document_id") diff --git a/l10n_br_account/wizards/account_invoice_refund.py b/l10n_br_account/wizards/account_invoice_refund.py index 89758b7011a1..9b4d3ab35821 100644 --- a/l10n_br_account/wizards/account_invoice_refund.py +++ b/l10n_br_account/wizards/account_invoice_refund.py @@ -35,59 +35,59 @@ def compute_refund(self, mode="refund"): if ( not self.force_fiscal_operation_id - and not invoice.operation_id + and not invoice.fiscal_operation_id ): raise UserError(_("Document without Operation !")) if ( not self.force_fiscal_operation_id - and not invoice.operation_id.return_operation_id + and not invoice.fiscal_operation_id.return_operation_id ): raise UserError( _( "Fiscal Operation: There is not Return Operation " "for %s !" ) - % invoice.operation_id.name + % invoice.fiscal_operation_id.name ) - invoice.operation_id = ( + invoice.fiscal_operation_id = ( self.force_fiscal_operation_id.id - or invoice.operation_id.return_operation_id.id + or invoice.fiscal_operation_id.return_operation_id.id ) invoice_values = { - "operation_id": invoice.operation_id.id, + "fiscal_operation_id": invoice.fiscal_operation_id.id, } for line in invoice.invoice_line_ids: if ( not self.force_fiscal_operation_id - and not line.operation_id + and not line.fiscal_operation_id ): raise UserError(_("Document line without Operation !")) if ( not self.force_fiscal_operation_id - and not line.operation_id.refund_operation_id + and not line.fiscal_operation_id.refund_operation_id ): raise UserError( _( "Fiscal Operation: There is not Return " "Operation for %s !" ) - % line.operation_id.name + % line.fiscal_operation_id.name ) - line.operation_id = ( + line.fiscal_operation_id = ( self.force_fiscal_operation_id.id - or line.operation_id.return_operation_id + or line.fiscal_operation_id.return_operation_id ) line._onchange_operation_id() line_values = { - "operation_id": line.operation_id.id, + "fiscal_operation_id": line.fiscal_operation_id.id, "fiscal_operation_line_id": line.fiscal_operation_line_id.id, } line.write(line_values) @@ -104,10 +104,10 @@ def fields_view_get(self, view_id=None, view_type="form", toolbar=False, fiscal_operation_type = REFUND_TO_OPERATION[invoice_type] fiscal_type = FISCAL_TYPE_REFUND[fiscal_operation_type] eview = etree.fromstring(result["arch"]) - operation_id = eview.xpath( + fiscal_operation_id = eview.xpath( "//field[@name='force_fiscal_operation_id']") - for field in operation_id: + for field in fiscal_operation_id: field.set( "domain", "[('fiscal_operation_type', '=', '%s'), ('fiscal_type', 'in', %s)]" diff --git a/l10n_br_account_payment_order/README.rst b/l10n_br_account_payment_order/README.rst index 20d8f3c607d2..7650a5f3c3e2 100644 --- a/l10n_br_account_payment_order/README.rst +++ b/l10n_br_account_payment_order/README.rst @@ -117,14 +117,6 @@ Contributors * Magno Costa -Other credits -~~~~~~~~~~~~~ - -The development of this module has been financially supported by: - -* KMEE INFORMATICA LTDA - www.kmee.com.br -* AKRETION LTDA - www.akretion.com - Maintainers ~~~~~~~~~~~ diff --git a/l10n_br_account_payment_order/__init__.py b/l10n_br_account_payment_order/__init__.py index 11edac49f06d..c50673613615 100644 --- a/l10n_br_account_payment_order/__init__.py +++ b/l10n_br_account_payment_order/__init__.py @@ -3,4 +3,5 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models +from . import wizards from . import tests diff --git a/l10n_br_account_payment_order/__manifest__.py b/l10n_br_account_payment_order/__manifest__.py index 37b53c868065..15c9ccce5931 100644 --- a/l10n_br_account_payment_order/__manifest__.py +++ b/l10n_br_account_payment_order/__manifest__.py @@ -4,9 +4,10 @@ { 'name': 'Brazilian Payment Order', - 'version': '12.0.1.0.0', + 'version': '12.0.3.0.0', 'license': 'AGPL-3', 'author': "KMEE, " + "Akretion, " "Odoo Community Association (OCA)", 'website': 'https://github.com/OCA/l10n-brazil', 'category': 'Banking addons', @@ -17,16 +18,61 @@ 'account_cancel', ], 'data': [ - 'views/account_due_list.xml', + # Security + 'security/cnab_cobranca_security.xml', + 'security/ir.model.access.csv', + + # Data + 'data/cnab_data.xml', + 'data/l10n_br_payment_export_type.xml', + 'data/boleto_data.xml', + 'data/account_analytic_tag_data.xml', + 'data/l10n_br_cnab_return_move_code_data.xml', + 'data/l10n_br_cnab_mov_instruction_code_data.xml', + 'data/l10n_br_cnab_option_data.xml', + + # Reports + 'reports/report_print_button_view.xml', + + # Wizards + 'wizards/account_payment_line_create_view.xml', + 'wizards/account_move_line_change.xml', + + # Views + 'views/account_journal.xml', 'views/account_payment_order.xml', - 'views/account_payment_order_menu_views.xml', 'views/account_payment_line.xml', 'views/account_payment_mode.xml', + 'views/res_company.xml', + 'views/bank_payment_line.xml', + # TODO - Separação dos dados de importação para um objeto especifico + # cnab.return.log armazenando o LOG do Arquivo de Retorno CNAB + # de forma separada e permitindo a integração com a alteração feita no + # modulo do BRCobranca onde se esta utilizando o modulo + # account_base_move_import para fazer essa tarefa de wizard de importação, + # o objeto l10n_br_cnab esta comentado para permitir, caso seja necessário, + # a implementação de outra forma de importação pois tem os metodos que eram + # usados pela KMEE e o historico git do arquivo + # 'views/l10n_br_cnab_retorno_view.xml', + # 'views/l10n_br_cnab_evento_views.xml', + # 'views/l10n_br_payment_cnab.xml', + # 'views/l10n_br_cobranca_cnab.xml', + # 'views/l10n_br_cobranca_cnab_lines.xml', + 'views/l10n_br_cnab_return_log_view.xml', + 'views/account_invoice.xml', + 'views/account_move_line.xml', + 'views/l10n_br_cnab_return_move_code_view.xml', + 'views/account_payment_views.xml', + 'views/l10n_br_cnab_mov_instruction_code_view.xml', + 'views/account_move_view.xml' ], 'demo': [ 'demo/res_partner_bank.xml', + 'demo/account_account.xml', 'demo/account_journal.xml', 'demo/account_payment_mode.xml', + 'demo/account_invoice.xml', + 'demo/res_users.xml', 'demo/account_payment_order.xml', ], 'installable': True, diff --git a/l10n_br_account_payment_order/constants.py b/l10n_br_account_payment_order/constants.py new file mode 100644 index 000000000000..eac36e4aad4e --- /dev/null +++ b/l10n_br_account_payment_order/constants.py @@ -0,0 +1,416 @@ +# © 2012 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +NAO_EMITE_AVISO = ("0", "0 - Não Emite Aviso") +EMITE_AVISO_REMETENTE = ("2", "2 - Emite Aviso Somente para o Remetente") +EMITE_AVISO_FAVORECIDO = ("5", "5 - Emite Aviso Somente para o Favorecido") +EMITE_AVISO_REMETENTE_FAVORECIDO = ( + "6", + "6 - Emite Aviso para o Remetente e Favorecido", +) +EMITE_AVISO_FAVORECIDO_2_VIAS_REMETENTE = ( + "7", + "7 - Emite Aviso para o Favorecido e 2 Vias para o Remetente", +) + +AVISO_FAVORECIDO = [ + NAO_EMITE_AVISO, + EMITE_AVISO_REMETENTE, + EMITE_AVISO_FAVORECIDO, + EMITE_AVISO_REMETENTE_FAVORECIDO, + EMITE_AVISO_FAVORECIDO_2_VIAS_REMETENTE, +] + +INDICATIVO_FORMA_PAGAMENTO = [ + ("01", "01 - Débito em Conta Corrente"), + ("02", "02 - Débito Empréstimo/Financiamento"), + ("03", "03 - Débito Cartão de Crédito"), +] + +TIPO_MOVIMENTO = [ + ("0", "0 - Indica INCLUSÃO"), + ("1", "1 - Indica CONSULTA"), + ("2", "2 - Indica SUSPENSÃO"), + ("3", "3 - Indica ESTORNO (somente para retorno)"), + ("4", "4 - Indica REATIVAÇÃO"), + ("5", "5 - Indica ALTERAÇÃO"), + ("7", "7 - Indica LIQUIDAÇAO"), + ("9", "9 - Indica EXCLUSÃO"), +] + +CODIGO_OCORRENCIAS = [ + ("00", "00 - Crédito ou Débito Efetivado"), + ("01", "01 - Insuficiência de Fundos - Débito Não Efetuado"), + ("02", "02 - Crédito ou Débito Cancelado pelo Pagador/Credor"), + ("03", "03 - Débito Autorizado pela Agência - Efetuado"), + ("AA", "AA - Controle Inválido"), + ("AB", "AB - Tipo de Operação Inválido"), + ("AC", "AC - Tipo de Serviço Inválido"), + ("AD", "AD - Forma de Lançamento Inválida"), + ("AE", "AE - Tipo/Número de Inscrição Inválido"), + ("AF", "AF - Código de Convênio Inválido"), + ("AG", "AG - Agência/Conta Corrente/DV Inválido"), + ("AH", "AH - Nº Seqüencial do Registro no Lote Inválido"), + ("AI", "AI - Código de Segmento de Detalhe Inválido"), + ("AJ", "AJ - Tipo de Movimento Inválido"), + ( + "AK", + "AK - Código da Câmara de Compensação do Banco" + " Favorecido/Depositário Inválido", + ), + ( + "AL", + "AL - Código do Banco Favorecido, Instituição de Pagamento" + " ou Depositário Inválido", + ), + ("AM", "AM - Agência Mantenedora da Conta Corrente do" " Favorecido Inválida"), + ("AN", "AN - Conta Corrente/DV/Conta de Pagamento do" " Favorecido Inválido"), + ("AO", "AO - Nome do Favorecido Não Informado"), + ("AP", "AP - Data Lançamento Inválido"), + ("AQ", "AQ - Tipo/Quantidade da Moeda Inválido"), + ("AR", "AR - Valor do Lançamento Inválido"), + ("AS", "AS - Aviso ao Favorecido - Identificação Inválida"), + ("AT", "AT - Tipo/Número de Inscrição do Favorecido Inválido"), + ("AU", "AU - Logradouro do Favorecido Não Informado"), + ("AV", "AV - Nº do Local do Favorecido Não Informado"), + ("AW", "AW - Cidade do Favorecido Não Informada"), + ("AX", "AX - CEP/Complemento do Favorecido Inválido"), + ("AY", "AY - Sigla do Estado do Favorecido Inválida"), + ("AZ", "AZ - Código/Nome do Banco Depositário Inválido"), + ("BA", "BA - Código/Nome da Agência Depositária Não Informado"), + ("BB", "BB - Seu Número Inválido"), + ("BC", "BC - Nosso Número Inválido"), + ("BD", "BD - Inclusão Efetuada com Sucesso"), + ("BE", "BE - Alteração Efetuada com Sucesso"), + ("BF", "BF - Exclusão Efetuada com Sucesso"), + ("BG", "BG - Agência/Conta Impedida Legalmente"), + ("BH", "BH - Empresa não pagou salário"), + ("BI", "BI - Falecimento do mutuário"), + ("BJ", "BJ - Empresa não enviou remessa do mutuário"), + ("BK", "BK - Empresa não enviou remessa no vencimento"), + ("BL", "BL - Valor da parcela inválida"), + ("BM", "BM - Identificação do contrato inválida"), + ("BN", "BN - Operação de Consignação Incluída com Sucesso"), + ("BO", "BO - Operação de Consignação Alterada com Sucesso"), + ("BP", "BP - Operação de Consignação Excluída com Sucesso"), + ("BQ", "BQ - Operação de Consignação Liquidada com Sucesso"), + ("BR", "BR - Reativação Efetuada com Sucesso"), + ("BS", "BS - Suspensão Efetuada com Sucesso"), + ("CA", "CA - Código de Barras - Código do Banco Inválido"), + ("CB", "CB - Código de Barras - Código da Moeda Inválido"), + ("CC", "CC - Código de Barras - Dígito Verificador Geral Inválido"), + ("CD", "CD - Código de Barras - Valor do Título Inválido"), + ("CE", "CE - Código de Barras - Campo Livre Inválido"), + ("CF", "CF - Valor do Documento Inválido"), + ("CG", "CG - Valor do Abatimento Inválido"), + ("CH", "CH - Valor do Desconto Inválido"), + ("CI", "CI - Valor de Mora Inválido"), + ("CJ", "CJ - Valor da Multa Inválido"), + ("CK", "CK - Valor do IR Inválido"), + ("CL", "CL - Valor do ISS Inválido"), + ("CM", "CM - Valor do IOF Inválido"), + ("CN", "CN - Valor de Outras Deduções Inválido"), + ("CO", "CO - Valor de Outros Acréscimos Inválido"), + ("CP", "CP - Valor do INSS Inválido"), + ("HA", "HA - Lote Não Aceito"), + ("HB", "HB - Inscrição da Empresa Inválida para o Contrato"), + ("HC", "HC - Convênio com a Empresa Inexistente/Inválido" " para o Contrato"), + ( + "HD", + "HD - Agência/Conta Corrente da Empresa Inexistente/Inválido" + " para o Contrato", + ), + ("HE", "HE - Tipo de Serviço Inválido para o Contrato"), + ("HF", "HF - Conta Corrente da Empresa com Saldo Insuficiente"), + ("HG", "HG - Lote de Serviço Fora de Seqüência"), + ("HH", "HH - Lote de Serviço Inválido"), + ("HI", "HI - Arquivo não aceito"), + ("HJ", "HJ - Tipo de Registro Inválido"), + ("HK", "HK - Código Remessa / Retorno Inválido"), + ("HL", "HL - Versão de layout inválida"), + ("HM", "HM - Mutuário não identificado"), + ("HN", "HN - Tipo do beneficio não permite empréstimo"), + ("HO", "HO - Beneficio cessado/suspenso"), + ("HP", "HP - Beneficio possui representante legal"), + ("HQ", "HQ - Beneficio é do tipo PA (Pensão alimentícia)"), + ("HR", "HR - Quantidade de contratos permitida excedida"), + ("HS", "HS - Beneficio não pertence ao Banco informado"), + ("HT", "HT - Início do desconto informado já ultrapassado"), + ("HU", "HU - Número da parcela inválida"), + ("HV", "HV - Quantidade de parcela inválida"), + ( + "HW", + "HW - Margem consignável excedida para o mutuário dentro" + " do prazo do contrato", + ), + ("HX", "HX - Empréstimo já cadastrado"), + ("HY", "HY - Empréstimo inexistente"), + ("HZ", "HZ - Empréstimo já encerrado"), + ("H1", "H1 - Arquivo sem trailer"), + ("H2", "H2 - Mutuário sem crédito na competência"), + ("H3", "H3 - Não descontado – outros motivos"), + ("H4", "H4 - Retorno de Crédito não pago"), + ("H5", "H5 - Cancelamento de empréstimo retroativo"), + ("H6", "H6 - Outros Motivos de Glosa"), + ( + "H7", + "H7 - Margem consignável excedida para o mutuário acima" + " do prazo do contrato", + ), + ("H8", "H8 - Mutuário desligado do empregador"), + ("H9", "H9 - Mutuário afastado por licença"), + ( + "IA", + "IA - Primeiro nome do mutuário diferente do primeiro nome" + " do movimento do censo ou diferente da base de Titular" + " do Benefício", + ), + ("IB", "IB - Benefício suspenso/cessado pela APS ou Sisobi"), + ("IC", "IC - Benefício suspenso por dependência de cálculo"), + ("ID", "ID - Benefício suspenso/cessado pela inspetoria/auditoria"), + ("IE", "IE - Benefício bloqueado para empréstimo pelo beneficiário"), + ("IF", "IF - Benefício bloqueado para empréstimo por TBM"), + ("IG", "IG - Benefício está em fase de concessão de PA ou desdobramento"), + ("IH", "IH - Benefício cessado por óbito"), + ("II", "II - Benefício cessado por fraude"), + ("IJ", "IJ - Benefício cessado por concessão de outro benefício"), + ("IK", "IK - Benefício cessado: estatutário transferido" " para órgão de origem"), + ("IL", "IL - Empréstimo suspenso pela APS"), + ("IM", "IM - Empréstimo cancelado pelo banco"), + ("IN", "IN - Crédito transformado em PAB"), + ("IO", "IO - Término da consignação foi alterado"), + ( + "IP", + "IP - Fim do empréstimo ocorreu durante período" " de suspensão ou concessão", + ), + ("IQ", "IQ - Empréstimo suspenso pelo banco"), + ( + "IR", + "IR - Não averbação de contrato – quantidade de" + " parcelas/competências informadas ultrapassou a data limite" + " da extinção de cota do dependente titular de benefícios", + ), + ("TA", "TA - Lote Não Aceito - Totais do Lote com Diferença"), + ("YA", "YA - Título Não Encontrado"), + ("YB", "YB - Identificador Registro Opcional Inválido"), + ("YC", "YC - Código Padrão Inválido"), + ("YD", "YD - Código de Ocorrência Inválido"), + ("YE", "YE - Complemento de Ocorrência Inválido"), + ("YF", "YF - Alegação já Informada"), + ("ZA", "ZA - Agência / Conta do Favorecido Substituída"), + ( + "ZB", + "ZB - Divergência entre o primeiro e último nome do beneficiário" + " versus primeiro e último nome na Receita Federal", + ), + ("ZC", "ZC - Confirmação de Antecipação de Valor"), + ("ZD", "ZD - Antecipação parcial de valor"), + ("ZE", "ZE - Título bloqueado na base"), + ("ZF", "ZF - Sistema em contingência" " – título valor maior que referência"), + ("ZG", "ZG - Sistema em contingência – título vencido"), + ("ZH", "ZH - Sistema em contingência – título indexado"), + ("ZI", "ZI - Beneficiário divergente"), + ("ZJ", "ZJ - Limite de pagamentos parciais excedido"), + ("ZK", "ZK - Boleto já liquidado"), +] + +ESTADOS_CNAB = [ + ("draft", "Inicial"), + ("added", "Adicionada à ordem de pagamento"), + ("added_paid", "Adicionada para Baixa"), + ("exported", "Exportada"), + ("exporting_error", "Erro ao exportar"), + ("accepted", "Aceita"), + ("accepted_hml", "Aceita em Homologação"), + ("not_accepted", "Não aceita pelo banco"), + ("done", "Concluído"), +] + +SITUACAO_PAGAMENTO = [ + ("inicial", "Inicial"), + ("aberta", "Aberta"), + ("paga", "Paga"), + ("liquidada", "Liquidada"), + ("baixa", "Baixa Simples"), + ("baixa_liquidacao", "Baixa por Liquidação em Dinheiro"), +] + +BOLETO_ESPECIE = [ + ("01", "DUPLICATA MERCANTIL"), + ("02", "NOTA PROMISSÓRIA"), + ("03", "NOTA DE SEGURO"), + ("04", "MENSALIDADE ESCOLAR"), + ("05", "RECIBO"), + ("06", "CONTRATO"), + ("07", "COSSEGUROS"), + ("08", "DUPLICATA DE SERVIÇO"), + ("09", "LETRA DE CÂMBIO"), + ("13", "NOTA DE DÉBITOS"), + ("15", "DOCUMENTO DE DÍVIDA"), + ("16", "ENCARGOS CONDOMINIAIS"), + ("17", "CONTA DE PRESTAÇÃO DE SERVIÇOS"), + ("99", "DIVERSOS"), +] + +STATE_CNAB = [ + ("draft", "Novo"), + ("done", "Processado"), + ("error", "Erro no Processamento") +] + +TIPO_OPERACAO_CNAB = { + "C": "Lançamento a Crédito", + "D": "Lançamento a Débito", + "E": "Extrato para Conciliação", + "G": "Extrato para Gestão de Caixa", + "I": "Informações de Títulos Capturados do Próprio Banco", + "R": "Arquivo Remessa", + "T": "Arquivo Retorno", +} + +# COD_REGISTROS_REJEITADOS_CNAB400 -> USADO QUANDO HA CODIGO DE OCORRENCIA 03 +# NA POSIÇÃO 109-110 +COD_REGISTROS_REJEITADOS_CNAB400 = { + 3: "AG. COBRADORA - CEP SEM ATENDIMENTO DE PROTESTO NO MOMENTO", + 4: "ESTADO - SIGLA DO ESTADO INVÁLIDA", + 5: "DATA VENCIMENTO - PRAZO DA OPERAÇÃO MENOR QUE PRAZO MÍNIMO OU MAIOR QUE O MÁXIMO", # noqa + 7: "VALOR DO TÍTULO - VALOR DO TÍTULO MAIOR QUE 10.000.000,00", + 8: "NOME DO PAGADOR - NÃO INFORMADO OU DESLOCADO", + 9: "AGENCIA/CONTA - AGÊNCIA ENCERRADA", + 10: "LOGRADOURO - NÃO INFORMADO OU DESLOCADO", + 11: "CEP - CEP NÃO NUMÉRICO OU CEP INVÁLIDO", + 12: "SACADOR / AVALISTA - NOME NÃO INFORMADO OU DESLOCADO (BANCOS CORRESPONDENTES)", # noqa + 13: "ESTADO/CEP - CEP INCOMPATÍVEL COM A SIGLA DO ESTADO", + 14: "NOSSO NÚMERO - NOSSO NÚMERO JÁ REGISTRADO NO CADASTRO DO BANCO OU FORA DA FAIXA", # noqa + 15: "NOSSO NÚMERO - NOSSO NÚMERO EM DUPLICIDADE NO MESMO MOVIMENTO", + 18: "DATA DE ENTRADA - DATA DE ENTRADA INVÁLIDA PARA OPERAR COM ESTA CARTEIRA", + 19: "OCORRÊNCIA - OCORRÊNCIA INVÁLIDA", + 21: "AG. COBRADORA - CARTEIRA NÃO ACEITA DEPOSITÁRIA CORRESPONDENTE ESTADO DA AGÊNCIA DIFERENTE DO ESTADO DO PAGADOR AG. COBRADORA NÃO CONSTA NO CADASTRO OU ENCERRANDO", # noqa + 22: "CARTEIRA - CARTEIRA NÃO PERMITIDA (NECESSÁRIO CADASTRAR FAIXA LIVRE)", + 26: "AGÊNCIA/CONTA - AGÊNCIA/CONTA NÃO LIBERADA PARA OPERAR COM COBRANÇA", + 27: "CNPJ INAPTO - CNPJ DO BENEFICIÁRIO INAPTO DEVOLUÇÃO DE TÍTULO EM GARANTIA", + 29: "CÓDIGO EMPRESA - CATEGORIA DA CONTA INVÁLIDA", + 30: "ENTRADA BLOQUEADA - ENTRADAS BLOQUEADAS, CONTA SUSPENSA EM COBRANÇA", + 31: "AGÊNCIA/CONTA - CONTA NÃO TEM PERMISSÃO PARA PROTESTAR (CONTATE SEU GERENTE)", + 35: "VALOR DO IOF - IOF MAIOR QUE 5%", + 36: "QTDADE DE MOEDA - QUANTIDADE DE MOEDA INCOMPATÍVEL COM VALOR DO TÍTULO", + 37: "CNPJ/CPF DO PAGADOR - NÃO NUMÉRICO OU IGUAL A ZEROS", + 42: "NOSSO NÚMERO - NOSSO NÚMERO FORA DE FAIXA", + 52: "AG. COBRADORA - EMPRESA NÃO ACEITA BANCO CORRESPONDENTE", + 53: "AG. COBRADORA - EMPRESA NÃO ACEITA BANCO CORRESPONDENTE - COBRANÇA MENSAGEM", + 54: "DATA DE VENCTO - BANCO CORRESPONDENTE - TÍTULO COM VENCIMENTO INFERIOR A 15 DIAS", # noqa + 55: "DEP/BCO CORRESP - CEP NÃO PERTENCE À DEPOSITÁRIA INFORMADA", + 56: "DT VENCTO/BCO CORRESP - VENCTO SUPERIOR A 180 DIAS DA DATA DE ENTRADA", + 57: "DATA DE VENCTO - CEP SÓ DEPOSITÁRIA BCO DO BRASIL COM VENCTO INFERIOR A 8 DIAS", # noqa + 60: "ABATIMENTO - VALOR DO ABATIMENTO INVÁLIDO", + 61: "JUROS DE MORA - JUROS DE MORA MAIOR QUE O PERMITIDO", + 62: "DESCONTO - VALOR DO DESCONTO MAIOR QUE VALOR DO TÍTULO", + 63: "DESCONTO DE ANTECIPAÇÃO - VALOR DA IMPORTÂNCIA POR DIA DE DESCONTO (IDD) NÃO PERMITIDO", # noqa + 64: "DATA DE EMISSÃO - DATA DE EMISSÃO DO TÍTULO INVÁLIDA", + 65: "TAXA FINANCTO - TAXA INVÁLIDA (VENDOR)", + 66: "DATA DE VENCTO - INVALIDA/FORA DE PRAZO DE OPERAÇÃO (MÍNIMO OU MÁXIMO)", + 67: "VALOR/QTIDADE - VALOR DO TÍTULO/QUANTIDADE DE MOEDA INVÁLIDO", + 68: "CARTEIRA - CARTEIRA INVÁLIDA OU NÃO CADASTRADA NO INTERCÂMBIO DA COBRANÇA", + 69: "CARTEIRA - CARTEIRA INVÁLIDA PARA TÍTULOS COM RATEIO DE CRÉDITO", + 70: "AGÊNCIA/CONTA - BENEFICIÁRIO NÃO CADASTRADO PARA FAZER RATEIO DE CRÉDITO", + 78: "AGÊNCIA/CONTA - DUPLICIDADE DE AGÊNCIA/CONTA BENEFICIÁRIA DO RATEIO DE CRÉDITO", # noqa + 80: "AGÊNCIA/CONTA - QUANTIDADE DE CONTAS BENEFICIÁRIAS DO RATEIO MAIOR DO QUE O PERMITIDO (MÁXIMO DE 30 CONTAS POR TÍTULO)", # noqa + 81: "AGÊNCIA/CONTA - CONTA PARA RATEIO DE CRÉDITO INVÁLIDA / NÃO PERTENCE AO ITAÚ", + 82: "DESCONTO/ABATI-MENTO - DESCONTO/ABATIMENTO NÃO PERMITIDO PARA TÍTULOS COM RATEIO DE CRÉDITO", # noqa + 83: "VALOR DO TÍTULO - VALOR DO TÍTULO MENOR QUE A SOMA DOS VALORES ESTIPULADOS PARA RATEIO", # noqa + 84: "AGÊNCIA/CONTA - AGÊNCIA/CONTA BENEFICIÁRIA DO RATEIO É A CENTRALIZADORA DE CRÉDITO DO BENEFICIÁRIO", # noqa + 85: "AGÊNCIA/CONTA - AGÊNCIA/CONTA DO BENEFICIÁRIO É CONTRATUAL / RATEIO DE CRÉDITO NÃO PERMITIDO", # noqa + 86: "TIPO DE VALOR - CÓDIGO DO TIPO DE VALOR INVÁLIDO / NÃO PREVISTO PARA TÍTULOS COM RATEIO DE CRÉDITO", # noqa + 87: "AGÊNCIA/CONTA - REGISTRO TIPO 4 SEM INFORMAÇÃO DE AGÊNCIAS/CONTAS BENEFICIÁRIAS DO RATEIO", # noqa + 90: "NRO DA LINHA - COBRANÇA MENSAGEM - NÚMERO DA LINHA DA MENSAGEM INVÁLIDO OU QUANTIDADE DE LINHAS EXCEDIDAS", # noqa + 97: "SEM MENSAGEM - COBRANÇA MENSAGEM SEM MENSAGEM (SÓ DE CAMPOS FIXOS), PORÉM COM REGISTRO DO TIPO 7 OU 8", # noqa + 98: "FLASH INVÁLIDO - REGISTRO MENSAGEM SEM FLASH CADASTRADO OU FLASH INFORMADO DIFERENTE DO CADASTRADO", # noqa + 99: "FLASH INVÁLIDO - CONTA DE COBRANÇA COM FLASH CADASTRADO E SEM REGISTRO DE MENSAGEM CORRESPONDENTE", # noqa +} + + +CODIGO_OCORRENCIAS_CNAB200 = { + 2: "ENTRADA CONFIRMADA COM POSSIBILIDADE DE MENSAGEM (NOTA 20 – TABELA 10)", # noqa + 3: "ENTRADA REJEITADA (NOTA 20 – TABELA 1)", # noqa + 4: "ALTERAÇÃO DE DADOS – NOVA ENTRADA OU ALTERAÇÃO/EXCLUSÃO DE DADOS ACATADA", # noqa + 5: "ALTERAÇÃO DE DADOS – BAIXA", + 6: "LIQUIDAÇÃO NORMAL", + 7: "LIQUIDAÇÃO PARCIAL – COBRANÇA INTELIGENTE (B2B)", + 8: "LIQUIDAÇÃO EM CARTÓRIO", + 9: "BAIXA SIMPLES", + 10: "BAIXA POR TER SIDO LIQUIDADO", + 11: "EM SER (SÓ NO RETORNO MENSAL)", + 12: "ABATIMENTO CONCEDIDO", + 13: "ABATIMENTO CANCELADO", + 14: "VENCIMENTO ALTERADO", + 15: "BAIXAS REJEITADAS (NOTA 20 – TABELA 4)", + 16: "INSTRUÇÕES REJEITADAS (NOTA 20 – TABELA 3)", + 17: "ALTERAÇÃO/EXCLUSÃO DE DADOS REJEITADOS (NOTA 20 – TABELA 2)", + 18: "COBRANÇA CONTRATUAL – INSTRUÇÕES/ALTERAÇÕES REJEITADAS/PENDENTES (NOTA 20 – TABELA 5)", # noqa + 19: "CONFIRMA RECEBIMENTO DE INSTRUÇÃO DE PROTESTO", + 20: "CONFIRMA RECEBIMENTO DE INSTRUÇÃO DE SUSTAÇÃO DE PROTESTO /TARIFA", + 21: "CONFIRMA RECEBIMENTO DE INSTRUÇÃO DE NÃO PROTESTAR", + 23: "TÍTULO ENVIADO A CARTÓRIO/TARIFA", + 24: "INSTRUÇÃO DE PROTESTO REJEITADA / SUSTADA / PENDENTE (NOTA 20 – TABELA 7)", # noqa + 25: "ALEGAÇÕES DO PAGADOR (NOTA 20 – TABELA 6)", + 26: "TARIFA DE AVISO DE COBRANÇA", + 27: "TARIFA DE EXTRATO POSIÇÃO (B40X)", + 28: "TARIFA DE RELAÇÃO DAS LIQUIDAÇÕES", + 29: "TARIFA DE MANUTENÇÃO DE TÍTULOS VENCIDOS", + 30: "DÉBITO MENSAL DE TARIFAS (PARA ENTRADAS E BAIXAS)", + 32: "BAIXA POR TER SIDO PROTESTADO", + 33: "CUSTAS DE PROTESTO", + 34: "CUSTAS DE SUSTAÇÃO", + 35: "CUSTAS DE CARTÓRIO DISTRIBUIDOR", + 36: "CUSTAS DE EDITAL", + 37: "TARIFA DE EMISSÃO DE BOLETO/TARIFA DE ENVIO DE DUPLICATA", + 38: "TARIFA DE INSTRUÇÃO", + 39: "TARIFA DE OCORRÊNCIAS", + 40: "TARIFA MENSAL DE EMISSÃO DE BOLETO/TARIFA MENSAL DE ENVIO DE DUPLICATA", # noqa + 41: "DÉBITO MENSAL DE TARIFAS – EXTRATO DE POSIÇÃO (B4EP/B4OX)", + 42: "DÉBITO MENSAL DE TARIFAS – OUTRAS INSTRUÇÕES", + 43: "DÉBITO MENSAL DE TARIFAS – MANUTENÇÃO DE TÍTULOS VENCIDOS", + 44: "DÉBITO MENSAL DE TARIFAS – OUTRAS OCORRÊNCIAS", + 45: "DÉBITO MENSAL DE TARIFAS – PROTESTO", + 46: "DÉBITO MENSAL DE TARIFAS – SUSTAÇÃO DE PROTESTO", + 47: "BAIXA COM TRANSFERÊNCIA PARA DESCONTO", + 48: "CUSTAS DE SUSTAÇÃO JUDICIAL", + 51: "TARIFA MENSAL REF A ENTRADAS BANCOS CORRESPONDENTES NA CARTEIRA", + 52: "TARIFA MENSAL BAIXAS NA CARTEIRA", + 53: "TARIFA MENSAL BAIXAS EM BANCOS CORRESPONDENTES NA CARTEIRA", + 54: "TARIFA MENSAL DE LIQUIDAÇÕES NA CARTEIRA", + 55: "TARIFA MENSAL DE LIQUIDAÇÕES EM BANCOS CORRESPONDENTES NA CARTEIRA", + 56: "CUSTAS DE IRREGULARIDADE", + 57: "INSTRUÇÃO CANCELADA (NOTA 20 – TABELA 8)", + 59: "BAIXA POR CRÉDITO EM C/C ATRAVÉS DO SISPAG", + 60: "ENTRADA REJEITADA CARNÊ (NOTA 20 – TABELA 1)", + 61: "TARIFA EMISSÃO AVISO DE MOVIMENTAÇÃO DE TÍTULOS (2154)", + 62: "DÉBITO MENSAL DE TARIFA – AVISO DE MOVIMENTAÇÃO DE TÍTULOS (2154)", + 63: "TÍTULO SUSTADO JUDICIALMENTE", + 64: "ENTRADA CONFIRMADA COM RATEIO DE CRÉDITO", + 65: "PAGAMENTO COM CHEQUE – AGUARDANDO COMPENSAÇÃO", + 69: "CHEQUE DEVOLVIDO (NOTA 20 – TABELA 9)", + 71: "ENTRADA REGISTRADA, AGUARDANDO AVALIAÇÃO", + 72: "BAIXA POR CRÉDITO EM C/C ATRAVÉS DO SISPAG SEM TÍTULO CORRESPONDENTE", + 73: "CONFIRMAÇÃO DE ENTRADA NA COBRANÇA SIMPLES – ENTRADA NÃO ACEITA NA COBRANÇA CONTRATUAL", # noqa + 74: "INSTRUÇÃO DE NEGATIVAÇÃO EXPRESSA REJEITADA (NOTA 20 – TABELA 11)", + 75: "CONFIRMAÇÃO DE RECEBIMENTO DE INSTRUÇÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA", # noqa + 76: "CHEQUE COMPENSADO", + 77: "CONFIRMAÇÃO DE RECEBIMENTO DE INSTRUÇÃO DE EXCLUSÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA", # noqa + 78: "CONFIRMAÇÃO DE RECEBIMENTO DE INSTRUÇÃO DE CANCELAMENTO DE NEGATIVAÇÃO EXPRESSA", # noqa + 79: "NEGATIVAÇÃO EXPRESSA INFORMACIONAL (NOTA 20 – TABELA 12)", + 80: "CONFIRMAÇÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA – TARIFA", + 82: "CONFIRMAÇÃO DO CANCELAMENTO DE NEGATIVAÇÃO EXPRESSA – TARIFA", + 83: "CONFIRMAÇÃO DE EXCLUSÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA POR LIQUIDAÇÃO – TARIFA", # noqa + 85: "TARIFA POR BOLETO (ATÉ 03 ENVIOS) COBRANÇA ATIVA ELETRÔNICA", + 86: "TARIFA EMAIL COBRANÇA ATIVA ELETRÔNICA", + 87: "TARIFA SMS COBRANÇA ATIVA ELETRÔNICA", + 88: "TARIFA MENSAL POR BOLETO (ATÉ 03 ENVIOS) COBRANÇA ATIVA ELETRÔNICA", + 89: "TARIFA MENSAL EMAIL COBRANÇA ATIVA ELETRÔNICA", + 90: "TARIFA MENSAL SMS COBRANÇA ATIVA ELETRÔNICA", + 91: "TARIFA MENSAL DE EXCLUSÃO DE ENTRADA DE NEGATIVAÇÃO EXPRESSA", + 92: "TARIFA MENSAL DE CANCELAMENTO DE NEGATIVAÇÃO EXPRESSA", + 93: "TARIFA MENSAL DE EXCLUSÃO DE NEGATIVAÇÃO EXPRESSA POR LIQUIDAÇÃO", +} + +STR_EVENTO_FORMAT = "%d%m%y" diff --git a/l10n_br_account_payment_order/data/account_analytic_tag_data.xml b/l10n_br_account_payment_order/data/account_analytic_tag_data.xml new file mode 100644 index 000000000000..879d1b6ceb04 --- /dev/null +++ b/l10n_br_account_payment_order/data/account_analytic_tag_data.xml @@ -0,0 +1,12 @@ + + + + + Juros + + + + Taxa + + + diff --git a/l10n_br_account_payment_order/data/boleto_data.xml b/l10n_br_account_payment_order/data/boleto_data.xml new file mode 100644 index 000000000000..f863f162698a --- /dev/null +++ b/l10n_br_account_payment_order/data/boleto_data.xml @@ -0,0 +1,17 @@ + + + + + Nosso número + nosso.numero + + + + + + + + 1 + + + diff --git a/l10n_br_account_payment_order/data/cnab_data.xml b/l10n_br_account_payment_order/data/cnab_data.xml new file mode 100644 index 000000000000..d098b1b35758 --- /dev/null +++ b/l10n_br_account_payment_order/data/cnab_data.xml @@ -0,0 +1,12 @@ + + + + + Sequencia Arquivo CNAB + Sequencia Arquivo CNAB + + + + + + diff --git a/l10n_br_account_payment_order/data/l10n_br_cnab_mov_instruction_code_data.xml b/l10n_br_account_payment_order/data/l10n_br_cnab_mov_instruction_code_data.xml new file mode 100644 index 000000000000..9d34e573acd1 --- /dev/null +++ b/l10n_br_account_payment_order/data/l10n_br_cnab_mov_instruction_code_data.xml @@ -0,0 +1,185 @@ + + + + + + + + Inclusão de Registro Detalhe Liberado + 00 + + + + + + Inclusão do Registro Detalhe Bloqueado + 09 + + + + + + Alteração do Pagamento Liberado para Bloqueado (Bloqueio) + 10 + + + + + + Alteração do Pagamento Bloqueado para Liberado (Liberação) + 11 + + + + + + Alteração do Valor do Título + 17 + + + + + + Alteração da Data de Pagamento + 19 + + + + + + Pagamento Direto ao Fornecedor - Baixar + 23 + + + + + + Manutenção em Carteira - Não Pagar + 25 + + + + + + Retirada de Carteira - Não Pagar + 27 + + + + + + Estorno por Devolução da Câmara Centralizadora (somente para Tipo de Movimento = '3') + 33 + + + + + + Alegação do Pagador + 40 + + + + + + Exclusão do Registro Detalhe Incluído Anteriormente + 99 + + + + + + + Remessa* + 01 + + + Na inclusão de título em carteira, poderá ser definido “Protesto Automático” se forem obrigatoriamente respeitados: 1.Beneficiário estiver habilitado para uso de Protesto e 2.forem informados: 158 a 158 - Código para Protesto e 159 a 160 - Número de Dias para Protesto.Para configurar “Protesto Automático” para Títulos em Carteira deve ser utilizado a intrução 26 – Protesto automático. + + + + Pedido de Baixa + 02 + + + + + + Concessão de Abatimento* + 04 + + + Necessário ao enviar esta instrução 4 e também inserir 206 a 218 Valor do Abatimento. + + + + Cancelamento de Abatimento + 05 + + + + + + Alteração de vencimento + 06 + + + + + + Alteração de Seu Número + 08 + + + + + + Protestar* + 09 + + + Instrução utilizada para títulos vencidos e que não possuam protesto automático registrado. Neste caso, sem protesto automático cadastrado (automático é prioritário ao manual), o sistema encaminha o título à protesto, pois o fato gerador já aconteceu, ou seja, título já vencido. Deverá ser usada como “Protesto Manual”.Se for usado em título “À Vencer”, o sistema vai rejeitar instrução.IMPORTANTE: Carência 1 dia para Protesto Tanto Protesto Automático quando Protesto Manual, terá sempre 1 dia a mais para iniciar o envio do pedido de Protesto ao cartório. Esta carência é devido a ser possível receber pagamento via Compensação em D+1 (Correspondentes ou outro Bancos) Exemplos Título com data para vencimento hoje (D+0), será possível enviar “protesto manual” apenas em D+2 (dia útil) e mesmo se estiver “protesto automático” cadastrado, só será enviado em D+2 (dia útil ), respeitando a carência 1 dia útil.Caso seja enviado pedido de protesto sem respeitar o prazo de “1 dia”, a instrução será rejeitada. + + + + Sustar Protesto e Manter em Carteira + 11 + + + + + + Sustar Protesto e Baixar Título + 25 + + + + + + Protesto automático + 26 + + + (Instrução para Criar, Alterar, Remover): Instrução indicada para títulos a vencer, utilizada para protesto futuro, quando o fato gerador do protesto acontecer.Criar: Esta instrução deverá ser informada, somente, para títulos a vencer, registrados na carteira e que não possuam ‘Código para Protesto’ e ‘Número de Dias para Protesto’ cadastrados, ou seja, não foram registrados com as informações básicas de protesto (Código e Número de Dias). Neste caso o sistema irá encaminhar o título para protesto quando o fato gerador acontecer.Deverá ser informado um dos itens do ‘158 a 158 - Código para Protesto’ o Código ‘1’ ou o Código ‘2’ e ‘159 a 160 - Número de Dias para Protesto’, maior que zeros.Alterar: Esta instrução deverá ser informada para títulos a vencer, registrados na carteira e que possuam ‘Código para Protesto’ e ‘Número de Dias para Protesto’ cadastrados, com o objetivo de alterar essas informações básicas de protesto (Código e Número de Dias). Neste caso o sistema irá sobrescrever as informações enviadas sobre as informações cadastradas.Deverá ser informado um dos itens do ‘158 a 158 - Código para Protesto’ o Código ‘1’ ou o Código ‘2’ e ‘159 a 160 - Número de Dias para Protesto’, maior que zeros. Remover: Esta instrução deverá ser informada para títulos, que o fato gerador do protesto não ocorreu, registrados na carteira e que possuam ‘Código para Protesto’ e ‘Número de Dias para Protesto’ cadastrados, com o objetivo de excluir essas informações básicas de protesto automático. Neste caso o sistema excluí a possibilidade de protesto futuro automático.Deverá ser informado um dos itens do ‘158 a 158 - Código para Protesto’ o Código ‘3’ e ‘159 a 160 - Número de Dias para Protesto’, igual a zero. + + + + Alteração de outros dados (Alteração de dados do pagador) + 31 + + + + + + Alteração de Carteira + 40 + + + + + diff --git a/l10n_br_account_payment_order/data/l10n_br_cnab_option_data.xml b/l10n_br_account_payment_order/data/l10n_br_cnab_option_data.xml new file mode 100644 index 000000000000..644d211fa2ef --- /dev/null +++ b/l10n_br_account_payment_order/data/l10n_br_cnab_option_data.xml @@ -0,0 +1,925 @@ + + + + + + + 01 + CRÉDITO EM CONTA CORRENTE NO ITAÚ + release_form + + + + 02 + CHEQUE PAGAMENTO/ADMINISTRATIVO + release_form + + + + 03 + DOC “C ” + release_form + + + + 05 + CRÉDITO EM CONTA POUPANÇA NO ITAÚ + release_form + + + + 06 + CRÉDITO EM CONTA CORRENTE DE MESMA TITULARIDADE + release_form + + + + 07 + DOC “D ” + release_form + + + + 10 + ORDEM DE PAGAMENTO À DISPOSIÇÃO + release_form + + + + 11 + ORDEM DE PAGAMENTO DE ACERTO – SOMENTE RETORNO - VER OBSERVAÇÃO ABAIXO + release_form + + + + 13 + PAGAMENTO DE CONCESSIONÁRIAS + release_form + + + + 16 + DARF NORMAL + release_form + + + + 17 + GPS - GUIA DA PREVIDÊNCIA SOCIAL + release_form + + + + 18 + DARF SIMPLES + release_form + + + + 19 + IPTU/ISS/OUTROS TRIBUTOS MUNICIPAIS + release_form + + + + 21 + DARJ + release_form + + + + 22 + GARE – SP ICMS + release_form + + + + 25 + IPVA + release_form + + + + 27 + DPVAT + release_form + + + + 30 + PAGAMENTO DE TÍTULOS EM COBRANÇA NO ITAÚ + release_form + + + + 31 + PAGAMENTO DE TÍTULOS EM COBRANÇA EM OUTROS BANCOS + release_form + + + + 32 + NOTA FISCAL – LIQUIDAÇÃO ELETRÔNICA + release_form + + + + 35 + FGTS – GFIP + release_form + + + + 41 + TED – OUTRO TITULAR + release_form + + + + 43 + TED – MESMO TITULAR + release_form + + + + 60 + CARTÃO SALÁRIO + release_form + + + + 91 + GNRE E TRIBUTOS COM CÓDIGO DE BARRAS + release_form + + + + + + + 10 + Dividendos + service_type + + + + 15 + Debêntures + service_type + + + + 20 + Fornecedores + service_type + + + + 22 + TRIBUTOS + service_type + + + + 30 + Salários + service_type + + + + 40 + Fundos de Investimentos + service_type + + + + 50 + Sinistros DE Seguros + service_type + + + + 60 + Despesas Viajante em Trânsito + service_type + + + + 80 + Representantes Autorizados + service_type + + + + 90 + Benefícios + service_type + + + + 98 + Diversos + service_type + + + + + + + 01 + Crédito em Conta + doc_finality_code + + + + 02 + Pagamento de Aluguel / Condomínio + doc_finality_code + + + + 03 + Pagamento de Duplicata / Títulos + doc_finality_code + + + + 04 + Pagamento de Dividendos + doc_finality_code + + + + 05 + Pagamento de Mensalidade Escolar + doc_finality_code + + + + 06 + Pagamento de Salários + doc_finality_code + + + + 07 + Pagamento de Fornecedores / Honorários + doc_finality_code + + + + 08 + Operações de Câmbio / Fundos + doc_finality_code + + + + 09 + Repasse de Arrecadação / Pagamento de Tributos + doc_finality_code + + + + 10 + Transferência Internacional de Reais + doc_finality_code + + + + 11 + DOC para Poupança + doc_finality_code + + + + 12 + DOC para Depósito Judicial + doc_finality_code + + + + 13 + Pensão Alimentícia + doc_finality_code + + + + 99 + Outros + doc_finality_code + + + + + + + 01 + Crédito em Conta Corrente/Salário + release_form + + + 02 + Cheque Pagamento / Administrativo + release_form + + + 03 + DOC/TED (1) (2) + release_form + + + 04 + Cartão Salário (somente para Tipo de Serviço = '30') + release_form + + + 05 + Crédito em Conta Poupança + release_form + + + 10 + OP à Disposição + release_form + + + 11 + Pagamento de Contas e Tributos com Código de Barras + release_form + + + 16 + Tributo - DARF Normal + release_form + + + 17 + Tributo - GPS (Guia da Previdência Social) + release_form + + + 18 + Tributo - DARF Simples + release_form + + + 19 + Tributo - IPTU – Prefeituras + release_form + + + 20 + Pagamento com Autenticação + release_form + + + 21 + Tributo – DARJ + release_form + + + 22 + Tributo - GARE-SP ICMS + release_form + + + 23 + Tributo - GARE-SP DR + release_form + + + 24 + Tributo - GARE-SP ITCMD + release_form + + + 25 + Tributo - IPVA + release_form + + + 26 + Tributo - Licenciamento + release_form + + + 27 + Tributo – DPVAT + release_form + + + 30 + Liquidação de Títulos do Próprio Banco + release_form + + + 31 + Pagamento de Títulos de Outros Bancos + release_form + + + 40 + Extrato de Conta Corrente + release_form + + + 41 + TED – Outra Titularidade (1) + release_form + + + 43 + TED – Mesma Titularidade (1) + release_form + + + 44 + TED para Transferência de Conta Investimento + release_form + + + 50 + Débito em Conta Corrente + release_form + + + 70 + Extrato para Gestão de Caixa + release_form + + + 71 + Depósito Judicial em Conta Corrente + release_form + + + 72 + Depósito Judicial em Poupança + release_form + + + 73 + Extrato de Conta Investimento + release_form + + + + + + 01 + Cobrança + service_type + + + 03 + Boleto de Pagamento Eletrônico + service_type + + + 04 + Conciliação Bancária + service_type + + + 05 + Débitos + service_type + + + 06 + Custódia de Cheques + service_type + + + 07 + Gestão de Caixa + service_type + + + 08 + Consulta/Informação Margem + service_type + + + 09 + Averbação da Consignação/Retenção + service_type + + + 10 + Pagamento Dividendos + service_type + + + 11 + Manutenção da Consignação + service_type + + + 12 + Consignação de Parcelas + service_type + + + 13 + Glosa da Consignação (INSS) + service_type + + + 14 + Consulta de Tributos a pagar + service_type + + + 20 + Pagamento Fornecedor + service_type + + + 22 + Pagamento de Contas, Tributos e Impostos + service_type + + + 23 + Interoperabilidade entre Contas de Instituições de Pagamentos + service_type + + + 25 + Compror + service_type + + + 26 + Compror Rotativo + service_type + + + 29 + Alegação do Pagador + service_type + + + 30 + Pagamento Salários + service_type + + + 32 + Pagamento de honorários + service_type + + + 33 + Pagamento de bolsa auxílio + service_type + + + 34 + Pagamento de prebenda (remuneração a padres e sacerdotes) + service_type + + + 40 + Vendor + service_type + + + 41 + Vendor a Termo + service_type + + + 50 + Pagamento Sinistros Segurados + service_type + + + 60 + Pagamento Despesas Viajante em Trânsito + service_type + + + 70 + Pagamento Autorizado + service_type + + + 75 + Pagamento Credenciados + service_type + + + 77 + Pagamento de Remuneração + service_type + + + 80 + Pagamento Representantes / Vendedores Autorizados + service_type + + + 90 + Pagamento Benefícios + service_type + + + 98 + Pagamentos Diversos + service_type + + + + + + 00001 + Pagamento de Impostos, Tributos e Taxas + ted_finality_code + + + 00002 + Pagamento a Concessionárias de Serviço Público + ted_finality_code + + + 00003 + Pagamento de Dividendos + ted_finality_code + + + 00004 + Pagamento de Salários + ted_finality_code + + + 00005 + Pagamento de Fornecedores + ted_finality_code + + + 00006 + Pagamento de Honorários + ted_finality_code + + + 00007 + Pagamento de Aluguéis e Taxas e Condomínio + ted_finality_code + + + 00008 + Pagamento de Duplicatas e Títulos + ted_finality_code + + + 00009 + Pagamento de Honorários + ted_finality_code + + + 00010 + Crédito em Conta + ted_finality_code + + + 00011 + Pagamento a Corretoras + ted_finality_code + + + 00016 + Crédito em Conta Investimento + ted_finality_code + + + 00100 + Depósito Judicial + ted_finality_code + + + 00101 + Pensão Alimentícia + ted_finality_code + + + 00200 + Transferência Internacional de Reais + ted_finality_code + + + 00201 + Ajuste Posição Mercado Futuro + ted_finality_code + + + 00204 + Compra/Venda de Ações – Bolsas de Valores e Mercado de Balcão + ted_finality_code + + + 00205 + Contrato referenciado em Ações/Índices de Ações – BV/BMF + ted_finality_code + + + 00300 + Restituição de Imposto de Renda + ted_finality_code + + + 00500 + Restituição de Prêmio de Seguros + ted_finality_code + + + 00501 + Pagamento de indenização de Sinistro de Seguro + ted_finality_code + + + 00502 + Pagamento de Prêmio de Co-seguro + ted_finality_code + + + 00503 + Restituição de prêmio de Co-seguro + ted_finality_code + + + 00504 + Pagamento de indenização de Co-seguro + ted_finality_code + + + 00505 + Pagamento de prêmio de Resseguro + ted_finality_code + + + 00506 + Restituição de prêmio de Resseguro + ted_finality_code + + + 00507 + Pagamento de Indenização de Sinistro de Resseguro + ted_finality_code + + + 00508 + Restituição de Indenização de Sinistro de Resseguro + ted_finality_code + + + 00509 + Pagamento de Despesas com Sinistros + ted_finality_code + + + 00510 + Pagamento de Inspeções/Vistorias Prévias + ted_finality_code + + + 00511 + Pagamento de Resgate de Título de Capitalização + ted_finality_code + + + 00512 + Pagamento de Sorteio de Título de Capitalização + ted_finality_code + + + 00513 + Pagamento de Devolução de Mensalidade de Título de Capitalização + ted_finality_code + + + 00514 + Restituição de Contribuição de Plano Previdenciário + ted_finality_code + + + 00515 + Pagamento de Benefício Previdenciário de Pecúlio + ted_finality_code + + + 00516 + Pagamento de Benefício Previdenciário de Pensão + ted_finality_code + + + 00517 + Pagamento de Benefício Previdenciário de Aposentadoria + ted_finality_code + + + 00518 + Pagamento de Resgate Previdenciário + ted_finality_code + + + 00519 + Pagamento de Comissão de Corretagem + ted_finality_code + + + 00520 + Pagamento de Transferências/Portabilidade de Reserva de Seguro/Previdência + ted_finality_code + + + + + + 01 + Crédito em Conta + doc_finality_code + + + 02 + Pagamento de Aluguel/Condomínio + doc_finality_code + + + 03 + Pagamento de Duplicata/Títulos + doc_finality_code + + + 04 + Pagamento de Dividendos + doc_finality_code + + + 05 + Pagamento de Mensalidade Escolar + doc_finality_code + + + 06 + Pagamento de Salários + doc_finality_code + + + 07 + Pagamento a Fornecedores + doc_finality_code + + + 08 + Operações de Câmbios/Fundos/Bolsa de Valores + doc_finality_code + + + 09 + Repasse de Arrecadação/Pagamento de Tributos + doc_finality_code + + + 10 + Transferência Internacional em Real + doc_finality_code + + + 11 + DOC para Poupança + doc_finality_code + + + 12 + DOC para Depósito Judicial + doc_finality_code + + + 13 + Outros + doc_finality_code + + + 16 + Pagamento de bolsa auxílio + doc_finality_code + + + 17 + Remuneração à cooperado + doc_finality_code + + + 18 + Pagamento de honorários + doc_finality_code + + + 19 + Pagamento de prebenda (Remuneração a padres e sacerdotes) + doc_finality_code + + + diff --git a/l10n_br_account_payment_order/data/l10n_br_cnab_return_move_code_data.xml b/l10n_br_account_payment_order/data/l10n_br_cnab_return_move_code_data.xml new file mode 100644 index 000000000000..5d90f6cfb526 --- /dev/null +++ b/l10n_br_account_payment_order/data/l10n_br_cnab_return_move_code_data.xml @@ -0,0 +1,1023 @@ + + + + + + + + Entrada Confirmada + 02 + + + + + + Entrada Rejeitada + 03 + + + + + + Liquidação + 06 + + + + + + Confirmação do Recebimento da Instrução de Desconto + 07 + + + + + + Confirmação do Recebimento do Cancelamento da Instrução de Desconto + 08 + + + + + + Baixa + 09 + + + + + + Confirmação do Recebimento da Instrução de Repactuação + 10 + + + + + + Confirmação do Recebimento da Instrução de Abatimento + 12 + + + + + + Confirmação do Recebimento do Cancelamento da Instrução de Abatimento + 13 + + + + + + Confirmação do Recebimento da Instrução de Alteração de Vencimento + 14 + + + + + + Liquidação após Baixa ou Liquidação Título não Registrado + 17 + + + + + + Instrução Rejeitada + 26 + + + + + + Confirmação do Pedido de Alteração de Outros Dados + 27 + + + + + + Alteração de Dados Rejeitada + 30 + + + + + + Concentração (Será informado apenas no arquivo retorno dos dados do Comprador) + 36 + + + + + + Títulos debitados a Empresa após o término da carência + 37 + + + + + + Títulos pago sem atraso creditados a Empresa + 38 + + + + + + + Pago (Título protestado pago em cartório) + 01 + + + + + + Instrução Confirmada* + 02 + + + + + + Instrução Rejeitada* + 03 + + + + + + Sustado Judicial (Título protestado sustado judicialmente) + 04 + + + + + + Liquidação Normal * + 06 + + + + + + Liquidação em Condicional (Título liquidado em cartório com cheque do próprio devedor) + 07 + + + + + + Sustado Definitivo (Título protestado sustado judicialmente) + 08 + + + + + + Liquidação de Título Descontado + 09 + + + + + + Protesto solicitado + 10 + + + + + + Protesto Em cartório + 11 + + + + + + Sustação solicitada + 12 + + + + + + + Entrada Confirmada + 02 + + + + + + Entrada Rejeitada + 03 + + + + + + Liquidação Normal * + 06 + + + + + + Baixado Automat. via Arquivo + 09 + + + + + + Baixado conforme instruções da Agência + 10 + + + + + + Em Ser - Arquivo de Títulos pendentes + 11 + + + + + + Abatimento Concedido + 12 + + + + + + Abatimento Cancelado + 13 + + + + + + Vencimento Alterado + 14 + + + + + + Liquidação em Cartório + 15 + + + + + + Título Pago em Cheque – Vinculado + 16 + + + + + + Liquidação após baixa ou Título não registrado + 17 + + + + + + Acerto de Depositária + 18 + + + + + + Confirmação Receb. Inst. de Protesto + 19 + + + + + + Confirmação Recebimento Instrução Sustação de Protesto + 20 + + + + + + Acerto do Controle do Participante (sem motivo) + 21 + + + + + + Título Com Pagamento Cancelado + 22 + + + + + + Entrada do Título em Cartório (sem motivo) + 23 + + + + + + Entrada rejeitada por CEP Irregular + 24 + + + + + + Confirmação Receb.Inst.de Protesto Falimentar + 25 + + + + + + Baixa Rejeitada + 27 + + + + + + Débito de tarifas/custas + 28 + + + + + + Ocorrências do Pagador (NOVO) + 29 + + + + + + Alteração de Outros Dados Rejeitados + 30 + + + + + + Instrução Rejeitada + 32 + + + + + + Confirmação Pedido Alteração Outros Dados (sem motivo) + 33 + + + + + + Retirado de Cartório e Manutenção Carteira + 34 + + + + + + Desagendamento do débito automático + 35 + + + + + + Estorno de pagamento + 40 + + + + + + Sustado judicial + 55 + + + + + + Acerto dos dados do rateio de Crédito + 68 + + + + + + Cancelamento dos dados do rateio + 69 + + + + + + Confirmação Receb. Pedido de Negativação + 73 + + + + + + Confir Pedido de Excl de Negat (com ou sem baixa) + 74 + + + + + + Nota: Para as ocorrências sem motivos, as posições serão informadas com Zeros. + 00 + + + + + + + ENTRADA CONFIRMADA COM POSSIBILIDADE DE MENSAGEM + 02 + + + + + + ENTRADA REJEITADA + 03 + + + + + + ALTERAÇÃO DE DADOS – NOVA ENTRADA OU ALTERAÇÃO/EXCLUSÃO DE DADOS ACATADA + 04 + + + + + + ALTERAÇÃO DE DADOS – BAIXA + 05 + + + + + + Liquidação Normal + 06 + + + + + + LIQUIDAÇÃO PARCIAL – COBRANÇA INTELIGENTE (B2B) + 07 + + + + + + LIQUIDAÇÃO EM CARTÓRIO + 08 + + + + + + BAIXA SIMPLES + 09 + + + + + + BAIXA POR TER SIDO LIQUIDADO + 10 + + + + + + EM SER (SÓ NO RETORNO MENSAL) + 11 + + + + + + ABATIMENTO CONCEDIDO + 12 + + + + + + ABATIMENTO CANCELADO + 13 + + + + + + VENCIMENTO ALTERADO + 14 + + + + + + BAIXAS REJEITADAS (NOTA 20 – TABELA 4) + 15 + + + + + + INSTRUÇÕES REJEITADAS (NOTA 20 – TABELA 3) + 16 + + + + + + ALTERAÇÃO/EXCLUSÃO DE DADOS REJEITADOS (NOTA 20 – TABELA 2) + 17 + + + + + + COBRANÇA CONTRATUAL – INSTRUÇÕES/ALTERAÇÕES REJEITADAS/PENDENTES (NOTA 20 – TABELA 5) + 18 + + + + + + CONFIRMA RECEBIMENTO DE INSTRUÇÃO DE PROTESTO + 19 + + + + + + CONFIRMA RECEBIMENTO DE INSTRUÇÃO DE SUSTAÇÃO DE PROTESTO /TARIFA + 20 + + + + + + CONFIRMA RECEBIMENTO DE INSTRUÇÃO DE NÃO PROTESTAR + 21 + + + + + + TÍTULO ENVIADO A CARTÓRIO/TARIFA + 23 + + + + + + INSTRUÇÃO DE PROTESTO REJEITADA / SUSTADA / PENDENTE (NOTA 20 – TABELA 7) + 24 + + + + + + ALEGAÇÕES DO PAGADOR (NOTA 20 – TABELA 6) + 25 + + + + + + TARIFA DE AVISO DE COBRANÇA + 26 + + + + + + TARIFA DE EXTRATO POSIÇÃO (B40X) + 27 + + + + + + TARIFA DE RELAÇÃO DAS LIQUIDAÇÕES + 28 + + + + + + TARIFA DE MANUTENÇÃO DE TÍTULOS VENCIDOS + 29 + + + + + + DÉBITO MENSAL DE TARIFAS (PARA ENTRADAS E BAIXAS) + 30 + + + + + + BAIXA POR TER SIDO PROTESTADO + 32 + + + + + + CUSTAS DE PROTESTO + 33 + + + + + + CUSTAS DE SUSTAÇÃO + 34 + + + + + + CUSTAS DE CARTÓRIO DISTRIBUIDOR + 35 + + + + + + CUSTAS DE EDITAL + 36 + + + + + + TARIFA DE EMISSÃO DE BOLETO/TARIFA DE ENVIO DE DUPLICATA + 37 + + + + + + TARIFA DE INSTRUÇÃO + 38 + + + + + + TARIFA DE OCORRÊNCIAS + 39 + + + + + + TARIFA MENSAL DE EMISSÃO DE BOLETO/TARIFA MENSAL DE ENVIO DE DUPLICATA + 40 + + + + + + DÉBITO MENSAL DE TARIFAS – EXTRATO DE POSIÇÃO (B4EP/B4OX) + 41 + + + + + + DÉBITO MENSAL DE TARIFAS – OUTRAS INSTRUÇÕES + 42 + + + + + + DÉBITO MENSAL DE TARIFAS – MANUTENÇÃO DE TÍTULOS VENCIDOS + 43 + + + + + + DÉBITO MENSAL DE TARIFAS – OUTRAS OCORRÊNCIAS + 44 + + + + + + DÉBITO MENSAL DE TARIFAS – PROTESTO + 45 + + + + + + DÉBITO MENSAL DE TARIFAS – SUSTAÇÃO DE PROTESTO + 46 + + + + + + BAIXA COM TRANSFERÊNCIA PARA DESCONTO + 47 + + + + + + CUSTAS DE SUSTAÇÃO JUDICIAL + 48 + + + + + + TARIFA MENSAL REF A ENTRADAS BANCOS CORRESPONDENTES NA CARTEIRA + 51 + + + + + + TARIFA MENSAL BAIXAS NA CARTEIRA + 52 + + + + + + TARIFA MENSAL BAIXAS EM BANCOS CORRESPONDENTES NA CARTEIRA + 53 + + + + + + TARIFA MENSAL DE LIQUIDAÇÕES NA CARTEIRA + 54 + + + + + + TARIFA MENSAL DE LIQUIDAÇÕES EM BANCOS CORRESPONDENTES NA CARTEIRA + 55 + + + + + + CUSTAS DE IRREGULARIDADE + 56 + + + + + + INSTRUÇÃO CANCELADA (NOTA 20 – TABELA 8) + 57 + + + + + + BAIXA POR CRÉDITO EM C/C ATRAVÉS DO SISPAG + 59 + + + + + + ENTRADA REJEITADA CARNÊ (NOTA 20 – TABELA 1) + 60 + + + + + + TARIFA EMISSÃO AVISO DE MOVIMENTAÇÃO DE TÍTULOS (2154) + 61 + + + + + + DÉBITO MENSAL DE TARIFA – AVISO DE MOVIMENTAÇÃO DE TÍTULOS (2154) + 62 + + + + + + TÍTULO SUSTADO JUDICIALMENTE + 63 + + + + + + ENTRADA CONFIRMADA COM RATEIO DE CRÉDITO + 64 + + + + + + PAGAMENTO COM CHEQUE – AGUARDANDO COMPENSAÇÃO + 65 + + + + + + CHEQUE DEVOLVIDO (NOTA 20 – TABELA 9) + 69 + + + + + + ENTRADA REGISTRADA, AGUARDANDO AVALIAÇÃO + 71 + + + + + + BAIXA POR CRÉDITO EM C/C ATRAVÉS DO SISPAG SEM TÍTULO CORRESPONDENTE + 72 + + + + + + CONFIRMAÇÃO DE ENTRADA NA COBRANÇA SIMPLES – ENTRADA NÃO ACEITA NA COBRANÇA CONTRATUAL + 73 + + + + + + INSTRUÇÃO DE NEGATIVAÇÃO EXPRESSA REJEITADA (NOTA 20 – TABELA 11) + 74 + + + + + + CONFIRMAÇÃO DE RECEBIMENTO DE INSTRUÇÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA + 75 + + + + + + CHEQUE COMPENSADO + 76 + + + + + + CONFIRMAÇÃO DE RECEBIMENTO DE INSTRUÇÃO DE EXCLUSÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA + 77 + + + + + + CONFIRMAÇÃO DE RECEBIMENTO DE INSTRUÇÃO DE CANCELAMENTO DE NEGATIVAÇÃO EXPRESSA + 78 + + + + + + NEGATIVAÇÃO EXPRESSA INFORMACIONAL (NOTA 20 – TABELA 12) + 79 + + + + + + CONFIRMAÇÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA – TARIFA + 80 + + + + + + CONFIRMAÇÃO DO CANCELAMENTO DE NEGATIVAÇÃO EXPRESSA – TARIFA + 82 + + + + + + CONFIRMAÇÃO DE EXCLUSÃO DE ENTRADA EM NEGATIVAÇÃO EXPRESSA POR LIQUIDAÇÃO – TARIFA + 83 + + + + + + TARIFA POR BOLETO (ATÉ 03 ENVIOS) COBRANÇA ATIVA ELETRÔNICA + 85 + + + + + + TARIFA EMAIL COBRANÇA ATIVA ELETRÔNICA + 86 + + + + + + TARIFA SMS COBRANÇA ATIVA ELETRÔNICA + 87 + + + + + + TARIFA MENSAL POR BOLETO (ATÉ 03 ENVIOS) COBRANÇA ATIVA ELETRÔNICA + 88 + + + + + + TARIFA MENSAL EMAIL COBRANÇA ATIVA ELETRÔNICA + 89 + + + + + + TARIFA MENSAL SMS COBRANÇA ATIVA ELETRÔNICA + 90 + + + + + + TARIFA MENSAL DE EXCLUSÃO DE ENTRADA DE NEGATIVAÇÃO EXPRESSA + 91 + + + + + + TARIFA MENSAL DE CANCELAMENTO DE NEGATIVAÇÃO EXPRESSA + 92 + + + + + + TARIFA MENSAL DE EXCLUSÃO DE NEGATIVAÇÃO EXPRESSA POR LIQUIDAÇÃO + 93 + + + + + diff --git a/l10n_br_account_payment_order/data/l10n_br_payment_export_type.xml b/l10n_br_account_payment_order/data/l10n_br_payment_export_type.xml new file mode 100644 index 000000000000..35def00374e3 --- /dev/null +++ b/l10n_br_account_payment_order/data/l10n_br_payment_export_type.xml @@ -0,0 +1,32 @@ + + + + + + + 240 + Cnab240 + True + False + inbound + + + + + 400 + Cnab400 + True + False + inbound + + + + + 500 + Cnab500 + True + False + inbound + + + diff --git a/l10n_br_account_payment_order/demo/account_account.xml b/l10n_br_account_payment_order/demo/account_account.xml new file mode 100644 index 000000000000..2d95b20d71bf --- /dev/null +++ b/l10n_br_account_payment_order/demo/account_account.xml @@ -0,0 +1,60 @@ + + + + + + 3.01.01.01.01.02.00 + Receita da Venda no Mercado Interno + de Produtos de Fabricação Própria - AVOID_TRAVIS_ERROR + + + + + + + + 3.01.01.01.01.03.00-* + Taxa do Boleto - AVOID_TRAVIS_ERROR + + + + + + + + 3.2.3.02-* + Outras Despesas Financeiras - AVOID_TRAVIS_ERROR + + + + + + + + 3.1.2.02-* + Juros Ativos - AVOID_TRAVIS_ERROR + + + + + + + + 3.2.2.02-* + Despesas com Vendas - AVOID_TRAVIS_ERROR + + + + + + + + 3.2.2.03-* + Outras Despesas Gerais - AVOID_TRAVIS_ERROR + + + + + + + diff --git a/l10n_br_account_payment_order/demo/account_invoice.xml b/l10n_br_account_payment_order/demo/account_invoice.xml new file mode 100644 index 000000000000..b41ffe4ac81e --- /dev/null +++ b/l10n_br_account_payment_order/demo/account_invoice.xml @@ -0,0 +1,171 @@ + + + + + + + + Test Payment Order + + + out_invoice + + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + Teste Itau CNAB240 + + + out_invoice + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + Teste Itau CNAB400 + + + out_invoice + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + Teste Unicred CNAB400 + + + out_invoice + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + Teste Caixa Economica Federal CNAB240 + + + out_invoice + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + Teste Banco do Brasil CNAB400 + + + out_invoice + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + Teste Cheque - quando o Modo de Pagto não gera Ordem de Pagto + + + out_invoice + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + Manual Main Company + + + out_invoice + + + + + + + + [E-COM06] Computador Personalizado (kit) + + + 100 + 10 + + + + + + + + diff --git a/l10n_br_account_payment_order/demo/account_journal.xml b/l10n_br_account_payment_order/demo/account_journal.xml index 85df64a250b4..314520389747 100644 --- a/l10n_br_account_payment_order/demo/account_journal.xml +++ b/l10n_br_account_payment_order/demo/account_journal.xml @@ -1,9 +1,10 @@ + - Diário de Banco(teste l10n_br_account_payment_order) + Diário de Banco - Empresa Principal TPO sale @@ -11,7 +12,7 @@ - Diário de Banco(teste l10n_br_account_payment_order) + Diário de Banco - Simples Nacional TPO sale @@ -19,10 +20,71 @@ - Diário de Banco(teste l10n_br_account_payment_order) + Diário de Banco - Lucro Presumido TPO sale + + + Banco Bradesco + bank + BNC2 + + + + + + + Banco Unicred + bank + BNC3 + + + + + + + Banco Itau + bank + BNC4 + + + + + + + Banco do Brasil + bank + BNC5 + + + + + + + Banco Caixa Economica Federal + bank + BNC6 + + + + + + + Diário de Banco(teste l10n_br_account_payment_order) + TPO + sale + + + + + + Diário Cheque + DCQ + sale + + + diff --git a/l10n_br_account_payment_order/demo/account_payment_mode.xml b/l10n_br_account_payment_order/demo/account_payment_mode.xml index 6303be6b5dd3..92f06dedc201 100644 --- a/l10n_br_account_payment_order/demo/account_payment_mode.xml +++ b/l10n_br_account_payment_order/demo/account_payment_mode.xml @@ -1,13 +1,19 @@ - - + + Boleto Bancario - + variable + False + False + False + 0001222130126 + fixed + @@ -17,6 +23,10 @@ variable + False + False + False + 0001222130126 @@ -26,6 +36,225 @@ variable + False + False + False + 0001222130126 + + + + + Cobrança Bradesco400 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 03 + DM + 19 + S + + False + False + False + 0001222130126 + + + + + Cobrança Unicred400 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 21 + DM + 19 + N + + 2 + 5 + 2 + 2 + 2 + 2 + 72234050 + False + False + False + + + + + 92035760 + + + + + + + + Cobrança Unicred240 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 3 + DM + 19 + N + + 2 + 5 + 72234050 + False + False + False + + + + + + + + + Cobrança Itau240 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 3 + DM + 19 + S + + False + False + False + + + + + 0001222130126 + + + + + + + + Cobrança Caixa Economica Federal 240 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 3 + DM + 19 + S + + False + False + False + + + + + + 000122 + + + + + + + + Cobrança Itau400 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 175 + DM + 19 + S + + False + False + False + + + + + 0001222130126 + + + + + Produto Taxa Boleto + + 5.0 + 5.0 + service + + + TAX_BOLETO + + + + + Cobrança Banco do Brasil 400 + + Pagavel em qualquer banco ate o vencimento + fixed + + True + + 18 + DM + 19 + S + + + + False + False + False + + + + + 0001222130126 + + + + + Cheque + + fixed + + False + + False + False diff --git a/l10n_br_account_payment_order/demo/account_payment_order.xml b/l10n_br_account_payment_order/demo/account_payment_order.xml index 3947832957c3..9c33779f6f2e 100644 --- a/l10n_br_account_payment_order/demo/account_payment_order.xml +++ b/l10n_br_account_payment_order/demo/account_payment_order.xml @@ -1,26 +1,163 @@ - - - Test Payment Order - - - out_invoice - - - - - - - - - [E-COM06] Computador Personalizado (kit) - - - 100 - 10 - + + + + + + + + + + + + + + Pagamentos + 240 + outbound + + + + + + + + + + + TED + + + + fixed + + + + + + + + + DAS + + + + fixed + + + + + + + + + ISS + + + + fixed + + + + + + + + + Pagamento de Utilitário + + + + fixed + + + + + + + + + + + + + + + + + 858000000275581712382016500711231320312356470477 + + + + + + + + + 858000000275581712382016500711231320312356470477 + + + + + + + + + 818300000000351237012007512320036434688123299220 + + + + + + + + + 836000000015522801380034710717288116000212965610 + + + + + + + + + 836400000011079401380070610530261110080671594119 + + + + + + + + + 836100000022434201380079213410922115000104587191 + + + + + + + + outbound + 01 + 00 + 0 + + diff --git a/l10n_br_account_payment_order/demo/res_partner_bank.xml b/l10n_br_account_payment_order/demo/res_partner_bank.xml index 1d08cd40426e..651121d1bcac 100644 --- a/l10n_br_account_payment_order/demo/res_partner_bank.xml +++ b/l10n_br_account_payment_order/demo/res_partner_bank.xml @@ -336,4 +336,14 @@ Sicredi - Instituição Financeira Cooperativa + + 371 + 0 + 1234 + 0 + + + Unicred + + diff --git a/l10n_br_account_payment_order/demo/res_users.xml b/l10n_br_account_payment_order/demo/res_users.xml new file mode 100644 index 000000000000..3b8e149f9240 --- /dev/null +++ b/l10n_br_account_payment_order/demo/res_users.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/l10n_br_account_payment_order/i18n/l10n_br_account_payment_order.pot b/l10n_br_account_payment_order/i18n/l10n_br_account_payment_order.pot deleted file mode 100644 index 503ad9ddbc55..000000000000 --- a/l10n_br_account_payment_order/i18n/l10n_br_account_payment_order.pot +++ /dev/null @@ -1,137 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * l10n_br_account_payment_order -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_res_partner_bank -msgid "Bank Accounts" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:account.payment.mode,name:l10n_br_account_payment_order.lucro_presumido_payment_mode_boleto -#: model:account.payment.mode,name:l10n_br_account_payment_order.main_company_payment_mode_boleto -#: model:account.payment.mode,name:l10n_br_account_payment_order.simples_nacional_payment_mode_boleto -msgid "Boleto Bancario" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model_terms:ir.ui.view,arch_db:l10n_br_account_payment_order.l10n_br-account_payment_mode_form -msgid "Configurações Brasileiras" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_move_line__date_scheduled -msgid "Data Prevista" -msgstr "" - -#. module: l10n_br_account_payment_order -#: selection:account.payment.mode,operation_type:0 -#: selection:account.payment.order,operation_type:0 -msgid "Debito em conta corrente" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model_terms:ir.ui.view,arch_db:l10n_br_account_payment_order.l10n_br-account_payment_mode_form -msgid "Geral" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__invoice_print -msgid "Gerar relatorio na conclusão da fatura?" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__instrucoes -msgid "Instruções de cobrança" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_move_line__journal_entry_ref -msgid "Journal Entry Ref" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_move_line -msgid "Journal Item" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__linha_digitavel -msgid "Linha Digitável" -msgstr "" - -#. module: l10n_br_account_payment_order -#: code:addons/l10n_br_account_payment_order/models/res_partner_bank.py:18 -#, python-format -msgid "O cógido da Agencia Bancaria do Santander deve ter no máximo quatro caracteres." -msgstr "" - -#. module: l10n_br_account_payment_order -#: selection:account.payment.mode,operation_type:0 -#: selection:account.payment.order,operation_type:0 -msgid "Pagamento" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_payment_line -msgid "Payment Lines" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_payment_mode -msgid "Payment Modes" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_payment_order -msgid "Payment Order" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__percent_interest -msgid "Percentual de Juros" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.ui.menu,name:l10n_br_account_payment_order.menu_remessa_categ -msgid "Remessa" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.ui.menu,name:l10n_br_account_payment_order.menu_retorno_categ -msgid "Retorno" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__internal_sequence_id -msgid "Sequência" -msgstr "" - -#. module: l10n_br_account_payment_order -#: sql_constraint:account.payment.mode:0 -msgid "Sequência já usada! Crie uma sequência unica para cada modo" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__operation_type -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__operation_type -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_order__operation_type -msgid "Tipo de Operação" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__amount_interest -msgid "Valor Juros" -msgstr "" - diff --git a/l10n_br_account_payment_order/i18n/pt_BR.po b/l10n_br_account_payment_order/i18n/pt_BR.po deleted file mode 100644 index 3947a7c5b049..000000000000 --- a/l10n_br_account_payment_order/i18n/pt_BR.po +++ /dev/null @@ -1,178 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * l10n_br_account_banking_payment -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-11-22 14:13+0000\n" -"PO-Revision-Date: 2017-11-22 14:13+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_res_partner_bank -msgid "Bank Accounts" -msgstr "Contas Bancárias" - -#. module: l10n_br_account_payment_order -#: model:account.payment.mode,name:l10n_br_account_payment_order.lucro_presumido_payment_mode_boleto -#: model:account.payment.mode,name:l10n_br_account_payment_order.main_company_payment_mode_boleto -#: model:account.payment.mode,name:l10n_br_account_payment_order.simples_nacional_payment_mode_boleto -msgid "Boleto Bancario" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model_terms:ir.ui.view,arch_db:l10n_br_account_payment_order.l10n_br-account_payment_mode_form -msgid "Configurações Brasileiras" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_move_line__date_scheduled -msgid "Data Prevista" -msgstr "Data Prevista" - -#. module: l10n_br_account_payment_order -#: selection:account.payment.mode,operation_type:0 -#: selection:account.payment.order,operation_type:0 -msgid "Debito em conta corrente" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model_terms:ir.ui.view,arch_db:l10n_br_account_payment_order.l10n_br-account_payment_mode_form -msgid "Geral" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__invoice_print -msgid "Gerar relatorio na conclusão da fatura?" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__instrucoes -msgid "Instruções de cobrança" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_move_line__journal_entry_ref -#, fuzzy -msgid "Journal Entry Ref" -msgstr "Entrada do Diário" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_move_line -#, fuzzy -msgid "Journal Item" -msgstr "Itens do Diário" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__linha_digitavel -msgid "Linha Digitável" -msgstr "Linha Digitável" - -#. module: l10n_br_account_payment_order -#: code:addons/l10n_br_account_payment_order/models/res_partner_bank.py:18 -#, python-format -msgid "" -"O cógido da Agencia Bancaria do Santander deve ter no máximo quatro " -"caracteres." -msgstr "" - -#. module: l10n_br_account_payment_order -#: selection:account.payment.mode,operation_type:0 -#: selection:account.payment.order,operation_type:0 -#, fuzzy -msgid "Pagamento" -msgstr "Ordens de Pagamentos" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_payment_line -#, fuzzy -msgid "Payment Lines" -msgstr "Linha de Pagamento" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_payment_mode -#, fuzzy -msgid "Payment Modes" -msgstr "Ordens de Pagamentos" - -#. module: l10n_br_account_payment_order -#: model:ir.model,name:l10n_br_account_payment_order.model_account_payment_order -msgid "Payment Order" -msgstr "Ordem de Pagamento" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__percent_interest -msgid "Percentual de Juros" -msgstr "Percentual de Juros" - -#. module: l10n_br_account_payment_order -#: model:ir.ui.menu,name:l10n_br_account_payment_order.menu_remessa_categ -msgid "Remessa" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.ui.menu,name:l10n_br_account_payment_order.menu_retorno_categ -msgid "Retorno" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__internal_sequence_id -msgid "Sequência" -msgstr "" - -#. module: l10n_br_account_payment_order -#: sql_constraint:account.payment.mode:0 -msgid "Sequência já usada! Crie uma sequência unica para cada modo" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__operation_type -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_mode__operation_type -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_order__operation_type -msgid "Tipo de Operação" -msgstr "" - -#. module: l10n_br_account_payment_order -#: model:ir.model.fields,field_description:l10n_br_account_payment_order.field_account_payment_line__amount_interest -msgid "Valor Juros" -msgstr "" - -#~ msgid "Bank" -#~ msgstr "Banco" - -#~ msgid "Data Programada" -#~ msgstr "Data Programada" - -#~ msgid "Entry Lines" -#~ msgstr "Linhas de Entrada" - -#~ msgid "Impossible confirm empty line!" -#~ msgstr "Impossível confirmar linha vazia!" - -#~ msgid "Total Credit" -#~ msgstr "Total de Crédito" - -#~ msgid "Total Debit" -#~ msgstr "Total de Débito" - -#~ msgid "Títulos em aberto" -#~ msgstr "Títulos em aberto" - -#~ msgid "" -#~ "{'display_credit': context.get('display_credit', False),'display_debit': " -#~ "context.get('display_debit', False),'journal_type': 'sale', " -#~ "'tree_view_ref' : 'account_banking_payment_export." -#~ "payment_order_populate_view_move_line_tree'}" -#~ msgstr "" -#~ "{'display_credit': context.get('display_credit', False),'display_debit': " -#~ "context.get('display_debit', False),'journal_type': 'sale', " -#~ "'tree_view_ref' : 'account_banking_payment_export." -#~ "payment_order_populate_view_move_line_tree'}" diff --git a/l10n_br_account_payment_order/migrations/12.0.2.0.0/pre-migration.py b/l10n_br_account_payment_order/migrations/12.0.2.0.0/pre-migration.py new file mode 100644 index 000000000000..37c3ea618f5d --- /dev/null +++ b/l10n_br_account_payment_order/migrations/12.0.2.0.0/pre-migration.py @@ -0,0 +1,144 @@ +# @ 2020 Akretion - www.akretion.com.br - +# Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from openupgradelib import openupgrade + +_column_renames = { + 'account.payment.mode': [ + ('instrucoes', 'instructions'), + ('condicao_da_papeleta', 'condition_issuing_paper'), + ('comunicacao_2', 'communication_2'), + ('tipo_servico', 'service_type'), + ('forma_lancamento', 'release_form'), + ('codigo_convenio', 'code_convetion'), + ('codigo_finalidade_doc', 'doc_finality_code'), + ('codigo_finalidade_ted', 'ted_finality_code'), + ('codigo_finalidade_complementar', 'complementary_finality_code'), + ('aviso_ao_favorecido', 'favored_warning'), + ('boleto_carteira', 'boleto_wallet'), + ('boleto_modalidade', 'boleto_modality'), + ('boleto_convenio', 'boleto_convetion'), + ('boleto_variacao', 'boleto_variation'), + ('boleto_aceite', 'boleto_accept'), + ('boleto_especie', 'boleto_species'), + ('boleto_cod_protesto', 'boleto_protest_code'), + ('boleto_dias_protesto', 'boleto_days_protest'), + ('gera_nosso_numero', 'generate_own_number'), + ('boleto_posto', 'boleto_post'), + ('boleto_cod_mora', 'boleto_interest_code'), + ('boleto_perc_mora', 'boleto_interest_perc'), + ('boleto_cod_multa', 'boleto_fee_code'), + ('boleto_perc_multa', 'boleto_fee_perc'), + ('tax_account_id', 'product_tax_account_id'), + ], + 'account.payment.line': [ + ('linha_digitavel', 'digitable_line'), + ('nosso_numero', 'own_number'), + ('numero_documento', 'document_number'), + ('identificacao_titulo_empresa', 'company_title_identification'), + ('codigo_finalidade_doc', 'doc_finality_code'), + ('codigo_finalidade_ted', 'ted_finality_code'), + ('codigo_finalidade_complementar', 'complementary_finality_code'), + ('aviso_ao_favorecido', 'favored_warning'), + ('abatimento', 'rebate_value'), + ('desconto', 'discount_value'), + ('mora', 'interest_value'), + ('multa', 'fee_value'), + ], + 'account.payment.order': [ + ('tipo_servico', 'service_type'), + ('forma_lancamento', 'release_form'), + ('codigo_convenio', 'code_convetion'), + ('indicativo_forma_pagamento', 'indicative_form_payment'), + ('tipo_movimento', 'movement_type'), + ('codigo_instrucao_movimento', 'movement_instruction_code'), + ], + 'bank.payment.line': [ + ('codigo_finalidade_doc', 'doc_finality_code'), + ('codigo_finalidade_ted', 'ted_finality_code'), + ('codigo_finalidade_complementar', 'complementary_finality_code'), + ('aviso_ao_favorecido', 'favored_warning'), + ('abatimento', 'rebate_value'), + ('desconto', 'discount_value'), + ('mora', 'interest_value'), + ('multa', 'fee_value'), + ('evento_id', 'event_id'), + ('nosso_numero', 'own_number'), + ('numero_documento', 'document_number'), + ('identificacao_titulo_empresa', 'company_title_identification'), + ('is_erro_exportacao', 'is_export_error'), + ('mensagem_erro_exportacao', 'export_error_message'), + ('ultimo_estado_cnab', 'last_cnab_state') + ], + 'l10n_br.cnab.evento': [ + ('data_real_pagamento', 'real_payment_date'), + ('data_ocorrencia', 'occurrence_date'), + ('data_vencimento', 'due_date'), + ('favorecido_conta_bancaria_id', 'favored_bank_account_id'), + ('favorecido_id', 'favored_id'), + ('identificacao_titulo_empresa', 'company_title_identification'), + ('juros_mora_multa', 'interest_fee_value'), + ('nosso_numero', 'own_number'), + ('ocorrencias', 'occurrences'), + ('outros_creditos', 'other_credits'), + ('segmento', 'segment'), + ('numero_documento', 'document_number'), + ('seu_numero', 'your_number'), + ('tipo_moeda', 'currency_type'), + ('tarifa_cobranca', 'tariff_charge'), + ('valor', 'title_value'), + ('valor_abatimento', 'rebate_value'), + ('valor_desconto', 'discount_value'), + ('valor_iof', 'iof_value'), + ('valor_pagamento', 'payment_value'), + ('lote_id', 'lot_id'), + ], + 'l10n_br.cnab.lote': [ + ('empresa_inscricao_numero', 'company_registration_number'), + ('empresa_inscricao_tipo', 'company_registration_type'), + ('mensagem', 'message'), + ('qtd_registros', 'register_qty'), + ('servico_operacao', 'operation_service'), + ('tipo_servico', 'service_type'), + ('total_valores', 'total_value'), + ], + # TODO - Separação dos dados de importação para um objeto especifico + # l10n_br_cnab.return.log armazenando o LOG do Arquivo de Retorno CNAB + # de forma separada e permitindo a integração com a alteração feita no + # modulo do BRCobranca onde se esta utilizando o modulo + # account_base_move_import para fazer essa tarefa de wizard de importação, + # o objeto l10n_br_cnab esta comentado para permitir, caso seja necessário, + # a implementação de outra forma de importação pois tem os metodos que eram + # usados pela KMEE e o historico git do arquivo + 'l10n_br.cnab': [ + ('arquivo_retorno', 'return_file'), + ('data', 'cnab_date'), + ('data_arquivo', 'date_file'), + ('sequencial_arquivo', 'sequential_file'), + ('motivo_erro', 'reason_error'), + ('lote_id', 'lot_id'), + ('num_eventos', 'number_events'), + ('num_lotes', 'number_lots'), + ], + 'account.move.line': [ + ('state_cnab', 'cnab_state'), + ('nosso_numero', 'own_number'), + ('numero_documento', 'document_number'), + ('identificacao_titulo_empresa', 'company_title_identification'), + ('situacao_pagamento', 'payment_situation'), + ('instrucoes', 'instructions'), + ], + 'account.invoice': [ + ('instrucoes', 'instructions'), + ('eval_payment_mode_instrucoes', 'eval_payment_mode_instructions') + ], +} +# TODO - verificar na migração da 8/10 para 12, em uma base de dados nova não +# existe os campos e objetos o que causa erro +_column_renames = {} + + +@openupgrade.migrate(use_env=True) +def migrate(env, version): + openupgrade.rename_columns(env.cr, _column_renames) diff --git a/l10n_br_account_payment_order/migrations/12.0.3.0.0/pre-migration.py b/l10n_br_account_payment_order/migrations/12.0.3.0.0/pre-migration.py new file mode 100644 index 000000000000..a83c05208916 --- /dev/null +++ b/l10n_br_account_payment_order/migrations/12.0.3.0.0/pre-migration.py @@ -0,0 +1,22 @@ +# @ 2020 Akretion - www.akretion.com.br - +# Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from openupgradelib import openupgrade + +_table_renames = [ + ('cnab_return_move_code', 'l10n_br_cnab_return_move_code'), +] + +_model_renames = [ + ('cnab.return.move.code', 'l10n_br_cnab.return.move.code'), + ('cnab.return.log', 'l10n_br_cnab.return.log'), + ('cnab.return.event', 'l10n_br_cnab.return.event'), + ('cnab.return.lot', 'l10n_br_cnab.return.lot'), +] + + +@openupgrade.migrate(use_env=True) +def migrate(env, version): + openupgrade.rename_tables(env.cr, _table_renames) + openupgrade.rename_models(env.cr, _model_renames) diff --git a/l10n_br_account_payment_order/models/__init__.py b/l10n_br_account_payment_order/models/__init__.py index 02dd0fe79663..3042ff059cc5 100644 --- a/l10n_br_account_payment_order/models/__init__.py +++ b/l10n_br_account_payment_order/models/__init__.py @@ -2,9 +2,31 @@ # Luis Felipe Miléo - mileo@kmee.com.br # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - +from . import res_company +from . import account_invoice +from . import account_journal +from . import account_move from . import account_move_line +from . import l10n_br_cnab_configuration from . import account_payment_mode from . import account_payment_order from . import account_payment_line -from . import res_partner_bank +from . import account_payment +from . import bank_payment_line +# TODO - Separação dos dados de importação para um objeto especifico +# cnab.return.log armazenando o LOG do Arquivo de Retorno CNAB +# de forma separada e permitindo a integração com a alteração feita no +# modulo do BRCobranca onde se esta utilizando o modulo +# account_base_move_import para fazer essa tarefa de wizard de importação, +# o objeto l10n_br_cnab esta comentado para permitir, caso seja necessário, +# a implementação de outra forma de importação pois tem os metodos que eram +# usados pela KMEE e o historico git do arquivo +# from . import l10n_br_cnab +from . import l10n_br_cnab_event +from . import l10n_br_cnab_lot +from . import l10n_br_cnab_return_log +from . import ir_attachment +from . import l10n_br_cnab_data_abstract +from . import l10n_br_cnab_return_move_code +from . import l10n_br_cnab_mov_intruction_code +from . import l10n_br_cnab_option diff --git a/l10n_br_account_payment_order/models/account_invoice.py b/l10n_br_account_payment_order/models/account_invoice.py new file mode 100644 index 000000000000..70e9c466bd48 --- /dev/null +++ b/l10n_br_account_payment_order/models/account_invoice.py @@ -0,0 +1,369 @@ +# @author Danimar Ribeiro +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + move_line_receivable_ids = fields.Many2many( + comodel_name='account.move.line', + string='Receivables', + store=True, + compute='_compute_receivables', + ) + + eval_payment_mode_instructions = fields.Text( + string='Instruções de Cobrança do Modo de Pagamento', + related='payment_mode_id.instructions', + readonly=True, + ) + + instructions = fields.Text( + string='Instruções de cobrança', + ) + + # eval_situacao_pagamento = fields.Selection( + # string=u'Situação do Pagamento', + # related='move_line_receivable_id.situacao_pagamento', + # readonly=True, + # store=True, + # index=True, + # ) + + @api.multi + @api.depends('state', 'move_id.line_ids', 'move_id.line_ids.account_id') + def _compute_receivables(self): + for record in self: + lines = self.env['account.move.line'] + for line in record.move_id.line_ids: + if (line.account_id.id == record.account_id.id + and line.account_id.internal_type in ('receivable', + 'payable')): + lines |= line + record.move_line_receivable_ids = lines.sorted() + + @api.onchange('payment_mode_id') + def _onchange_payment_mode_id(self): + tax_analytic_tag_id = self.env.ref( + 'l10n_br_account_payment_order.account_analytic_tag_tax') + + to_remove_invoice_line_ids = self.invoice_line_ids.filtered( + lambda i: tax_analytic_tag_id in i.analytic_tag_ids + ) + + self.invoice_line_ids -= to_remove_invoice_line_ids + + payment_mode_id = self.payment_mode_id + if payment_mode_id.product_tax_id: + invoice_line_data = { + 'name': 'Taxa adicional do modo de pagamento escolhido', + 'partner_id': self.partner_id.id, + 'account_id': payment_mode_id.product_tax_account_id.id, + 'product_id': payment_mode_id.product_tax_id.id, + 'price_unit': payment_mode_id.product_tax_id.lst_price, + 'quantity': 1, + 'analytic_tag_ids': [(6, 0, [tax_analytic_tag_id.id])], + } + + self.update( + { + 'invoice_line_ids': [ + (6, 0, self.invoice_line_ids.ids), + (0, 0, invoice_line_data), + ] + } + ) + + # TODO: Criar um movimento de baixa + def _remove_payment_order_line(self, _raise=True): + """ Try to search payment orders related to the account move of this + invoice, we can't remove a payment.order.line / bank.line of a invoice + that already sent to the bank. + + The only way to do that is to say that you want to cancel it. + + Creating a new move of "BAIXA/ESTORNO" + + :param _raise: + :return: + """ + move_line_receivable_ids = self.move_line_receivable_ids + payment_order_ids = self.env['account.payment.order'] + + payment_order_ids |= self.env['account.payment.order'].search([ + ('payment_line_ids.move_line_id', 'in', move_line_receivable_ids.ids), + ]) + + if payment_order_ids: + draft_cancel_payment_order_ids = payment_order_ids.filtered( + lambda p: p.state in ('draft', 'cancel') + ) + if payment_order_ids - draft_cancel_payment_order_ids: + if _raise: + raise UserError(_( + 'A fatura não pode ser cancelada pois a mesma já se ' + 'encontra exportada por uma ordem de pagamento. \n', + 'Envie um novo lançamento solicitando a Baixa/Cancelamento' + )) + + for po_id in draft_cancel_payment_order_ids: + p_line_id = self.env['account.payment.line'] + for line in move_line_receivable_ids: + p_line_id |= self.env['account.payment.line'].search([ + ('order_id', '=', po_id.id), + ('move_line_id', '=', line.id)]) + po_id.payment_line_ids -= p_line_id + + @api.multi + def action_invoice_cancel(self): + """ Before cancel the invoice, check if this invoice have any payment order + related to it. + :return: + """ + for record in self: + record._remove_payment_order_line() + return super().action_invoice_cancel() + + @api.multi + def get_invoice_fiscal_number(self): + """ Como neste modulo nao temos o numero do documento fiscal, + vamos retornar o numero do core e deixar este metodo + para caso alguem queira sobrescrever""" + self.ensure_one() + return self.number + + @api.multi + def _pos_action_move_create(self): + for inv in self: + # TODO - apesar do campo move_line_receivable_ids ser do tipo + # compute esta sendo preciso chamar o metodo porque as vezes + # ocorre da linha vir vazia o que impede de entrar no FOR + # abaixo causando o não preenchimento de dados usados no Boleto, + # isso deve ser melhor investigado + if not inv.payment_mode_id: + continue + inv._compute_receivables() + + # Verifica se gera Ordem de Pagamento + if not inv.payment_mode_id.payment_order_ok: + continue + + for index, interval in enumerate(inv.move_line_receivable_ids): + inv_number = inv.get_invoice_fiscal_number().split('/')[-1].zfill(8) + numero_documento = inv_number + '/' + str(index + 1).zfill(2) + + sequence = inv.payment_mode_id.get_own_number_sequence( + inv, numero_documento) + + interval.transaction_ref = sequence + interval.own_number = ( + sequence if interval.payment_mode_id.generate_own_number + else '0' + ) + interval.document_number = numero_documento + interval.company_title_identification = hex(interval.id).upper() + instructions = '' + if inv.eval_payment_mode_instructions: + instructions = inv.eval_payment_mode_instructions + '\n' + if inv.instructions: + instructions += inv.instructions + '\n' + interval.instructions = instructions + # Codigo de Instrução do Movimento pode variar, + # mesmo no CNAB 240 + interval.mov_instruction_code_id = \ + inv.payment_mode_id.cnab_sending_code_id.id + + @api.multi + def action_move_create(self): + result = super().action_move_create() + self._pos_action_move_create() + return result + + @api.multi + def create_account_payment_line_baixa(self, amount_payment): + """ + Em caso de CNAB é preciso verificar e criar linha(s) + com Codigo de Instrução do Movimento de Baixa + :param amount_payment: Valor Pago + :return: + """ + + for inv in self: + if not inv.payment_mode_id.payment_order_ok: + # TODO - deveria fazer algo, testar + return False + + applicable_lines = inv.move_id.line_ids.filtered( + lambda x: ( + x.payment_mode_id.payment_order_ok + and x.account_id.internal_type in ('receivable', 'payable') + )) + + if not applicable_lines: + raise UserError(_( + 'No Payment Line created for invoice %s because ' + "it's internal type isn't receivable or payable." + ) % inv.number) + + payment_modes = applicable_lines.mapped('payment_mode_id') + + if not payment_modes: + raise UserError(_('No Payment Mode on invoice %s') % inv.number) + + result_payorder_ids = [] + apo = self.env['account.payment.order'] + for payment_mode in payment_modes: + payorder = apo.search([ + ('payment_mode_id', '=', payment_mode.id), + ('state', '=', 'draft')], limit=1) + + new_payorder = False + if not payorder: + payorder = apo.create( + inv._prepare_new_payment_order(payment_mode) + ) + new_payorder = True + result_payorder_ids.append(payorder.id) + count = 0 + line_to_update_cnab = self.env['account.move.line'] + for line in applicable_lines.filtered( + lambda x: x.payment_mode_id == payment_mode + ): + # Identificar a Linha CNAB que vai ser dado Baixa, + # é preciso que o valor que está sendo pago seja igual + # ao valor de uma das Parcelas em aberto ou ao Valor + # Total pois até onde vi não há possibilidade de + # uma baixa parcial para ser enviada na Remessa CNAB + + if line.debit == amount_payment: + line_to_update_cnab |= line + + if not line_to_update_cnab: + # Valor Total ? Baixar todas as Parcelas em aberto + if inv.amount_total == amount_payment: + line_to_update_cnab |= applicable_lines + else: + # TODO - existe possibilidade de baixas parciais ? + raise UserError(_( + 'Payment amount R$ %d of invoice %s can not' + ' be made because the amount must be equal to one' + ' of Installments or the Total amount of Invoice' + ' to be able to make the Request to Write Off the' + ' title with the Bank by CNAB.' + ) % (amount_payment, inv.number)) + + line_update = False + for line in line_to_update_cnab: + # TODO - O Banco aceita receber uma instrução parcial ou + # isso precisa ser resolvido de outra forma ? + # Existe o caso do cliente pagar antecipadamente um valor + # como um "Sinal" ( em vendas de produtos de alto valor + # para garantir a intenção é pedido um pagto como uma + # garantia de intenção e assim evitar prejuízos por + # desistencia ) caso a Ordem de Pagto ainda não tenha sido + # enviada ao Banco apagamos a Linha + + if line.cnab_state in ('draft', 'added'): + # Caso o arquivo já esteja criado a linha + # não pode ser atualizada + for payment_line in line.payment_line_ids: + if payment_line.order_id.state == 'generated': + raise UserError(_( + 'There is a CNAB file related to invoice' + ' %s created, this file should be sent to' + ' bank, because after that only Payment' + ' Order in status Exported allows make an' + ' payment and inform it in another Payment' + ' Order.' + ) % inv.number) + + line.payment_line_ids.unlink() + line.message_post(body=_( + 'Removed Payline that would be sent to Bank %s' + ' by CNAB because amount payment of %d was made ' + ' before sending.') % ( + inv.payment_mode_id.fixed_journal_id.bank_id.name, + amount_payment)) + # Atualização do Codigo de Instrução do Movimento + # para Remessa - Cada banco pode possuir um + # cnab 240 mais padronizado que o 400 + if line.cnab_state in ('exported', 'accepted'): + line_update = True + line.mov_instruction_code_id =\ + line.payment_mode_id.cnab_write_off_code_id.id + line.payment_situation = 'paga' + line.message_post(body=_( + 'Movement Instruction Code Updated for Request to' + ' Write Off, because payment done in another way.')) + line.create_payment_line_from_move_line(payorder) + count += 1 + + if line_update: + if new_payorder: + inv.message_post(body=_( + '%d payment lines added to the new draft payment ' + 'order %s which has been automatically created.' + ) % (count, payorder.name)) + else: + inv.message_post(body=_( + '%d payment lines added to the existing draft ' + 'payment order %s.' + ) % (count, payorder.name)) + + @api.multi + def invoice_validate(self): + result = super().invoice_validate() + filtered_invoice_ids = self.filtered(lambda s: s.payment_mode_id) + if filtered_invoice_ids: + for filtered_invoice_id in filtered_invoice_ids: + # TODO - essa validação já é feita no super, confirmar + # com o teste do modo de pagto q não deve gerar Ordem + # de Pagto, modo Cheque + if filtered_invoice_id.payment_mode_id.payment_order_ok: + filtered_invoice_id.create_account_payment_line() + return result + + @api.multi + def assign_outstanding_credit(self, credit_aml_id): + self.ensure_one() + + # TODO - Existe necessidade de ser feito algo nesse metodo ? + # Criar o teste do caso de uso de um Pagto por fora do CNAB + # p/ validar + # if self.eval_situacao_pagamento in ['paga', 'liquidada', + # 'baixa_liquidacao']: + # raise UserError( + # _( + # 'Não é possível adicionar pagamentos em uma fatura que ' + # 'já está paga.' + # ) + # ) + # if self.eval_state_cnab in ['accepted', 'exported', 'done']: + # raise UserError( + # _( + # 'Não é possível adicionar pagamentos em uma fatura já ' + # 'exportada ou aceita no banco.' + # ) + # ) + return super().assign_outstanding_credit(credit_aml_id) + + @api.multi + def register_payment( + self, payment_line, writeoff_acc_id=False, writeoff_journal_id=False + ): + res = super().register_payment( + payment_line, writeoff_acc_id, writeoff_journal_id) + + self._pos_action_move_create() + + for inv in self: + inv._compute_receivables() + receivable_id = inv.move_line_receivable_ids + receivable_id.residual = inv.residual + + return res diff --git a/l10n_br_account_payment_order/models/account_journal.py b/l10n_br_account_payment_order/models/account_journal.py new file mode 100644 index 000000000000..af9ce3b85bc1 --- /dev/null +++ b/l10n_br_account_payment_order/models/account_journal.py @@ -0,0 +1,11 @@ +# Copyright 2020 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class AccountJournal(models.Model): + + _inherit = 'account.journal' + + bank_code_bc = fields.Char(related='bank_id.code_bc') diff --git a/l10n_br_account_payment_order/models/account_move.py b/l10n_br_account_payment_order/models/account_move.py new file mode 100644 index 000000000000..0d658ddd9163 --- /dev/null +++ b/l10n_br_account_payment_order/models/account_move.py @@ -0,0 +1,40 @@ +# © 2019 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, models, fields +from odoo.exceptions import ValidationError + + +class AccountMove(models.Model): + _inherit = 'account.move' + + cnab_return_log_id = fields.Many2one( + string='CNAB Return Log', + comodel_name='l10n_br_cnab.return.log', + readonly=True, + inverse_name='move_id' + ) + + # Usados para deixar invisivel o campo + # relacionado ao CNAB na visao + is_cnab = fields.Boolean( + string='Is CNAB ?' + ) + + @api.multi + def unlink(self): + for record in self: + payment_line_ids = record.line_ids.mapped("payment_line_ids") + if any( + state not in ("draft", "cancel") + for state in payment_line_ids.mapped("state") + ): + raise ValidationError( + _( + "Não foi possível cancelar a fatura, pois existem linhas " + "de pagamentos ativas vinculadas ao lançamento de diário" + "dela." + ) + ) + payment_line_ids.unlink() + return super().unlink() diff --git a/l10n_br_account_payment_order/models/account_move_line.py b/l10n_br_account_payment_order/models/account_move_line.py index 737c890bb073..d6d7676d2f28 100644 --- a/l10n_br_account_payment_order/models/account_move_line.py +++ b/l10n_br_account_payment_order/models/account_move_line.py @@ -2,15 +2,116 @@ # Luis Felipe Miléo - mileo@kmee.com.br # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields, api +from odoo import api, fields, models + +from ..constants import ESTADOS_CNAB, SITUACAO_PAGAMENTO class AccountMoveLine(models.Model): - _inherit = 'account.move.line' + _name = 'account.move.line' + _inherit = ['account.move.line', 'mail.thread'] + # As linhas de cobrança precisam ser criadas conforme sequencia de + # Data de Vencimentos/date_maturity senão ficam fora de ordem: + # ex.: own_number 201 31/12/2020, own_number 202 18/11/2020 + # Isso causa confusão pois a primeira parcela fica como sendo a segunda. + _order = 'date desc, date_maturity ASC, id desc' + + # TODO - possível tornar um compute ? + cnab_state = fields.Selection( + selection=ESTADOS_CNAB, + string='Estados CNAB', + default='draft', + ) + + own_number = fields.Char( + string='Nosso Numero', + track_visibility='onchange', + ) + + # No arquivo de retorno do CNAB o campo pode ter um tamanho diferente, + # o tamanho do campo é preenchido na totalidade com zeros a esquerda, + # e no odoo o tamanho do sequencial pode estar diferente + # ex.: retorno cnab 0000000000000201 own_number 0000000201 + # o campo abaixo foi a forma que encontrei para poder usar o + # nosso_numero_cnab_retorno.strip("0") e ter algo: + # ex.: retorno cnab 201 own_number_without_zfill 201 + # Assim o metodo que faz o retorno do CNAB consegue encontrar + # a move line relacionada ao Evento. + own_number_without_zfill = fields.Char( + compute='_compute_own_number_without_zfill', + store=True, copy=False, + ) + + # Podem existir sequencias do nosso numero/own_number iguais entre bancos + # diferentes, porém o Diario/account.journal não pode ser o mesmo. + journal_payment_mode_id = fields.Many2one( + comodel_name='account.journal', + compute='_compute_journal_payment_mode', + store=True, copy=False + ) + + document_number = fields.Char( + string='Número documento', + track_visibility='onchange', + ) + + company_title_identification = fields.Char( + string='Identificação Titulo Empresa', + track_visibility='onchange', + ) + + payment_situation = fields.Selection( + selection=SITUACAO_PAGAMENTO, + string='Situação do Pagamento', + default='inicial', + track_visibility='onchange', + ) + + instructions = fields.Text( + string='Instruções de cobrança', + readonly=True, + ) + + journal_entry_ref = fields.Char( + string="Journal Entry Ref", + compute="_compute_journal_entry_ref", + store=True, + ) + payment_mode_id = fields.Many2one( + track_visibility='onchange' + ) + date_maturity = fields.Date( + readonly=True, + track_visibility='onchange' + ) + last_change_reason = fields.Text( + readonly=True, + track_visibility='onchange', + string="Justificativa", + ) + + mov_instruction_code_id = fields.Many2one( + comodel_name='l10n_br_cnab.mov.instruction.code', + string='Código da Instrução para Movimento', + help='Campo G061 do CNAB', + track_visibility='onchange', + ) + + # Usados para deixar invisiveis/somente leitura + # os campos relacionados ao CNAB + payment_method_id = fields.Many2one( + comodel_name='account.payment.method', + related='payment_mode_id.payment_method_id', + string='Payment Method', + ) - date_scheduled = fields.Date(string='Data Prevista') + payment_method_code = fields.Char( + related='payment_method_id.code', + readonly=True, store=True, + string='Payment Method Code' + ) - @api.depends('move_id') + @api.depends("move_id") def _compute_journal_entry_ref(self): for record in self: if record.name: @@ -20,11 +121,85 @@ def _compute_journal_entry_ref(self): elif record.invoice_id and record.invoice_id.number: record.journal_entry_ref = record.invoice_id.number else: - record.journal_entry_ref = '*' + str(record.move_id.id) + record.journal_entry_ref = "*" + str(record.move_id.id) - journal_entry_ref = fields.Char( - compute='_compute_journal_entry_ref', - string='Journal Entry Ref', store=True) + @api.multi + def _prepare_payment_line_vals(self, payment_order): + vals = super()._prepare_payment_line_vals(payment_order) + vals['own_number'] = self.own_number + vals['document_number'] = self.document_number + vals['company_title_identification'] = self.company_title_identification + + vals['payment_mode_id'] = self.payment_mode_id.id + + # Codigo de Instrução do Movimento para Remessa + vals['mov_instruction_code_id'] = self.mov_instruction_code_id.id + + # Se for uma solicitação de baixa do título é preciso informar o + # campo debit o codigo original coloca o amount_residual + if self.mov_instruction_code_id.id ==\ + self.payment_mode_id.cnab_write_off_code_id.id: + vals['amount_currency'] = self.credit or self.debit + + # TODO - ainda necessário ? + # if self.invoice_id.state == 'paid': + # vals['amount_currency'] = self.credit or self.debit + + return vals + + @api.multi + def create_payment_line_from_move_line(self, payment_order): + """ + Altera estado do cnab para adicionado a ordem + :param payment_order: + :return: + """ + cnab_state = 'added' + if self.invoice_id.state == 'paid': + cnab_state = 'added_paid' + + self.cnab_state = cnab_state + + return super().create_payment_line_from_move_line( + payment_order + ) + + @api.multi + def generate_boleto(self, validate=True): + raise NotImplementedError + + @api.multi + def _update_check(self): + + if self._context.get('reprocessing'): + return True + + return super(AccountMoveLine, self)._update_check() + + @api.multi + def write(self, values): + """ + Sobrescrita do método Write. Não deve ser possível voltar o cnab_state + ou a situacao_pagamento para um estado anterior + :param values: + :return: + """ + for record in self: + cnab_state = values.get('cnab_state') + + if cnab_state and ( + record.cnab_state == 'done' + or ( + record.cnab_state in ['accepted', 'accepted_hml'] + and cnab_state not in ['accepted', 'accepted_hml', 'done'] + ) + ): + values.pop('cnab_state', False) + + if record.payment_situation not in ['inicial', 'aberta']: + values.pop('payment_situation', False) + + return super().write(values) @api.multi def get_balance(self): @@ -38,3 +213,59 @@ def get_balance(self): for line in self: total += (line.debit or 0.0) - (line.credit or 0.0) return total + + def _create_payment_order_change(self, **kwargs): + self.ensure_one() + # TODO: + + def _change_date_maturity(self, new_date, reason, **kwargs): + moves_to_sync = self.filtered(lambda m: m.date_maturity != new_date) + moves_to_sync._create_payment_order_change(new_date=new_date, **kwargs) + moves_to_sync.write({ + 'date_maturity': new_date, + 'last_change_reason': reason, + }) + + def _change_payment_mode(self, reason, new_payment_mode_id, **kwargs): + moves_to_sync = self.filtered( + lambda m: m.payment_mode_id != new_payment_mode_id) + moves_to_sync._create_payment_order_change( + new_payment_mode_id=new_payment_mode_id, **kwargs) + moves_to_sync.write({ + 'payment_mode_id': new_payment_mode_id.id, + 'last_change_reason': reason, + }) + + def _create_baixa(self, reason, **kwargs): + moves_to_sync = self.filtered(lambda m: True) + # TODO: Verificar restrições possíveis + moves_to_sync._create_payment_order_change(baixa=True, **kwargs) + moves_to_sync.write({ + 'last_change_reason': reason, + 'payment_situation': 'baixa', # FIXME: Podem ser múltiplos motivos + }) + + def _create_change(self, change_type, reason='', **kwargs): + if change_type == 'change_date_maturity': + self._change_date_maturity(reason, **kwargs) + elif change_type == 'change_payment_mode': + self._change_payment_mode(reason, **kwargs) + elif change_type == 'baixa': + self._create_baixa(reason, **kwargs) + + @api.multi + @api.depends('own_number') + def _compute_own_number_without_zfill(self): + for record in self: + if record.own_number: + record.own_number_without_zfill = record.own_number.strip('0') + + @api.multi + @api.depends('payment_mode_id') + def _compute_journal_payment_mode(self): + for record in self: + if record.payment_mode_id: + # CNAB usa sempre a opção fixed_journal_id + if record.payment_mode_id.fixed_journal_id: + record.journal_payment_mode_id =\ + record.payment_mode_id.fixed_journal_id.id diff --git a/l10n_br_account_payment_order/models/account_payment.py b/l10n_br_account_payment_order/models/account_payment.py new file mode 100644 index 000000000000..2b7c5771e190 --- /dev/null +++ b/l10n_br_account_payment_order/models/account_payment.py @@ -0,0 +1,36 @@ +# © 2012 KMEE INFORMATICA LTDA +# @author Daniel Sadamo Hirayama +# @author Hugo Uchôas Borges +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models, _ +from odoo.exceptions import UserError + + +class AccountPayment(models.Model): + _inherit = 'account.payment' + + @api.multi + def post(self): + + # TODO - Rodando 2 For para não chamar o super em caso do + # metodo de pagto ser CNAB, necessário devido o problema abaixo + for rec in self: + if rec.payment_method_code in ('240', '400', '500'): + # TODO - Idealmente isso deveria ser resolvido com um + # domain=[('code', 'not in', ('400','240','500'))] + # no campo payment_method_id, mas mesmo adicionando isso na + # visão ou sobre escrevendo o campo não funciona e não gera + # erros, não consegui identificar o motivo do problema ( + # seria algum problema no orm ? Não encontrei um issue aberto + # com referencia a isso ), para reproduzir o erro basta tentar + # incluir o domain no campo como comentado acima e testar + # na tela. + # Testar na migração. + raise UserError(_( + "CNAB Payment Method can't be used to make" + ' direct Payments, just used in Payment Orders,' + ' choose another one.')) + super().post() + for record in self: + record.invoice_ids.create_account_payment_line_baixa(record.amount) diff --git a/l10n_br_account_payment_order/models/account_payment_line.py b/l10n_br_account_payment_order/models/account_payment_line.py index e35f5a6abc2e..0d7ac8af7c1e 100644 --- a/l10n_br_account_payment_order/models/account_payment_line.py +++ b/l10n_br_account_payment_order/models/account_payment_line.py @@ -2,31 +2,141 @@ # Luis Felipe Miléo - mileo@kmee.com.br # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields, api +from odoo import api, fields, models from odoo.addons import decimal_precision as dp from odoo.tools.float_utils import float_round as round -from .account_payment_mode import OPERATION_TYPE +from ..constants import ( + AVISO_FAVORECIDO, + TIPO_MOVIMENTO, +) -class PaymentLine(models.Model): - _inherit = 'account.payment.line' - @api.model - def _get_info_partner(self, partner_record): - if not partner_record: - return False - st = partner_record.street or '' - n = partner_record.street_number or '' - st1 = partner_record.street2 or '' - zip = partner_record.zip or '' - city = partner_record.city_id.name or '' - uf = partner_record.state_id.code or '' - zip_city = city + '-' + uf + '\n' + zip - cntry = partner_record.country_id and \ - partner_record.country_id.name or '' - cnpj = partner_record.cnpj_cpf or '' - return partner_record.legal_name or '' + "\n" + cnpj + "\n" + st \ - + ", " + n + " " + st1 + "\n" + zip_city + "\n" + cntry +class AccountPaymentLine(models.Model): + _name = 'account.payment.line' + _inherit = ['account.payment.line', 'l10n_br.cnab.configuration'] + + digitable_line = fields.Char( + string='Linha Digitável', + ) + + percent_interest = fields.Float( + string='Percentual de Juros', + digits=dp.get_precision('Account'), + ) + + amount_interest = fields.Float( + string='Valor Juros', + compute='_compute_interest', + digits=dp.get_precision('Account'), + ) + + own_number = fields.Char( + string='Nosso Numero', + ) + + document_number = fields.Char( + string='Número documento', + ) + + company_title_identification = fields.Char( + string='Identificação Titulo Empresa', + ) + + complementary_finality_code = fields.Char( + string='Código de finalidade complementar', + size=2, + help='Campo P013 do CNAB', + ) + + favored_warning = fields.Selection( + selection=AVISO_FAVORECIDO, + string='Aviso ao Favorecido', + help='Campo P006 do CNAB', + default='0', + ) + + rebate_value = fields.Float( + string='Valor do Abatimento', + help='Campo G045 do CNAB', + default=0.00, + digits=(13, 2), + ) + + discount_value = fields.Float( + string='Valor do Desconto', + digits=(13, 2), + default=0.00, + help='Campo G046 do CNAB', + ) + + interest_value = fields.Float( + string='Valor da Mora', + digits=(13, 2), + default=0.00, + help='Campo G047 do CNAB', + ) + + fee_value = fields.Float( + string='Valor da Multa', + digits=(13, 2), + default=0.00, + help='Campo G048 do CNAB', + ) + + payment_mode_id = fields.Many2one( + comodel_name='account.payment.mode', + string='Payment Mode', + ondelete='set null', + domain="[('id', 'in', payment_mode_ids)]", + ) + + payment_mode_ids = fields.Many2many( + comodel_name='account.payment.mode', + string="Payment Modes", + readonly=True, + related='order_id.payment_mode_ids', + domain="[('is_cnab_lot', '=', True)]", + ) + + # Campo não usado no BRCobranca + movement_type = fields.Selection( + selection=TIPO_MOVIMENTO, + string='Tipo de Movimento', + help='Campo G060 do CNAB', + default='0', + ) + + mov_instruction_code_id = fields.Many2one( + comodel_name='l10n_br_cnab.mov.instruction.code', + string='Código da Instrução para Movimento', + help='Campo G061 do CNAB', + ) + + # Usados para deixar invisiveis/somente leitura + # os campos relacionados ao CNAB + payment_method_id = fields.Many2one( + comodel_name='account.payment.method', + related='payment_mode_id.payment_method_id', + string='Payment Method', + ) + + payment_method_code = fields.Char( + related='payment_method_id.code', + readonly=True, store=True, + string='Payment Method Code' + ) + + @api.depends('payment_mode_id') + def _compute_bank_id(self): + for record in self: + record.bank_id = record.payment_mode_id.fixed_journal_id.bank_id + record.service_type_id = record.payment_mode_id.service_type_id + record.release_form_id = record.payment_mode_id.release_form_id + record.doc_finality_code_id = \ + record.payment_mode_id.doc_finality_code_id + record.ted_finality_code_id = \ + record.payment_mode_id.ted_finality_code_id @api.multi @api.depends('percent_interest', 'amount_currency') @@ -38,16 +148,23 @@ def _compute_interest(self): record.amount_currency * ( record.percent_interest / 100), precision) - linha_digitavel = fields.Char(string="Linha Digitável") - percent_interest = fields.Float(string="Percentual de Juros", - digits=dp.get_precision('Account')) - amount_interest = fields.Float(string="Valor Juros", - compute='_compute_interest', - digits=dp.get_precision('Account')) - - operation_type = fields.Selection( - selection=OPERATION_TYPE, - string='Tipo de Operação', - related='order_id.operation_type', - store=True - ) + @api.model + def default_get(self, fields_list): + res = super().default_get(fields_list) + mode = ( + self.env['account.payment.order'] + .browse(self.env.context.get('order_id')) + .payment_mode_id + ) + if mode.doc_finality_code_id: + res.update({'doc_finality_code_id': mode.doc_finality_code_id}) + if mode.ted_finality_code_id: + res.update({'ted_finality_code_id': mode.ted_finality_code_id}) + if mode.complementary_finality_code: + res.update({ + 'complementary_finality_code': + mode.complementary_finality_code + }) + if mode.favored_warning: + res.update({'favored_warning': mode.favored_warning}) + return res diff --git a/l10n_br_account_payment_order/models/account_payment_mode.py b/l10n_br_account_payment_order/models/account_payment_mode.py index 15889cb7b52a..dc81d1c360bf 100644 --- a/l10n_br_account_payment_order/models/account_payment_mode.py +++ b/l10n_br_account_payment_order/models/account_payment_mode.py @@ -1,30 +1,348 @@ # Copyright (C) 2012-Today - KMEE (). # @author Luis Felipe Miléo - mileo@kmee.com.br +# @author Renato Lima - renato.lima@akretion.com.br # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields +from odoo import _, api, fields, models +from odoo.addons import decimal_precision as dp +from odoo.exceptions import ValidationError, UserError -OPERATION_TYPE = [ - ('1', 'Pagamento'), - ('2', 'Debito em conta corrente'), -] +from ..constants import ( + AVISO_FAVORECIDO, + BOLETO_ESPECIE, +) class AccountPaymentMode(models.Model): - _inherit = 'account.payment.mode' + _name = 'account.payment.mode' + _inherit = [ + 'account.payment.mode', + 'l10n_br.cnab.configuration', + 'mail.thread', + ] + + internal_sequence_id = fields.Many2one( + comodel_name='ir.sequence', + string='Sequência', + ) + + instructions = fields.Text( + string='Instruções de cobrança', + ) - internal_sequence_id = fields.Many2one('ir.sequence', 'Sequência') - instrucoes = fields.Text('Instruções de cobrança') invoice_print = fields.Boolean( - 'Gerar relatorio na conclusão da fatura?') + string='Gerar relatorio na conclusão da fatura?' + ) - operation_type = fields.Selection( - selection=OPERATION_TYPE, - string='Tipo de Operação' + condition_issuing_paper = fields.Selection( + selection=[ + ('1', 'Banco emite e Processa'), + ('2', 'Cliente emite e banco processa')], + string='Condição Emissão de Papeleta', + default='1', ) - _sql_constraints = [ - ('internal_sequence_id_unique', - 'unique(internal_sequence_id)', - 'Sequência já usada! Crie uma sequência unica para cada modo') - ] + communication_2 = fields.Char( + string='Comunicação para o sacador avalista', + ) + + code_convetion = fields.Char( + string='Código do Convênio no Banco', + size=20, + help='Campo G007 do CNAB', + track_visibility='always', + ) + + complementary_finality_code = fields.Char( + string='Código de finalidade complementar', + size=2, + help='Campo P013 do CNAB', + ) + + favored_warning = fields.Selection( + selection=AVISO_FAVORECIDO, + string='Aviso ao Favorecido', + help='Campo P006 do CNAB', + default=0, + ) + + # A exportação CNAB não se encaixa somente nos parâmetros de + # débito e crédito. + boleto_wallet = fields.Char( + string='Carteira', + size=3, + track_visibility='always', + ) + + boleto_modality = fields.Char( + string='Modalidade', + size=2, + track_visibility='always', + ) + + boleto_variation = fields.Char( + string='Variação', + size=2, + track_visibility='always', + ) + + boleto_accept = fields.Selection( + selection=[ + ('S', 'Sim'), + ('N', 'Não')], + string='Aceite', + default='N', + track_visibility='always', + ) + + boleto_species = fields.Selection( + selection=BOLETO_ESPECIE, + string='Espécie do Título', + default='01', + track_visibility='always', + ) + + # Na configuração ou implementação de outros campos é + # melhor seguir a idéia abaixo pois os campos não são usados com + # frequencia e incluir um campo do tipo Char permitindo que seja + # informado o valor de acordo com a configuração do Boleto ao + # invês de diversos campos do Tipo Select para cada Banco parece + # ser melhor. + # [ Deixado manualmente, pois cada banco parece ter sua tabela. + # ('0', u'Sem instrução'), + # ('1', u'Protestar (Dias Corridos)'), + # ('2', u'Protestar (Dias Úteis)'), + # ('3', u'Não protestar'), + # ('7', u'Negativar (Dias Corridos)'), + # ('8', u'Não Negativar') + # ] + boleto_protest_code = fields.Char( + string='Código de Protesto', + default='0', + help='Código adotado pela FEBRABAN para identificar o tipo ' + 'de prazo a ser considerado para o protesto.', + track_visibility='always', + ) + + boleto_days_protest = fields.Char( + string='Número de Dias para Protesto', + size=2, + help='Número de dias decorrentes após a data de vencimento ' + 'para inicialização do processo de cobrança via protesto.', + track_visibility='always', + ) + + generate_own_number = fields.Boolean( + string='Gerar nosso número?', + default=True, + help='Dependendo da carteira, banco, etc. ' + 'O nosso número pode ser gerado pelo banco.', + ) + + product_tax_id = fields.Many2one( + comodel_name='product.product', + string='Taxa Adicional', + track_visibility='always', + ) + + product_tax_account_id = fields.Many2one( + comodel_name='account.account', + string='Conta de Taxa do Produto', + help='Conta padrão para a Taxa do Produto', + track_visibility='always', + ) + + cnab_sequence_id = fields.Many2one( + comodel_name='ir.sequence', + string='Sequencia do Arquivo CNAB', + track_visibility='always', + ) + + boleto_byte_idt = fields.Char( + string='Byte IDT', + size=1, + help='Byte de identificação do cedente do bloqueto ' + 'utilizado para compor o nosso número, ' + 'usado pelos bancos Sicred/Unicred e Sicoob.', + track_visibility='always', + ) + + boleto_post = fields.Char( + string='Posto da Cooperativa de Crédito', + size=2, + help='Código do Posto da Cooperativa de Crédito,' + ' usado pelos bancos Sicred/Unicred e Sicoob.', + track_visibility='always', + ) + + # Field used to make invisible banks specifics fields + bank_code_bc = fields.Char( + related='fixed_journal_id.bank_id.code_bc', + ) + + own_number_sequence_id = fields.Many2one( + comodel_name='ir.sequence', + string='Sequência do Nosso Número', + help='Para usar essa Sequencia é preciso definir o campo Tipo do ' + 'Nosso Número como Sequencial Único por Carteira no cadastro da ' + 'empresa', + track_visibility='always', + ) + + # Field used to make invisible own_number_sequence_id + own_number_type = fields.Selection( + related='fixed_journal_id.company_id.own_number_type', + ) + + boleto_interest_code = fields.Char( + string='Código da Mora', + size=1, + help='Código adotado pela FEBRABAN para identificação ' + 'do tipo de pagamento de mora de juros.', + track_visibility='always', + ) + + boleto_interest_perc = fields.Float( + string='Percentual de Juros de Mora', + digits=dp.get_precision('Account'), + track_visibility='always', + ) + + # TODO - criar outro campo para separar a Conta Contabil de Multa ? + # o valor vem somado ao Juros Mora no retorno do cnab 400 unicred, + # isso seria o padrão dos outros bancos ? + interest_fee_account_id = fields.Many2one( + comodel_name='account.account', + string='Conta Contabil de Juros Mora e Multa', + help='Conta padrão para Juros Mora', + track_visibility='always', + ) + + boleto_fee_code = fields.Char( + string='Código da Multa', + size=1, + help='Código adotado pela FEBRABAN para identificação ' + 'do tipo de pagamento de multa.', + track_visibility='always', + ) + + boleto_fee_perc = fields.Float( + string='Percentual de Multa', + digits=dp.get_precision('Account'), + track_visibility='always', + ) + + boleto_discount_perc = fields.Float( + string=u"Percentual de Desconto até a Data de Vencimento", + digits=dp.get_precision('Account'), + track_visibility='always', + ) + + discount_account_id = fields.Many2one( + comodel_name='account.account', + string='Conta Contabil de Desconto', + help='Conta padrão para Desconto', + track_visibility='always', + ) + + rebate_account_id = fields.Many2one( + comodel_name='account.account', + string='Conta Contabil de Abatimanto', + help='Conta padrão para Abatimento', + track_visibility='always', + ) + + tariff_charge_account_id = fields.Many2one( + comodel_name='account.account', + string='Conta Contabil Tarifa Bancaria', + help='Conta padrão para a Tarifa Bancaria', + track_visibility='always', + ) + + cnab_liq_return_move_code_ids = fields.Many2many( + comodel_name='l10n_br_cnab.return.move.code', + relation='l10n_br_cnab_return_liquidity_move_code_rel', + column1='cnab_liq_return_move_code_id', + column2='payment_mode_id', + string='CNAB Liquidity Return Move Code', + track_visibility='always', + ) + + is_cnab_lot = fields.Boolean( + string="Is it a CNAB lot?", + ) + + # Codigo de Remessa/Inclusão de Registro Detalhe Liberado + cnab_sending_code_id = fields.Many2one( + comodel_name='l10n_br_cnab.mov.instruction.code', + string='Sending Movement Instruction Code', + help='Sending Movement Instruction Code', + track_visibility='always', + ) + + # Codigo para Título/Pagamento Direto ao Fornecedor -Baixar + cnab_write_off_code_id = fields.Many2one( + comodel_name='l10n_br_cnab.mov.instruction.code', + string='Write Off Movement Instruction Code', + help='Write Off Movement Instruction Code', + track_visibility='always', + ) + + # Field used to make invisible banks specifics fields + bank_id = fields.Many2one( + related='fixed_journal_id.bank_id', + ) + + @api.constrains( + 'boleto_type', + 'boleto_wallet', + 'boleto_modality', + 'boleto_variation', + ) + def boleto_restriction(self): + if self.bank_code_bc == '341' and not self.boleto_wallet: + raise ValidationError('Carteira no banco Itaú é obrigatória') + if self.group_lines: + raise ValidationError( + _('The Payment mode can not be used for Boleto/CNAB with the group' + ' lines active. \n Please uncheck it to continue.') + ) + if self.generate_move or self.post_move: + raise ValidationError( + _('The Payment mode can not be used for Boleto/CNAB with the' + ' generated moves or post moves active. \n Please uncheck it' + ' to continue.') + ) + + @api.onchange('product_tax_id') + def _onchange_product_tax_id(self): + if not self.product_tax_id: + self.tax_account_id = False + + @api.multi + def get_own_number_sequence(self, inv, numero_documento): + if inv.company_id.own_number_type == '0': + # SEQUENCIAL_EMPRESA + sequence = inv.company_id.own_number_sequence_id.next_by_id() + elif inv.company_id.own_number_type == '1': + # SEQUENCIAL_FATURA + sequence = numero_documento.replace('/', '') + elif inv.company_id.own_number_type == '2': + # SEQUENCIAL_CARTEIRA + sequence = inv.payment_mode_id.own_number_sequence_id.next_by_id() + else: + raise UserError(_( + 'Favor acessar aba Cobrança da configuração da' + ' sua empresa para determinar o tipo de ' + 'sequencia utilizada nas cobrancas' + )) + + return sequence + + @api.constrains('boleto_discount_perc') + def _check_discount_perc(self): + for record in self: + if record.boleto_discount_perc > 100 or\ + record.boleto_discount_perc < 0: + raise ValidationError( + _('O percentual deve ser um valor entre 0 a 100.')) diff --git a/l10n_br_account_payment_order/models/account_payment_order.py b/l10n_br_account_payment_order/models/account_payment_order.py index 5ed69f16f384..823bb72a47a0 100644 --- a/l10n_br_account_payment_order/models/account_payment_order.py +++ b/l10n_br_account_payment_order/models/account_payment_order.py @@ -1,15 +1,120 @@ +# © 2012 KMEE INFORMATICA LTDA +# @author Fernando Marcato +# @author Hendrix Costa # Copyright (C) 2020 - KMEE (). # author Daniel Sadamo +# Copyright (C) 2020 - Akretion (). +# author Magno Costa +# author Renato Lima # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models -from .account_payment_mode import OPERATION_TYPE +import logging + +from odoo import api, fields, models + +from ..constants import ( + INDICATIVO_FORMA_PAGAMENTO, +) + +_logger = logging.getLogger(__name__) class AccountPaymentOrder(models.Model): - _inherit = 'account.payment.order' + _name = 'account.payment.order' + _inherit = ['account.payment.order', 'l10n_br.cnab.configuration'] + + file_number = fields.Integer( + string='Número sequencial do arquivo', + ) + + cnab_file = fields.Binary( + string='CNAB File', + readonly=True, + ) + + cnab_filename = fields.Char( + string='CNAB Filename', + ) + + code_convetion = fields.Char( + related='payment_mode_id.code_convetion', + help='Campo G007 do CNAB', + ) + + indicative_form_payment = fields.Selection( + selection=INDICATIVO_FORMA_PAGAMENTO, + string='Indicativo de Forma de Pagamento', + help='Campo P014 do CNAB', + default='01', + ) + + bank_line_error_ids = fields.One2many( + comodel_name='bank.payment.line', + inverse_name='order_id', + string='Bank Payment Error Lines', + readonly=True, + domain=[('is_export_error', '=', True)], + ) + + # Usados para deixar invisiveis/somente leitura + # os campos relacionados ao CNAB + payment_method_code = fields.Char( + related='payment_method_id.code', + readonly=True, + store=True, + string='Payment Method Code' + ) + + is_cnab_lot = fields.Boolean( + string="Is it a CNAB lot?", + related='payment_mode_id.is_cnab_lot', + readonly=True, + ) - operation_type = fields.Selection( - selection=OPERATION_TYPE, - string='Tipo de Operação', + payment_mode_ids = fields.Many2many( + comodel_name='account.payment.mode', + string="Payment Modes", + domain="[('is_cnab_lot', '=', True)]", ) + + @api.model + def _prepare_bank_payment_line(self, paylines): + result = super()._prepare_bank_payment_line(paylines) + result['own_number'] = paylines[0].own_number + result['document_number'] = paylines[0].document_number + result['company_title_identification'] =\ + paylines[0].company_title_identification + result['last_cnab_state'] = paylines[0].move_line_id.cnab_state + result['payment_mode_id'] = paylines[0].payment_mode_id.id + result['service_type_id'] = paylines[0].service_type_id.id + result['release_form_id'] = paylines[0].release_form_id.id + result['doc_finality_code_id'] = paylines[0].doc_finality_code_id.id + result['ted_finality_code_id'] = paylines[0].ted_finality_code_id.id + result['mov_instruction_code_id'] = \ + paylines[0].move_line_id.mov_instruction_code_id.id + return result + + @api.multi + def open2generated(self): + result = super().open2generated() + + for record in self: + # TODO - exemplos de caso de uso ? Qdo isso ocorre ? + # Já não gera erro ao tentar criar o arquivo ? + if record.bank_line_error_ids: + record.message_post( + body=('Erro ao gerar o arquivo, ' + 'verifique a aba Linhas com problemas.') + ) + for payment_line in record.payment_line_ids: + payment_line.move_line_id.cnab_state = 'exporting_error' + continue + else: + record.message_post(body='Arquivo gerado com sucesso.') + + return result + + @api.depends('company_partner_bank_id') + def _compute_bank_id(self): + for record in self: + record.bank_id = record.company_partner_bank_id.bank_id diff --git a/l10n_br_account_payment_order/models/bank_payment_line.py b/l10n_br_account_payment_order/models/bank_payment_line.py new file mode 100644 index 000000000000..00dc6ab404e9 --- /dev/null +++ b/l10n_br_account_payment_order/models/bank_payment_line.py @@ -0,0 +1,215 @@ +# © 2012 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# Copyright 2020 Akretion +# @author Magno Costa + +import logging + +from odoo import api, fields, models + +from ..constants import ( + AVISO_FAVORECIDO, + ESTADOS_CNAB, +) + +_logger = logging.getLogger(__name__) + +try: + from erpbrasil.base import misc +except ImportError: + _logger.error("Biblioteca erpbrasil.base não instalada") + + +class BankPaymentLine(models.Model): + _name = 'bank.payment.line' + _inherit = ['bank.payment.line', 'l10n_br.cnab.configuration'] + + @api.model + def default_get(self, fields_list): + res = super().default_get(fields_list) + mode = ( + self.env['account.payment.order'].browse( + self.env.context.get('order_id')).payment_mode_id + ) + if mode.doc_finality_code_id: + res.update({'doc_finality_code_id': mode.doc_finality_code_id}) + if mode.ted_finality_code_id: + res.update({'ted_finality_code_id': mode.ted_finality_code_id}) + if mode.complementary_finality_code: + res.update( + {'complementary_finality_code': mode.complementary_finality_code} + ) + if mode.favored_warning: + res.update({'favored_warning': mode.favored_warning}) + return res + + complementary_finality_code = fields.Char( + string='Código de finalidade complementar', + size=2, + help='Campo P013 do CNAB', + ) + + favored_warning = fields.Selection( + selection=AVISO_FAVORECIDO, + string='Aviso ao Favorecido', + default='0', + help='Campo P006 do CNAB', + ) + + rebate_value = fields.Float( + string='Valor do Abatimento', + digits=(13, 2), + default=0.00, + help='Campo G045 do CNAB', + ) + + discount_value = fields.Float( + string='Valor do Desconto', + digits=(13, 2), + default=0.00, + help='Campo G046 do CNAB', + ) + + interest_value = fields.Float( + string='Valor da Mora', + digits=(13, 2), + default=0.00, + help='Campo G047 do CNAB', + ) + + fee_value = fields.Float( + string='Valor da Multa', + digits=(13, 2), + default=0.00, + help='Campo G048 do CNAB', + ) + + event_id = fields.One2many( + string='Eventos CNAB', + comodel_name='l10n_br_cnab.return.event', + inverse_name='bank_payment_line_id', + readonly=True, + ) + + own_number = fields.Char( + string='Nosso Numero', + ) + + document_number = fields.Char( + string='Número documento', + ) + + company_title_identification = fields.Char( + string='Identificação Titulo Empresa', + ) + + is_export_error = fields.Boolean( + string='Contem erro de exportação', + ) + + export_error_message = fields.Char( + string='Mensagem de erro', + ) + + last_cnab_state = fields.Selection( + selection=ESTADOS_CNAB, + string='Último Estado do CNAB', + help='Último Estado do CNAB antes da confirmação de ' + 'pagamento nas Ordens de Pagamento', + ) + + payment_mode_id = fields.Many2one( + comodel_name='account.payment.mode', + string='Payment Mode', + ondelete='set null', + domain="[('id', 'in', payment_mode_ids)]", + ) + + payment_mode_ids = fields.Many2many( + comodel_name='account.payment.mode', + string="Payment Modes", + readonly=True, + related='order_id.payment_mode_ids', + domain="[('is_cnab_lot', '=', True)]", + ) + + @api.depends('payment_mode_id') + def _compute_bank_id(self): + for record in self: + record.bank_id = record.payment_mode_id.fixed_journal_id.bank_id + record.service_type_id = record.payment_mode_id.service_type_id + record.release_form_id = record.payment_mode_id.release_form_id + record.doc_finality_code_id = \ + record.payment_mode_id.doc_finality_code_id + record.ted_finality_code_id = \ + record.payment_mode_id.ted_finality_code_id + + mov_instruction_code_id = fields.Many2one( + comodel_name='l10n_br_cnab.mov.instruction.code', + string='Código da Instrução para Movimento', + help='Campo G061 do CNAB', + ) + + @api.multi + def unlink(self): + for record in self: + if not record.last_cnab_state: + continue + + move_line_id = self.env['account.move.line'].search( + [ + ( + 'company_title_identification', + '=', + record.company_title_identification, + ) + ] + ) + move_line_id.state_cnab = record.last_cnab_state + + return super().unlink() + + @api.model + def same_fields_payment_line_and_bank_payment_line(self): + """ + This list of fields is used both to compute the grouping + hashcode and to copy the values from payment line + to bank payment line + The fields must have the same name on the 2 objects + """ + same_fields = super().same_fields_payment_line_and_bank_payment_line() + + # TODO: Implementar campo brasileiros que permitem mesclar linhas + + same_fields = [] # Por segurança não vamos mesclar nada + # 'currency', 'partner_id', + # 'bank_id', 'date', 'state'] + + return same_fields + + # TODO: Implementar métodos para outros tipos cnab. + # _prepare_boleto_bank_line_vals + # _prepare_pagamento_bank_line_vals + # _prepare_debito_automatico_bank_line_vals + # _prepare_[...]_bank_line_vals + + def _prepare_bank_line_vals(self): + return { + 'valor': self.amount_currency, + 'data_vencimento': self.date.strftime('%Y/%m/%d'), + 'nosso_numero': self.own_number, + 'documento_sacado': misc.punctuation_rm(self.partner_id.cnpj_cpf), + 'nome_sacado': + self.partner_id.legal_name.strip()[:40], + 'numero': str(self.document_number)[:10], + 'endereco_sacado': str( + self.partner_id.street + ', ' + str( + self.partner_id.street_number))[:40], + 'bairro_sacado': + self.partner_id.district.strip(), + 'cep_sacado': misc.punctuation_rm(self.partner_id.zip), + 'cidade_sacado': + self.partner_id.city_id.name, + 'uf_sacado': self.partner_id.state_id.code, + 'identificacao_ocorrencia': self.mov_instruction_code_id.id + } diff --git a/l10n_br_account_payment_order/models/ir_attachment.py b/l10n_br_account_payment_order/models/ir_attachment.py new file mode 100644 index 000000000000..fa8fe9777bc5 --- /dev/null +++ b/l10n_br_account_payment_order/models/ir_attachment.py @@ -0,0 +1,19 @@ +# Copyright 2020 Akretion +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models, SUPERUSER_ID +from odoo.exceptions import ValidationError + + +class IrAttachment(models.Model): + _inherit = 'ir.attachment' + + @api.multi + def unlink(self): + for rec in self: + if rec.res_model in ['cnab.return.log']\ + and rec.res_id and self._uid != SUPERUSER_ID: + raise ValidationError( + 'Sorry, you are not allowed to delete the attachment.') + return super().unlink() diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab.py b/l10n_br_account_payment_order/models/l10n_br_cnab.py new file mode 100644 index 000000000000..f0630ad2b8b9 --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab.py @@ -0,0 +1,549 @@ +# © 2012 KMEE INFORMATICA LTDA +# @author Luiz Felipe do Divino Costa +# @author Luis Felipe Mileo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +import re +from datetime import datetime + +from odoo import api, fields, models + +from ..constants import ( + CODIGO_OCORRENCIAS, STATE_CNAB, RETORNO_400_CONFIRMADA, RETORNO_400_REJEITADA, + RETORNO_400_LIQUIDACAO, RETORNO_400_BAIXA, RETORNOS_TRATADOS, + COD_REGISTROS_REJEITADOS_CNAB400, CODIGO_OCORRENCIAS_CNAB200, STR_EVENTO_FORMAT) + +_logger = logging.getLogger(__name__) + +TIPO_OPERACAO = { + 'C': 'Lançamento a Crédito', + 'D': 'Lançamento a Débito', + 'E': 'Extrato para Conciliação', + 'G': 'Extrato para Gestão de Caixa', + 'I': 'Informações de Títulos Capturados do Próprio Banco', + 'R': 'Arquivo Remessa', + 'T': 'Arquivo Retorno', +} + +TIPO_SERVICO = { + '01': 'Cobrança', + '03': 'Boleto de Pagamento Eletrônico', + '04': 'Conciliação Bancária', + '05': 'Débitos', + '06': 'Custódia de Cheques', + '07': 'Gestão de Caixa', + '08': 'Consulta/Informação Margem', + '09': 'Averbação da Consignação/Retenção', + '10': 'Pagamento Dividendos', + '11': 'Manutenção da Consignação', + '12': 'Consignação de Parcelas', + '13': 'Glosa da Consignação (INSS)', + '14': 'Consulta de Tributos a pagar', + '20': 'Pagamento Fornecedor', + '22': 'Pagamento de Contas, Tributos e Impostos', + '23': 'Interoperabilidade entre Contas de Instituições de Pagamentos', + '25': 'Compror', + '26': 'Compror Rotativo', + '29': 'Alegação do Pagador', + '30': 'Pagamento Salários', + '32': 'Pagamento de honorários', + '33': 'Pagamento de bolsa auxílio', + '34': 'Pagamento de prebenda (remuneração a padres e sacerdotes)', + '40': 'Vendor', + '41': 'Vendor a Termo', + '50': 'Pagamento Sinistros Segurados', + '60': 'Pagamento Despesas Viajante em Trânsito', + '70': 'Pagamento Autorizado', + '75': 'Pagamento Credenciados', + '77': 'Pagamento de Remuneração', + '80': 'Pagamento Representantes / Vendedores Autorizados', + '90': 'Pagamento Benefícios', + '98': 'Pagamentos Diversos', +} + +TIPO_INSCRICAO_EMPRESA = { + 0: 'Isento / Não informado', + 1: 'CPF', + 2: 'CGC / CNPJ', + 3: 'PIS / PASEP', + 9: 'Outros', +} + + +class L10nBrCnab(models.Model): + _name = 'l10n_br.cnab' + _description = 'l10n_br CNAB' + + display_name = fields.Char(compute='_compute_display_name', store=True, index=True) + + return_file = fields.Binary(string='Arquivo Retorno') + filename = fields.Char(string='Filename') + bank_account_id = fields.Many2one( + string='Conta cedente', comodel_name='res.partner.bank' + ) + cnab_date = fields.Date( + string='Data CNAB', required=True, default=datetime.now().date()) + date_file = fields.Date(string='Data Criação no Banco') + sequential_file = fields.Char(string='Sequencial do Arquivo') + reason_error = fields.Char(string='Motivo do Erro') + lot_id = fields.One2many( + string='Lotes', comodel_name='l10n_br.cnab.lote', inverse_name='cnab_id' + ) + name = fields.Char(string='Name') + number_events = fields.Integer(string='Número de Eventos') + number_lots = fields.Integer(string='Número de Lotes') + state = fields.Selection(string='Estágio', selection=STATE_CNAB, default='draft') + + @api.one + @api.depends('name') + def _compute_display_name(self): + self.display_name = self.name + + def _busca_conta(self, banco, agencia, conta): + return ( + self.env['res.partner.bank'] + .search( + [ + # ('acc_number', '=', str(banco)), + ('bra_number', '=', str(agencia)), + ('acc_number', '=', str(conta)), + ] + ) + .id + ) + + def _cria_lote(self, header, lote, evento, trailer): + + if lote.header: + lote_bank_account_id = self._busca_conta( + lote.header.codigo_do_banco, + lote.header.cedente_agencia, + lote.header.cedente_conta, + ).id + else: + lote_bank_account_id = self.bank_account_id + + vals = { + 'account_bank_id': lote_bank_account_id.id, + 'servico_operacao': header.literal_retorno, + 'tipo_servico': header.literal_servico, + 'qtd_registros': trailer.totais_quantidade_registros, + 'total_valores': float(trailer.valor_total_titulos) / 100, + 'cnab_id': self.id, + } + + lote_id = self.env['l10n_br.cnab.lote'].create(vals) + + return lote_id, lote_bank_account_id + + def _lote_400(self, evento, lote_id): + + bank_payment_line_id = self.env['bank.payment.line'].search( + [('nosso_numero', '=', evento.nosso_numero)], limit=1 + ) + + vals_evento = { + 'bank_payment_line_id': bank_payment_line_id.id, + 'data_ocorrencia': datetime.strptime( + str(evento.data_ocorrencia).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_ocorrencia + else '', + 'data_real_pagamento': datetime.strptime( + str(evento.data_credito).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_credito + else '', + 'identificacao_titulo_empresa': evento.identificacao_titulo_empresa, + 'invoice_id': bank_payment_line_id.payment_line_ids[ + :1 + ].move_line_id.invoice_id.id, + 'juros_mora_multa': float(evento.juros_mora_multa) / 100, + 'lote_id': lote_id.id, + 'nosso_numero': str(evento.nosso_numero), + 'ocorrencias': CODIGO_OCORRENCIAS_CNAB200[evento.codigo_ocorrencia], + 'outros_creditos': float(evento.outros_creditos) / 100, + 'partner_id': bank_payment_line_id.partner_id.id, + 'seu_numero': evento.numero_documento, + 'str_motiv_a': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[0:2])) + if evento.erros[0:2] + else '', + 'str_motiv_b': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[2:4])) + if evento.erros[2:4] + else '', + 'str_motiv_c': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[4:6])) + if evento.erros[4:6] + else '', + 'str_motiv_d': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[6:8])) + if evento.erros[6:8] + else '', + 'tarifa_cobranca': float(evento.tarifa_cobranca), + 'valor': float(evento.valor) / 100, + 'valor_abatimento': float(evento.valor_abatimento) / 100, + 'valor_desconto': float(evento.valor_desconto) / 100, + 'valor_iof': float(evento.valor_iof) / 100, + 'valor_pagamento': evento.valor_principal, + } + cnab_event_id = self.env['l10n_br.cnab.evento'].create(vals_evento) + + amount = 0.0 + line_values = [] + invoices = [] + codigo_ocorrencia = evento.codigo_ocorrencia + if codigo_ocorrencia and bank_payment_line_id: + cnab_state = False + bank_state = False + if codigo_ocorrencia in RETORNO_400_CONFIRMADA: + cnab_state = 'accepted' + bank_state = 'aberta' + elif codigo_ocorrencia in RETORNO_400_REJEITADA: + cnab_state = 'not_accepted' + bank_state = 'inicial' + elif codigo_ocorrencia in RETORNO_400_LIQUIDACAO: + cnab_state = 'accepted' + bank_state = 'liquidada' + elif codigo_ocorrencia in RETORNO_400_BAIXA: + cnab_state = 'accepted' + if codigo_ocorrencia == 9: + bank_state = 'baixa' + else: + bank_state = 'baixa_liquidacao' + else: + cnab_event_id.str_motiv_e = ( + str(codigo_ocorrencia) + ': Ocorrência não tratada' + ) + + if cnab_state: + + for pay_order_line_id in bank_payment_line_id.payment_line_ids: + pay_order_line_id.move_line_id.state_cnab = cnab_state + pay_order_line_id.move_line_id.nosso_numero = str( + evento.nosso_numero + ) + move_line = pay_order_line_id.move_line_id + invoice = move_line.invoice_id + payment_mode = invoice.payment_mode_id + if bank_state == 'liquidada' and invoice.state == 'open': + line_dict = { + 'name': evento.nosso_numero, + 'nosso_numero': evento.nosso_numero, + 'numero_documento': evento.numero_documento, + 'identificacao_titulo_empresa': + evento.identificacao_titulo_empresa, + 'credit': float(evento.valor_principal) + + float(evento.tarifa_cobranca), + 'account_id': payment_mode.default_account_id.id + or invoice.account_id.id, + 'journal_id': bank_payment_line_id.order_id.journal_id.id, + 'date_maturity': datetime.strptime( + str(evento.data_vencimento).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_vencimento + else '', + 'date': datetime.strptime( + str(evento.data_ocorrencia).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_ocorrencia + else '', + 'partner_id': bank_payment_line_id.partner_id.id, + } + + line_values.append((0, 0, line_dict)) + amount += float(evento.valor_principal) + invoices.append(invoice) + + invoice_line_tax_id = invoice.invoice_line_ids.filtered( + lambda i: i.price_subtotal == float(evento.tarifa_cobranca) + ) + if invoice_line_tax_id: + # amount += float(evento.tarifa_cobranca) + + line_dict_tarifa = dict(line_dict) + line_dict_tarifa.update( + { + 'name': str(evento.nosso_numero) + ' - Tarifa', + 'credit': 0, + 'debit': float(evento.tarifa_cobranca), + 'account_id': + payment_mode.default_tax_account_id.id + or invoice.account_id.id, + } + ) + line_values.append((0, 0, line_dict_tarifa)) + + # TODO: Juros / iof / Desconto / Abatimento / + # Outros Créditos + # if evento.juros_mora_multa: + # amount += float(evento.juros_mora_multa) + # line_dict_multa = dict(line_dict) + # line_dict_multa.update({ + # 'name': str(evento.nosso_numero) + ' - Juros', + # 'credit': float(evento.juros_mora_multa), + # 'account_id': invoice.account_id.id, + # }) + # line_values.append((0, 0, line_dict_multa)) + + if bank_state: + move_line.situacao_pagamento = bank_state + if cnab_state: + move_line.state_cnab = cnab_state + + return line_values, amount, invoices + + def _lote_240(self, evento, lote_id): + data_evento = str(evento.credito_data_real) + data_evento = fields.Date.from_string( + data_evento[4:] + '-' + data_evento[2:4] + '-' + data_evento[0:2] + ) + lote_bank_account_id = self.env['res.partner.bank'].search( + [ + ('bra_number', '=', evento.favorecido_agencia), + ('bra_number_dig', '=', evento.favorecido_agencia_dv), + ('acc_number', '=', evento.favorecido_conta), + ('acc_number_dig', '=', evento.favorecido_conta_dv), + ] + ) + lote_bank_account_id = ( + lote_bank_account_id.ids[0] if lote_bank_account_id else False + ) + favorecido_partner = self.env['res.partner.bank'].search( + [('owner_name', 'ilike', evento.favorecido_nome)] + ) + favorecido_partner = ( + favorecido_partner[0].partner_id.id if favorecido_partner else False + ) + bank_payment_line_id = self.env['bank.payment.line'].search( + [('name', '=', evento.credito_seu_numero)] + ) + ocorrencias_dic = dict(CODIGO_OCORRENCIAS) + ocorrencias = [ + evento.ocorrencias[0:2], + evento.ocorrencias[2:4], + evento.ocorrencias[4:6], + evento.ocorrencias[6:8], + evento.ocorrencias[8:10], + ] + vals_evento = { + 'data_real_pagamento': data_evento, + 'segmento': evento.servico_segmento, + 'favorecido_nome': favorecido_partner, + 'favorecido_conta_bancaria': lote_bank_account_id, + 'nosso_numero': str(evento.credito_nosso_numero), + 'seu_numero': evento.credito_seu_numero, + 'tipo_moeda': evento.credito_moeda_tipo, + 'valor_pagamento': evento.credito_valor_pagamento, + 'ocorrencias': evento.ocorrencias, + 'str_motiv_a': ocorrencias_dic[ocorrencias[0]] if ocorrencias[0] else '', + 'str_motiv_b': ocorrencias_dic[ocorrencias[1]] if ocorrencias[1] else '', + 'str_motiv_c': ocorrencias_dic[ocorrencias[2]] if ocorrencias[2] else '', + 'str_motiv_d': ocorrencias_dic[ocorrencias[3]] if ocorrencias[3] else '', + 'str_motiv_e': ocorrencias_dic[ocorrencias[4]] if ocorrencias[4] else '', + 'lote_id': lote_id.id, + 'bank_payment_line_id': bank_payment_line_id.id, + } + self.env['l10n_br.cnab.evento'].create(vals_evento) + if evento.ocorrencias and bank_payment_line_id: + if '00' in ocorrencias: + bank_state = 'paid' + cnab_state = 'accepted' + + else: + bank_state = 'exception' + cnab_state = 'not_accepted' + + bank_payment_line_id.state2 = bank_state + for payment_line in bank_payment_line_id.payment_line_ids: + payment_line.move_line_id.state_cnab = cnab_state + + def _reprocessa_lote_240(self, evento, lote_id): + raise NotImplementedError('FALTA FAZER') + + def _reprocessa_lote_400(self, evento, lote_id): + bank_payment_line_id = self.env['bank.payment.line'].search( + [ + ( + 'identificacao_titulo_empresa', + '=', + evento.identificacao_titulo_empresa, + ) + ], + limit=1, + ) + + cnab_event_id = self.env['l10n_br.cnab.evento'].search( + [ + ('lote_id', '=', lote_id.id), + ('bank_payment_line_id', '!=', False), + ('bank_payment_line_id', '=', bank_payment_line_id.id), + ] + ) + + vals_evento = { + 'bank_payment_line_id': cnab_event_id.bank_payment_line_id.id + or bank_payment_line_id.id, + 'data_ocorrencia': datetime.strptime( + str(evento.data_ocorrencia).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_ocorrencia + else '', + 'data_real_pagamento': datetime.strptime( + str(evento.data_credito).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_credito + else '', + 'identificacao_titulo_empresa': evento.identificacao_titulo_empresa, + 'invoice_id': cnab_event_id.invoice_id.id + or bank_payment_line_id.payment_line_ids[:1].move_line_id.invoice_id.id, + 'juros_mora_multa': cnab_event_id.juros_mora_multa + or float(evento.juros_mora_multa) / 100, + 'lote_id': cnab_event_id.lote_id.id or lote_id.id, + 'nosso_numero': str(evento.nosso_numero), + 'ocorrencias': CODIGO_OCORRENCIAS_CNAB200[evento.codigo_ocorrencia], + 'outros_creditos': cnab_event_id.outros_creditos + or float(evento.outros_creditos) / 100, + 'partner_id': bank_payment_line_id.partner_id.id, + 'seu_numero': evento.numero_documento, + 'str_motiv_a': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[0:2])) + if evento.erros[0:2] + else '', + 'str_motiv_b': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[2:4])) + if evento.erros[2:4] + else '', + 'str_motiv_c': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[4:6])) + if evento.erros[4:6] + else '', + 'str_motiv_d': COD_REGISTROS_REJEITADOS_CNAB400.get(int(evento.erros[6:8])) + if evento.erros[6:8] + else '', + 'tarifa_cobranca': cnab_event_id.tarifa_cobranca + or float(evento.tarifa_cobranca), + 'valor': cnab_event_id.valor or float(evento.valor) / 100, + 'valor_abatimento': cnab_event_id.valor_abatimento + or float(evento.valor_abatimento) / 100, + 'valor_desconto': cnab_event_id.valor_desconto + or float(evento.valor_desconto) / 100, + 'valor_iof': cnab_event_id.valor_iof or float(evento.valor_iof) / 100, + 'valor_pagamento': cnab_event_id.valor_pagamento or evento.valor_principal, + } + + if not cnab_event_id: + cnab_event_id = cnab_event_id.create(vals_evento) + else: + cnab_event_id.write(vals_evento) + + codigo_ocorrencia = evento.codigo_ocorrencia + if codigo_ocorrencia and bank_payment_line_id: + + if not any(codigo_ocorrencia in x for x in RETORNOS_TRATADOS): + cnab_event_id.str_motiv_e = ( + str(codigo_ocorrencia) + ': Ocorrência não tratada' + ) + + bank_payment_line_id.nosso_numero = str(evento.nosso_numero) + for pay_order_line_id in bank_payment_line_id.payment_line_ids: + pay_order_line_id.move_line_id.nosso_numero = str(evento.nosso_numero) + pay_order_line_id.nosso_numero = str(evento.nosso_numero) + debit_move_line = pay_order_line_id.move_line_id + credit_move_line = self.env['account.move.line'].search( + [ + '|', + ('nosso_numero', '=', evento.nosso_numero), + ('name', '=', evento.nosso_numero), + ('credit', '>', 0), + ] + ) + + if not credit_move_line and debit_move_line.full_reconcile_id: + credit_move_line = ( + debit_move_line.full_reconcile_id.reconciled_line_ids + - debit_move_line + ) + + if not credit_move_line: + return + # raise UserError( + # 'Não foi encontrada uma linha correspondente para a ' + # 'linha de nosso_numero: %s' % evento.nosso_numero) + + line_values = { + 'name': evento.nosso_numero, + 'nosso_numero': evento.nosso_numero, + 'numero_documento': evento.numero_documento, + 'identificacao_titulo_empresa': + evento.identificacao_titulo_empresa, + 'date_maturity': datetime.strptime( + str(evento.data_vencimento).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_vencimento + else '', + 'date': datetime.strptime( + str(evento.data_ocorrencia).zfill(6), STR_EVENTO_FORMAT + ) + if evento.data_ocorrencia + else '', + } + + credit_move_line.with_context(reprocessing=True).write(line_values) + + @api.model + def processar_retorno_multi(self): + active_ids = self._context.get('active_ids') + + for cnab_id in self.browse(active_ids): + if cnab_id.state in ['draft']: + cnab_id.processar_arquivo_retorno() + + @api.model + def reprocessar_retorno_multi(self): + active_ids = self._context.get('active_ids') + + for cnab_id in self.browse(active_ids): + if cnab_id.state in ['done']: + cnab_id.reprocessar_arquivo_retorno() + + def reprocessar_arquivo_retorno(self): + raise NotImplementedError + + def processar_arquivo_retorno(self): + raise NotImplementedError + + def _get_name(self, data, filename): + cnab_ids = self.search([('cnab_date', '=', data)], order='id desc') + cnab_idx = 1 + if cnab_ids: + search_result = list( + filter( + lambda x: x is not None, + [ + re.search(r'\((\d)\)', name) + for name in self.search( + [('cnab_date', '=', data), ('id', '!=', self.id)], + order='id desc', + ).mapped('name') + ], + ) + ) + if search_result: + cnab_idx = max(int(result.group(1)) for result in search_result) + 1 + + cnab_name = '{}({}){}'.format( + data, cnab_idx, ' - ' + filename if filename else '' + ) + return cnab_name + + @api.multi + def write(self, vals): + if any(v in vals for v in ['data', 'filename']): + data = vals.get('data') or self.data + filename = vals.get('filename') or self.filename + + name = self._get_name(data, filename) + vals.update({'name': name}) + return super().write(vals) + + @api.model + def create(self, vals): + name = self._get_name(vals.get('data'), vals.get('filename')) + vals.update({'name': name}) + return super().create(vals) diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_configuration.py b/l10n_br_account_payment_order/models/l10n_br_cnab_configuration.py new file mode 100644 index 000000000000..5249ed9eb168 --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_configuration.py @@ -0,0 +1,52 @@ +# Copyright 2020 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class L10nBrCnabConfiguration(models.Model): + _name = 'l10n_br.cnab.configuration' + + bank_id = fields.Many2one( + comodel_name='res.bank', + compute='_compute_bank_id', + ) + + service_type_id = fields.Many2one( + comodel_name='l10n_br.cnab.option', + string='Tipo de Serviço', + help='Campo G025 do CNAB', + domain='[("option_type", "=", "service_type"), ' + '("bank_id", "=", bank_id)]', + store=True, + ) + + release_form_id = fields.Many2one( + comodel_name='l10n_br.cnab.option', + string='Forma Lançamento', + help='Campo G029 do CNAB', + domain='[("option_type", "=", "release_form"), ' + '("bank_id", "=", bank_id)]', + store=True, + ) + + doc_finality_code_id = fields.Many2one( + comodel_name='l10n_br.cnab.option', + string='Complemento do Tipo de Serviço', + help='Campo P005 do CNAB', + domain='[("option_type", "=", "doc_finality_code"), ' + '("bank_id", "=", bank_id)]', + store=True, + ) + + ted_finality_code_id = fields.Many2one( + comodel_name='l10n_br.cnab.option', + string='Código Finalidade da TED', + help='Campo P011 do CNAB', + domain='[("option_type", "=", "ted_finality_code"), ' + '("bank_id", "=", bank_id)]', + store=True, + ) + + def _compute_bank_id(self): + raise NotImplementedError diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_data_abstract.py b/l10n_br_account_payment_order/models/l10n_br_cnab_data_abstract.py new file mode 100644 index 000000000000..922466287c63 --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_data_abstract.py @@ -0,0 +1,56 @@ +# Copyright 2020 Akretion +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models, api, fields, _ +from odoo.exceptions import ValidationError + + +class L10nBrCNABDataAbstract(models.AbstractModel): + _name = 'l10n_br_cnab.data.abstract' + _inherit = 'mail.thread' + _description = 'CNAB Data Abstract' + + name = fields.Char( + string='Name', + index=True, + track_visibility='always', + ) + code = fields.Char( + string='Code', + index=True, + track_visibility='always', + ) + + @api.multi + def name_get(self): + result = [] + for record in self: + result.append(( + record.id, '%s - %s' % ( + record.code, record.name) + )) + return result + + @api.constrains('code') + def check_code(self): + for record in self: + # Tamanho do campo é padrão 2 p/ todos os codigos CNAB ? + if len(record.code) != 2: + raise ValidationError(_( + 'The field Code should have two characters.')) + + # Mesmo o record que está sendo alterado não ter sido ainda salvo + # a pesquisa acaba trazendo ele, por isso o filtro 'id' + code_already_exist = record.search([ + ('id', '!=', record.id), + ('code', '=', record.code), + ('payment_method_ids', 'in', record.payment_method_ids.ids), + ('bank_ids', 'in', record.bank_ids.ids) + ]) + if code_already_exist: + code_name_exist = \ + code_already_exist.code + ' - ' + code_already_exist.name + raise ValidationError(_( + 'The Code %s already exist %s for Bank and CNAB type.') % ( + record.code, code_name_exist)) diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_event.py b/l10n_br_account_payment_order/models/l10n_br_cnab_event.py new file mode 100644 index 000000000000..2af0744c153d --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_event.py @@ -0,0 +1,78 @@ +# © 2012 KMEE INFORMATICA LTDA +# @author Luiz Felipe do Divino Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class L10nBrCNABReturnEvent(models.Model): + """ + The class is used to register the Events of CNAB return file. + """ + _name = 'l10n_br_cnab.return.event' + _description = 'CNAB Return Event' + + cnab_return_log_id = fields.Many2one( + string='CNAB Return Log', comodel_name='l10n_br_cnab.return.log', + ) + # Field used to make invisible/visible fields refer to Lot + is_cnab_lot = fields.Boolean(string='Is CNAB Lot?') + # O arquivo de Retorno pode ter ou não Lotes + lot_id = fields.Many2one( + string='Lote', + comodel_name='l10n_br_cnab.return.lot', + ondelete='cascade' + ) + bank_payment_line_id = fields.Many2one( + string='Bank Payment Line', comodel_name='bank.payment.line' + ) + real_payment_date = fields.Date(string='Data do Crédito') + occurrence_date = fields.Date(string='Data da Ocorrência') + due_date = fields.Date(string='Data de Vencimento') + favored_bank_account_id = fields.Many2one( + string='Conta Bancária', comodel_name='res.partner.bank' + ) + favored_id = fields.Many2one(string='Favorecido', comodel_name='res.partner') + company_title_identification = fields.Char( + string='Identificação do Título da Empresa', required=False + ) + invoice_id = fields.Many2one(comodel_name='account.invoice', string='Fatura') + interest_fee_value = fields.Float(string='Juros de Mora/Multa') + own_number = fields.Char(string='Nosso Número') + occurrences = fields.Char(string='Ocorrências') + other_credits = fields.Float(string='Outros Créditos') + partner_id = fields.Many2one(comodel_name='res.partner', string='Associado') + segment = fields.Char(string='Segmento') + your_number = fields.Char(string='Seu Número') + str_motiv_a = fields.Char('Motivo da ocorrência 01') + str_motiv_b = fields.Char('Motivo de ocorrência 02') + str_motiv_c = fields.Char('Motivo de ocorrência 03') + str_motiv_d = fields.Char('Motivo de ocorrência 04') + str_motiv_e = fields.Char('Motivo de ocorrência 05') + currency_type = fields.Char(string='Tipo de Moeda') + tariff_charge = fields.Float(string='Tarifa') + title_value = fields.Float(string='Valor da Linha') + rebate_value = fields.Float( + string='Valor do Abatimento', + help='''Se o desconto ou abatimento é concedido na entrada do boleto + estes campos são retornados zerados(apesar de corretamente registrados + no Itaú). Se concedidos após a entrada, retornam com os valores + do desconto ou abatimento. + Na liquidação, desconto e abatimento retornam somados no campo + desconto; opcionalmente, mediante cadastro prévio em nosso sistema, + estes valores poderão retornar separados, conforme mostra o + indicador 36.4 do Item 5 - Condições Personalizadas.''', + ) + discount_value = fields.Float( + string='Valor do Desconto', + help='''Se o desconto ou abatimento é concedido na entrada do boleto + estes campos são retornados zerados(apesar de corretamente registrados + no Itaú). Se concedidos após a entrada, retornam com os valores + do desconto ou abatimento. + Na liquidação, desconto e abatimento retornam somados no campo + desconto; opcionalmente, mediante cadastro prévio em nosso sistema, + estes valores poderão retornar separados, conforme mostra o + indicador 36.4 do Item 5 - Condições Personalizadas.''', + ) + iof_value = fields.Float(string='Valor do IOF') + payment_value = fields.Float(string='Valor do Pagamento') diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_lot.py b/l10n_br_account_payment_order/models/l10n_br_cnab_lot.py new file mode 100644 index 000000000000..01768f1d4f10 --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_lot.py @@ -0,0 +1,33 @@ +# © 2012 KMEE INFORMATICA LTDA +# @author Luiz Felipe do Divino Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class L10nBrCNABReturnLot(models.Model): + """ + The class is used to register the Lots of Events in CNAB return file. + """ + _name = 'l10n_br_cnab.return.lot' + _description = 'CNAB Return Lot' + + lot_event_ids = fields.One2many( + string='Eventos', comodel_name='l10n_br_cnab.return.event', + inverse_name='lot_id' + ) + # TODO - deveria ter alguma relação com o objeto cnab.return.log + # diretamente ? Já que já existe com no Evento + # cnab_return_log_id = fields.Many2one( + # string='CNAB Return Log', comodel_name='cnab.return.log', ondelete='cascade' + # ) + account_bank_id = fields.Many2one( + string='Conta Bancária', comodel_name='res.partner.bank' + ) + company_registration_number = fields.Char(string='Número de Inscrição') + company_registration_type = fields.Char(string='Tipo de Inscrição') + message = fields.Char(string='Mensagem') + register_qty = fields.Integer(string='Quantidade de Registros') + operation_service = fields.Char(string='Tipo de Operação') + service_type = fields.Char(string='Tipo do Serviço') + total_value = fields.Float(string='Valor Total') diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_mov_intruction_code.py b/l10n_br_account_payment_order/models/l10n_br_cnab_mov_intruction_code.py new file mode 100644 index 000000000000..8f93a4f7da8a --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_mov_intruction_code.py @@ -0,0 +1,33 @@ +# Copyright 2020 Akretion +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models, fields + + +class L10nBrCNABMovInstructionCode(models.Model): + _name = 'l10n_br_cnab.mov.instruction.code' + _inherit = 'l10n_br_cnab.data.abstract' + _description = 'CNAB Movement Instruction Code' + + bank_ids = fields.Many2many( + string='Bank', + comodel_name='res.bank', + relation='l10n_br_cnab_mov_instruction_code_bank_rel', + column1='bank_id', + column2='l10n_br_cnab_mov_instruction_code_id', + track_visibility='always', + ) + + payment_method_ids = fields.Many2many( + comodel_name='account.payment.method', + string='Payment Method', + relation='l10n_br_cnab_mov_instruction_code_payment_method_rel', + column1='payment_method_id', + column2='l10n_br_cnab_mov_instruction_code_id', + track_visibility='always', + ) + + comment = fields.Text( + string='Comment' + ) diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_option.py b/l10n_br_account_payment_order/models/l10n_br_cnab_option.py new file mode 100644 index 000000000000..d1388e59103f --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_option.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models, fields + + +class L10nBrCnabOption(models.Model): + _name = 'l10n_br.cnab.option' + + code = fields.Char( + string='Code', + ) + + description = fields.Char( + string='Description', + ) + + option_type = fields.Selection( + string='Option Type', + selection=[ + ("release_form", "Forma de Lançamento"), + ("service_type", "Tipo de Serviço"), + ("ted_finality_code", "Código Finalidade da TED"), + ("doc_finality_code", "Código Finalidade da DOC"), + ] + ) + + bank_id = fields.Many2one( + comodel_name='res.bank', + ) + + @api.multi + @api.depends('code', 'description') + def name_get(self): + result = [] + for record in self: + result.append( + (record.id, '%s - %s' % (record.code, record.description)) + ) + return result + + @api.model + def name_search(self, name, args=None, operator='ilike', limit=100): + args = args or [] + recs = self.browse() + if name: + recs = self.search([('code', '=', name)] + args, limit=limit) + if not recs: + recs = self.search( + [('description', operator, name)] + args, limit=limit) + return recs.name_get() diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_return_log.py b/l10n_br_account_payment_order/models/l10n_br_cnab_return_log.py new file mode 100644 index 000000000000..ed167ff05582 --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_return_log.py @@ -0,0 +1,59 @@ +# Copyright 2020 Akretion +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models, fields + + +class L10nBrCNABReturnLog(models.Model): + """ + The class is used to register the LOG of CNAB return file. + """ + _name = 'l10n_br_cnab.return.log' + _inherit = ['mail.thread', 'mail.activity.mixin'] + _description = 'CNAB Return Log' + + name = fields.Char(string='Name') + filename = fields.Char(string='Nome do Arquivo') + number_events = fields.Integer(string='Número de Eventos') + number_lots = fields.Integer(string='Número de Lotes') + cnab_date_import = fields.Datetime(string='CNAB Date Import') + bank_account_id = fields.Many2one( + string='Conta cedente', comodel_name='res.partner.bank' + ) + # TODO - validar o campo a partir do primeiro arquivo incluido + # para evitar de 'pular' a sequencia ? + # O BRCobranca ignora a linha do header + sequential_file = fields.Char(string='Sequencial do Arquivo') + cnab_date_file = fields.Date(string='CNAB Date File') + + event_ids = fields.One2many( + string='Eventos', comodel_name='l10n_br_cnab.return.event', + inverse_name='cnab_return_log_id' + ) + amount_total_title = fields.Float( + string='Valor Total Títulos' + ) + amount_total_received = fields.Float( + string='Valor Total Recebido' + ) + amount_total_tariff_charge = fields.Float( + string='Valor Total de Tarifas' + ) + amount_total_rebate = fields.Float( + string='Valor Total de Abatimentos' + ) + amount_total_discount = fields.Float( + string='Valor Total de Descontos' + ) + amount_total_interest_fee = fields.Float( + string='Valor Total de Juros Mora/Multa' + ) + # Field used to make invisible/visible fields refer to Lot + is_cnab_lot = fields.Boolean( + string='Is CNAB Lot?' + ) + # The LOG can have or not Journal Entry + move_id = fields.Many2one( + string='Journal Entry', comodel_name='account.move' + ) diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_return_move_code.py b/l10n_br_account_payment_order/models/l10n_br_cnab_return_move_code.py new file mode 100644 index 000000000000..8449ce400e23 --- /dev/null +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_return_move_code.py @@ -0,0 +1,29 @@ +# Copyright 2020 Akretion +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models, fields + + +class L10nBrCNABReturnMoveCode(models.Model): + _name = 'l10n_br_cnab.return.move.code' + _inherit = 'l10n_br_cnab.data.abstract' + _description = 'CNAB Return Move Code' + + bank_ids = fields.Many2many( + string='Bank', + comodel_name='res.bank', + relation='l10n_br_cnab_return_move_code_bank_rel', + column1='bank_id', + column2='l10n_br_cnab_return_move_code_id', + track_visibility='always', + ) + + payment_method_ids = fields.Many2many( + comodel_name='account.payment.method', + string='Payment Method', + relation='l10n_br_cnab_return_move_code_payment_method_rel', + column1='payment_method_id', + column2='l10n_br_cnab_mov_instruction_code_id', + track_visibility='always', + ) diff --git a/l10n_br_account_payment_order/models/res_company.py b/l10n_br_account_payment_order/models/res_company.py new file mode 100644 index 000000000000..0ae20ff53bcd --- /dev/null +++ b/l10n_br_account_payment_order/models/res_company.py @@ -0,0 +1,23 @@ +# © 2012 KMEE INFORMATICA LTDA +# @author Luis Felipe Mileo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = 'res.company' + + own_number_type = fields.Selection( + selection=[ + ('0', 'Sequêncial único por empresa'), + ('1', 'Numero sequêncial da Fatura'), + ('2', 'Sequêncial único por carteira'), + ], + string='Tipo de nosso número', + default='1', + ) + + own_number_sequence_id = fields.Many2one( + comodel_name='ir.sequence', string='Sequência do Nosso Número' + ) diff --git a/l10n_br_account_payment_order/models/res_partner_bank.py b/l10n_br_account_payment_order/models/res_partner_bank.py deleted file mode 100644 index 5c275ba410aa..000000000000 --- a/l10n_br_account_payment_order/models/res_partner_bank.py +++ /dev/null @@ -1,21 +0,0 @@ -# @ 2018 Akretion - www.akretion.com.br - -# Magno Costa -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -from odoo import models, api, _ -from odoo.exceptions import Warning as UserError - - -class ResPartnerBank(models.Model): - _inherit = 'res.partner.bank' - - @api.multi - @api.constrains('bra_number') - def check_bra_number(self): - for record in self: - if record.bank_id.code_bc == '033': - if len(record.bra_number) > 4: - raise UserError(_( - u'O cógido da Agencia Bancaria do Santander' - u' deve ter no máximo quatro caracteres.' - )) diff --git a/l10n_br_account_payment_order/readme/CONFIGURE.rst b/l10n_br_account_payment_order/readme/CONFIGURE.rst index 1b48c9c3b603..e7dc235973ab 100644 --- a/l10n_br_account_payment_order/readme/CONFIGURE.rst +++ b/l10n_br_account_payment_order/readme/CONFIGURE.rst @@ -1 +1 @@ -No configuration required. \ No newline at end of file +No configuration required. diff --git a/l10n_br_account_payment_order/readme/CONTRIBUTORS.rst b/l10n_br_account_payment_order/readme/CONTRIBUTORS.rst index 87a88f53e92c..15e157d0dc85 100644 --- a/l10n_br_account_payment_order/readme/CONTRIBUTORS.rst +++ b/l10n_br_account_payment_order/readme/CONTRIBUTORS.rst @@ -2,4 +2,3 @@ * Fernando Marcato * Hendrix Costa * Magno Costa - diff --git a/l10n_br_account_payment_order/readme/CREDITS.rst b/l10n_br_account_payment_order/readme/CREDITS.rst index 186f5e96a375..a9acbd0203b2 100644 --- a/l10n_br_account_payment_order/readme/CREDITS.rst +++ b/l10n_br_account_payment_order/readme/CREDITS.rst @@ -1,4 +1,4 @@ The development of this module has been financially supported by: * KMEE INFORMATICA LTDA - www.kmee.com.br -* AKRETION LTDA - www.akretion.com \ No newline at end of file +* AKRETION LTDA - www.akretion.com diff --git a/l10n_br_account_payment_order/readme/HISTORY.rst b/l10n_br_account_payment_order/readme/HISTORY.rst index f9edf64f0b04..495eb888ddb3 100644 --- a/l10n_br_account_payment_order/readme/HISTORY.rst +++ b/l10n_br_account_payment_order/readme/HISTORY.rst @@ -27,4 +27,4 @@ 12.0.1.0.0 (2019-06-06) ~~~~~~~~~~~~~~~~~~~~~~~ -* [MIG] Migração para a versão 12.0. \ No newline at end of file +* [MIG] Migração para a versão 12.0. diff --git a/l10n_br_account_payment_order/reports/report_print_button_view.xml b/l10n_br_account_payment_order/reports/report_print_button_view.xml new file mode 100644 index 000000000000..8265fa33db05 --- /dev/null +++ b/l10n_br_account_payment_order/reports/report_print_button_view.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/l10n_br_account_payment_order/security/cnab_cobranca_security.xml b/l10n_br_account_payment_order/security/cnab_cobranca_security.xml new file mode 100644 index 000000000000..963afdc3ff1f --- /dev/null +++ b/l10n_br_account_payment_order/security/cnab_cobranca_security.xml @@ -0,0 +1,30 @@ + + + + + CNAB + Helps you handle your CNAB needs. + 99 + + + + CNAB User + + + + + + CNAB Manager + + + + + + + + + + + + + diff --git a/l10n_br_account_payment_order/security/ir.model.access.csv b/l10n_br_account_payment_order/security/ir.model.access.csv new file mode 100644 index 000000000000..4c1cbf974dac --- /dev/null +++ b/l10n_br_account_payment_order/security/ir.model.access.csv @@ -0,0 +1,13 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_l10n_br_cnab_return_move_code_user","access_l10n_br_cnab_return_move_code_user","model_l10n_br_cnab_return_move_code","group_cnab_user",1,0,0,0 +"access_l10n_br_cnab_return_move_code_manager","access_l10n_br_cnab_return_move_code_manager","model_l10n_br_cnab_return_move_code","group_cnab_manager",1,1,1,1 +"access_l10n_br_cnab_return_log_user","access_l10n_br_cnab_return_log_user","model_l10n_br_cnab_return_log","group_cnab_user",1,1,1,0 +"access_l10n_br_cnab_return_log_manager","access_l10n_br_cnab_return_log_manager","model_l10n_br_cnab_return_log","group_cnab_manager",1,1,1,1 +"access_l10n_br_cnab_return_event_user","access_l10n_br_cnab_return_event_user","model_l10n_br_cnab_return_event","group_cnab_user",1,1,1,0 +"access_l10n_br_cnab_return_event_manager","access_l10n_br_cnab_return_event_manager","model_l10n_br_cnab_return_event","group_cnab_manager",1,1,1,1 +"access_l10n_br_cnab_return_lot_user","access_l10n_br_cnab_return_lot_user","model_l10n_br_cnab_return_lot","group_cnab_user",1,1,1,0 +"access_l10n_br_cnab_return_lot_manager","access_l10n_br_cnab_return_lot_manager","model_l10n_br_cnab_return_lot","group_cnab_manager",1,1,1,1 +"access_l10n_br_cnab_mov_instruction_code_user","access_l10n_br_cnab_mov_instruction_code_user","model_l10n_br_cnab_mov_instruction_code","group_cnab_user",1,0,0,0 +"access_l10n_br_cnab_mov_instruction_code_manager","access_l10n_br_cnab_mov_instruction_code_manager","model_l10n_br_cnab_mov_instruction_code","group_cnab_manager",1,1,1,1 +"access_l10n_br_cnab_option","access_l10n_br_cnab_option_manager","model_l10n_br_cnab_option","group_cnab_manager",1,1,1,1 +"access_l10n_br_cnab_configuration","access_l10n_br_cnab_configuration_manager","model_l10n_br_cnab_configuration","group_cnab_manager",1,1,1,1 diff --git a/l10n_br_account_payment_order/static/description/index.html b/l10n_br_account_payment_order/static/description/index.html index 1e985bae4364..54ba06418df3 100644 --- a/l10n_br_account_payment_order/static/description/index.html +++ b/l10n_br_account_payment_order/static/description/index.html @@ -389,8 +389,7 @@

Brazilian Payment Order

  • Credits
  • @@ -482,16 +481,8 @@

    Contributors

  • Magno Costa <magno.costa@akretion.com.br>
  • -
    -

    Other credits

    -

    The development of this module has been financially supported by:

    -
      -
    • KMEE INFORMATICA LTDA - www.kmee.com.br
    • -
    • AKRETION LTDA - www.akretion.com
    • -
    -
    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association

    OCA, or the Odoo Community Association, is a nonprofit organization whose diff --git a/l10n_br_account_payment_order/tests/__init__.py b/l10n_br_account_payment_order/tests/__init__.py index c1180c63ef51..479d51fe9ee3 100644 --- a/l10n_br_account_payment_order/tests/__init__.py +++ b/l10n_br_account_payment_order/tests/__init__.py @@ -3,3 +3,4 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) from . import test_payment_order +from . import test_payment_order_inbound diff --git a/l10n_br_account_payment_order/tests/test_payment_order.py b/l10n_br_account_payment_order/tests/test_payment_order.py index c3ccd8a948d5..a7154265cb6f 100644 --- a/l10n_br_account_payment_order/tests/test_payment_order.py +++ b/l10n_br_account_payment_order/tests/test_payment_order.py @@ -4,7 +4,7 @@ from openerp.tests.common import TransactionCase -from openerp.exceptions import UserError, ValidationError +from openerp.exceptions import ValidationError class TestPaymentOrder(TransactionCase): @@ -13,21 +13,22 @@ def setUp(self): super().setUp() # Get Invoice for test self.invoice_customer_original = self.env.ref( - 'l10n_br_account_payment_order.demo_invoice_payment_order' + 'l10n_br_account_payment_order.' + 'demo_invoice_payment_order_itau_cnab400' ) # Payment Mode self.payment_mode = self.env.ref( - 'l10n_br_account_payment_order.main_company_payment_mode_boleto' + 'l10n_br_account_payment_order.payment_mode_cobranca_itau400' ) - self.env['account.payment.order'].search([]) - # Configure to be possibile create Payment Order self.payment_mode.payment_order_ok = True self.invoice_customer_original.payment_mode_id = self.payment_mode.id + self.invoice_customer_original._onchange_payment_mode_id() + # Configure Journal to update posted self.invoice_customer_original.journal_id.update_posted = True @@ -44,6 +45,9 @@ def setUp(self): assert self.invoice_customer_original.move_id,\ "Move not created for open invoice" + payment_order = self.env['account.payment.order'].search([]) + assert payment_order, "Payment Order not created." + def test_implemented_fields_payment_order(self): """ Test implemented fields in object account.move.line """ # Check Payment Mode field @@ -59,7 +63,9 @@ def test_implemented_fields_payment_order(self): self.assertEquals( line.journal_entry_ref, line.invoice_id.name, "Error with compute field journal_entry_ref") - test_balance_value = line.get_balance() + # testar com a parcela 700 + if line.debit == 700.0: + test_balance_value = line.get_balance() # Return the status of Move to Posted self.invoice_customer_original.move_id.action_post() @@ -67,10 +73,14 @@ def test_implemented_fields_payment_order(self): for line in self.invoice_customer_original.move_id.line_ids.filtered( lambda l: l.account_id.id == self.invoice_customer_original.account_id.id): + assert line.own_number,\ + 'own_number field is not filled in created Move Line.' self.assertEquals( line.journal_entry_ref, line.invoice_id.name, "Error with compute field journal_entry_ref") - test_balance_value = line.get_balance() + # testar com a parcela 700 + if line.debit == 700.0: + test_balance_value = line.get_balance() self.assertEquals( test_balance_value, 700.0, @@ -79,11 +89,12 @@ def test_implemented_fields_payment_order(self): def test_cancel_payment_order(self): """ Test create and cancel a Payment Order.""" # Add to payment order - self.invoice_customer_original.create_account_payment_line() + payment_order = self.env['account.payment.order'].search([ + ('payment_mode_id', '=', self.payment_mode.id)]) + + bank_journal = self.env.ref( + 'l10n_br_account_payment_order.itau_journal') - payment_order = self.env['account.payment.order'].search([]) - bank_journal = self.env['account.journal'].search( - [('type', '=', 'bank')], limit=1) # Set journal to allow cancelling entries bank_journal.update_posted = True @@ -95,40 +106,39 @@ def test_cancel_payment_order(self): self.assertEquals(len(payment_order.bank_line_ids), 0) for line in payment_order.payment_line_ids: - line.percent_interest = 1.5 - self.assertEquals(line._get_info_partner( - self.invoice_customer_original.partner_id), - 'AKRETION LTDA', - "Error with method _get_info_partner" - ) - test_amount_interest = line.amount_interest - self.assertEquals( - test_amount_interest, 10.5, - "Error with compute field amount_interest.") + # testar com a parcela 700 + if line.amount_currency == 700.0: + line.percent_interest = 1.5 + test_amount_interest = line.amount_interest + if line.amount_currency == 700.0: + self.assertEquals( + test_amount_interest, 10.5, + "Error with compute field amount_interest.") # Open payment order payment_order.draft2open() self.assertEquals(len(payment_order.bank_line_ids), 2) + # TODO # Generate and upload - payment_order.open2generated() - payment_order.generated2uploaded() - - self.assertEquals(payment_order.state, 'uploaded') - with self.assertRaises(UserError): - payment_order.unlink() + # payment_order.open2generated() + # payment_order.generated2uploaded() + # self.assertEquals(payment_order.state, 'uploaded') + # with self.assertRaises(UserError): + # payment_order.unlink() bank_line = payment_order.bank_line_ids - with self.assertRaises(UserError): - bank_line.unlink() + # with self.assertRaises(UserError): + bank_line.unlink() payment_order.action_done_cancel() self.assertEquals(payment_order.state, 'cancel') payment_order.unlink() - self.assertEquals(len(self.env['account.payment.order'].search([])), 0) + self.assertEquals(len(self.env['account.payment.order'].search([ + ('payment_mode_id', '=', self.payment_mode.id)])), 0) def test_bra_number_constrains(self): """ Test bra_number constrains. """ @@ -141,3 +151,10 @@ def test_bra_number_constrains(self): partner_id=self.ref('l10n_br_base.res_partner_akretion'), bra_number='12345' )) + + def test_cancel_invoice(self): + """ Test Cancel Invoice """ + self.invoice_customer_original.action_invoice_cancel() + + # I check that the invoice state is "Cancel" + self.assertEquals(self.invoice_customer_original.state, 'cancel') diff --git a/l10n_br_account_payment_order/tests/test_payment_order_inbound.py b/l10n_br_account_payment_order/tests/test_payment_order_inbound.py new file mode 100644 index 000000000000..4a39cda13556 --- /dev/null +++ b/l10n_br_account_payment_order/tests/test_payment_order_inbound.py @@ -0,0 +1,169 @@ +# @ 2020 Akretion - www.akretion.com.br - +# Magno Costa +# @ 2020 KMEE - www.kmee.com.br +# Luis Felipe Mileo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + + +from odoo.tests.common import TransactionCase + + +class TestPaymentOrderInbound(TransactionCase): + + def setUp(self): + super().setUp() + + # Get Invoice for test + self.invoice_customer_original = self.env.ref( + 'l10n_br_account_payment_order.demo_invoice_payment_order' + ) + + self.invoice_customer_original.journal_id.update_posted = True + + # Product Tax Boleto + self.invoice_product_tax_boleto = self.env.ref( + 'l10n_br_account_payment_order.demo_invoice_payment_order_bb_cnab400' + ) + + # Product Tax Boleto + self.invoice_cheque = self.env.ref( + 'l10n_br_account_payment_order.demo_invoice_payment_order_cheque' + ) + + def test_payment_order(self): + """Test automatic creation of Payment Order.""" + + # I check that Initially customer invoice is in the "Draft" state + self.assertEquals(self.invoice_customer_original.state, 'draft') + + # I validate invoice by creating on + self.invoice_customer_original.action_invoice_open() + + # I check that the invoice state is "Open" + self.assertEquals(self.invoice_customer_original.state, 'open') + + # I check that now there is a move attached to the invoice + assert self.invoice_customer_original.move_id,\ + "Move not created for open invoice" + + payment_order = self.env['account.payment.order'].search([ + ('state', '=', 'draft') + ]) + # I check creation of Payment Order + assert payment_order, "Payment Order not created." + payment_order.draft2open() + # The file generation need additional module to use BRCobranca or PyBoleto + # payment_order.open2generated() + + def test_product_tax_boleto(self): + """ Test Invoice where Payment Mode has Product Tax. """ + self.invoice_product_tax_boleto._onchange_payment_mode_id() + # I validate invoice by creating on + self.invoice_customer_original.action_invoice_open() + + # I check that the invoice state is "Open" + self.assertEquals(self.invoice_customer_original.state, 'open') + + def test_payment_mode_without_payment_order(self): + """ Test Invoice when Payment Mode not generate Payment Order. """ + self.invoice_cheque._onchange_payment_mode_id() + # I validate invoice by creating on + self.invoice_cheque.action_invoice_open() + + # I check that the invoice state is "Open" + self.assertEquals(self.invoice_cheque.state, 'open') + + def test_payment_inbound_change_due_date(self): + """ Change account.move.line due date. Automatic add this aml to a new + payment.order, export the movement to the bank and process it's accept return. + :return: + """ + pass + + def test_payment_inbound_cancel_invoice_not_registred(self): + """ Cancel the invoice with a payment that isn't registred at the bank + :return: + """ + pass + + def test_payment_inbound_cancel_invoice_alread_registred_raise(self): + """ Cancel the invoice with a payment that is already registred at the bank. + For that you have to create bank movement of "BAIXA" before you can cancel + the invoice. + + In this test we must get a raise when trying to cancel the invoice. + + :return: + """ + pass + + def test_payment_inbound_payment_in_cash(self): + """ Pay a invoice in cash, with a payment already registred to in the bank. + Then we must cancel the boleto at the bank, creating a movement of "BAIXA". + :return: + """ + pass + + def test_payment_inbound_cancel_invoice_alread_registred_with_baixa(self): + """ Cancel the invoice with a payment that is already registred at the bank. + For that you have to create bank movement of "BAIXA" before you can cancel + the invoice. + :return: + """ + pass + + def test_payment_inbound_return_accept(self): + """ The payment was exported and the bank return that it's accepted + :return: + """ + pass + + def test_payment_inbound_return_denied(self): + """ The payment was exported and the bank return that it's denied + :return: + """ + pass + + def test_payment_inbound_return_paid(self): + """ The payment was exported, accepted, and after some days the bank + return that it's paid (LIQUIDADO) by the customer + :return: + """ + pass + + def test_payment_inbound_return_baixado(self): + """ The payment was exported, accepted, and after some days the user at + internet banking cancel it (STATE: BAIXADO). The invoice must stay + open, waiting to the user to do a new manual action. + + - The user must be warned that the state of the invoice/aml + was changed at the bank; + - The user can record manual/statement payment with another payment method; + - The user can cancel the invoice/aml; + + This test is similar with "test_payment_inbound_payment_in_cash" buy + it is not exported again to the bank because i'ts already set manualy at the + internet banking + :return: + """ + pass + + def test_payment_inbound_return_paid_with_interest(self): + """ The payment was exported, accepted, and after some days the bank + return that it's paid (LIQUIDADO) by the customer but with interest + :return: + """ + pass + + def test_payment_inbound_return_paid_with_discount(self): + """ The payment was exported, accepted, and after some days the bank + return that it's paid (LIQUIDADO) by the customer but with discount + :return: + """ + pass + + def test_payment_inbound_protesto(self): + """ Protesto movement sent and accepted + :return: + """ + pass diff --git a/l10n_br_account_payment_order/tests/test_remessa.REM b/l10n_br_account_payment_order/tests/test_remessa.REM new file mode 100644 index 000000000000..98e34ca146f4 --- /dev/null +++ b/l10n_br_account_payment_order/tests/test_remessa.REM @@ -0,0 +1,6 @@ +23100000 281583054000129 01611000000000039500Sua Empresa BANCO BRADESCO S.A. 11303201712000000000108400000 +23100011R01 042 2081583054000129 01611000000000039500Sua Empresa 000001011303201700000000 +2310001300001P 01016110000000000395000000000000000000000030 0 001 0503201700000000010000000000 01A130320170050320170000000000000000000000000000000000000000000000000000000000000000000001 00020 000000000000 +2310001300002Q 012081493979000189Cliente 1 SP Rua Samuel Morse 135 Brooklin 04576060Sao Paulo SP0000000000000000 000 +23100015 00000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000 +23199999 000001000006000000 diff --git a/l10n_br_account_payment_order/views/account_due_list.xml b/l10n_br_account_payment_order/views/account_due_list.xml deleted file mode 100644 index 2269b063c65d..000000000000 --- a/l10n_br_account_payment_order/views/account_due_list.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - l10n_br_account_payment_order.aml - account.move.line - - - - - - - - - diff --git a/l10n_br_account_payment_order/views/account_invoice.xml b/l10n_br_account_payment_order/views/account_invoice.xml new file mode 100644 index 000000000000..0d50c27453c7 --- /dev/null +++ b/l10n_br_account_payment_order/views/account_invoice.xml @@ -0,0 +1,36 @@ + + + + + + view.l10n_br_account.invoice.form.form.inherit + account.invoice + + + + + + + + + + + + + view.account.invoice.filter.inherit + account.invoice + search + + + + {'group_by': 'partner_id'} + + + [('state','!=','paid')] + + + + diff --git a/l10n_br_account_payment_order/views/account_journal.xml b/l10n_br_account_payment_order/views/account_journal.xml new file mode 100644 index 000000000000..1b4ae33ad2e1 --- /dev/null +++ b/l10n_br_account_payment_order/views/account_journal.xml @@ -0,0 +1,29 @@ + + + + + + + account.journal.bank.form (in l10n_br_account_payment_order) + account.journal + + + + + + + + + + account.journal.form (in l10n_br_account_payment_order) + account.journal + + + + + + + + + diff --git a/l10n_br_account_payment_order/views/account_move_line.xml b/l10n_br_account_payment_order/views/account_move_line.xml new file mode 100644 index 000000000000..7e5caa39e3f8 --- /dev/null +++ b/l10n_br_account_payment_order/views/account_move_line.xml @@ -0,0 +1,57 @@ + + + + + cnab.account.move.line.form.inherit + account.move.line + + + + +

    + +
    + + + + + + + + + + + + + +
    + +
    +
    + + + + + cnab.account.move.line.tree.inherit + account.move.line + + + + + +
    + + +
    + +
    + + + + + + diff --git a/payment_cielo/tests/__init__.py b/payment_cielo/tests/__init__.py new file mode 100644 index 000000000000..b4328d2b076c --- /dev/null +++ b/payment_cielo/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2020 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_cielo diff --git a/payment_cielo/tests/test_cielo.py b/payment_cielo/tests/test_cielo.py new file mode 100644 index 000000000000..6a1e7da0956e --- /dev/null +++ b/payment_cielo/tests/test_cielo.py @@ -0,0 +1,226 @@ +# Copyright 2020 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import unittest +import odoo +from odoo import fields +from odoo.addons.payment.tests.common import PaymentAcquirerCommon +from odoo.tools import mute_logger +import logging + +_logger = logging.getLogger(__name__) + + +class CieloCommon(PaymentAcquirerCommon): + + def setUp(self): + super(CieloCommon, self).setUp() + self.cielo = self.env.ref('payment_cielo.payment_acquirer_cielo') + self.cielo.write({ + 'cielo_merchant_id': 'be87a4be-a40d-4a2d-b2c8-b8b6cc19cddd', + 'cielo_merchant_key': 'POHAWRXFBSIXTMTFVBCYSKNWZBMOATDNYUQDGBUE', + }) + + +@odoo.tests.tagged('post_install', '-at_install') +class CieloTest(CieloCommon): + + def test_10_cielo_s2s(self): + self.assertEqual(self.cielo.environment, 'test', + 'test without test environment') + + # Add Cielo credentials + self.cielo.write({ + 'cielo_merchant_id': 'be87a4be-a40d-4a2d-b2c8-b8b6cc19cddd', + 'cielo_merchant_key': 'POHAWRXFBSIXTMTFVBCYSKNWZBMOATDNYUQDGBUE', + }) + + # Create payment meethod for Cielo + payment_token = self.env['payment.token'].create({ + 'acquirer_id': self.cielo.id, + 'partner_id': self.buyer_id, + 'cc_number': '4024007197692931', + 'cc_expiry': '02 / 26', + 'cc_brand': 'visa', + 'cvc': '111', + 'cc_holder_name': 'Johndoe', + }) + + # Create transaction + tx = self.env['payment.transaction'].create({ + 'reference': 'test_ref_%s' % fields.date.today(), + 'currency_id': self.currency_euro.id, + 'acquirer_id': self.cielo.id, + 'partner_id': self.buyer_id, + 'payment_token_id': payment_token.id, + 'type': 'server2server', + 'amount': 115.0 + }) + tx.cielo_s2s_do_transaction() + self.assertEqual(tx.state, 'authorized', + 'transaction state should be authorized') + tx.action_capture() + self.assertEqual(tx.state, 'done', + 'transaction state should be done') + tx.cielo_s2s_void_transaction() + self.assertEqual(tx.state, 'done', + 'transaction state should be done') + + def test_20_cielo_s2s(self): + # Test invalid card + self.assertEqual(self.cielo.environment, 'test', + 'test without test environment') + + # Add Cielo credentials + self.cielo.write({ + 'cielo_merchant_id': 'be87a4be-a40d-4a2d-b2c8-b8b6cc19cddd', + 'cielo_merchant_key': 'POHAWRXFBSIXTMTFVBCYSKNWZBMOATDNYUQDGBUE', + }) + + # Create payment meethod for Cielo + try: + payment_token = self.env['payment.token'].create({ + 'acquirer_id': self.cielo.id, + 'partner_id': self.buyer_id, + 'cc_number': '5324007197691291', + 'cc_expiry': '02 / 12', + 'cc_brand': 'visa', + 'cvc': '111', + 'cc_holder_name': 'Johndoe', + }) + except Exception as e: + _logger.warning(e) + + # Create transaction + try: + tx = self.env['payment.transaction'].create({ + 'reference': 'test_ref_%s' % fields.date.today(), + 'currency_id': self.currency_euro.id, + 'acquirer_id': self.cielo.id, + 'partner_id': self.buyer_id, + 'payment_token_id': payment_token.id, + 'type': 'server2server', + 'amount': 115.0 + }) + except Exception as e: + _logger.warning(e) + + try: + tx.cielo_s2s_do_transaction() + except Exception as e: + _logger.warning(e) + + with self.assertRaises(NameError): + self.assertEqual(tx, None) + + @unittest.skip( + "as the test is post-install and because payment_strip_sca changes" + "the code logic and is automatically installed, this test is invalid.") + def test_30_cielo_form_management(self): + self.assertEqual(self.cielo.environment, 'test', + 'test without test environment') + + # typical data posted by Cielo after client has successfully paid + cielo_post_data = { + u'amount': 470000, + u'amount_refunded': 0, + u'application_fee': None, + u'balance_transaction': u'txn_172xfnGMfVJxozLwssrsQZyT', + u'captured': True, + u'created': 1446529775, + u'currency': u'eur', + u'customer': None, + u'description': None, + u'destination': None, + u'dispute': None, + u'failure_code': None, + u'failure_message': None, + u'fraud_details': {}, + u'id': u'ch_172xfnGMfVJxozLwEjSfpfxD', + u'invoice': None, + u'livemode': False, + u'metadata': {u'reference': u'SO100-1'}, + u'object': u'charge', + u'paid': True, + u'receipt_email': None, + u'receipt_number': None, + u'refunded': False, + u'refunds': { + u'data': [], + u'has_more': False, + u'object': u'list', + u'total_count': 0, + u'url': + u'/v1/charges/ch_172xfnGMfVJxozLwEjSfpfxD/refunds' + }, + u'shipping': None, + u'source': { + u'address_city': None, + u'address_country': None, + u'address_line1': None, + u'address_line1_check': None, + u'address_line2': None, + u'address_state': None, + u'address_zip': None, + u'address_zip_check': None, + u'brand': u'Visa', + u'country': u'US', + u'customer': None, + u'cvc_check': u'pass', + u'dynamic_last4': None, + u'exp_month': 2, + u'exp_year': 2022, + u'fingerprint': u'9tJA9bUEuvEb3Ell', + u'funding': u'credit', + u'id': u'card_172xfjGMfVJxozLw1QO6gYNM', + u'last4': u'4242', + u'metadata': {}, + u'name': u'norbert.buyer@example.com', + u'object': u'card', + u'tokenization_method': None + }, + u'statement_descriptor': None, + u'status': u'succeeded' + } + + tx = self.env['payment.transaction'].create({ + 'amount': 4700.0, + 'acquirer_id': self.cielo.id, + 'currency_id': self.currency_euro.id, + 'reference': 'SO100-1', + 'partner_name': 'Norbert Buyer', + 'partner_country_id': self.country_france.id + }) + + # validate it + tx.form_feedback(cielo_post_data, 'Cielo') + self.assertEqual(tx.state, 'done', + 'Cielo: validation did not put tx into done state') + self.assertEqual(tx.acquirer_reference, cielo_post_data.get('id'), + 'cielo: validation did not update tx id') + cielo_post_data['metadata']['reference'] = u'SO100-2' + # reset tx + tx = self.env['payment.transaction'].create({ + 'amount': 4700.0, + 'acquirer_id': self.cielo.id, + 'currency_id': self.currency_euro.id, + 'reference': 'SO100-2', + 'partner_name': 'Norbert Buyer', + 'partner_country_id': self.country_france.id + }) + # simulate an error + cielo_post_data['status'] = 'error' + cielo_post_data.update({ + u'error': { + u'message': u"Your card's expiration year is invalid.", + u'code': u'invalid_expiry_year', u'type': u'card_error', + u'param': u'exp_year' + } + }) + with mute_logger('odoo.addons.payment_cielo.models.payment'): + with mute_logger('odoo.addons.payment_cielo_sca.models.payment'): + tx.form_feedback(cielo_post_data, 'cielo') + # check state + self.assertEqual(tx.state, 'cancel', + 'Cielo: erroneous validation did not put tx into ' + 'error state') diff --git a/payment_cielo/views/payment_cielo_templates.xml b/payment_cielo/views/payment_cielo_templates.xml new file mode 100644 index 000000000000..b5473c9a3904 --- /dev/null +++ b/payment_cielo/views/payment_cielo_templates.xml @@ -0,0 +1,52 @@ + + + + + + + + diff --git a/payment_cielo/views/payment_views.xml b/payment_cielo/views/payment_views.xml new file mode 100644 index 000000000000..b4e06be258ee --- /dev/null +++ b/payment_cielo/views/payment_views.xml @@ -0,0 +1,21 @@ + + + + payment.acquirer.form.inherit + payment.acquirer + + + + + + + + + + + + + + + + diff --git a/requirements.txt b/requirements.txt index d4af491eb280..b44b92450516 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,5 +9,5 @@ erpbrasil.edoc.pdf==0.1.0 xmldiff==2.4 lxml==4.2.3 -e git://github.com/erpbrasil/nfelib.git#egg=nfelib --e git://github.com/erpbrasil/nfselib.git#egg=nfselib +-e git://github.com/erpbrasil/nfselib.git@feature/ginfes2#egg=nfselib -e git+https://github.com/OCA/openupgradelib.git@master#egg=openupgradelib diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt index 059914c87fbb..2eff624abb10 100644 --- a/setup/_metapackage/VERSION.txt +++ b/setup/_metapackage/VERSION.txt @@ -1 +1 @@ -12.0.20200923.0 \ No newline at end of file +12.0.20201031.0 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py index fe92fca6e3a3..e878c533f6f4 100644 --- a/setup/_metapackage/setup.py +++ b/setup/_metapackage/setup.py @@ -19,12 +19,16 @@ 'odoo12-addon-l10n_br_fiscal', 'odoo12-addon-l10n_br_hr', 'odoo12-addon-l10n_br_hr_contract', + 'odoo12-addon-l10n_br_mis_report', 'odoo12-addon-l10n_br_nfse', 'odoo12-addon-l10n_br_portal', 'odoo12-addon-l10n_br_resource', 'odoo12-addon-l10n_br_sale', 'odoo12-addon-l10n_br_stock', + 'odoo12-addon-l10n_br_stock_account', + 'odoo12-addon-l10n_br_website_sale', 'odoo12-addon-l10n_br_zip', + 'odoo12-addon-payment_cielo', ], classifiers=[ 'Programming Language :: Python', diff --git a/setup/l10n_br_mis_report/odoo/addons/l10n_br_mis_report b/setup/l10n_br_mis_report/odoo/addons/l10n_br_mis_report new file mode 120000 index 000000000000..649de4039ab5 --- /dev/null +++ b/setup/l10n_br_mis_report/odoo/addons/l10n_br_mis_report @@ -0,0 +1 @@ +../../../../l10n_br_mis_report \ No newline at end of file diff --git a/setup/l10n_br_mis_report/setup.py b/setup/l10n_br_mis_report/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/l10n_br_mis_report/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/l10n_br_stock_account/odoo/addons/l10n_br_stock_account b/setup/l10n_br_stock_account/odoo/addons/l10n_br_stock_account new file mode 120000 index 000000000000..a9be5f1cc7ab --- /dev/null +++ b/setup/l10n_br_stock_account/odoo/addons/l10n_br_stock_account @@ -0,0 +1 @@ +../../../../l10n_br_stock_account \ No newline at end of file diff --git a/setup/l10n_br_stock_account/setup.py b/setup/l10n_br_stock_account/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/l10n_br_stock_account/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/l10n_br_website_sale/odoo/addons/l10n_br_website_sale b/setup/l10n_br_website_sale/odoo/addons/l10n_br_website_sale new file mode 120000 index 000000000000..665756cfe7b4 --- /dev/null +++ b/setup/l10n_br_website_sale/odoo/addons/l10n_br_website_sale @@ -0,0 +1 @@ +../../../../l10n_br_website_sale \ No newline at end of file diff --git a/setup/l10n_br_website_sale/setup.py b/setup/l10n_br_website_sale/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/l10n_br_website_sale/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/payment_cielo/odoo/addons/payment_cielo b/setup/payment_cielo/odoo/addons/payment_cielo new file mode 120000 index 000000000000..c09c8ffc9f87 --- /dev/null +++ b/setup/payment_cielo/odoo/addons/payment_cielo @@ -0,0 +1 @@ +../../../../payment_cielo \ No newline at end of file diff --git a/setup/payment_cielo/setup.py b/setup/payment_cielo/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/payment_cielo/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)