diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/cnab_240.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/cnab_240.py index b67d6b8..e9e9146 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/cnab_240.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/cnab_240.py @@ -114,7 +114,8 @@ def _prepare_header(self): # 09.0 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, # 10.0 - 'cedente_conta': int(self.order.mode.bank_id.acc_number), + 'cedente_conta': + int(punctuation_rm(self.order.mode.bank_id.acc_number)), # 11.0 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], # 12.0 @@ -123,7 +124,9 @@ def _prepare_header(self): if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', # 13.0 'cedente_nome': - self.order.mode.bank_id.partner_id.legal_name[:30], + self.order.mode.bank_id.partner_id.legal_name[:30] + if self.order.mode.bank_id.partner_id.legal_name + else self.order.mode.bank_id.partner_id.name[:30], # 14.0 'nome_banco': self.order.mode.bank_id.bank_name, # 15.0 @@ -195,7 +198,8 @@ def _prepare_header_lote(self): # 13.1 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, # 14.1 - 'cedente_conta': int(self.order.mode.bank_id.acc_number), + 'cedente_conta': + int(punctuation_rm(self.order.mode.bank_id.acc_number)), # 15.1 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], # 16.1 @@ -204,7 +208,9 @@ def _prepare_header_lote(self): if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', # 17.1 'cedente_nome': - self.order.mode.bank_id.partner_id.legal_name[:30], + self.order.mode.bank_id.partner_id.legal_name[:30] + if self.order.mode.bank_id.partner_id.legal_name + else self.order.mode.bank_id.partner_id.name[:30], # 18.1 'mensagem1': '', diff --git a/l10n_br_account_banking_payment_cnab/model/__init__.py b/l10n_br_account_banking_payment_cnab/model/__init__.py index c630028..06babab 100644 --- a/l10n_br_account_banking_payment_cnab/model/__init__.py +++ b/l10n_br_account_banking_payment_cnab/model/__init__.py @@ -9,5 +9,5 @@ from . import res_partner from .. import constantes from . import payment_line -from . import bank_payment_line +# from . import bank_payment_line from . import l10n_br_cnab diff --git a/l10n_br_account_banking_payment_cnab/model/bank_payment_line.py b/l10n_br_account_banking_payment_cnab/model/bank_payment_line.py index ddd64c9..f7c4560 100644 --- a/l10n_br_account_banking_payment_cnab/model/bank_payment_line.py +++ b/l10n_br_account_banking_payment_cnab/model/bank_payment_line.py @@ -3,13 +3,6 @@ from ..constantes import COMPLEMENTO_TIPO_SERVICO, CODIGO_FINALIDADE_TED, \ AVISO_FAVORECIDO -STATE = [ - ('draft', 'Draft'), - ('wait', 'Waiting Paiment'), - ('exception', 'Exception'), - ('paid', 'Paid'), -] - class BankPaymentLine(models.Model): _inherit = 'bank.payment.line' @@ -82,11 +75,6 @@ def default_get(self, fields_list): help=u'Campo G048 do CNAB', default=0.00 ) - state2 = fields.Selection( - string="State", - selection=STATE, - default="draft", - ) evento_id = fields.One2many( string="Eventos CNAB", comodel_name="l10n.br.cnab.evento", @@ -98,3 +86,23 @@ def default_get(self, fields_list): string=u'Código de finalidade complementar', help=u'Campo P013 do CNAB', ) + + @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( + BankPaymentLine, self + ).same_fields_payment_line_and_bank_payment_line() + + # TODO: Implementar campo brasileiros que permitem mesclar linhas + + # same_fields = [ + # 'currency', 'partner_id', + # 'bank_id', 'date', 'state'] + + return same_fields \ No newline at end of file diff --git a/l10n_br_account_banking_payment_cnab/model/payment_line.py b/l10n_br_account_banking_payment_cnab/model/payment_line.py index 0c66474..d9f78a2 100644 --- a/l10n_br_account_banking_payment_cnab/model/payment_line.py +++ b/l10n_br_account_banking_payment_cnab/model/payment_line.py @@ -3,13 +3,6 @@ from ..constantes import COMPLEMENTO_TIPO_SERVICO, CODIGO_FINALIDADE_TED, \ AVISO_FAVORECIDO -STATE = [ - ('draft', 'Draft'), - ('wait', 'Waiting Paiment'), - ('exception', 'Exception'), - ('paid', 'Paid'), -] - class PaymentLine(models.Model): _inherit = 'payment.line' @@ -87,8 +80,3 @@ def default_get(self, fields_list): help=u'Campo G048 do CNAB', default=0.00 ) - state2 = fields.Selection( - related="bank_line_id.state2", - selection=STATE, - default="draft", - ) diff --git a/l10n_br_account_banking_payment_cnab/view/bank_payment_line.xml b/l10n_br_account_banking_payment_cnab/view/bank_payment_line.xml index 738b932..51bba21 100644 --- a/l10n_br_account_banking_payment_cnab/view/bank_payment_line.xml +++ b/l10n_br_account_banking_payment_cnab/view/bank_payment_line.xml @@ -6,11 +6,6 @@ bank.payment.line - -
- -
-
diff --git a/l10n_br_account_banking_payment_cnab/view/payment_line.xml b/l10n_br_account_banking_payment_cnab/view/payment_line.xml index bf79e1d..c5dfbf9 100644 --- a/l10n_br_account_banking_payment_cnab/view/payment_line.xml +++ b/l10n_br_account_banking_payment_cnab/view/payment_line.xml @@ -21,17 +21,5 @@ - - payment.line.form - payment.line - - - -
- -
-
-
-
\ No newline at end of file diff --git a/l10n_br_account_payment_boleto/models/res_company.py b/l10n_br_account_payment_boleto/models/res_company.py index 446d0e7..9d34486 100644 --- a/l10n_br_account_payment_boleto/models/res_company.py +++ b/l10n_br_account_payment_boleto/models/res_company.py @@ -27,11 +27,18 @@ class ResCompany(models.Model): _inherit = 'res.company' own_number_type = fields.Selection( - [('0', u'Sequêncial único por empresa'), - ('1', u'Numero sequêncial da Fatura'), - ('2', u'Sequêncial único por modo de pagamento'), ], - string=u'Tipo de nosso número', default='2') - own_number_sequence = fields.Many2one('ir.sequence', - string=u'Sequência do Nosso Número') + selection=[ + ('0', u'Sequêncial único por empresa'), + ('1', u'Numero sequêncial da Fatura'), + ('2', u'Sequêncial único por modo de pagamento'), ], + string=u'Tipo de nosso número', + default='2' + ) + + own_number_sequence = fields.Many2one( + comodel_name='ir.sequence', + string=u'Sequência do Nosso Número' + ) + transaction_id_sequence = fields.Many2one('ir.sequence', string=u'Sequência da fatura') diff --git a/l10n_br_financial_payment_order/README.rst b/l10n_br_financial_payment_order/README.rst new file mode 100644 index 0000000..ec0d556 --- /dev/null +++ b/l10n_br_financial_payment_order/README.rst @@ -0,0 +1,79 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=============================== +L10n Br Financial Payment Order +=============================== + +Integracao entre o modulo financeiro e a ordem de pagamento + +Installation +============ + +To install this module, you need to: + +#. Do this ... + +Configuration +============= + +To configure this module, you need to: + +#. Go to ... + +Usage +===== + +To use this module, you need to: + +#. Go to ... + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +Known issues / Roadmap +====================== + +* ... + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Firstname Lastname +* Second Person + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/l10n_br_financial_payment_order/__init__.py b/l10n_br_financial_payment_order/__init__.py new file mode 100644 index 0000000..b83f59e --- /dev/null +++ b/l10n_br_financial_payment_order/__init__.py @@ -0,0 +1,3 @@ +from . import models +from . import wizards +from . import reports diff --git a/l10n_br_financial_payment_order/__openerp__.py b/l10n_br_financial_payment_order/__openerp__.py new file mode 100644 index 0000000..beaa6a0 --- /dev/null +++ b/l10n_br_financial_payment_order/__openerp__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'L10n Br Financial Payment Order', + 'summary': """ + Integracao entre o modulo financeiro e a ordem de pagamento""", + 'version': '8.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'KMEE,Odoo Community Association (OCA)', + 'website': 'www.kmee.com.br', + 'external_dependencies': { + 'python': [ + 'pyboleto', + ], + }, + 'depends': [ + 'account_banking_payment_export', + 'l10n_br_account_product', + 'financial', + ], + 'data': [ + 'wizards/ordem_pagamento_holerite_wizard.xml', + 'wizards/l10n_br_payment_cnab.xml', + 'views/payment_menu.xml', + 'views/bank_payment_line.xml', + 'views/financial_move.xml', + + 'views/inherited_financial_document_type_view.xml', + 'views/inherited_financial_move_debt_2pay_view.xml', + + 'views/payment_mode/payment_mode_base_view.xml', + 'views/payment_mode/payment_mode_pagamento_view.xml', + 'views/payment_mode/payment_mode_cobranca_view.xml', + + 'views/payment_order/payment_order_base_view.xml', + 'views/payment_order/payment_order_cobranca_view.xml', + 'views/payment_order/payment_order_pagamento_view.xml', + + 'views/financial_retorno_bancario.xml', + 'views/financial_move.xml', + 'workflows/payment_order_workflow.xml', + 'reports/report_boleto.xml', + # 'security/payment_mode.xml', + # 'security/payment_mode_type.xml', + # 'security/bank_payment_line.xml', + # 'security/payment_line.xml', + # 'security/payment_order.xml', + + # 'views/payment_mode.xml', + # 'views/payment_mode_type.xml', + # 'views/bank_payment_line.xml', + # 'views/payment_line.xml', + ], + 'demo': [ + # 'demo/payment_mode.xml', + # 'demo/payment_mode_type.xml', + # 'demo/bank_payment_line.xml', + # 'demo/payment_order.xml', + ], +} diff --git a/l10n_br_financial_payment_order/constantes.py b/l10n_br_financial_payment_order/constantes.py new file mode 100644 index 0000000..1ce3b44 --- /dev/null +++ b/l10n_br_financial_payment_order/constantes.py @@ -0,0 +1,560 @@ +# -*- coding: utf-8 -*- + +from __future__ import division, print_function, unicode_literals + + +TIPO_ORDEM_PAGAMENTO_BOLETO = 'boleto' +#TIPO_ORDEM_PAGAMENTO_DEBITO_AUTOMATICO = 'debito_automatico' +TIPO_ORDEM_PAGAMENTO_PAGAMENTO = 'pagamento' +TIPO_ORDEM_PAGAMENTO_FOLHA = 'folha' + +TIPO_ORDEM_PAGAMENTO = [ + (TIPO_ORDEM_PAGAMENTO_BOLETO, 'Cobrança / Boleto'), + #(TIPO_ORDEM_PAGAMENTO_DEBITO_AUTOMATICO, 'Cobrança / Débito automático'), + (TIPO_ORDEM_PAGAMENTO_PAGAMENTO, 'Pagamento de contas/impostos'), + (TIPO_ORDEM_PAGAMENTO_FOLHA, 'Folha de Pagamento'), +] + +TIPO_SERVICO_COBRANCA = '01' +TIPO_SERVICO_BOLETO_PAGAMENTO_ELETRONICO = '03' +TIPO_SERVICO_CONCILIACAO_BANCARIA = '04' +TIPO_SERVICO_DEBITOS = '05' +TIPO_SERVICO_CUSTODIA_CHEQUES = '06' +TIPO_SERVICO_GESTAO_CAIXA = '07' +TIPO_SERVICO_CONSULTA_INFORMACAO_MARGEM = '08' +TIPO_SERVICO_AVERBACAO_CONSIGNACAO_RETENCAO = '09' +TIPO_SERVICO_PAGAMENTO_DIVIDENDOS = '10' +TIPO_SERVICO_MANUTENCAO_CONSIGNACAO = '11' +TIPO_SERVICO_CONSIGNACAO_PARCELAS = '12' +TIPO_SERVICO_GLOSA_CONSIGNACAO = '13' +TIPO_SERVICO_CONSULTA_TRIBUTOS_PAGAR = '14' +TIPO_SERVICO_PAGAMENTO_FORNECEDOR = '20' +TIPO_SERVICO_PAGAMENTO_CONTAS_TRIBUTOS_IMPOSTOS = '22' +TIPO_SERVICO_INTEROPERABILIDADE_CONTAS = '23' +TIPO_SERVICO_COMPROR = '25' +TIPO_SERVICO_COMPROR_ROTATIVO = '26' +TIPO_SERVICO_ALEGACAO_PAGADOR = '29' +TIPO_SERVICO_PAGAMENTO_SALARIOS = '30' +TIPO_SERVICO_PAGAMENTO_HONORARIOS = '32' +TIPO_SERVICO_PAGAMENTO_BOLSA_AUXILIO = '33' +TIPO_SERVICO_PAGAMENTO_PREBENDA = '34' +TIPO_SERVICO_VENDOR = '40' +TIPO_SERVICO_VENDOR_TERMO = '41' +TIPO_SERVICO_PAGAMENTO_SINISTROS_SEGURADOS = '50' +TIPO_SERVICO_PAGAMENTO_DESPESAS_VIAJANTE = '60' +TIPO_SERVICO_PAGAMENTO_AUTORIZADO = '70' +TIPO_SERVICO_PAGAMENTO_CREDENCIADOS = '75' +TIPO_SERVICO_PAGAMENTO_REMUNERACAO = '77' +TIPO_SERVICO_PAGAMENTO_REPRESENTANTES = '80' +TIPO_SERVICO_PAGAMENTO_BENEFICIOS = '90' +TIPO_SERVICO_PAGAMENTOS_DIVERSOS = '98' + +TIPO_SERVICO = [ + (TIPO_SERVICO_COBRANCA, + '01 - Cobrança'), + (TIPO_SERVICO_BOLETO_PAGAMENTO_ELETRONICO, + '03 - Boleto de Pagamento Eletrônico'), + (TIPO_SERVICO_CONCILIACAO_BANCARIA, + '04 - Conciliação Bancária'), + (TIPO_SERVICO_DEBITOS, + '05 - Débitos'), + (TIPO_SERVICO_CUSTODIA_CHEQUES, + '06 - Custódia de Cheques'), + (TIPO_SERVICO_GESTAO_CAIXA, + '07 - Gestão de Caixa'), + (TIPO_SERVICO_CONSULTA_INFORMACAO_MARGEM, + '08 - Consulta/Informação Margem'), + (TIPO_SERVICO_AVERBACAO_CONSIGNACAO_RETENCAO, + '09 - Averbação da Consignação/Retenção'), + (TIPO_SERVICO_PAGAMENTO_DIVIDENDOS, + '10 - Pagamento Dividendos'), + (TIPO_SERVICO_MANUTENCAO_CONSIGNACAO, + '11 - Manutenção da Consignação'), + (TIPO_SERVICO_CONSIGNACAO_PARCELAS, + '12 - Consignação de Parcelas'), + (TIPO_SERVICO_GLOSA_CONSIGNACAO, + '13 - Glosa da Consignação (INSS)'), + (TIPO_SERVICO_CONSULTA_TRIBUTOS_PAGAR, + '14 - Consulta de Tributos a Pagar'), + (TIPO_SERVICO_PAGAMENTO_FORNECEDOR, + '20 - Pagamento a Fornecedor'), + (TIPO_SERVICO_PAGAMENTO_CONTAS_TRIBUTOS_IMPOSTOS, + '22 - Pagamento de Contas, Tributos e Impostos'), + (TIPO_SERVICO_INTEROPERABILIDADE_CONTAS, + '23 - Interoperabilidade entre Contas de Instituições de Pagamentos'), + (TIPO_SERVICO_COMPROR, + '25 - Compror'), + (TIPO_SERVICO_COMPROR_ROTATIVO, + '26 - Compror Rotativo'), + (TIPO_SERVICO_ALEGACAO_PAGADOR, + '29 - Alegação do Pagador'), + (TIPO_SERVICO_PAGAMENTO_SALARIOS, + '30 - Pagamento de Salários'), + (TIPO_SERVICO_PAGAMENTO_HONORARIOS, + '32 - Pagamento de Honorários'), + (TIPO_SERVICO_PAGAMENTO_BOLSA_AUXILIO, + '33 - Pagamento de Bolsa Auxílio'), + (TIPO_SERVICO_PAGAMENTO_PREBENDA, + '34 - Pagamento de Prebenda (remuneração a padres e sacerdotes)'), + (TIPO_SERVICO_VENDOR, + '40 - Vendor'), + (TIPO_SERVICO_VENDOR_TERMO, + '41 - Vendor a Termo'), + (TIPO_SERVICO_PAGAMENTO_SINISTROS_SEGURADOS, + '50 - Pagamento de Sinistros Segurados'), + (TIPO_SERVICO_PAGAMENTO_DESPESAS_VIAJANTE, + '60 - Pagamento de Despesas de Viajante em Trânsito'), + (TIPO_SERVICO_PAGAMENTO_AUTORIZADO, + '70 - Pagamento Autorizado'), + (TIPO_SERVICO_PAGAMENTO_CREDENCIADOS, + '75 - Pagamento a Credenciados'), + (TIPO_SERVICO_PAGAMENTO_REMUNERACAO, + '77 - Pagamento de Remuneração'), + (TIPO_SERVICO_PAGAMENTO_REPRESENTANTES, + '80 - Pagamento de Representantes / Vendedores Autorizados'), + (TIPO_SERVICO_PAGAMENTO_BENEFICIOS, + '90 - Pagamento de Benefícios'), + (TIPO_SERVICO_PAGAMENTOS_DIVERSOS, + '98 - Pagamentos Diversos'), +] + +TIPO_SERVICO_COMPLEMENTO_CREDITO_EM_CONTA = '01' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_ALUGUEL = '02' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_DUPLICATA_TITULOS = '03' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_DIVIDENDOS = '04' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_MENSALIDADE_ESCOLAR = '05' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_SALARIOS = '06' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_FORNECEDORES = '07' +TIPO_SERVICO_COMPLEMENTO_OPERACOES_CAMBIOS_FUNDOS_BOLSA = '08' +TIPO_SERVICO_COMPLEMENTO_REPASSE_ARRECADACAO = '09' +TIPO_SERVICO_COMPLEMENTO_TRANSFERECIA_INTERNACIONAL_EM_REAL = '10' +TIPO_SERVICO_COMPLEMENTO_DOC_POUPANCA = '11' +TIPO_SERVICO_COMPLEMENTO_DOC_DEPOSITO_JUDICIAL = '12' +TIPO_SERVICO_COMPLEMENTO_OUTROS = '13' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_BOLSA_AUXILIO = '16' +TIPO_SERVICO_COMPLEMENTO_REMUNERACAO_COOPERADO = '17' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_HONORARIOS = '18' +TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_PREBENDA = '19' + +TIPO_SERVICO_COMPLEMENTO = [ + (TIPO_SERVICO_COMPLEMENTO_CREDITO_EM_CONTA, + '01 - Crédito em Conta'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_ALUGUEL, + '02 - Pagamento de Aluguel/Condomínio'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_DUPLICATA_TITULOS, + '03 - Pagamento de Duplicata/Títulos'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_DIVIDENDOS, + '04 - Pagamento de Dividendos'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_MENSALIDADE_ESCOLAR, + '05 - Pagamento de Mensalidade Escolar'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_SALARIOS, + '06 - Pagamento de Salários'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_FORNECEDORES, + '07 - Pagamento a Fornecedores'), + (TIPO_SERVICO_COMPLEMENTO_OPERACOES_CAMBIOS_FUNDOS_BOLSA, + '08 - Operações de Câmbios/Fundos/Bolsa de Valores'), + (TIPO_SERVICO_COMPLEMENTO_REPASSE_ARRECADACAO, + '09 - Repasse de Arrecadação/Pagamento de Tributos'), + (TIPO_SERVICO_COMPLEMENTO_TRANSFERECIA_INTERNACIONAL_EM_REAL, + '10 - Transferência Internacional em Real'), + (TIPO_SERVICO_COMPLEMENTO_DOC_POUPANCA, + '11 - DOC para Poupança'), + (TIPO_SERVICO_COMPLEMENTO_DOC_DEPOSITO_JUDICIAL, + '12 - DOC para Depósito Judicial'), + (TIPO_SERVICO_COMPLEMENTO_OUTROS, + '13 - Outros'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_BOLSA_AUXILIO, + '16 - Pagamento de Bolsa Auxílio'), + (TIPO_SERVICO_COMPLEMENTO_REMUNERACAO_COOPERADO, + '17 - Remuneração a Cooperado'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_HONORARIOS, + '18 - Pagamento de Honorários'), + (TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_PREBENDA, + '19 - Pagamento de Prebenda (remuneração a padres e sacerdotes)'), +] + +FORMA_LANCAMENTO_CREDITO_CONTA_CORRENTE_SALARIO = '01' +FORMA_LANCAMENTO_CHEQUE_PAGAMENTO_ADMINISTRATIVO = '02' +FORMA_LANCAMENTO_DOC_TED = '03' +FORMA_LANCAMENTO_CARTAO_SALARIO = '04' +FORMA_LANCAMENTO_CREDITO_CONTA_POUPANCA = '05' +FORMA_LANCAMENTO_OP_A_DISPOSICAO = '10' +FORMA_LANCAMENTO_PAGAMENTO_CONTAS_TRIBUTOS_CODIGO_BARRAS = '11' +FORMA_LANCAMENTO_TRIBUTO_DARF_NORMAL = '16' +FORMA_LANCAMENTO_TRIBUTO_GPS = '17' +FORMA_LANCAMENTO_TRIBUTO_DARF_SIMPLES = '18' +FORMA_LANCAMENTO_TRIBUTO_IPTU_PREFEITURAS = '19' +FORMA_LANCAMENTO_PAGAMENTO_AUTENTICACAO = '20' +FORMA_LANCAMENTO_TRIBUTO_DARJ = '21' +FORMA_LANCAMENTO_TRIBUTO_GARE_SP_ICMS = '22' +FORMA_LANCAMENTO_TRIBUTO_GARE_SP_DR = '23' +FORMA_LANCAMENTO_TRIBUTO_GARE_SP_ITCMD = '24' +FORMA_LANCAMENTO_TRIBUTO_IPVA = '25' +FORMA_LANCAMENTO_TRIBUTO_LICENCIAMENTO = '26' +FORMA_LANCAMENTO_TRIBUTO_DPVAT = '27' +FORMA_LANCAMENTO_LIQUIDACAO_TITULOS_PROPRIO_BANCO = '30' +FORMA_LANCAMENTO_PAGAMENTO_TITULOS_OUTROS_BANCOS = '31' +FORMA_LANCAMENTO_EXTRATO_CONTA_CORRENTE = '40' +FORMA_LANCAMENTO_TED_OUTRA_TITULARIDADE = '41' +FORMA_LANCAMENTO_TED_MESMA_TITULARIDADE = '43' +FORMA_LANCAMENTO_TED_TRANSFERENCIA_CONTA_INVESTIMENTO = '44' +FORMA_LANCAMENTO_DEBITO_CONTA_CORRENTE = '50' +FORMA_LANCAMENTO_EXTRATO_GESTAO_CAIXA = '70' +FORMA_LANCAMENTO_DEPOSITO_JUDICIAL_CONTA_CORRENTE = '71' +FORMA_LANCAMENTO_DEPOSITO_JUDICIAL_POUPANCA = '72' +FORMA_LANCAMENTO_EXTRATO_CONTA_INVESTIMENTO = '73' + +FORMA_LANCAMENTO = [ + (FORMA_LANCAMENTO_CREDITO_CONTA_CORRENTE_SALARIO, + '01 - Crédito em Conta Corrente/Salário'), + (FORMA_LANCAMENTO_CHEQUE_PAGAMENTO_ADMINISTRATIVO, + '02 - Cheque Pagamento/Administrativo'), + (FORMA_LANCAMENTO_DOC_TED, + '03 - DOC/TED'), + (FORMA_LANCAMENTO_CARTAO_SALARIO, + '04 - Cartão Salário (somente para Tipo de Serviço = "30")'), + (FORMA_LANCAMENTO_CREDITO_CONTA_POUPANCA, + '05 - Crédito em Conta Poupança'), + (FORMA_LANCAMENTO_OP_A_DISPOSICAO, + '10 - OP à Disposição'), + (FORMA_LANCAMENTO_PAGAMENTO_CONTAS_TRIBUTOS_CODIGO_BARRAS, + '11 - Pagamento de Contas e Tributos com Código de Barras'), + (FORMA_LANCAMENTO_TRIBUTO_DARF_NORMAL, + '16 - Tributo - DARF Normal'), + (FORMA_LANCAMENTO_TRIBUTO_GPS, + '17 - Tributo - GPS (Guia da Previdência Social)'), + (FORMA_LANCAMENTO_TRIBUTO_DARF_SIMPLES, + '18 - Tributo - DARF Simples'), + (FORMA_LANCAMENTO_TRIBUTO_IPTU_PREFEITURAS, + '19 - Tributo - IPTU – Prefeituras'), + (FORMA_LANCAMENTO_PAGAMENTO_AUTENTICACAO, + '20 - Pagamento com Autenticação'), + (FORMA_LANCAMENTO_TRIBUTO_DARJ, + '21 - Tributo – DARJ'), + (FORMA_LANCAMENTO_TRIBUTO_GARE_SP_ICMS, + '22 - Tributo - GARE-SP ICMS'), + (FORMA_LANCAMENTO_TRIBUTO_GARE_SP_DR, + '23 - Tributo - GARE-SP DR'), + (FORMA_LANCAMENTO_TRIBUTO_GARE_SP_ITCMD, + '24 - Tributo - GARE-SP ITCMD'), + (FORMA_LANCAMENTO_TRIBUTO_IPVA, + '25 - Tributo - IPVA'), + (FORMA_LANCAMENTO_TRIBUTO_LICENCIAMENTO, + '26 - Tributo - Licenciamento'), + (FORMA_LANCAMENTO_TRIBUTO_DPVAT, + '27 - Tributo – DPVAT'), + (FORMA_LANCAMENTO_LIQUIDACAO_TITULOS_PROPRIO_BANCO, + '30 - Liquidação de Títulos do Próprio Banco'), + (FORMA_LANCAMENTO_PAGAMENTO_TITULOS_OUTROS_BANCOS, + '31 - Pagamento de Títulos de Outros Bancos'), + (FORMA_LANCAMENTO_EXTRATO_CONTA_CORRENTE, + '40 - Extrato de Conta Corrente'), + (FORMA_LANCAMENTO_TED_OUTRA_TITULARIDADE, + '41 - TED – Outra Titularidade'), + (FORMA_LANCAMENTO_TED_MESMA_TITULARIDADE, + '43 - TED – Mesma Titularidade'), + (FORMA_LANCAMENTO_TED_TRANSFERENCIA_CONTA_INVESTIMENTO, + '44 - TED para Transferência de Conta Investimento'), + (FORMA_LANCAMENTO_DEBITO_CONTA_CORRENTE, + '50 - Débito em Conta Corrente'), + (FORMA_LANCAMENTO_EXTRATO_GESTAO_CAIXA, + '70 - Extrato para Gestão de Caixa'), + (FORMA_LANCAMENTO_DEPOSITO_JUDICIAL_CONTA_CORRENTE, + '71 - Depósito Judicial em Conta Corrente'), + (FORMA_LANCAMENTO_DEPOSITO_JUDICIAL_POUPANCA, + '72 - Depósito Judicial em Poupança'), + (FORMA_LANCAMENTO_EXTRATO_CONTA_INVESTIMENTO, + '73 - Extrato de Conta Investimento'), +] + +# Codigo adotado pelo Banco Central para identificar a +# finalidade da TED. Utitilizar os +# códigos de finalidade cliente, disponíveis no site do Banco Central do Brasil +# (www.bcb.gov.br), Sistema de Pagamentos Brasileiro, +# Transferência de Arquivos, +# Dicionários de Domínios para o SPB. +CODIGO_FINALIDADE_TED = [ + (' ', 'Padrão') +] + +AVISO_FAVORECIDO_NAO_EMITE = '0' +AVISO_FAVORECIDO_EMITE_AO_REMETENTE = '2' +AVISO_FAVORECIDO_EMITE_AO_FAVORECIDO = '5' +AVISO_FAVORECIDO_EMITE_AO_REMETENTE_E_FAVORECIDO = '6' +AVISO_FAVORECIDO_EMITE_AO_FAVORECIDO_E_2_VIAS_AO_REMETENTE = '7' + +AVISO_FAVORECIDO = [ + (AVISO_FAVORECIDO_NAO_EMITE, + '0 - Não emite'), + (AVISO_FAVORECIDO_EMITE_AO_REMETENTE, + '2 - Emite aviso somente ao remetente'), + (AVISO_FAVORECIDO_EMITE_AO_FAVORECIDO, + '5 - Emite aviso somente ao favorecido'), + (AVISO_FAVORECIDO_EMITE_AO_REMETENTE_E_FAVORECIDO, + '6 - Emite aviso ao remetente e ao favorecido'), + (AVISO_FAVORECIDO_EMITE_AO_FAVORECIDO_E_2_VIAS_AO_REMETENTE, + '7 - Emite aviso ao favorecido e 2 vias ao remetente'), +] + +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 - Inclusão'), + ('1', '1 - Consulta'), + ('2', '2 - Suspensão'), + ('3', '3 - Estorno (somente para retorno)'), + ('4', '4 - Reativação'), + ('5', '5 - Alteração'), + ('7', '7 - Liquidação'), + ('9', '9 - Exclusão'), +] + +INSTRUCAO_MOVIMENTO = [ + ('00', '00 - Inclusão de Registro Detalhe Liberado'), + ('09', '09 - Inclusão do Registro Detalhe Bloqueado'), + ('10', '10 - Alteração do Pagamento Liberado para Bloqueado (Bloqueio)'), + ('11', '11 - Alteração do Pagamento Bloqueado para Liberado (Liberação)'), + ('17', '17 - Alteração do Valor do Título'), + ('19', '19 - Alteração da Data de Pagamento'), + ('23', '23 - Pagamento Direto ao Fornecedor - Baixar'), + ('25', '25 - Manutenção em Carteira - Não Pagar'), + ('27', '27 - Retirada de Carteira - Não Pagar'), + ('33', '33 - Estorno por Devolução da Câmara Centralizadora ' + '(somente para Tipo de Movimento = "3")'), + ('40', '40 - Alegação do Pagador'), + ('99', '99 - Exclusão do Registro Detalhe Incluído Anteriormente'), +] +INSTRUCAO_MOVIMENTO_INCLUSAO_DETALHE_LIBERADO = '00' + +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'), +] + + +BOLETO_ESPECIE = [ + ('01', 'CH Cheque'), + ('02', 'DM Duplicata Mercantil'), + ('03', 'DMI Duplicata Mercantil p/ Indicação'), + ('04', 'DS Duplicata de Serviço'), + ('05', 'DSI Duplicata de Serviço p/ Indicação'), + ('06', 'DR Duplicata Rural'), + ('07', 'LC Letra de Câmbio'), + ('08', 'NCC Nota de Crédito Comercial'), + ('09', 'NCE Nota de Crédito a Exportação'), + ('10', 'NCI Nota de Crédito Industrial'), + ('11', 'NCR Nota de Crédito Rural'), + ('12', 'NP Nota Promissória'), + ('13', 'NPR Nota Promissória Rural'), + ('14', 'TM Triplicata Mercantil'), + ('15', 'TS Triplicata de Serviço'), + ('16', 'NS Nota de Seguro'), + ('17', 'RC Recibo'), + ('18', 'FAT Fatura'), + ('19', 'ND Nota de Débito'), + ('20', 'AP Apólice de Seguro'), + ('21', 'ME Mensalidade Escolar'), + ('22', 'PC Parcela de Consórcio'), + ('23', 'NF Nota Fiscal'), + ('24', 'DD Documento de Dívida'), + ('25', 'Cédula de Produto Rural'), + ('26', 'Warrant'), + ('27', 'Dívida Ativa de Estado'), + ('28', 'Dívida Ativa de Município'), + ('29', 'Dívida Ativa da União'), + ('30', 'Encargos Condominiais'), + ('31', 'CC Cartão de Crédito'), + ('32', 'BDP Boleto de Proposta'), + ('99', 'Outros') +] + +BOLETO_ESPECIE_DUPLICATA_MERCANTIL = '01' +BOLETO_ESPECIE_NOTA_PROMISSORIA = '02' +BOLETO_ESPECIE_NOTA_SEGURO = '03' +BOLETO_ESPECIE_MENSALIDADE_ESCOLAR = '04' +BOLETO_ESPECIE_RECIBO = '05' +BOLETO_ESPECIE_CONTRATO = '06' +BOLETO_ESPECIE_COSSEGUROS = '07' +BOLETO_ESPECIE_DUPLICATA_SERVICO = '08' +BOLETO_ESPECIE_LETRA_CAMBIO = '09' +BOLETO_ESPECIE_NOTA_DEBITOS = '13' +BOLETO_ESPECIE_DOCUMENTO_DIVIDA = '15' +BOLETO_ESPECIE_ENCARGOS_CONDOMINIAIS = '16' +BOLETO_ESPECIE_CONTA_PRESTACAO_SERVICOS = '17' +BOLETO_ESPECIE_DIVERSOS = '99' + + +BOLETO_EMISSAO = [ + ('1', '1 - Banco emite'), + ('2', '2 - Beneficiário emite'), + #('3', '3 - Banco pré-emite, beneficiário complementa'), + #('4', '4 - Banco reemite'), + #('5', '5 - Banco não reemite'), + #('7', '7 - Banco emitente - aberta'), + #('8', '8 - Banco emitente - auto-envelopável'), +] +BOLETO_EMISSAO_BANCO = '1' +BOLETO_EMISSAO_BENEFICIARIO = '2' + +BOLETO_DISTRIBUICAO = [ + ('1', '1 - Banco distribui'), + ('2', '2 - Beneficiário distribui'), + ('3', '3 - Banco envia por email'), + ('4', '4 - Banco envia por SMS'), +] +BOLETO_DISTRIBUICAO_BANCO = '1' +BOLETO_DISTRIBUICAO_BENEFICIARIO = '2' diff --git a/l10n_br_financial_payment_order/demo/bank_payment_line.xml b/l10n_br_financial_payment_order/demo/bank_payment_line.xml new file mode 100644 index 0000000..1ce6210 --- /dev/null +++ b/l10n_br_financial_payment_order/demo/bank_payment_line.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/demo/payment_mode.xml b/l10n_br_financial_payment_order/demo/payment_mode.xml new file mode 100644 index 0000000..2434e3a --- /dev/null +++ b/l10n_br_financial_payment_order/demo/payment_mode.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/demo/payment_mode_type.xml b/l10n_br_financial_payment_order/demo/payment_mode_type.xml new file mode 100644 index 0000000..8fddc48 --- /dev/null +++ b/l10n_br_financial_payment_order/demo/payment_mode_type.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/demo/payment_order.xml b/l10n_br_financial_payment_order/demo/payment_order.xml new file mode 100644 index 0000000..19d9d78 --- /dev/null +++ b/l10n_br_financial_payment_order/demo/payment_order.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/febraban/__init__.py b/l10n_br_financial_payment_order/febraban/__init__.py new file mode 100644 index 0000000..0104e25 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/__init__.py @@ -0,0 +1,22 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/l10n_br_financial_payment_order/febraban/boleto/__init__.py b/l10n_br_financial_payment_order/febraban/boleto/__init__.py new file mode 100644 index 0000000..4696cde --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/boleto/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Account Payment Boleto module for Odoo +# Copyright (C) 2012-2015 KMEE (http://www.kmee.com.br) +# @author Luis Felipe Miléo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import document diff --git a/l10n_br_financial_payment_order/febraban/boleto/document.py b/l10n_br_financial_payment_order/febraban/boleto/document.py new file mode 100644 index 0000000..eeed59e --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/boleto/document.py @@ -0,0 +1,345 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Account Payment Boleto module for Odoo +# Copyright (C) 2012-2015 KMEE (http://www.kmee.com.br) +# @author Luis Felipe Miléo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from datetime import datetime, date +import logging +from openerp.addons.financial.constants import ( +FINANCIAL_DEBT_2RECEIVE, +FINANCIAL_DEBT_2PAY +) + +_logger = logging.getLogger(__name__) + +try: + from pyboleto import bank +except ImportError as err: + _logger.debug = err + + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +BoletoException = bank.BoletoException + + +class Boleto(object): + account_number = '' + account_digit = '' + + branch_number = '' + branch_digit = '' + + nosso_numero = '' + + @staticmethod + def getBoleto(financial_move, nosso_numero): + payment_mode = financial_move.payment_mode_id + carteira = payment_mode.boleto_carteira + banco = payment_mode.bank_id.bank.bic + + result = False + + if banco == '001': + result = BoletoBB + elif banco == '041': + result = BoletoBarisul + elif banco == '237': + result = BoletoBradesco + elif banco == '104': + if carteira == 'Sigcb': + result = BoletoCaixaSigcb + elif carteira in ['SR']: + result = BoletoCaixa + elif banco == '399': + result = BoletoHsbc + elif banco == '341': + if carteira == '157': + result = BoletoItau157 + elif carteira in ['175', '174', '178', '104', '109']: + result = BoletoItau + elif banco == '356': + result = BoletoReal + elif banco == '033': + if carteira == '102': + result = BoletoSantander102 + elif carteira in ['101', '201']: + result = BoletoStatander101201 + + if result: + return result(financial_move, nosso_numero) + else: + raise (BoletoException('Este banco não é suportado.')) + + @staticmethod + def getBoletoClass(financial_move): + bank_code = financial_move.payment_mode_id.bank_id.bank.bic + return bank.get_class_for_codigo(bank_code) + + def __init__(self, financial_move): + cedente = financial_move.payment_mode_id.bank_id.partner_id + if financial_move.type == FINANCIAL_DEBT_2RECEIVE: + sacado = financial_move.partner_id + elif financial_move.type == FINANCIAL_DEBT_2PAY: + sacado = financial_move.company_id + self._cedente(cedente) + self._sacado(sacado) + self._financial_move(financial_move) + # self.nosso_numero = '' + + def getAccountNumber(self): + if self.account_digit: + return str(self.account_number + '-' + + self.account_digit).encode('utf-8') + return self.account_number.encode('utf-8') + + def getBranchNumber(self): + if self.branch_digit: + return str(self.branch_number + '-' + + self.branch_digit).encode('utf-8') + return self.branch_number.encode('utf-8') + + def _financial_move(self, financial_move): + self._payment_mode(financial_move) + self.boleto.data_vencimento = datetime.date(datetime.strptime( + financial_move.date_business_maturity, '%Y-%m-%d')) + self.boleto.data_documento = datetime.date(datetime.strptime( + financial_move.date_document, '%Y-%m-%d')) + self.boleto.data_processamento = date.today() + self.boleto.valor = str("%.2f" % financial_move.amount_document) + self.boleto.valor_documento = str("%.2f" % + financial_move.amount_document) + self.boleto.especie = ( + financial_move.currency_id and + financial_move.currency_id.symbol or 'R$') + self.boleto.quantidade = '' + # str("%.2f" % financial_move.amount_currency) + self.boleto.numero_documento = \ + financial_move.document_number.encode('utf-8') + + def _payment_mode(self, financial_move): + """ + :param payment_mode: + :return: + """ + payment_mode_id = financial_move.payment_mode_id + self.boleto.convenio = payment_mode_id.convenio + self.boleto.especie_documento = \ + financial_move.document_type_id.boleto_especie + self.boleto.aceite = payment_mode_id.boleto_aceite + self.boleto.carteira = payment_mode_id.boleto_carteira + + def _cedente(self, partner_id): + """ + :param company: + :return: + """ + self.boleto.cedente = partner_id.legal_name.encode('utf-8') + self.boleto.cedente_documento = partner_id.cnpj_cpf.encode('utf-8') + self.boleto.cedente_bairro = partner_id.district + self.boleto.cedente_cep = partner_id.zip + self.boleto.cedente_cidade = partner_id.city + self.boleto.cedente_logradouro = partner_id.street + \ + ', ' + (partner_id.number or 'SN') + self.boleto.cedente_uf = partner_id.state_id.code + self.boleto.agencia_cedente = self.getBranchNumber() + self.boleto.conta_cedente = self.getAccountNumber() + + def _sacado(self, partner): + """ + + :param partner: + :return: + """ + self.boleto.sacado_endereco = partner.street + ', ' + ( + partner.number or 'SN') + self.boleto.sacado_cidade = partner.city + self.boleto.sacado_bairro = partner.district + self.boleto.sacado_uf = partner.state_id.code + self.boleto.sacado_cep = partner.zip + self.boleto.sacado_nome = partner.legal_name + self.boleto.sacado_documento = partner.cnpj_cpf + + @classmethod + def get_pdfs(cls, boleto_list): + """ + + :param boletoList: + :return: + """ + fbuffer = StringIO() + + fbuffer.reset() + from pyboleto.pdf import BoletoPDF + + boleto = BoletoPDF(fbuffer) + for i in range(len(boleto_list)): + boleto.drawBoleto(boleto_list[i]) + boleto.nextPage() + boleto.save() + boleto_file = fbuffer.getvalue() + + fbuffer.close() + return boleto_file + + +class BoletoBB(Boleto): + + def __init__(self, financial_move, nosso_numero): + # TODO: size o convenio and nosso numero, replace (7,2) + # Size of convenio 4, 6, 7 or 8 + # Nosso Numero format. 1 or 2 + # Used only for convenio=6 + # 1: Nosso Numero with 5 positions + # 2: Nosso Numero with 17 positions + self.boleto = Boleto.getBoletoClass(financial_move)(7, 2) + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoBarisul(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoBradesco(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + # bank specific + self.account_digit = \ + financial_move.payment_mode_id.bank_id.acc_number_dig + self.branch_digit = \ + financial_move.payment_mode_id.bank_id.bra_number_dig + # end bank specific + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoCaixa(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + # bank specific + self.account_digit = \ + financial_move.payment_mode_id.bank_id.acc_number_dig + # end bank specific + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoHsbc(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoItau157(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoItau(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoReal(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoSantander102(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.ios = '0' + self.boleto.nosso_numero = nosso_numero + + +class BoletoStatander101201(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.ios = '0' + self.boleto.nosso_numero = nosso_numero + + +class BoletoCaixaSigcb(Boleto): + + def __init__(self, financial_move, nosso_numero): + from pyboleto.bank.caixa_sigcb import BoletoCaixaSigcb + self.boleto = BoletoCaixaSigcb() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + # bank specific + self.account_digit = \ + financial_move.payment_mode_id.bank_id.acc_number_dig + # end bank specific + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero + + +class BoletoSicredi(Boleto): + + def __init__(self, financial_move, nosso_numero): + self.boleto = Boleto.getBoletoClass(financial_move)() + self.account_number = financial_move.payment_mode_id.bank_id.acc_number + self.branch_number = financial_move.payment_mode_id.bank_id.bra_number + Boleto.__init__(self, financial_move) + self.boleto.nosso_numero = nosso_numero diff --git a/l10n_br_financial_payment_order/febraban/cnab.py b/l10n_br_financial_payment_order/febraban/cnab.py new file mode 100644 index 0000000..2a384e4 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab.py @@ -0,0 +1,51 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +# TODO: implement abc factory? + +from __future__ import division, print_function, unicode_literals + + +class Cnab(object): + + def __init__(self): + pass + + @staticmethod + def get_cnab(bank, cnab_type='240'): + if cnab_type == '240': + from .cnab_240.cnab_240 import Cnab240 + return Cnab240.get_bank(bank) + elif cnab_type == '400': + from .cnab_400.cnab_400 import Cnab400 + return Cnab400.get_bank(bank) + elif cnab_type == '500': + from .pag_for.pag_for500 import PagFor500 + return PagFor500.get_bank(bank) + else: + return False + + def remessa(self, order): + return False + + def retorno(self, cnab_file): + return object diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/__init__.py b/l10n_br_financial_payment_order/febraban/cnab_240/__init__.py new file mode 100644 index 0000000..9a4bbb7 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/__init__.py @@ -0,0 +1,20 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/bancos/__init__.py b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/__init__.py new file mode 100644 index 0000000..0104e25 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/__init__.py @@ -0,0 +1,22 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/bancos/bb.py b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/bb.py new file mode 100644 index 0000000..5580359 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/bb.py @@ -0,0 +1,60 @@ +# coding: utf-8 + +from __future__ import division, print_function, unicode_literals + +import re +import string + +from ..cnab_240 import Cnab240 + + +class BB240(Cnab240): + + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import bancodobrasil + self.bank = bancodobrasil + + def _prepare_header(self): + """ + Preparar header do arquivo. + Adicionar informações no header do arquivo do Banco do Brasil + """ + vals = super(BB240, self)._prepare_header() + # vals['servico_servico'] = 1 + return vals + + def _prepare_cobranca(self, line): + """ + Preparar o evento (segmentoA e segmentoB) apartir da payment.line + :param line - payment.line + :return: dict - Informações + """ + vals = super(BB240, self)._prepare_cobranca(line) + # vals['prazo_baixa'] = unicode(str( + # vals['prazo_baixa']), "utf-8") + # vals['desconto1_percentual'] = Decimal('0.00') + # vals['valor_iof'] = Decimal('0.00') + # # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + # vals['identificacao_titulo_banco'] = int( + # vals['identificacao_titulo_banco']) + # vals['cedente_conta_dv'] = unicode(str( + # vals['cedente_conta_dv']), "utf-8") + # vals['cedente_agencia_dv'] = unicode(str( + # vals['cedente_agencia_dv']), "utf-8") + # vals['cedente_dv_ag_cc'] = unicode(str( + # vals['cedente_dv_ag_cc']), "utf-8") + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/bancos/bradesco.py b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/bradesco.py new file mode 100644 index 0000000..3dea8ad --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/bradesco.py @@ -0,0 +1,84 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +import re +import string +from decimal import Decimal + +from ..cnab_240 import Cnab240 + + +class Bradesco240(Cnab240): + + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import bradesco + self.bank = bradesco + + def _prepare_header(self): + """ + + :param order: + :return: + """ + + vals = super(Bradesco240, self)._prepare_header() + vals['servico_servico'] = 1 + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Bradesco240, self)._prepare_cobranca(line) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + vals['identificacao_titulo_banco'] = int( + vals['identificacao_titulo_banco']) + vals['cedente_conta_dv'] = unicode(str( + vals['cedente_conta_dv']), "utf-8") + vals['cedente_agencia_dv'] = unicode(str( + vals['cedente_agencia_dv']), "utf-8") + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + +def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/bancos/cef.py b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/cef.py new file mode 100644 index 0000000..14193fe --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/cef.py @@ -0,0 +1,108 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import re +import string +from decimal import Decimal + +from ..cnab_240 import Cnab240 + + +class Cef240(Cnab240): + + def __init__(self): + super(Cnab240, self).__init__() + from cnab240.bancos import cef + self.bank = cef + + def _prepare_header(self): + """ + + :return: + """ + vals = super(Cef240, self)._prepare_header() + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + vals['cedente_agencia_dv'] = unicode(str( + vals['cedente_agencia_dv']), "utf-8") + # TODO: adicionar campo para preencher o codigo do cedente no + # cadastro da conta bancária + vals['cedente_codigo_codCedente'] = 6088 + vals['nome_do_banco'] = u'CAIXA ECONOMICA FEDERAL' + # Não pode pegar comentário da payment_line. + vals['reservado_cedente_campo23'] = u'REMESSA TESTE' + # reservado_banco_campo22 não é required. Código atualizado na + # biblioteca cnab240 + vals['data_credito_hd_lote'] = 15052015 + + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Cef240, self)._prepare_cobranca(line) + + carteira, nosso_numero, digito = self.nosso_numero( + line.move_line_id.transaction_ref) + + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + # Informar o Número do Documento - Seu Número (mesmo das posições + # 63-73 do Segmento P) + vals['identificacao_titulo'] = unicode(str( + vals['numero_documento']), "utf-8") + # TODO: campo 27.3P CEF. Código do juros de mora + vals['juros_cod_mora'] = 3 + vals['carteira_numero'] = int(carteira) + vals['nosso_numero'] = int(nosso_numero) + vals['nosso_numero_dv'] = int(digito) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + + # Precisam estar preenchidos + # Header lote + # vals['servico_operacao'] = u'R' + # vals['servico_servico'] = 1 + vals['cedente_conta_dv'] = unicode(str( + vals['cedente_conta_dv']), "utf-8") + vals['cedente_codigo_codCedente'] = 6088 + vals['data_credito_hd_lote'] = 15052015 + + vals['desconto1_cod'] = 3 + vals['desconto1_data'] = 0 + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = 14 + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/bancos/itau.py b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/itau.py new file mode 100644 index 0000000..84c5706 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/itau.py @@ -0,0 +1,83 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import re +import string + +from ..cnab_240 import Cnab240 + + +class Itau240(Cnab240): + """ + + """ + + def __init__(self): + """ + + :return: + """ + super(Cnab240, self).__init__() + from cnab240.bancos import itau + self.bank = itau + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(Itau240, self)._prepare_header() + vals['cedente_dv_ag_cc'] = int( + vals['cedente_dv_ag_cc']) + vals['cedente_agencia_dv'] = int( + vals['cedente_agencia_dv']), + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Itau240, self)._prepare_cobranca(line) + + carteira, nosso_numero, digito = self.nosso_numero( + line.move_line_id.transaction_ref) + + vals['cedente_dv_ag_cc'] = int( + vals['cedente_dv_ag_cc']) + vals['carteira_numero'] = int(carteira) + vals['nosso_numero'] = int(nosso_numero) + vals['nosso_numero_dv'] = int(digito) + + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos entre + # CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/bancos/santander.py b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/santander.py new file mode 100644 index 0000000..cd8a3a5 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/bancos/santander.py @@ -0,0 +1,59 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Gustavo Lepri +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from ..cnab_240 import Cnab240 + + +class Santander240(Cnab240): + """ + + """ + + def __init__(self): + """ + + :return: + """ + super(Cnab240, self).__init__() + from cnab240.bancos import santander + self.bank = santander + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(Santander240, self)._prepare_header() + del vals['arquivo_hora_de_geracao'] + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Santander240, self)._prepare_cobranca(line) + return vals diff --git a/l10n_br_financial_payment_order/febraban/cnab_240/cnab_240.py b/l10n_br_financial_payment_order/febraban/cnab_240/cnab_240.py new file mode 100644 index 0000000..12f89e2 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_240/cnab_240.py @@ -0,0 +1,564 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from __future__ import division, print_function, unicode_literals + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from openerp.addons.l10n_br_base.tools.misc import punctuation_rm + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: + from cnab240.tipos import Arquivo, Lote +except ImportError as err: + _logger.debug = err + + +class Cnab240(Cnab): + """ + CNAB240 + """ + + def __init__(self): + super(Cnab, self).__init__() + + @staticmethod + def get_bank(bank): + ''' + Função chamada na criação do CNAB que dado o código do banco, + instancia o objeto do banco e retorna o obj ao CNAB que sera criado. + :param bank: str - Código do banco + :return: + ''' + if bank == '341': + from .bancos.itau import Itau240 + return Itau240 + elif bank == '237': + from .bancos.bradesco import Bradesco240 + return Bradesco240 + elif bank == '104': + from .bancos.cef import Cef240 + return Cef240 + elif bank == '033': + from .bancos.santander import Santander240 + return Santander240 + elif bank == '001': + from .bancos.bb import BB240 + return BB240 + else: + return Cnab240 + + def get_inscricao_tipo(self, partner_id): + # TODO: Implementar codigo para PIS/PASEP + if partner_id.is_company: + return 2 + else: + return 1 + + def _prepare_header(self): + """ + Preparar o header do arquivo do CNAB + :return: dict - Header do arquivo + """ + header_arquivo = { + # CONTROLE + # 01.0 + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.0 # Sequencia para o Arquivo + 'controle_lote': 1, + # 03.0 0- Header do Arquivo + 'controle_registro': 0, + # 04.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + + # EMPRESA + # 05.0 - 1 - CPF / 2 - CNPJ + 'cedente_inscricao_tipo': + self.get_inscricao_tipo(self.order.company_id.partner_id), + # 06.0 + 'cedente_inscricao_numero': + int(punctuation_rm(self.order.company_id.cnpj_cpf)), + # 07.0 + 'cedente_convenio': '0001222130126', + # 08.0 + 'cedente_agencia': + int(self.order.mode.bank_id.bra_number), + # 09.0 + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + # 10.0 + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + # 11.0 + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], + # 12.0 + 'cedente_agencia_conta_dv': + self.order.mode.bank_id.acc_number_dig[1] + if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', + # 13.0 + 'cedente_nome': + self.order.mode.bank_id.partner_id.legal_name[:30], + # 14.0 + 'nome_banco': self.order.mode.bank_id.bank_name, + # 15.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + + # ARQUIVO + # 16.0 Código Remessa = 1 / Retorno = 2 + 'arquivo_codigo': '1', + # 17.0 + 'arquivo_data_de_geracao': self.data_hoje(), + # 18.0 + 'arquivo_hora_de_geracao': self.hora_agora(), + # 19.0 TODO: Número sequencial de arquivo + 'arquivo_sequencia': int(self.get_file_numeration()), + # 20.0 + 'arquivo_layout': 103, + # 21.0 + 'arquivo_densidade': 0, + # 22.0 + 'reservado_banco': '', + # 23.0 + 'reservado_empresa': 'EMPRESA 100', + # 24.0 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + } + + return header_arquivo + + def _prepare_header_lote(self): + """ + Preparar o header de LOTE para arquivo do CNAB + :return: dict - Header do arquivo + """ + empresa = self.order.mode.bank_id.partner_id + + header_arquivo_lote = { + + # CONTROLE + # 01.1 + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.1 Sequencia para o Arquivo + 'controle_lote': 1, + # 03.1 0- Header do Arquivo + 'controle_registro': 1, + + # SERVICO + # 04.1 # Header do lote sempre 'C' + 'servico_operacao': 'C', + # 05.1 + 'servico_servico': self.order.order.mode.tipo_servico, + # 06.1 + 'servico_forma_lancamento': 1, + # 07.1 + 'servico_layout': 20, + # 08.1 + # CNAB - Uso Exclusivo da FEBRABAN/CNAB + + # EMPRESA CEDENTE + # 09.1 + 'empresa_inscricao_tipo': 2, + # self.get_inscricao_tipo(self.order.company_id.partner_id), + # 10.1 + 'empresa_inscricao_numero': punctuation_rm(empresa.cnpj_cpf), + # 11.1 + 'cedente_convenio': self.order.mode.convenio, + # 12.1 + 'cedente_agencia': + int(self.order.mode.bank_id.bra_number), + # 13.1 + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + # 14.1 + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + # 15.1 + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], + # 16.1 + 'cedente_agencia_conta_dv': + self.order.mode.bank_id.acc_number_dig[1] + if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', + # 17.1 + 'cedente_nome': + self.order.mode.bank_id.partner_id.legal_name[:30], + # 18.1 + 'mensagem1': '', + + # ENDERECO + # 19.1 + 'empresa_logradouro': empresa.street, + # 20.1 + 'empresa_endereco_numero': empresa.number, + # 21.1 + 'empresa_endereco_complemento': empresa.street2, + # 22.1 + 'empresa_endereco_cidade': empresa.l10n_br_city_id.name, + # 23.1 + 'empresa_endereco_cep': self.get_cep('prefixo', empresa.zip), + # 24.1 + 'empresa_endereco_cep_complemento': + self.get_cep('sufixo', empresa.zip), + # 25.1 + 'empresa_endereco_estado': empresa.state_id.code, + + # 26.1 + 'indicativo_forma_pagamento': '', + # 27.1 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + # 28.1 + 'ocorrencias': '', + } + return header_arquivo_lote + + def get_file_numeration(self): + # Função para retornar a numeração sequencial do arquivo + return 1 + + def _prepare_cobranca(self, line): + """ + :param line: + :return: + """ + # prefixo, sufixo = self.cep(line.partner_id.zip) + + aceite = u'N' + if not self.order.mode.boleto_aceite == 'S': + aceite = u'A' + + # Código agencia do cedente + # cedente_agencia = cedente_agencia + + # Dígito verificador da agência do cedente + # cedente_agencia_conta_dv = cedente_agencia_dv + + # Código da conta corrente do cedente + # cedente_conta = cedente_conta + + # Dígito verificador da conta corrente do cedente + # cedente_conta_dv = cedente_conta_dv + + # Dígito verificador de agencia e conta + # Era cedente_agencia_conta_dv agora é cedente_dv_ag_cc + + return { + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + 'cedente_agencia': int(self.order.mode.bank_id.bra_number), + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig, + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + 'identificacao_titulo': u'0000000', # TODO + 'identificacao_titulo_banco': u'0000000', # TODO + 'identificacao_titulo_empresa': line.move_line_id.move_id.name, + 'numero_documento': line.name, + 'vencimento_titulo': self.format_date( + line.ml_maturity_date), + 'valor_titulo': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + # TODO: fépefwfwe + # TODO: Código adotado para identificar o título de cobrança. + # 8 é Nota de cŕedito comercial + 'especie_titulo': int(self.order.mode.boleto_especie), + 'aceite_titulo': aceite, + 'data_emissao_titulo': self.format_date( + line.ml_date_created), + # TODO: trazer taxa de juros do Odoo. Depende do valor do 27.3P + # CEF/FEBRABAN e Itaú não tem. + 'juros_mora_data': self.format_date( + line.ml_maturity_date), + 'juros_mora_taxa_dia': Decimal('0.00'), + 'valor_abatimento': Decimal('0.00'), + 'sacado_inscricao_tipo': int( + self.get_inscricao_tipo(line.partner_id)), + 'sacado_inscricao_numero': int( + self.rmchar(line.partner_id.cnpj_cpf)), + 'sacado_nome': line.partner_id.legal_name, + 'sacado_endereco': ( + line.partner_id.street + ' ' + line.partner_id.number), + 'sacado_bairro': line.partner_id.district, + 'sacado_cep': self.get_cep('prefixo', line.partner_id.zip), + 'sacado_cep_sufixo': self.get_cep('sufixo', line.partner_id.zip), + 'sacado_cidade': line.partner_id.l10n_br_city_id.name, + 'sacado_uf': line.partner_id.state_id.code, + 'codigo_protesto': int(self.order.mode.boleto_protesto), + 'prazo_protesto': int(self.order.mode.boleto_protesto_prazo), + 'codigo_baixa': 2, + 'prazo_baixa': 0, # De 5 a 120 dias. + 'controlecob_data_gravacao': self.data_hoje(), + 'cobranca_carteira': int(self.order.mode.boleto_carteira), + } + + def _prepare_pagamento(self, line): + """ + Prepara um dict para preencher os valores do segmento A e B apartir de + uma linha da payment.order e insere informações que irão compor o + header do lote + :param line: payment.line - linha que sera base para evento + :return: dict - Dict contendo todas informações dos segmentos + """ + vals = { + + # SEGMENTO A + # CONTROLE + # 01.3A + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.3A + 'controle_lote': 1, + # 03.3A - 3-Registros Iniciais do Lote + 'controle_registro': 3, + + # SERVICO + # 04.3A - Nº Seqüencial do Registro - Inicia em 1 em cada novo lote + # TODO: Contador para o sequencial do lote + 'servico_numero_registro': 1, + # 05.3A + # Segmento Código de Segmento do Reg.Detalhe + # 06.3A + 'servico_tipo_movimento': self.order.mode.tipo_servico_complemento, + # 07.3A + 'servico_codigo_movimento': self.order.mode.instrucao_movimento, + + # FAVORECIDO + # 08.3A - 018-TED 700-DOC + 'favorecido_camara': 0, + # 09.3A + 'favorecido_banco': int(line.bank_id.bank_bic), + # 10.3A + 'favorecido_agencia': int(line.bank_id.bra_number), + # 11.3A + 'favorecido_agencia_dv': line.bank_id.bra_number_dig, + # 12.3A + 'favorecido_conta': punctuation_rm(line.bank_id.acc_number), + # 13.3A + 'favorecido_conta_dv': line.bank_id.acc_number_dig[0] + if line.bank_id.acc_number_dig else '', + # 14.3A + 'favorecido_dv': line.bank_id.acc_number_dig[1] + if len(line.bank_id.bra_number_dig or '') > 1 else '', + # 15.3A + 'favorecido_nome': line.partner_id.name, + + # CREDITO + # 16.3A - + 'credito_seu_numero': line.name, + # 17.3A + 'credito_data_pagamento': self.format_date(line.date), + # 18.3A + 'credito_moeda_tipo': line.currency.name, + # 19.3A + 'credito_moeda_quantidade': Decimal('0.00000'), + # 20.3A + 'credito_valor_pagamento': + Decimal(str(line.amount_currency)).quantize(Decimal('1.00')), + # 21.3A + # 'credito_nosLoteso_numero': '', + # 22.3A + # 'credito_data_real': '', + # 23.3A + # 'credito_valor_real': '', + + # INFORMAÇÔES + # 24.3A + # 'outras_informacoes': '', + # 25.3A + # 'codigo_finalidade_doc': line.codigo_finalidade_doc, + # 26.3A + 'codigo_finalidade_ted': self.order.mode.finalidade_ted or '' + # 27.3A + 'codigo_finalidade_complementar': + self.order.mode.finalidade_complementar or '', + # 28.3A + # CNAB - Uso Exclusivo FEBRABAN/CNAB + # 29.3A + # 'aviso_ao_favorecido': line.aviso_ao_favorecido, + 'aviso_ao_favorecido': 0, + # 'ocorrencias': '', + + # SEGMENTO B + # Preenchido no segmento A + # 01.3B + # 02.3B + # 03.3B + + # 04.3B + # 05.3B + # 06.3B + + # DADOS COMPLEMENTARES - FAVORECIDOS + # 07.3B + 'favorecido_tipo_inscricao': + self.get_inscricao_tipo(line.partner_id), + # 08.3B + 'favorecido_num_inscricao': + int(punctuation_rm(line.partner_id.cnpj_cpf)), + # 09.3B + 'favorecido_endereco_rua': line.partner_id.street or '', + # 10.3B + 'favorecido_endereco_num': int(line.partner_id.number) or 0, + # 11.3B + 'favorecido_endereco_complemento': line.partner_id.street2 or '', + # 12.3B + 'favorecido_endereco_bairro': line.partner_id.district or '', + # 13.3B + 'favorecido_endereco_cidade': + line.partner_id.l10n_br_city_id.name or '', + # 14.3B + # 'favorecido_cep': int(line.partner_id.zip[:5]) or 0, + 'favorecido_cep': self.get_cep('prefixo', line.partner_id.zip), + # 15.3B + 'favorecido_cep_complemento': + self.get_cep('sufixo', line.partner_id.zip), + # 16.3B + 'favorecido_estado': line.partner_id.state_id.code or '', + + # DADOS COMPLEMENTARES - PAGAMENTO + # 17.3B + 'pagamento_vencimento': 0, + # 18.3B + 'pagamento_valor_documento': Decimal('0.00'), + # 19.3B + 'pagamento_abatimento': Decimal('0.00'), + # 20.3B + 'pagamento_desconto': Decimal('0.00'), + # 21.3B + 'pagamento_mora': Decimal('0.00'), + # 22.3B + 'pagamento_multa': Decimal('0.00'), + # 23.3B + # TODO: Verificar se este campo é retornado no retorno + # 'cod_documento_favorecido': '', + # 24.3B - Informado No SegmentoA + # 'aviso_ao_favorecido': '0', + # 25.3B + # 'codigo_ug_centralizadora': '0', + # 26.3B + # 'codigo_ispb': '0', + } + return vals + + def _adicionar_evento(self, line): + """ + Adicionar o evento no arquivo de acordo com seu tipo + """ + # if self.order.payment_order_type == 'payment': + # incluir = self.arquivo.incluir_debito_pagamento + # prepare = self._prepare_pagamento + # else: + # incluir = self.arquivo.incluir_cobranca + # prepare = self._prepare_cobranca + pass + + def remessa(self, order): + """ + Cria a remessa de eventos que sera anexada ao arquivo + :param order: payment.order + :return: Arquivo Cnab pronto para download + """ + # cobrancasimples_valor_titulos = 0 + + self.order = order + + # Preparar Header do Arquivo + self.arquivo = Arquivo(self.bank, **self._prepare_header()) + + if order.payment_order_type == 'payment': + incluir = self.arquivo.incluir_debito_pagamento + prepare = self._prepare_pagamento + + header = self.bank.registros.HeaderLotePagamento( + **self._prepare_header_lote()) + + trailer = self.bank.registros.TrailerLotePagamento() + trailer.somatoria_valores = Decimal('0.00') + trailer.somatoria_quantidade_moedas = Decimal('0.00000') + + lote_pagamento = Lote(self.bank, header, trailer) + self.arquivo.adicionar_lote(lote_pagamento) + + else: + incluir = self.arquivo.incluir_cobranca + prepare = self._prepare_cobranca + + for line in order.bank_line_ids: + # para cada linha da payment order adicoinar como um novo evento + # self._adicionar_evento(line) + # try: + incluir(tipo_lote=30, **prepare(line)) + # except: + # from openerp import exceptions + # raise exceptions.ValidationError("Erro") + # self.arquivo.lotes[0].header.servico_servico = 30 + # TODO: tratar soma de tipos de cobranca + # cobrancasimples_valor_titulos += line.amount_currency + # self.arquivo.lotes[0].trailer.cobrancasimples_valor_titulos = \ + # Decimal(cobrancasimples_valor_titulos).quantize( + # Decimal('1.00')) + + remessa = unicode(self.arquivo) + return unicodedata.normalize('NFKD', remessa).encode('ascii', 'ignore') + + def get_cep(self, tipo, value): + ''' + :param tipo: + :param value: + :return: + ''' + if not value: + if tipo == 'prefixo': + return 0 + else: + return '' + value = punctuation_rm(value) + sufixo = value[-3:] + prefixo = value[:5] + if tipo == 'sufixo': + return sufixo + else: + return prefixo + + def format_date(self, srt_date): + if not srt_date: + return 0 + return int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%d%m%Y')) + + def data_hoje(self): + return (int(time.strftime("%d%m%Y"))) + + def hora_agora(self): + return (int(time.strftime("%H%M%S"))) + + def rmchar(self, format): + return re.sub('[%s]' % re.escape(string.punctuation), '', + format or '') + + def nosso_numero(self, format): + """ + Hook para ser sobrescrito e adicionar informação + :param format: + :return: + """ + pass diff --git a/l10n_br_financial_payment_order/febraban/cnab_400/__init__.py b/l10n_br_financial_payment_order/febraban/cnab_400/__init__.py new file mode 100644 index 0000000..a0d3830 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_400/__init__.py @@ -0,0 +1,19 @@ +# coding: utf-8 +# ########################################################################### +# +# Ainda não implementado! +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/l10n_br_financial_payment_order/febraban/cnab_400/bancos/__init__.py b/l10n_br_financial_payment_order/febraban/cnab_400/bancos/__init__.py new file mode 100644 index 0000000..cce59cd --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_400/bancos/__init__.py @@ -0,0 +1,20 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Fernando Marcato Rodrigues +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/l10n_br_financial_payment_order/febraban/cnab_400/bancos/bradesco.py b/l10n_br_financial_payment_order/febraban/cnab_400/bancos/bradesco.py new file mode 100644 index 0000000..fa3cf04 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_400/bancos/bradesco.py @@ -0,0 +1,113 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +import re +import string +from decimal import Decimal + +from ..cnab_400 import Cnab400 + + +class Bradesco400(Cnab400): + + def __init__(self): + super(Cnab400, self).__init__() + from cnab240.bancos import bradesco_cobranca_400 + self.bank = bradesco_cobranca_400 + self.controle_linha = 2 + + def _prepare_header(self): + """ + + :param order: + :return: + """ + + vals = super(Bradesco400, self)._prepare_header() + vals['servico_servico'] = 1 + return vals + + def _prepare_cobranca(self, line): + """ + + :param line: + :return: + """ + vals = super(Bradesco400, self)._prepare_cobranca(line) + vals['prazo_baixa'] = unicode(str( + vals['prazo_baixa']), "utf-8") + vals['desconto1_percentual'] = Decimal('0.00') + vals['valor_iof'] = Decimal('0.00') + # vals['cobrancasimples_valor_titulos'] = Decimal('02.00') + vals['identificacao_titulo_banco'] = int( + vals['identificacao_titulo_banco']) + vals['cedente_conta_dv'] = unicode(str( + vals['cedente_conta_dv']), "utf-8") + vals['cedente_agencia_dv'] = unicode(str( + vals['cedente_agencia_dv']), "utf-8") + vals['cedente_dv_ag_cc'] = unicode(str( + vals['cedente_dv_ag_cc']), "utf-8") + + vals['sacado_cc_dv'] = u'0' + vals['identificacao_empresa_beneficiaria_banco'] = \ + self.retorna_id_empr_benef() + vals['digito_conferencia_numero_bancario'] = u'0' + vals['condicao_emissao_papeleta'] = 1 + + vals['indicador_rateio_credito'] = u"" + self.controle_linha += 1 + + return vals + + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def retorna_id_empr_benef(self): + dig_cart = 3 + dig_ag = 5 + dig_conta = 7 + + carteira = self.adiciona_digitos( + self.order.mode.boleto_carteira, dig_cart) + agencia = self.adiciona_digitos( + self.order.mode.bank_id.bra_number, dig_ag) + conta = self.adiciona_digitos( + self.order.mode.bank_id.acc_number, dig_conta) + + ident = u'0' + (carteira) + (agencia) + (conta) + \ + (self.order.mode.bank_id.acc_number_dig) + return ident + + def adiciona_digitos(self, campo, num_digitos): + chars_faltantes = num_digitos - len(campo) + return (u'0' * chars_faltantes) + campo + + +def str_to_unicode(inp_str): + inp_str = unicode(inp_str, "utf-8") + return inp_str diff --git a/l10n_br_financial_payment_order/febraban/cnab_400/cnab_400.py b/l10n_br_financial_payment_order/febraban/cnab_400/cnab_400.py new file mode 100644 index 0000000..cb1e3d8 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/cnab_400/cnab_400.py @@ -0,0 +1,375 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Fernando Marcato Rodrigues +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from openerp.addons.l10n_br_base.tools.misc import punctuation_rm + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: + from cnab240.tipos import ArquivoCobranca400 +except ImportError as err: + _logger.debug = (err) + +IDENTIFICACAO_DA_OCORRENCIA = [ + ('01', u'Remessa'), + ('02', u'Pedido de baixa'), + ('03', u'Pedido de Protesto Falimentar'), + ('04', u'Concessão de abatimento'), + ('05', u'Cancelamento de abatimento concedido'), + ('06', u'Alteração de vencimento'), + ('07', u'Alteração do controle do participante'), + ('08', u'Alteração de seu número'), + ('09', u'Pedido de protesto'), + ('18', u'Sustar protesto e baixar Título'), + ('19', u'Sustar protesto e manter em carteira'), + ('22', u'Transferência Cessão crédito ID. Prod.10'), + ('23', u'Transferência entre Carteiras'), + ('24', u'Dev. Transferência entre Carteiras'), + ('31', u'Alteração de outros dados'), + ('45', u'Pedido de Negativação (NOVO)'), + ('46', u'Excluir Negativação com baixa (NOVO)'), + ('47', u'Excluir negativação e manter pendente (NOVO)'), + ('68', u'Acerto nos dados do rateio de Crédito'), + ('69', u'Cancelamento do rateio de crédito'), +] + +ESPECIE_DE_TITULO = [ + ('01', u'Duplicata'), + ('02', u'Nota Promissória'), + ('03', u'Nota de Seguro'), + ('04', u'Cobrança Seriada'), + ('05', u'Recibo'), + ('10', u'Letras de Câmbio'), + ('11', u'Nota de Débito'), + ('12', u'Duplicata de Serv'), + ('30', u'Boleto de Proposta'), + ('99', u'Outros'), +] + +# Essas instruções deverão ser enviadas no Arquivo-Remessa, quando da +# entrada, desde que código de ocorrência na posição 109 a 110 do registro +# de transação, seja “01”, para as instruções de protesto/negativação, o +# CNPJ / CPF e o endereço do Pagador deverão ser informados corretamente +LISTA_PRIMEIRA_INSTRUCAO = [ + ('05', u'Protesto Falimentar'), + ('06', u'Protestar'), + ('07', u'Negativar'), + ('18', u'Decurso de prazo'), + + ('08', u'Não cobrar juros de mora'), + ('09', u'Não receber após o vencimento'), + ('10', u'Multas de 10% após o 4o dia do Vencimento'), + ('11', u'Não receber após o 8o dia do vencimento.'), + ('12', u'Cobrar encargos após o 5o dia do vencimento'), + ('13', u'Cobrar encargos após o 10o dia do vencimento'), + ('14', u'Cobrar encargos após o 15o dia do vencimento'), + ('15', u'Conceder desconto mesmo se pago após o vencimento'), +] + + +class Cnab400(Cnab): + + def __init__(self): + super(Cnab, self).__init__() + + @staticmethod + def get_bank(bank): + if bank == '237': + from .bancos.bradesco import Bradesco400 + return Bradesco400 + else: + return Cnab400 + + @property + def inscricao_tipo(self): + # TODO: Implementar codigo para PIS/PASEP + if self.order.company_id.partner_id.is_company: + return 2 + else: + return 1 + + def _prepare_header(self): + """ + + :param: + :return: + """ + return { + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + 'arquivo_data_de_geracao': self.data_hoje(), + 'arquivo_hora_de_geracao': self.hora_agora(), + # TODO: Número sequencial de arquivo + 'arquivo_sequencia': int(self.get_file_numeration()), + 'cedente_inscricao_tipo': self.inscricao_tipo, + 'cedente_inscricao_numero': int(punctuation_rm( + self.order.company_id.cnpj_cpf)), + 'cedente_agencia': int( + self.order.mode.bank_id.bra_number), + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + 'cedente_conta_dv': (self.order.mode.bank_id.acc_number_dig), + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + 'cedente_nome': self.order.company_id.legal_name, + 'arquivo_codigo': 1, # Remessa/Retorno + 'servico_operacao': u'R', + 'nome_banco': unicode(self.order.mode.bank_id.bank_name), + 'codigo_empresa': int(self.order.mode.boleto_convenio), + } + + def get_file_numeration(self): + numero = self.order.get_next_number() + if not numero: + numero = 1 + return numero + + def format_date(self, srt_date): + return int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%d%m%y')) + + def nosso_numero(self, format): + pass + + def cep(self, format): + sulfixo = format[-3:] + prefixo = format[:5] + return prefixo, sulfixo + + def sacado_inscricao_tipo(self, partner_id): + # TODO: Implementar codigo para PIS/PASEP + if partner_id.is_company: + return 2 + else: + return 1 + + def rmchar(self, format): + return re.sub('[%s]' % re.escape(string.punctuation), '', + format or '') + + def codificar(self, texto): + return texto.encode('utf-8') + + def _prepare_cobranca(self, line): + """ + :param line: + :return: + """ + prefixo, sulfixo = self.cep(line.partner_id.zip) + + aceite = u'N' + if not self.order.mode.boleto_aceite == 'S': + aceite = u'A' + + codigo_protesto = 0 + dias_protestar = 0 + if self.order.mode.boleto_protesto == '3' \ + or self.order.mode.boleto_protesto == '0': + codigo_protesto = 0 + dias_protestar = 0 + elif self.order.mode.boleto_protesto == '1' \ + or self.order.mode.boleto_protesto == '2': + codigo_protesto = 6 + if (int(self.order.mode.boleto_protesto_prazo)) < 5: + dias_protestar = 5 + else: + dias_protestar = int(self.order.mode.boleto_protesto_prazo) + + sacado_endereco = self.retorna_endereco(line.partner_id.id) + + # Código agencia do cedente + # cedente_agencia = cedente_agencia + + # Dígito verificador da agência do cedente + # cedente_agencia_conta_dv = cedente_agencia_dv + + # Código da conta corrente do cedente + # cedente_conta = cedente_conta + + # Dígito verificador da conta corrente do cedente + # cedente_conta_dv = cedente_conta_dv + + # Dígito verificador de agencia e conta + # Era cedente_agencia_conta_dv agora é cedente_dv_ag_cc + + return { + + 'percentual_multa': Decimal('0.00'), + 'valor_desconto': Decimal('0.00'), + 'valor_abatimento_concedido_cancelado': Decimal('0.00'), + 'primeira_instrucao': codigo_protesto, + 'segunda_instrucao': dias_protestar, + 'sacado_cep': int(prefixo), + 'sacado_cep_sufixo': int(sulfixo), + 'sacador_avalista': self.order.mode.comunicacao_2, + # 'sacador_avalista': u'Protestar após 5 dias', + 'num_seq_registro': self.controle_linha, + + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + 'cedente_agencia': int(self.order.mode.bank_id.bra_number), + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig, + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + 'identificacao_titulo': u'0000000', # TODO + 'identificacao_titulo_banco': u'0000000', # TODO + 'identificacao_titulo_empresa': line.move_line_id.move_id.name, + + 'vencimento_titulo': self.format_date( + line.ml_maturity_date), + 'valor_titulo': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + # TODO: Código adotado para identificar o título de cobrança. + # 8 é Nota de cŕedito comercial + 'especie_titulo': int(self.order.mode.boleto_especie), + 'aceite_titulo': aceite, + 'data_emissao_titulo': self.format_date( + line.ml_date_created), + # TODO: trazer taxa de juros do Odoo. Depende do valor do 27.3P + # CEF/FEBRABAN e Itaú não tem. + 'juros_mora_data': self.format_date( + line.ml_maturity_date), + + # 'juros_mora_taxa_dia': Decimal('0.20'), + 'juros_mora_taxa_dia': self.calcula_valor_juros_dia( + line.amount_currency, line.percent_interest), + + 'valor_abatimento': Decimal('0.00'), + 'sacado_inscricao_tipo': int( + self.sacado_inscricao_tipo(line.partner_id)), + 'sacado_inscricao_numero': int( + self.rmchar(line.partner_id.cnpj_cpf)), + 'sacado_nome': line.partner_id.legal_name, + + # 'sacado_endereco': ( + # line.partner_id.street + + # ' ' + str(line.partner_id.number) + # ), + + 'sacado_endereco': sacado_endereco, + + 'sacado_bairro': line.partner_id.district, + 'sacado_cidade': line.partner_id.l10n_br_city_id.name, + 'sacado_uf': line.partner_id.state_id.code, + 'codigo_baixa': 2, + 'prazo_baixa': 0, # De 5 a 120 dias. + 'controlecob_data_gravacao': self.data_hoje(), + 'cobranca_carteira': int(self.order.mode.boleto_carteira), + + 'primeira_mensagem': u'', + # Trazer da nova tela do payment_mode + 'identificacao_ocorrencia': 1, + + # numero fatura esta copiando para communication + 'numero_documento': self.adiciona_digitos_num_doc( + line.communication), + # 'numero_documento': str(line.move_line_id.invoice.number), + + } + + def remessa(self, order): + """ + + :param order: + :return: + """ + self.order = order + self.arquivo = ArquivoCobranca400(self.bank, **self._prepare_header()) + for line in order.line_ids: + self.arquivo.incluir_cobranca(**self._prepare_cobranca(line)) + self.arquivo.trailer.num_seq_registro = self.controle_linha + + remessa = unicode(self.arquivo) + return unicodedata.normalize( + 'NFKD', remessa).encode('ascii', 'ignore') + + def data_hoje(self): + return (int(time.strftime("%d%m%y"))) + + def hora_agora(self): + return (int(time.strftime("%H%M%S"))) + + def calcula_valor_juros_dia(self, total_titulo, percent_juros): + valor_juros = 0 + valor_juros = (total_titulo * (percent_juros / 100)) + return (Decimal(valor_juros).quantize(Decimal('1.00'))) + + def adiciona_digitos_num_doc(self, campo): + num_digitos = 10 + campo = str(campo) + chars_faltantes = num_digitos - len(campo) + return (u' ' * chars_faltantes) + campo + + # @api.multi + def retorna_endereco(self, id_parceiro): + # self.ensure_one() + # workaround to get env + res_partner_model = self.order.env['res.partner'] + res_partner_end_cobranca = res_partner_model.search( + [('parent_id', '=', id_parceiro), ('type', '=', 'cnab_cobranca')], + limit=1) + if res_partner_end_cobranca: + str_endereco = self.monta_endereco(res_partner_end_cobranca) + else: + res_partner_end_cobranca = res_partner_model.search( + [('id', '=', id_parceiro)] + ) + str_endereco = self.monta_endereco(res_partner_end_cobranca) + # Essa abordagem substitui caracteres especiais por '?' + # str_endereco = / + # unicode(str_endereco.encode("ascii", errors="replace")) + + # Substitui sinal de grau por espaço + str_endereco = str_endereco.replace(u"\xb0", u" ") + + return str_endereco + + def monta_endereco(self, partner_item): + + street = self.check_address_item_filled(partner_item.street) + number = self.check_address_item_filled(partner_item.number) + complemento = self.check_address_item_filled(partner_item.street2) + distrito = self.check_address_item_filled(partner_item.district) + + str_endereco = ( + street + + ' ' + + number + + ' ' + + complemento + + ' ' + + distrito + # + ' ' + + # partner_item.l10n_br_city_id.name + + # ' ' + partner_item.state_id.name + ) + return str_endereco + + def check_address_item_filled(self, item): + if not item: + return ('') + else: + return item diff --git a/l10n_br_financial_payment_order/febraban/pag_for/__init__.py b/l10n_br_financial_payment_order/febraban/pag_for/__init__.py new file mode 100644 index 0000000..dec8c03 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/pag_for/__init__.py @@ -0,0 +1,24 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import pag_for500 diff --git a/l10n_br_financial_payment_order/febraban/pag_for/bancos/__init__.py b/l10n_br_financial_payment_order/febraban/pag_for/bancos/__init__.py new file mode 100644 index 0000000..0104e25 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/pag_for/bancos/__init__.py @@ -0,0 +1,22 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/l10n_br_financial_payment_order/febraban/pag_for/bancos/bradesco.py b/l10n_br_financial_payment_order/febraban/pag_for/bancos/bradesco.py new file mode 100644 index 0000000..1edd242 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/pag_for/bancos/bradesco.py @@ -0,0 +1,75 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +import re +import string + +from ..pag_for500 import PagFor500 + + +class BradescoPagFor(PagFor500): + + def __init__(self): + super(PagFor500, self).__init__() + from cnab240.bancos import bradescoPagFor + self.bank = bradescoPagFor + self.controle_linha = 2 + + def _prepare_header(self): + """ + + :param order: + :return: + """ + vals = super(BradescoPagFor, self)._prepare_header() + vals['codigo_comunicacao'] = int(self.order.mode.boleto_convenio) + return vals + + def _prepare_cobranca(self, line, vals): + """ + + :param line: + :return: + """ + vals = super(BradescoPagFor, self)._prepare_cobranca(line, vals) + + # TODO campo para informar a data do pagamento. + vals['data_para_efetivacao_pag'] = self.muda_campos_data( + vals['vencimento_titulo']) + self.controle_linha += 1 + + return vals + + # Override cnab_240.nosso_numero. Diferentes números de dígitos + # entre CEF e Itau + def nosso_numero(self, format): + digito = format[-1:] + carteira = format[:3] + nosso_numero = re.sub( + '[%s]' % re.escape(string.punctuation), '', format[3:-1] or '') + return carteira, nosso_numero, digito + + def muda_campos_data(self, campo): + campo = str(campo) + campo = campo[-4:] + campo[2:4] + campo[:2] + return int(campo) diff --git a/l10n_br_financial_payment_order/febraban/pag_for/pag_for500.py b/l10n_br_financial_payment_order/febraban/pag_for/pag_for500.py new file mode 100644 index 0000000..3666832 --- /dev/null +++ b/l10n_br_financial_payment_order/febraban/pag_for/pag_for500.py @@ -0,0 +1,575 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import datetime +import logging +import re +import string +import time +import unicodedata +from decimal import Decimal + +from openerp import _ +from openerp.addons.l10n_br_base.tools.misc import punctuation_rm +from openerp.exceptions import Warning as UserError + +from ..cnab import Cnab + +_logger = logging.getLogger(__name__) +try: + from cnab240.tipos import Arquivo +except ImportError as err: + _logger.debug = (err) +try: + from pyboleto.data import BoletoData +except ImportError as err: + _logger.debug = (err) + +TIPO_CONTA_FORNECEDOR = [ + ('1', u'Conta corrente'), + ('2', u'Conta Poupança'), +] + +TIPO_DOCUMENTO = [ + ('01', u'Nota Fiscal/Fatura'), + ('02', u'Fatura'), + ('03', u'Nota Fiscal'), + ('01', u'Duplicata'), + ('01', u'Outros'), +] + +MODALIDADE = [ + ('01', u'01 - Crédito em conta-corrente ou poupança Bradesco'), + ('02', u'02 - Cheque OP ( Ordem de Pagamento'), + ('03', u'03 - DOC COMPE'), + ('05', u'05 - Crédito em conta real time'), + ('08', u'08 - TED'), + ('30', u'30 - Rastreamento de Títulos'), + ('31', u'31 - Títulos de terceiros'), +] + +TIPO_MOVIMENTO = [ + ('0', u'Inclusão'), + ('5', u'Alteração'), + ('9', u'Exclusão'), +] + +CODIGO_MOVIMENTO = [ + ('00', u'Autoriza agendamento'), + ('25', u'Desautoriza Agendamento'), + ('50', u'Efetuar Alegçação'), +] + +TIPO_DOC = [ + ('C', u'Titularidade Diferente'), + ('D', u'Mesma Titularidade'), +] + +FINALIDADE_DOC_TED = [ + ('01', u'Crédito em Conta Corrente'), + ('02', u'Pagamento de Aluguel /Condomínios'), + ('03', u'Pagamento de Duplicatas/Títulos'), + ('04', u'Pagamento de Dividendos'), + ('05', u'Pagamento de Mensal. Escolares'), + ('06', u'Pagamento de Salário'), + ('07', u'Pagamento de Fornec/Honor.'), + ('08', u'Operações de Câmbio /Fundos /Bolsa de Valores'), + ('09', u'Repasse de Arrec./Pagto de Tributos'), + ('10', u'Transferência Internacional em Reais'), + ('11', u'DOC COMPE/TED para Poupança'), + ('12', u'DOC COMPE/TED para Depósito Judicial'), + ('13', u'Pensão Alimentícia'), + ('14', u'Restituição de Imposto de Renda'), + ('18', u'Operações Seguro Habit.', u'SFH'), + ('19', u'Operações do FDS', u'Caixa'), + ('20', u'Pagamento De Operação De Crédito'), + ('23', u'Taxa de Administração'), + ('27', u'Pagamento Acordo/Execução Judicial'), + ('28', u'Liquidação de Empréstimos Consignados'), + ('29', u'Pagamento de Bolsa Auxilio'), + ('30', u'Remuneração A Cooperado'), + ('31', u'Pagamento de Prebenda'), + ('33', u'Pagamento de Juros sobre Capital Próprio'), + ('34', u'Pagamento de Rendimentos ou Amortização s/ Cotas ' + u'e/ou Debêntures'), + ('35', u'Taxa De Serviço'), + ('37', u'Pagamento de Juros e/ou Amortização de Títulos ' + u'Depositados em Garantia.'), + ('38', u'Estorno Ou Restituição', u'Diversos'), + ('59', u'Restituição de Prêmios de Seguros'), + ('60', u'Pagamento de Indenização Sinistro Seguro'), + ('61', u'Pagamento de Premio de Co-Seguro'), + ('63', u'Pagamento de Indenização Sinistro Co-Seguro'), + ('64', u'Pagamento de Premio De Resseguro'), + ('65', u'Restituição de Premio De Resseguro'), + ('66', u'Pagamento de Indenização Sinistro Resseguro'), + ('67', u'Restituição Indenização Sinistro Resseguro'), + ('68', u'Pagamento de Despesas Com Sinistro'), + ('69', u'Pagamento de Inspeções/Vistorias Prévias'), + ('70', u'Pagamento de Resgate de Titulo de Capitalização'), + ('71', u'Pagamento de Sorteio de Titulo de Capitalização'), + ('72', u'Devolução Mensal de Titulo de Capitalização.'), + ('73', u'Restituição de Contribuição de Plano Previdenciário'), + ('74', u'Pagamento de Beneficio Previdenciário Pecúlio'), + ('75', u'Pagamento de Beneficio Previdenciário Pensão'), + ('76', u'Pagamento de Beneficio Previdenciário Aposentadoria'), + ('77', u'Pagamento de Resgate Previdenciário'), + ('78', u'Pagamento de Comissão de Corretagem'), + ('79', u'Pagamento de Transferências/Portabilidade de Reserva ' + u'Seguro/Previdência'), + ('80', u'Pagamento de Impostos'), + ('81', u'Pagamento de Serviços Públicos'), + ('82', u'Pagamento de Honorários'), + ('83', u'Pagamento de Corretoras'), + ('84', u'Repasse de Valores BNDES'), + ('85', u'Liquidação de Compromissos com BNDES'), + ('86', u'Compra e Venda de Ações'), + ('87', u'Contratos Referenciados em Ações ou Índices de Ações'), + ('88', u'Operação De Cambio'), + ('89', u'Pagamento de Boleto Bancário em Cartório'), + ('90', u'Pagamento de Tarifas pela Prestação de Serviços de Arrecadação' + u' de Convênios'), + ('91', u'Operações no Mercado de Renda Fixa e Variável com Utilização ' + u'de Intermediário'), + ('92', u'Operação de Câmbio Mercado Interbancário Instituições ' + u'sem Reservas Bancárias'), + ('93', u'Pagamento de Operações com Identificação de Destinatário Final'), + ('94', u'Ordem Bancaria do Tesouro - OBT'), + ('99', u'Outros'), +] + + +class PagFor500(Cnab): + """ + + """ + + def __init__(self): + super(Cnab, self).__init__() + + @staticmethod + def get_bank(bank): + if bank == '237': + from .bancos.bradesco import BradescoPagFor + return BradescoPagFor + else: + return PagFor500 + + @property + def inscricao_tipo(self): + # TODO: Implementar codigo para PIS/PASEP + if self.order.company_id.partner_id.is_company: + return 2 + else: + return 1 + + def _prepare_header(self): + """ + + :param: + :return: + """ + return { + 'arquivo_data_de_geracao': self.data_hoje_pag_for(), + 'arquivo_hora_de_geracao': self.hora_agora(), + # TODO: Número sequencial de arquivo + 'numero_remessa': int(self.get_file_numeration()), + 'cedente_inscricao_tipo': self.inscricao_tipo, + 'cnpj_cpf_base': int(punctuation_rm( + self.order.company_id.cnpj_cpf)[0:8]), + 'cnpj_cpf_filial': int(punctuation_rm( + self.order.company_id.cnpj_cpf)[9:12]), + 'sufixo_cnpj': int(punctuation_rm( + self.order.company_id.cnpj_cpf)[12:14]), + 'cedente_agencia': int(self.order.mode.bank_id.bra_number), + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + 'cedente_agencia_conta_dv': + self.order.mode.bank_id.bra_number_dig, + 'nome_empresa_pagadora': self.order.company_id.legal_name, + 'cedente_codigo_agencia_digito': + self.order.mode.bank_id.bra_number_dig, + 'arquivo_codigo': 1, # Remessa/Retorno + 'servico_operacao': u'R', + 'reservado_empresa': u'BRADESCO PAG FOR', + # Sequencial crescente e nunca pode ser repetido + 'numero_lista_debito': int(self.get_file_numeration()), + # TODO: Sequencial crescente de 1 a 1 no arquivo. O primeiro header + # será sempre 000001 + 'sequencial': 1 + } + + def get_file_numeration(self): + numero = self.order.get_next_number() + if not numero: + numero = 1 + return numero + + def format_date(self, srt_date): + return int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%d%m%Y')) + + def format_date_ano_mes_dia(self, srt_date): + return int(datetime.datetime.strptime( + srt_date, '%Y-%m-%d').strftime('%Y%m%d')) + + def nosso_numero(self, format): + pass + + def cep(self, format): + sulfixo = format[-3:] + prefixo = format[:5] + return prefixo, sulfixo + + def sacado_inscricao_tipo(self, partner_id): + # TODO: Implementar codigo para PIS/PASEP + if partner_id.is_company: + return 2 + else: + return 1 + + def rmchar(self, format): + return re.sub('[%s]' % re.escape(string.punctuation), '', format or '') + + def _prepare_cobranca(self, line, vals): + """ + + :param line: + :return: + """ + segmento = {} + + vals.update(segmento) + + # TODO this zip code + prefixo, sulfixo = self.cep(line.partner_id.zip) + + segmento = { + 'conta_complementar': int(self.order.mode.bank_id.acc_number), + # 'especie_titulo': 8, + + 'tipo_inscricao': int( + self.sacado_inscricao_tipo(line.partner_id)), + 'cnpj_cpf_base_forn': int( + self.rmchar(line.partner_id.cnpj_cpf)[0:8]), + 'cnpj_cpf_filial_forn': int( + self.rmchar(line.partner_id.cnpj_cpf)[9:12]), + 'cnpj_cpf_forn_sufixo': int( + self.rmchar(line.partner_id.cnpj_cpf)[12:14]), + 'nome_forn': line.partner_id.legal_name, + 'endereco_forn': ( + line.partner_id.street + ' ' + line.partner_id.number), + 'cep_forn': int(prefixo), + 'cep_complemento_forn': int(sulfixo), + + # TODO quando banco é 237, deve-se extrair da linha + # digitável. Do contrário, zeros. + # 'nosso_numero': 11, # FIXME + + # 'numero_documento': line.name, + # 'vencimento_titulo': self.format_date_ano_mes_dia( + # line.ml_maturity_date), + + 'data_emissao_titulo': self.format_date_ano_mes_dia( + line.ml_date_created), + + 'desconto1_data': 0, + 'fator_vencimento': 0, # FIXME + + 'valor_titulo': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + + 'valor_pagto': Decimal(str(line.amount_currency)).quantize( + Decimal('1.00')), + + 'valor_desconto': Decimal('0.00'), + + 'valor_acrescimo': Decimal('0.00'), + + # FIXME + 'tipo_documento': 2, # NF, Fatura, Duplicata... + # NF_Fatura_01/Fatura_02/NF_03/Duplicata_04/Outros_05 + 'numero_nf': int(line.ml_inv_ref.internal_number), + + 'modalidade_pagamento': int( + line.order_id.mode.type_purchase_payment), + + # Quando não informada o sistema assume a data constante do campo + # Vencimento + 'data_para_efetivacao_pag': 0, + + 'tipo_movimento': 0, + # TODO Tipo de Movimento. + # 0 - Inclusão. + # 5 - Alteração. + # 9 - Exclusão. + + 'codigo_movimento': 0, # Autoriza agendamento + + # Quando não informado consulta em todos processamentos + # 'horario_consulta_saldo': u'5', + + 'codigo_area_empresa': 0, + + 'codigo_lancamento': 0, # FIXME + + 'tipo_conta_fornecedor': 1, # FIXME + + # O Primeiro registro de transação sempre será o registro + # “000002”, e assim sucessivamente. + 'sequencial': 3, # FIXME + + # Trailer + 'totais_quantidade_registros': 0, + 'total_valor_arq': Decimal('0.00'), + # FIXME: lib nao reconhece campo + 'sequencial_trailer': int(self.get_file_numeration()), + 'sequencial_transacao': self.controle_linha, + 'codigo_protesto': int(self.order.mode.boleto_protesto), + 'prazo_protesto': int(self.order.mode.boleto_protesto_prazo), + 'codigo_baixa': 2, + 'prazo_baixa': 0, # De 5 a 120 dias. + 'controlecob_data_gravacao': self.data_hoje(), + + } + segmento.update(vals) + return segmento + + def remessa(self, order): + """ + + :param order: + :return: + """ + + pag_valor_titulos = 0 + + self.order = order + self.arquivo = Arquivo(self.bank, **self._prepare_header()) + cont_lote = 0 + + for line in order.line_ids: + self.arquivo.incluir_pagamento(**self.incluir_pagamento_for(line)) + pag_valor_titulos += line.amount_currency + self.arquivo.trailer.total_valor_arq = Decimal( + pag_valor_titulos).quantize(Decimal('1.00')) + self.arquivo.trailer.sequencial_transacao = self.controle_linha + + cont_lote += 1 + remessa = unicode(self.arquivo) + return unicodedata.normalize( + 'NFKD', remessa).encode('ascii', 'ignore') + + def data_hoje(self): + return (int(time.strftime("%d%m%Y"))) + + def data_hoje_pag_for(self): + return (int(time.strftime("%Y%m%d"))) + + def hora_agora(self): + return (int(time.strftime("%H%M%S"))) + + @staticmethod + def modulo11(num, base, r): + return BoletoData.modulo11(num, base=9, r=0) + + def incluir_pagamento_for(self, line): + mode = line.order_id.mode.type_purchase_payment + if mode in ('01'): + return self.lancamento_credito_bradesco(line) + elif mode in ('02'): + raise UserError(_(u'Operação não suportada')) + elif mode in ('03'): + return self.lancamento_doc(line) + elif mode in ('05'): + raise UserError(_(u'Operação não suportada')) + elif mode in ('08'): + return self.lancamento_ted(line) + elif mode in ('30'): + raise UserError(_(u'Operação não suportada')) + elif mode in ('31'): + # titulos de terceiros + return self.lancamento_titulos_terceiros(line) + raise UserError(_(u'Operação não suportada')) + + def lancamento_credito_bradesco(self, line): + # TODO: + # modalidade 01. + + vals = { + 'especie_titulo': line.order_id.mode.type_purchase_payment, + + 'codigo_banco_forn': 237, + 'codigo_agencia_forn': int(line.bank_id.bra_number), + 'digito_agencia_forn_transacao': line.bank_id.bra_number_dig, + 'conta_corrente_forn': int(line.bank_id.acc_number), + 'digito_conta_forn_transacao': line.bank_id.acc_number_dig, + + 'numero_pagamento': self.adiciona_digitos_num_pag( + line.communication), + + 'carteira': int(self.order.mode.boleto_carteira), + + 'nosso_numero': 0, + + 'vencimento_titulo': self.format_date_ano_mes_dia( + line.ml_maturity_date), + + 'informacoes_complementares': u'', + } + + return self._prepare_cobranca(line, vals) + + def lancamento_ted(self, line): + # TODO: + # modalidade 08. + + vals = { + 'conta_complementar': int(self.order.mode.bank_id.acc_number), + 'especie_titulo': line.order_id.mode.type_purchase_payment, + + + # TODO: código do banco. Para a Modalidade de Pagamento valor + # pode variar + 'codigo_banco_forn': int(line.bank_id.bank.bic), + 'codigo_agencia_forn': int(line.bank_id.bra_number), + 'digito_agencia_forn_transacao': line.bank_id.bra_number_dig, + 'conta_corrente_forn': int(line.bank_id.acc_number), + 'digito_conta_forn_transacao': line.bank_id.acc_number_dig, + # TODO Gerado pelo cliente pagador quando do agendamento de + # pagamento por parte desse, exceto para a modalidade 30 - + # Títulos em Cobrança Bradesco + # communication + 'numero_pagamento': self.adiciona_digitos_num_pag( + line.communication), + + 'carteira': 0, + + 'nosso_numero': 0, + + 'vencimento_titulo': self.format_date_ano_mes_dia( + line.ml_maturity_date), + + 'fator_vencimento': 0, # FIXME + + # 'modalidade_pagamento': int(self.order.mode.boleto_especie), + + 'tipo_movimento': 0, + # TODO Tipo de Movimento. + # 0 - Inclusão. + # 5 - Alteração. + # 9 - Exclusão. Wkf Odoo. + 'codigo_movimento': 0, # FIXME + # 'horario_consulta_saldo': u'5', # FIXME + + # 'informacoes_complementares': self.montar_info_comple_ted(), + 'informacoes_complementares': u'', + + 'codigo_lancamento': 0, # FIXME + 'tipo_conta_fornecedor': 1, # FIXME + + } + + return self._prepare_cobranca(line, vals) + + def lancamento_doc(self): + # TODO: + + vals = {} + + return self._prepare_cobranca(vals) + + def lancamento_titulos_terceiros(self, line): + # TODO: + + res_cods_ag_cc = \ + self.ler_linha_digitavel_codigos_ag_cc(line.linha_digitavel) + + vals = { + 'conta_complementar': int(self.order.mode.bank_id.acc_number), + 'especie_titulo': line.order_id.mode.type_purchase_payment, + + # extrair do código de barras + 'codigo_banco_forn': res_cods_ag_cc['codigo_banco_forn'], + 'codigo_agencia_forn': res_cods_ag_cc['codigo_agencia_forn'], + 'digito_agencia_forn_transacao': res_cods_ag_cc[ + 'digito_agencia_forn_transacao'], + 'conta_corrente_forn': res_cods_ag_cc['conta_corrente_forn'], + 'digito_conta_forn_transacao': res_cods_ag_cc[ + 'digito_conta_forn_transacao'], + + 'carteira': res_cods_ag_cc['carteira'] + + } + + return self._prepare_cobranca(vals) + + def adiciona_digitos_num_pag(self, campo): + num_digitos = 16 + campo = str(campo) + chars_faltantes = num_digitos - len(campo) + return (u' ' * chars_faltantes) + campo + + def montar_info_comple_ted(self): + tipo_doc_compe = TIPO_DOC[0][0] + num_doc_ted = '000000' + # pagamento duplicatas. Ou será 01? + finalidade_doc_compe = FINALIDADE_DOC_TED[2][0] + tipo_conta_doc_ted = '01' + codigo_identif_transf = '0000000000000000000000000' + fim_do_campo = ' ' + info_comple = tipo_doc_compe + num_doc_ted + finalidade_doc_compe + \ + tipo_conta_doc_ted + codigo_identif_transf + fim_do_campo + return (info_comple.encode('utf-8')) + + def ler_linha_digitavel_codigos_ag_cc(self, linha_digitavel): + codigo_banco_fornecedor = linha_digitavel[:3] + res = {} + + # para banco = 237, bradesco + if (codigo_banco_fornecedor == '237'): + res = { + 'codigo_banco_forn': int(codigo_banco_fornecedor), + 'codigo_agencia_forn': int(linha_digitavel[4:8]), + # Calcular usando modulo 11 base 7 + 'digito_agencia_forn_transacao': u'', + 'conta_corrente_forn': int(linha_digitavel[23:30]), + # Calcular usando modulo 11 base 7 + 'digito_conta_forn_transacao': u'', + + 'carteira': int(linha_digitavel[8:10]), + + 'nosso_numero': int(linha_digitavel[11:21]) + } + # para outros bancos + else: + res = { + 'codigo_banco_forn': int(codigo_banco_fornecedor), + 'codigo_agencia_forn': 0, + 'digito_agencia_forn_transacao': u'', + 'conta_corrente_forn': 0, + 'digito_conta_forn_transacao': u'', + + 'carteira': 0, + + 'nosso_numero': 0, + } + return res diff --git a/l10n_br_financial_payment_order/models/__init__.py b/l10n_br_financial_payment_order/models/__init__.py new file mode 100644 index 0000000..acd67d7 --- /dev/null +++ b/l10n_br_financial_payment_order/models/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import inherited_financial_document_type +from . import inherited_financial_move +from . import bank_payment_line +from . import payment_line +from . import payment_mode +from . import payment_mode_type +# from . import hr_payslip +# +# Manter sempre operações abaixo de payment_order +# +from . import inherited_payment_order +from . import operacoes +from . import financial_retorno_bancario +from . import res_bank +from . import res_partner_bank diff --git a/l10n_br_financial_payment_order/models/bank_payment_line.py b/l10n_br_financial_payment_order/models/bank_payment_line.py new file mode 100644 index 0000000..9ede5f0 --- /dev/null +++ b/l10n_br_financial_payment_order/models/bank_payment_line.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import api, fields, models, _ + +STATE = [ + ('draft', 'Draft'), + ('wait', 'Waiting Paiment'), + ('exception', 'Exception'), + ('paid', 'Paid'), +] + + +class BankPaymentLine(models.Model): + _inherit = b'bank.payment.line' + + state2 = fields.Selection( + string="State", + selection=STATE, + default="draft", + ) + + @api.multi + def set_paid(self): + self.write({'state2': 'paid'}) + + @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( + BankPaymentLine, self + ).same_fields_payment_line_and_bank_payment_line() + + # TODO: Implementar campo brasileiros que permitem mesclar linhas + + # same_fields = [ + # 'currency', 'partner_id', + # 'bank_id', 'date', 'state'] + + return same_fields diff --git a/l10n_br_financial_payment_order/models/financial_retorno_bancario.py b/l10n_br_financial_payment_order/models/financial_retorno_bancario.py new file mode 100644 index 0000000..7870a88 --- /dev/null +++ b/l10n_br_financial_payment_order/models/financial_retorno_bancario.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +import base64 +import codecs +import logging +from datetime import datetime +from ..constantes import CODIGO_OCORRENCIAS + +from openerp import api, models, fields, exceptions + +_logger = logging.getLogger(__name__) +try: + from cnab240.bancos import bancodobrasil + from cnab240.tipos import Arquivo + from pybrasil import data +except ImportError as err: + _logger.debug = (err) + +STATE = [ + ('draft', 'Novo'), + ('done', 'Processado'), +] + +TIPO_OPERACAO = { + 'C': u'Lançamento a Crédito', + 'D': u'Lançamento a Débito', + 'E': u'Extrato para Conciliação', + 'G': u'Extrato para Gestão de Caixa', + 'I': u'Informações de Títulos Capturados do Próprio Banco', + 'R': u'Arquivo Remessa', + 'T': u'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 FinancialRetornoBancario(models.Model): + _name = b'financial.retorno.bancario' + _rec_name = 'name' + + name = fields.Char(string='Nome') + + data_arquivo = fields.Date(string='Data Criação no Banco') + + num_lotes = fields.Integer(string='Número de Lotes') + + num_eventos = fields.Integer(string='Número de Eventos') + + codigo_convenio = fields.Char(string='Código Convenio') + + arquivo_retorno = fields.Binary( + string='Arquivo Retorno', + required=True, + ) + + lote_id = fields.One2many( + string='Lotes', + comodel_name='financial.retorno.bancario.lote', + inverse_name='cnab_id', + ) + + evento_id = fields.One2many( + string='Eventos', + comodel_name='financial.retorno.bancario.evento', + inverse_name='cnab_id', + ) + + state = fields.Selection( + string=u"Estágio", + selection=STATE, + default="draft", + ) + + bank_account_id = fields.Many2one( + string="Conta cedente", + comodel_name="res.partner.bank", + ) + + payment_mode_id = fields.Many2one( + string='Integração Bancária', + comodel_name='payment.mode', + ) + + @api.multi + def processar_arquivo_retorno(self): + + arquivo_retono = base64.b64decode(self.arquivo_retorno) + f = open('/tmp/cnab_retorno.ret', 'wb') + f.write(arquivo_retono) + f.close() + arquivo_retono = codecs.open('/tmp/cnab_retorno.ret', encoding='ascii') + arquivo_parser = Arquivo(bancodobrasil, arquivo=arquivo_retono) + + if not arquivo_parser.header.arquivo_codigo == u'2': + raise exceptions.Warning('Este não é um arquivo de retorno!') + + self.codigo_convenio = arquivo_parser.header.cedente_convenio + # Buscar payment_mode + + payment_mode = self.env['payment.mode'].search([ + ('convenio', '=', self.codigo_convenio)] + ) + + if len(payment_mode) < 1: + raise exceptions.Warning( + 'Não encontrado nenhuma integração bancária com código de ' + 'Convênio %s ' % self.codigo_convenio) + + if len(payment_mode) > 1: + raise exceptions.Warning( + 'Código de Convênio em duplicidade nas integrações bancárias') + + if arquivo_parser.header.cedente_conta != \ + int(payment_mode.bank_id.acc_number): + raise exceptions.Warning( + 'Conta do beneficiário não encontrado no payment_mode.') + + self.payment_mode_id = payment_mode + self.num_lotes = arquivo_parser.trailer.totais_quantidade_lotes + self.num_eventos = arquivo_parser.trailer.totais_quantidade_registros + + data_arquivo = str(arquivo_parser.header.arquivo_data_de_geracao) + self.data_arquivo = fields.Date.from_string( + data_arquivo[4:] + "-" + data_arquivo[2:4] + "-" + + data_arquivo[0:2] + ) + + # Nome do arquivo + self.name = str(arquivo_parser.header.arquivo_sequencia) + \ + ' Retorno de ' + payment_mode.tipo_pagamento + ' ' + \ + data.formata_data(self.data_arquivo) + + # Busca o cedente/beneficiario do arquivo baseado no numero da conta + self.bank_account_id = self.env['res.partner.bank'].search( + [('acc_number', '=', arquivo_parser.header.cedente_conta)]).id + + + for lote in arquivo_parser.lotes: + # Busca o beneficiario do lote baseado no numero da conta + account_bank_id_lote = self.env['res.partner.bank'].search( + [('acc_number', '=', lote.header.cedente_conta)] + ).id + + vals = { + 'account_bank_id': account_bank_id_lote, + 'empresa_inscricao_numero': + str(lote.header.empresa_inscricao_numero), + 'empresa_inscricao_tipo': + TIPO_INSCRICAO_EMPRESA[lote.header.empresa_inscricao_tipo], + 'servico_operacao': + TIPO_OPERACAO[lote.header.servico_operacao], + 'tipo_servico': TIPO_SERVICO[str(lote.header.servico_servico)], + 'mensagem': lote.header.mensagem1, + 'qtd_registros': lote.trailer.quantidade_registros, + 'total_valores': float(lote.trailer.somatoria_valores), + 'cnab_id': self.id, + } + + lote_id = self.env['financial.retorno.bancario.lote'].create(vals) + + for evento in lote.eventos: + + data_evento = str(evento.credito_data_real) + data_evento = fields.Date.from_string( + data_evento[4:] + "-" + data_evento[2:4] + "-" + + data_evento[0:2] + ) + + # Busca a conta do benefiario do evento baseado em sua conta + account_bank_id_lote = 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), + ]) + account_bank_id_lote = account_bank_id_lote.ids[0] \ + if account_bank_id_lote else False + + account_bank_id_infos = \ + 'Agência: ' + str(evento.favorecido_agencia) + \ + '-' + str(evento.favorecido_agencia_dv) + \ + '\nConta: ' + str(evento.favorecido_conta) + \ + '-' + str(evento.favorecido_conta_dv) + + favorecido_partner_id = self.env['res.partner.bank'].search( + [('owner_name', 'ilike', evento.favorecido_nome)] + ) + favorecido_partner_id = favorecido_partner_id[0].partner_id.id \ + if favorecido_partner_id else False + + # Busca o bank payment line relativo à remessa enviada + 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': evento.favorecido_nome, + 'favorecido_partner_id': favorecido_partner_id, + 'favorecido_conta_bancaria': account_bank_id_infos, + 'favorecido_conta_bancaria_id': account_bank_id_lote, + '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, + 'cnab_id': self.id, + } + self.env['financial.retorno.bancario.evento'].create(vals_evento) + if evento.ocorrencias and bank_payment_line_id: + if '00' in ocorrencias: + bank_payment_line_id.write({'state2': 'paid'}) + else: + bank_payment_line_id.write({'state2': 'exception'}) + + return self.write({'state': 'done'}) + + # @api.multi + # def _get_name(self, data): + # cnab_ids = self.search([('data', '=', data)]) + # return data + " - " + ( + # str(len(cnab_ids) + 1) if cnab_ids else '1' + # ) + # + # @api.model + # def create(self, vals): + # name = self._get_name(vals['data']) + # vals.update({'name': name}) + # return super(FinancialRetornoBancario, self).create(vals) + + +class FinancialRetornoBancarioLote(models.Model): + _name = b'financial.retorno.bancario.lote' + + empresa_inscricao_numero = fields.Char(string=u"Número de Inscrição") + empresa_inscricao_tipo = fields.Char(string=u"Tipo de Inscrição") + servico_operacao = fields.Char(string=u"Tipo de Operação") + tipo_servico = fields.Char(strin=u"Tipo do Serviço") + mensagem = fields.Char(string="Mensagem") + qtd_registros = fields.Integer(string="Quantidade de Registros") + total_valores = fields.Float(string="Valor Total") + + account_bank_id = fields.Many2one( + string=u"Conta Bancária", + comodel_name="res.partner.bank", + ) + + evento_id = fields.One2many( + string="Eventos", + comodel_name="financial.retorno.bancario.evento", + inverse_name="lote_id", + ) + + cnab_id = fields.Many2one( + string="CNAB", + comodel_name="financial.retorno.bancario" + ) + + state = fields.Selection( + string="State", + related="cnab_id.state", + selection=STATE, + default="draft", + ) + + +class FinancialRetornoBancarioEvento(models.Model): + _name = b'financial.retorno.bancario.evento' + + data_real_pagamento = fields.Date(string='Data Real do Pagamento') + + segmento = fields.Char(string='Segmento') + + nosso_numero = fields.Char(string=u'Nosso Número') + + seu_numero = fields.Char(string=u'Seu Número') + + tipo_moeda = fields.Char(string=u'Tipo de Moeda') + + valor_pagamento = fields.Float(string='Valor do Pagamento') + + ocorrencias = fields.Char(string=u'Ocorrências') + + str_motiv_a = fields.Char(u'Motivo da ocorrência 01') + str_motiv_b = fields.Char(u'Motivo de ocorrência 02') + str_motiv_c = fields.Char(u'Motivo de ocorrência 03') + str_motiv_d = fields.Char(u'Motivo de ocorrência 04') + str_motiv_e = fields.Char(u'Motivo de ocorrência 05') + + state = fields.Selection( + string='State', + related='lote_id.state', + selection=STATE, + default='draft', + ) + + favorecido_nome = fields.Char(string='Nome Favorecido') + + favorecido_partner_id = fields.Many2one( + string="Favorecido", + comodel_name="res.partner" + ) + + favorecido_conta_bancaria_id = fields.Many2one( + string='Conta Bancária', + comodel_name='res.partner.bank', + ) + + favorecido_conta_bancaria = fields.Char(string='Conta Bancária') + + bank_payment_line_id = fields.Many2one( + string='Bank Payment Line', + comodel_name='bank.payment.line', + ) + + lote_id = fields.Many2one( + string='Lote', + comodel_name='financial.retorno.bancario.lote', + ) + + cnab_id = fields.Many2one( + string="CNAB", + comodel_name="financial.retorno.bancario" + ) diff --git a/l10n_br_financial_payment_order/models/hr_payslip.py b/l10n_br_financial_payment_order/models/hr_payslip.py new file mode 100644 index 0000000..1ae26d2 --- /dev/null +++ b/l10n_br_financial_payment_order/models/hr_payslip.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import api, fields, models, _ +from openerp.exceptions import Warning as UserError + + +class HrPayslip(models.Model): + + _inherit = 'hr.payslip' + + payment_mode_id = fields.Many2one( + string="Payment Mode", + comodel_name='payment.mode', + # domain="[('type', '=', type)]" + ) + + payment_line_ids = fields.One2many( + string="Ordens de Pagamento", + comodel_name="payment.line", + inverse_name="payslip_id", + ) + + paid_order = fields.Boolean( + compute='_compute_paid', + readonly=True, + store=True, + ) + + @api.multi + def test_paid(self): + if not self.payment_line_ids: + return False + for line in self.payment_line_ids: + if not line.state2: + return False + if line.state2 != 'paid': + return False + return True + + @api.one + @api.depends('payment_line_ids.bank_line_id.state2') + def _compute_paid(self): + self.paid_order = self.test_paid() + + @api.multi + def action_done(self): + self.write({'state': 'done'}) + return True + + def create_payorder(self, mode_payment): + ''' + Cria um payment order com base no metodo de pagamento + :param mode_payment: Modo de pagamento + :return: objeto do payment.order + ''' + payment_order_model = self.env['payment.order'] + vals = {'mode': mode_payment.id, } + return payment_order_model.create(vals) + + @api.multi + def create_payment_order_line( + self, payment_order, total, communication, partner_id): + """ + Cria a linha da ordem de pagamento + """ + payment_line_model = self.env['payment.line'] + vals = { + 'order_id': payment_order.id, + 'bank_id': self.contract_id.conta_bancaria_id.id, + 'partner_id': partner_id.id, + # 'move_line_id': self.id, + 'communication': communication, + # 'communication_type': communication_type, + # 'currency_id': currency_id, + 'amount_currency': total, + # date is set when the user confirms the payment order + 'payslip_id': self.id, + } + return payment_line_model.create(vals) + + @api.multi + def create_payment_order(self): + + payment_order_model = self.env['payment.order'] + + for holerite in self: + if holerite.state != 'draft': + raise UserError(_( + "The payslip %s is not in Open state") % + holerite.contract_id.nome_contrato) + if not holerite.payment_mode_id: + raise UserError(_( + "No Payment Mode on holerite %s") % holerite.number) + + # Buscar ordens de pagamento do mesmo tipo + payorders = payment_order_model.search([ + ('mode', '=', holerite.payment_mode_id.id), + ('state', '=', 'draft')] + ) + + if payorders: + payorder = payorders[0] + else: + payorder = self.create_payorder(holerite.payment_mode_id) + + for rubrica in holerite.line_ids: + if rubrica.code == 'LIQUIDO': + self.create_payment_order_line( + payorder, rubrica.total, + 'SALARIO ' + holerite.data_mes_ano, rubrica.partner_id) + + if rubrica.code == 'PENSAO_ALIMENTICIA': + self.create_payment_order_line( + payorder, rubrica.total, + 'PENSAO ALIMENTICIA ' + holerite.data_mes_ano, + rubrica.partner_id) diff --git a/l10n_br_financial_payment_order/models/inherited_financial_document_type.py b/l10n_br_financial_payment_order/models/inherited_financial_document_type.py new file mode 100644 index 0000000..62e8da9 --- /dev/null +++ b/l10n_br_financial_payment_order/models/inherited_financial_document_type.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import api, fields, models, _ + + +from ..constantes import TIPO_SERVICO, TIPO_SERVICO_COMPLEMENTO, \ + FORMA_LANCAMENTO, BOLETO_ESPECIE + + +class FinancialDocumentType(models.Model): + _inherit = b'financial.document.type' + + # + # Integração bancária via CNAB + # + tipo_servico = fields.Selection( + selection=TIPO_SERVICO, + string='Tipo de serviço', + help='Campo G025 do CNAB' + ) + tipo_servico_complemento = fields.Selection( + selection=TIPO_SERVICO_COMPLEMENTO, + string='Complemento do tipo de serviço', + help='Campo P005 do CNAB' + ) + forma_lancamento = fields.Selection( + selection=FORMA_LANCAMENTO, + string='Forma de lançamento', + help='Campo G029 do CNAB' + ) + boleto_especie = fields.Selection( + string='Espécie do Título', + selection=BOLETO_ESPECIE, + ) \ No newline at end of file diff --git a/l10n_br_financial_payment_order/models/inherited_financial_move.py b/l10n_br_financial_payment_order/models/inherited_financial_move.py new file mode 100644 index 0000000..19a661e --- /dev/null +++ b/l10n_br_financial_payment_order/models/inherited_financial_move.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import api, fields, models, _ + +from pybrasil.febraban import (valida_codigo_barras, valida_linha_digitavel, + identifica_codigo_barras, monta_linha_digitavel, monta_codigo_barras, + formata_linha_digitavel) + +import base64 + +from ..febraban.boleto.document import Boleto +from ..febraban.boleto.document import BoletoException + +from datetime import date +import logging +_logger = logging.getLogger(__name__) + + +from ..constantes import TIPO_SERVICO, TIPO_SERVICO_COMPLEMENTO, \ + FORMA_LANCAMENTO, BOLETO_ESPECIE + + +class FinancialMove(models.Model): + _inherit = b'financial.move' + + # + # Integração bancária via CNAB + # + payment_mode_id = fields.Many2one( + comodel_name='payment.mode', + string='Carteira de cobrança', + ondelete='restrict', + ) + tipo_pagamento = fields.Selection( + related='payment_mode_id.tipo_pagamento', + store=True + ) + # + # Implementa o nosso número como NUMERIC no Postgres, pois alguns + # bancos têm números bem grandes, que não dão certo com integers + # + nosso_numero = fields.Float( + string='Nosso número', + digits=(21, 0), + ) + # + # Para pagamentos automatizados de boletos de terceiros + # + boleto_linha_digitavel = fields.Char( + string='Linha digitável', + size=55, + ) + boleto_codigo_barras = fields.Char( + string='Código de barras', + size=44, + ) + + def _trata_linha_digitavel(self): + self.ensure_one() + + if not self.boleto_linha_digitavel: + return + + # + # Foi informado o número via leitura do codigo de barras? + # + if valida_codigo_barras(self.boleto_linha_digitavel): + codigo_barras = self.boleto_linha_digitavel + linha_digitavel = monta_linha_digitavel(codigo_barras) + # + # Ou foi informado via digitação mesmo? + # + elif valida_linha_digitavel(self.boleto_linha_digitavel): + codigo_barras = monta_codigo_barras(self.boleto_linha_digitavel) + linha_digitavel = \ + formata_linha_digitavel(self.boleto_linha_digitavel) + + else: + return + #raise código inválido + + identificacao = identifica_codigo_barras(codigo_barras) + + if identificacao is None: + return + #raise código inválido + + self.boleto_linha_digitavel = linha_digitavel + self.boleto_codigo_barras = codigo_barras + + if 'valor' in identificacao: + self.amount_document = identificacao['valor'] + + if 'vencimento' in identificacao and \ + identificacao['vencimento'] is not None: + self.date_maturity = str(identificacao['vencimento']) + + @api.multi + @api.onchange('boleto_linha_digitavel') + def _onchange_linha_digitavel(self): + for move in self: + move._trata_linha_digitavel() + + @api.multi + @api.depends('boleto_linha_digitavel') + def _depends_linha_digitavel(self): + for move in self: + move._trata_linha_digitavel() + + @api.multi + def button_boleto(self): + self.ensure_one() + return self.env['report'].get_action( + self, b'l10n_br_financial_payment_order.report') + + @api.multi + def gera_boleto(self): + + boleto_list = [] + + for financial_move in self: + try: + + # if True: + # if financial_move.payment_mode_id.type_payment == '00': + # number_type = financial_move.company_id.own_number_type + # if not financial_move.boleto_own_number: + # if number_type == '0': + # nosso_numero = self.env['ir.sequence'].next_by_id( + # financial_move.company_id.own_number_sequence.id) + # elif number_type == '1': + # nosso_numero = \ + # financial_move.transaction_ref.replace('/', '') + # else: + # nosso_numero = self.env['ir.sequence'].next_by_id( + # financial_move.payment_mode_id. + # internal_sequence_id.id) + # else: + # nosso_numero = financial_move.boleto_own_number + + seq_id = \ + financial_move.payment_mode_id.\ + sequence_nosso_numero_id.id + nosso_numero = str(int(self.nosso_numero)) or \ + self.env['ir.sequence'].next_by_id(seq_id) + + + boleto = Boleto.getBoleto(financial_move, nosso_numero) + + if boleto: + # financial_move.date_payment_created = date.today() + # financial_move.transaction_ref = \ + # boleto.boleto.format_nosso_numero() + financial_move.nosso_numero = nosso_numero + + boleto_list.append(boleto.boleto) + except BoletoException as be: + _logger.error(be.message or be.value, exc_info=True) + continue + except Exception as e: + _logger.error(e.message or e.value, exc_info=True) + continue + return boleto_list diff --git a/l10n_br_financial_payment_order/models/inherited_payment_order.py b/l10n_br_financial_payment_order/models/inherited_payment_order.py new file mode 100644 index 0000000..aa4fe36 --- /dev/null +++ b/l10n_br_financial_payment_order/models/inherited_payment_order.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import models, fields, api, exceptions, workflow, _ +from openerp.exceptions import ValidationError +# from openerp.addons.l10n_br_hr_payroll.models.hr_payslip import TIPO_DE_FOLHA +from openerp.addons.financial.constants import ( + FINANCIAL_DEBT_2RECEIVE, + FINANCIAL_DEBT_2PAY, +) +from ..constantes import ( + TIPO_ORDEM_PAGAMENTO, + TIPO_ORDEM_PAGAMENTO_BOLETO, + TIPO_ORDEM_PAGAMENTO_PAGAMENTO, +) + + +class PaymentOrder(models.Model): + + _name = b'payment.order' + _inherit = ['payment.order', 'mail.thread', 'ir.needaction_mixin'] + + @api.multi + @api.depends('mode.nivel_aprovacao') + def _compute_nivel_aprovacao(self): + for record in self: + record.nivel_aprovacao = int(record.mode.nivel_aprovacao) + + @api.multi + @api.depends('mode.tipo_pagamento') + def _compute_financial_type(self): + for record in self: + if record.mode.tipo_pagamento == TIPO_ORDEM_PAGAMENTO_BOLETO: + record.financial_type = FINANCIAL_DEBT_2RECEIVE + else: + record.financial_type = FINANCIAL_DEBT_2PAY + + state = fields.Selection( + selection=[ + ('draft', 'Rascunho'), + ('waiting', 'Aguardando aprovação'), + ('waiting2', 'Aguardando segunda aprovação'), + ('open', 'Confirmado'), + ('generated', 'Arquivo gerado'), + ('done', 'Arquivo enviado ao banco'), # v10: uploaded + ('cancel', 'Cancel'), + ], + string='Status', + readonly=True, + copy=False, + default='draft', + track_visibility='onchange', + ) + tipo_pagamento = fields.Selection( + string="Tipos de Ordem de Pagamento", + selection=TIPO_ORDEM_PAGAMENTO, + help="Tipos de Ordens de Pagamento.", + states={'done': [('readonly', True)]}, + ) + tipo_exportacao = fields.Char( + string='Tipo de exportação', + related='mode.type.code', + size=64, + readonly=True, + ) + search_date_start = fields.Date( + string="De", + states={'draft': [('readonly', False)]}, + ) + search_date_stop = fields.Date( + string="Até", + states={'draft': [('readonly', False)]}, + ) + search_date_type = fields.Selection( + selection=[ + ('date_document', 'Documento'), + ('date_maturity', 'Vencimento'), + ('date_business_maturity', 'Vencimento útil'), + ('date_payment', 'Pagamento'), + ], + string="Data", + states={'draft': [('readonly', False)]}, + ) + search_financial_document_type_id = fields.Many2one( + comodel_name='financial.document.type', + string='Tipo de documento' + ) + nivel_aprovacao = fields.Integer( + compute='_compute_nivel_aprovacao', + + ) + financial_type = fields.Selection( + selection=[ + (FINANCIAL_DEBT_2RECEIVE,'A receber'), + (FINANCIAL_DEBT_2PAY, 'A pagar'), + ], + compute='_compute_financial_type', + ) + + @api.multi + def action_open(self): + """ + Validacao ao confirmar ordem: + """ + for record in self: + if not record.line_ids: + raise ValidationError( + _("Impossivel confirmar linha vazia!")) + res = super(PaymentOrder, self).action_open() + return res + + @api.multi + def cancel(self): + for line in self.line_ids: + if line.payslip_id: + line.write({'payslip_id': ''}) + self.write({'state': 'cancel'}) + return True + + @api.multi + def _prepare_financial_payment_line(self, line): + """This function is designed to be inherited + The resulting dict is passed to the create method of payment.line""" + + self.ensure_one() + _today = fields.Date.context_today(self) + date_to_pay = False # no payment date => immediate payment + + if self.date_prefered == 'due': + # + # Caso a data preferida seja a data de vencimento + # + + # + # TODO: Verificar o que fazer com lançamentos vencidos + # + + date_to_pay = ( + line.date_maturity + if line.date_maturity and line.date_maturity > _today + else False) + + elif self.date_prefered == 'fixed': + # + # Caso da data preferida seja uma data fixa e esta data seja maior + # que a data de hoje. + # + date_to_pay = ( + self.date_scheduled + if self.date_scheduled and self.date_scheduled > _today + else False) + + state = 'normal' + communication = line.document_number or '-' + # communication = line.ref or '-' + # TODO: + # - Implementar novamente o campo ref? Pois o display name pode + # ser alterado + # - Como devemos lidar com um deposito identificado? + # - Podemos inserir com uma moeda diferente da ordem de pagamento? + # + + amount_currency = line.amount_residual + + # TODO: Devemos expressar o valor com sinal negativo em alguns casos? + # if self.payment_order_type == 'debit': + # amount_currency *= -1 + # + + # + # Método para buscar a conta bancária aplicável a operação: + # - Exemplo de um caso de uso possível: + # - O funcionário tem 2 contas, mas ao receber o seu salário, + # o valor deve ser depositado na conta salário + + # line2bank = line.line2bank(self.mode.id) + + res = { + 'financial_id': line.id, + 'amount_currency': amount_currency, + # 'bank_id': line2bank.get(line.id), + 'order_id': self.id, + 'partner_id': line.partner_id and line.partner_id.id or False, + 'communication': communication, + 'state': state, + 'date': date_to_pay, + 'currency': (line.currency_id and line.currency_id.id or + line.journal_id.currency.id or + line.journal_id.company_id.currency_id.id) + } + return res + + @api.multi + def filter_financial_lines(self, lines): + """ Filter move lines before proposing them for inclusion + in the payment order. + + This implementation filters out financial lines that are already + included in draft or open payment orders. This prevents the + user to include the same line in two different open payment + orders. + + See also https://github.com/OCA/bank-payment/issues/93. + + :param lines: recordset of move lines + :returns: list of move line ids + """ + self.ensure_one() + to_exclude = self.env['payment.line']. \ + search([('order_id.state', 'in', ('draft', 'open')), + ('financial_id', 'in', lines.ids)]).mapped('financial_id') + + # TODO: Verificar quando podemos incluir duas vezes um financial_move. + + return lines - to_exclude + + @api.multi + def extend_payment_order_domain(self, domain): + self.ensure_one() + + domain += [ + ('company_id', '=', self.company_id.id), + # ('amount_residual', '>', 0), # FIXME + ] + + if self.search_date_start: + domain += [ + (self.search_date_type, '>=', self.search_date_start), + ] + if self.search_date_stop: + domain += [ + (self.search_date_type, '<=', self.search_date_stop), + ] + if self.search_financial_document_type_id: + domain += [ + ('document_type_id', '=', + self.search_financial_document_type_id.id), + ] + if self.mode.tipo_pagamento == TIPO_ORDEM_PAGAMENTO_BOLETO: + domain += [ + ('payment_mode_id', '=', self.mode.id), + ('type', '=', FINANCIAL_DEBT_2RECEIVE), + ] + elif self.mode.tipo_pagamento == TIPO_ORDEM_PAGAMENTO_PAGAMENTO: + domain += [ + ('type', '=', FINANCIAL_DEBT_2PAY), + ] + else: + raise NotImplemented + + @api.one + def financial_payment_import(self): + """ A importação de lançamentos financeiros nas payment orders + funciona da seguinte maneira: + + 1. Prepara o dominio de busca: extend_payment_order_domain + 2. Realiza a busca + 3. Filtrar os registros já inseridos em payment.orders: + filter_financial_lines + 4. Preparar: Prepara os dados para inclusão: + _prepare_financial_payment_line + 5. Criar + + :return: + """ + + self.line_ids.unlink() + + domain = [] + + self.extend_payment_order_domain(domain) + lines = self.env['financial.move'].search(domain) + filtered_lines = self.filter_financial_lines(lines) + + for line in filtered_lines: + vals = self._prepare_financial_payment_line(line) + self.line_ids.create(vals) + + return + + @api.multi + def gera_financeiro_remessa(self): + for record in self: + if len(record.line_ids) == 1: + partner = record.line_ids[0].partner_id + else: + partner = record.company_id.partner_id + + date = record.date_scheduled + + dados = { + 'date_document': record.date_done, + 'partner_id': partner.id, + 'company_id': record.company_id.id, + 'doc_source_id': 'payment.order,' + str(record.id), + 'currency_id': record.company_id.currency_id.id, + # 'payment_order_id': record.id, + 'document_type_id': + record.mode.remessa_document_type_id.id, + 'account_id': record.mode.remessa_financial_account_id.id, + 'date_maturity': date, + 'amount_document': record.total, + 'document_number': + '{0.name}-{1.reference}-({2})'.format( + record.mode, record, + unicode(len(record.line_ids))), + 'payment_mode_id': record.mode.id, + 'type': record.financial_type, + } + + finacial_move_id = self.env['financial.move'].create(dados) + # TODO: Melhorar este metodo! + + @api.multi + def action_done(self): + result = super(PaymentOrder, self).action_done() + + # for record in self: + # if record.state == 'done' and record.mode.gera_financeiro_remessa: + # record.gera_financeiro_remessa() + return True + + @api.multi + def launch_wizard(self): + """Search for a wizard to launch according to the type. + If type is manual. just confirm the order. + Previously (pre-v6) in account_payment/wizard/wizard_pay.py + """ + context = self.env.context.copy() + order = self[0] + # check if a wizard is defined for the first order + if order.mode.type and order.mode.type.ir_model_id: + context['active_ids'] = self.ids + wizard_model = order.mode.type.ir_model_id.model + wizard_obj = self.env[wizard_model] + return { + 'name': wizard_obj._description or _('Payment Order Export'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': wizard_model, + 'domain': [], + 'context': context, + 'type': 'ir.actions.act_window', + 'target': 'new', + 'nodestroy': True, + } + else: + # should all be manual orders without type or wizard model + for order in self[1:]: + if order.mode.type and order.mode.type.ir_model_id: + raise exceptions.Warning( + _('Error'), + _('You can only combine payment orders of the same ' + 'type')) + # process manual payments + for order_id in self.ids: + workflow.trg_validate(self.env.uid, 'payment.order', + order_id, 'generated', self.env.cr) + return {} + + @api.multi + def buscar_holerites_wizard(self): + context = dict(self.env.context) + context.update({ + 'active_id': self.id, + }) + form = self.env.ref( + 'l10n_br_financial_payment_order.' + 'payslip_payment_create_order_view', + True + ) + return { + 'view_type': 'form', + 'view_id': [form.id], + 'view_mode': 'form', + 'res_model': 'payslip.payment.order.created', + 'views': [(form.id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + 'context': context, + } diff --git a/l10n_br_financial_payment_order/models/operacoes/__init__.py b/l10n_br_financial_payment_order/models/operacoes/__init__.py new file mode 100644 index 0000000..d4d9eaf --- /dev/null +++ b/l10n_br_financial_payment_order/models/operacoes/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import cobranca diff --git a/l10n_br_financial_payment_order/models/operacoes/cobranca.py b/l10n_br_financial_payment_order/models/operacoes/cobranca.py new file mode 100644 index 0000000..bc89d09 --- /dev/null +++ b/l10n_br_financial_payment_order/models/operacoes/cobranca.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import api, fields, models, _ +from openerp.exceptions import ValidationError +from openerp.addons.financial.constants import FINANCIAL_DEBT_2RECEIVE + + +class PaymentOrder(models.Model): + _inherit = b'payment.order' + + # @api.one + # def financial_payment_import(self): + # self.ensure_one() + # + # if self.tipo_pagamento == 'cobranca': + # financial_move_ids = self.env['financial.move'].search([ + # ('company_id', '=', self.company_id.id), + # ('type', '=', FINANCIAL_DEBT_2RECEIVE), + # ('payment_mode_id', '=', self.mode.id), + # # ('document_type_id', '=', ) + # ]) + # + # print (financial_move_ids) + # + # result = super(PaymentOrder, self).financial_payment_import() + # + # return result \ No newline at end of file diff --git a/l10n_br_financial_payment_order/models/payment_line.py b/l10n_br_financial_payment_order/models/payment_line.py new file mode 100644 index 0000000..ce688ba --- /dev/null +++ b/l10n_br_financial_payment_order/models/payment_line.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + + +from openerp import api, fields, models, _ +from openerp.addons.l10n_br_financial_payment_order.models.bank_payment_line \ + import STATE + + + + +class PaymentLine(models.Model): + _inherit = b'payment.line' + + # @api.one + # @api.depends('percent_interest', 'amount_currency') + # def _compute_interest(self): + # precision = self.env['decimal.precision'].precision_get('Account') + # self.amount_interest = round(self.amount_currency * + # (self.percent_interest / 100), + # precision) + + def _get_payment_line_reference(self): + return [ + ( + self.env['financial.move']._name, + self.env['financial.move']._description + ), + ] + + @api.multi + @api.depends('financial_id') + def _compute_reference_id(self): + + for record in self: + if record.financial_id: + record.reference_id = ( + record.financial_id._name + + ',' + + str(record.financial_id.id) + ) + + amount_other_discounts = fields.Float( + string='Valor Abatimento', + ) + amount_discount = fields.Float( + string='Valor Desconto', + ) + amount_interest = fields.Float( + string='Valor Mora', + ) + amount_penalty = fields.Float( + string='Valor Multa', + ) + # TODO: Definir campos do segmento P/Q/R/T/U + payslip_id = fields.Many2one( + string="Ref do Holerite", + comodel_name="hr.payslip", + ) + linha_digitavel = fields.Char(string=u"Linha Digitável") + state2 = fields.Selection( + related="bank_line_id.state2", + selection=STATE, + default="draft", + ) + + reference_id = fields.Reference( + compute='_compute_reference_id', + selection=_get_payment_line_reference, + string='Origem' + ) + + financial_id = fields.Many2one( + comodel_name='financial.move', + string="Financeiro", + ) + fn_date_document = fields.Date( + related='financial_id.date_document', + string="Criação", + readonly=True, + ) + fn_date_maturity = fields.Date( + related='financial_id.date_maturity', + string='Vencimento', + readonly=True, + ) + fn_date_business_maturity = fields.Date( + related='financial_id.date_business_maturity', + string='Vencimento útil', + readonly=True, + ) + fn_boleto_linha_digitavel = fields.Char( + related='financial_id.boleto_linha_digitavel', + string='Linha digitável', + readonly=True, + ) + fb_boleto_codigo_barras = fields.Char( + related='financial_id.boleto_codigo_barras', + string='Código de barras', + readonly=True, + ) + fn_nosso_numero = fields.Float( + string='Nosso número', + related='financial_id.nosso_numero', + ) + + + def _get_info_partner(self, cr, uid, partner_record, context=None): + # TODO: Melhorar este método + if not partner_record: + return False + st = partner_record.street or '' + n = partner_record.number or '' + st1 = partner_record.street2 or '' + zip = partner_record.zip or '' + city = partner_record.l10n_br_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 + diff --git a/l10n_br_financial_payment_order/models/payment_mode.py b/l10n_br_financial_payment_order/models/payment_mode.py new file mode 100644 index 0000000..1ed1654 --- /dev/null +++ b/l10n_br_financial_payment_order/models/payment_mode.py @@ -0,0 +1,249 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import api, fields, models, _ + +# from ..constantes import TIPO_SERVICO, FORMA_LANCAMENTO, \ +# TIPO_SERVICO_COMPLEMENTO, CODIGO_FINALIDADE_TED, AVISO_FAVORECIDO, \ +# INSTRUCAO_MOVIMENTO, TIPO_ORDEM_PAGAMENTO, \ +# BOLETO_ESPECIE, BOLETO_ESPECIE_DUPLICATA_MERCANTIL, \ +# BOLETO_EMISSAO, BOLETO_EMISSAO_BENEFICIARIO, \ +# BOLETO_ENTREGA, BOLETO_ENTREGA_BENEFICIARIO +from ..constantes import * + + +class PaymentMode(models.Model): + ''' + O objetivo deste model é gerenciar as interações do módulo + financeiro com o sistema bancário brasileiro, no que toca + a troca dos chamados arquivos padrão CNAB, tratando de + arquivos de cobrança (vindos do contas a receber, os boletos), + e várias modalidades de pagamento (vindos do contas a pagar) + ''' + _inherit = b'payment.mode' + + # + # Primeiro, removemos o vínculo fixo da classe com o módulo original + # account + # + journal = fields.Many2one( + required=False, + ) + + # + # Campos comuns a todas ou pelo menos a maioria dos tipos de arquivo + # + tipo_pagamento = fields.Selection( + string='Tipos da ordem de pagamento', + selection=TIPO_ORDEM_PAGAMENTO, + help='Tipos de Ordens de Pagamento.', + ) + tipo_servico = fields.Selection( + selection=TIPO_SERVICO, + string='Tipo de serviço', + help='Campo G025 do CNAB' + ) + tipo_servico_complemento = fields.Selection( + selection=TIPO_SERVICO_COMPLEMENTO, + string='Complemento do tipo de serviço', + help='Campo P005 do CNAB' + ) + forma_lancamento = fields.Selection( + selection=FORMA_LANCAMENTO, + string='Forma de lançamento', + help='Campo G029 do CNAB' + ) + convenio = fields.Char( + string='Convênio', + size=20, + help='Campo G007 do CNAB', + ) + instrucao_movimento = fields.Selection( + selection=INSTRUCAO_MOVIMENTO, + string='Instrução para Movimento', + help='Campo G061 do CNAB', + default=INSTRUCAO_MOVIMENTO_INCLUSAO_DETALHE_LIBERADO, + ) + aviso_favorecido = fields.Selection( + selection=AVISO_FAVORECIDO, + string='Aviso ao favorecido', + help='Campo P006 do CNAB', + default=0, + ) + finalidade_ted = fields.Selection( + selection=CODIGO_FINALIDADE_TED, + string='Finalidade da TED', + help='Campo P011 do CNAB' + ) + finalidade_complementar = fields.Char( + string='Finalidade complementar', + size=2, + help='Campo P013 do CNAB', + ) + + # + # Controle dos arquivos e nossos números + # + sufixo_arquivo = fields.Integer( + string='Sufixo do arquivo', + ) + sequence_arquivo_id = fields.Many2one( + comodel_name='ir.sequence', + string='Sequência do arquivo', + ) + sequence_arquivo_proximo_numero = fields.Integer( + related='sequence_arquivo_id.number_next_actual', + string='Próximo número do arquivo', + ) + sequence_nosso_numero_id = fields.Many2one( + comodel_name='ir.sequence', + string='Sequência do Nosso Número', + ) + sequence_nosso_numero_proximo_numero = fields.Integer( + string='Próximo nosso número', + related='sequence_nosso_numero_id.number_next_actual', + ) + + # + # Campos antigos que agora são calculados + # + sale_ok = fields.Boolean( + compute='_compute_sale_purchase_ok', + ) + purchase_ok = fields.Boolean( + compute='_compute_sale_purchase_ok', + ) + + # + # Configurações para emissão de boleto + # + boleto_carteira = fields.Char( + string='Carteira', + size=3, + ) + boleto_modalidade = fields.Char( + string='Modalidade', + size=2, + ) + boleto_variacao = fields.Char( + string='Variação', + size=2, + ) + boleto_codigo_cnab = fields.Char( + string='Código Cnab', + size=20, + ) + # boleto_protesto = fields.Selection([ + # ('0', 'Sem instrução'), + # ('1', 'Protestar (Dias Corridos)'), + # ('2', 'Protestar (Dias Úteis)'), + # ('3', 'Não protestar'), + # ('7', 'Negativar (Dias Corridos)'), + # ('8', 'Não Negativar') + # ], string='Códigos de Protesto', default='0') + boleto_dias_protesto = fields.Integer( + string='Dias para protesto', + ) + boleto_aceite = fields.Selection( + string='Aceite', + selection=[('S', 'Sim'), ('N', 'Não')], + default='N', + ) + boleto_especie = fields.Selection( + string='Espécie do Título', + selection=BOLETO_ESPECIE, + default=BOLETO_ESPECIE_DUPLICATA_MERCANTIL, + ) + boleto_emissao = fields.Selection( + selection=BOLETO_EMISSAO, + string='Emissão', + default=BOLETO_EMISSAO_BENEFICIARIO, + ) + boleto_entrega = fields.Selection( + selection=BOLETO_DISTRIBUICAO, + string='Entrega', + default=BOLETO_DISTRIBUICAO_BENEFICIARIO, + ) + nivel_aprovacao = fields.Selection( + selection=[ + ('0', 'Nenhuma / Aprovar e gerar o arquivo'), + ('1', 'Uma aprovação'), + ('2', 'Duas aprovações'), + ], + required=True, + default='0', + ) + aprovacao_grupo_1 = fields.Many2one( + comodel_name='res.groups', + string='Grupo primeira aprovação' + ) + aprovacao_grupo_2 = fields.Many2one( + comodel_name='res.groups', + string='Grupo segunda aprovação' + ) + gera_financeiro_remessa = fields.Boolean( + string='Gerar lançamento financeiro ao processar a remessa', + ) + remessa_financial_account_id = fields.Many2one( + comodel_name='financial.account', + string='Conta financeira', + domain=[('type', '=', 'A')], + ) + remessa_document_type_id = fields.Many2one( + comodel_name='financial.document.type', + string='Tipo de documento', + ) + gera_financeiro_retorno = fields.Boolean( + string='Gerar lançamento financeiro ao processar o retorno', + ) + retorno_financial_account_id = fields.Many2one( + comodel_name='financial.account', + string='Conta financeira', + domain=[('type', '=', 'A')], + ) + retorno_document_type_id = fields.Many2one( + comodel_name='financial.document.type', + string='Tipo de documento', + ) + + @api.depends('tipo_servico') + def _compute_sale_purchase_ok(self): + for payment_mode in self: + if payment_mode.tipo_servico in ['01']: + payment_mode.sale_ok = True + elif payment_mode.tipo_servico in ['03']: + payment_mode.purchase_ok = True + + @api.depends('tipo_servico') + def _onchange_tipo_servico(self): + for payment_mode in self: + if payment_mode.tipo_servico == TIPO_SERVICO_PAGAMENTO_FORNECEDOR: + payment_mode.tipo_servico_complemento = \ + TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_FORNECEDORES + + elif payment_mode.tipo_servico == TIPO_SERVICO_PAGAMENTO_SALARIOS: + payment_mode.tipo_servico_complemento = \ + TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_SALARIOS + + elif payment_mode.tipo_servico == \ + TIPO_SERVICO_PAGAMENTO_HONORARIOS: + payment_mode.tipo_servico_complemento = \ + TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_HONORARIOS + + elif payment_mode.tipo_servico == \ + TIPO_SERVICO_PAGAMENTO_BOLSA_AUXILIO: + payment_mode.tipo_servico_complemento = \ + TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_BOLSA_AUXILIO + + elif payment_mode.tipo_servico == \ + TIPO_SERVICO_PAGAMENTO_REMUNERACAO: + payment_mode.tipo_servico_complemento = \ + TIPO_SERVICO_COMPLEMENTO_REMUNERACAO_COOPERADO + + elif payment_mode.tipo_servico == \ + TIPO_SERVICO_PAGAMENTO_PREBENDA: + payment_mode.tipo_servico_complemento = \ + TIPO_SERVICO_COMPLEMENTO_PAGAMENTO_PREBENDA diff --git a/l10n_br_financial_payment_order/models/payment_mode_type.py b/l10n_br_financial_payment_order/models/payment_mode_type.py new file mode 100644 index 0000000..02e8c37 --- /dev/null +++ b/l10n_br_financial_payment_order/models/payment_mode_type.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import division, print_function, unicode_literals + +from openerp import api, fields, models, _ + +from ..constantes import TIPO_ORDEM_PAGAMENTO + + +class PaymentModeType(models.Model): + + _inherit = b'payment.mode.type' + + tipo_pagamento = fields.Selection( + string="Tipos de Ordem de Pagamento", + selection=TIPO_ORDEM_PAGAMENTO, + help="Tipos de Ordens de Pagamento.", + ) diff --git a/l10n_br_financial_payment_order/models/res_bank.py b/l10n_br_financial_payment_order/models/res_bank.py new file mode 100644 index 0000000..4cd58a3 --- /dev/null +++ b/l10n_br_financial_payment_order/models/res_bank.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import api, models + + +class ResBank(models.Model): + _inherit = 'res.bank' + + @api.multi + @api.constrains('bic') + def check_bic_length(self): + ''' + sobrescrever constrains do core que nao leva em consideração bancos + que nao são intenacionais. + ''' + return True diff --git a/l10n_br_financial_payment_order/models/res_partner_bank.py b/l10n_br_financial_payment_order/models/res_partner_bank.py new file mode 100644 index 0000000..2f7c685 --- /dev/null +++ b/l10n_br_financial_payment_order/models/res_partner_bank.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import api, models + + +class ResPartnerBank(models.Model): + _inherit = 'res.partner.bank' + + @api.multi + @api.constrains('bank_bic') + def check_bic_length(self): + ''' + sobrescrever constrains do core que não leva em consideração bancos + que nao são internacionais. + ''' + return True diff --git a/l10n_br_financial_payment_order/reports/__init__.py b/l10n_br_financial_payment_order/reports/__init__.py new file mode 100644 index 0000000..7203ec3 --- /dev/null +++ b/l10n_br_financial_payment_order/reports/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import report_boleto diff --git a/l10n_br_financial_payment_order/reports/report_boleto.py b/l10n_br_financial_payment_order/reports/report_boleto.py new file mode 100644 index 0000000..2c8d035 --- /dev/null +++ b/l10n_br_financial_payment_order/reports/report_boleto.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE INFORMATICA LTDA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import with_statement, unicode_literals + +from openerp import pooler +from openerp.osv import osv +from openerp.report.interface import report_int +from openerp.report.render import render + +from ..febraban.boleto.document import Boleto + +class ExternalPdf(render): + + def __init__(self, pdf): + render.__init__(self) + self.pdf = pdf + self.output_type = 'pdf' + + def _render(self): + return self.pdf + + +class ReportCustom(report_int): + """ + Custom report for return boletos + """ + + def create(self, cr, uid, ids, datas, context=False): + if not context: + context = {} + active_ids = context.get('active_ids') + active_model = context.get('active_model') + pool = pooler.get_pool(cr.dbname) + ids_financial_lines = [] + + financial_obj = pool.get('financial.move') + + if active_model == 'account.invoice': + ai_obj = pool.get('account.invoice') + for account_invoice in ai_obj.browse(cr, uid, active_ids): + for move_line in account_invoice.financial_ids: + ids_financial_lines.append(move_line.id) + elif active_model == 'financial.move': + ids_financial_lines = active_ids + else: + return False + + boleto_list = financial_obj.gera_boleto(cr, uid, ids_financial_lines) + if not boleto_list: + raise osv.except_osv( + 'Error !', ('Não é possível gerar os boletos\n' + 'Certifique-se que a fatura esteja confirmada e o ' + 'forma de pagamento seja duplicatas')) + pdf_string = Boleto.get_pdfs(boleto_list) + self.obj = ExternalPdf(pdf_string) + self.obj.render() + return self.obj.pdf, 'pdf' + + +ReportCustom('report.l10n_br_financial_payment_order.report') diff --git a/l10n_br_financial_payment_order/reports/report_boleto.xml b/l10n_br_financial_payment_order/reports/report_boleto.xml new file mode 100644 index 0000000..548ff13 --- /dev/null +++ b/l10n_br_financial_payment_order/reports/report_boleto.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/l10n_br_financial_payment_order/security/bank_payment_line.xml b/l10n_br_financial_payment_order/security/bank_payment_line.xml new file mode 100644 index 0000000..6cb5701 --- /dev/null +++ b/l10n_br_financial_payment_order/security/bank_payment_line.xml @@ -0,0 +1,20 @@ + + + + + + + + bank.payment.line access name + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/security/payment_line.xml b/l10n_br_financial_payment_order/security/payment_line.xml new file mode 100644 index 0000000..4f663de --- /dev/null +++ b/l10n_br_financial_payment_order/security/payment_line.xml @@ -0,0 +1,20 @@ + + + + + + + + payment.line access name + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/security/payment_mode.xml b/l10n_br_financial_payment_order/security/payment_mode.xml new file mode 100644 index 0000000..56f428d --- /dev/null +++ b/l10n_br_financial_payment_order/security/payment_mode.xml @@ -0,0 +1,20 @@ + + + + + + + + payment.mode access name + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/security/payment_mode_type.xml b/l10n_br_financial_payment_order/security/payment_mode_type.xml new file mode 100644 index 0000000..f30ad9f --- /dev/null +++ b/l10n_br_financial_payment_order/security/payment_mode_type.xml @@ -0,0 +1,20 @@ + + + + + + + + payment.mode.type access name + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/security/payment_order.xml b/l10n_br_financial_payment_order/security/payment_order.xml new file mode 100644 index 0000000..559abc8 --- /dev/null +++ b/l10n_br_financial_payment_order/security/payment_order.xml @@ -0,0 +1,20 @@ + + + + + + + + payment.order access name + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/static/description/icon.png b/l10n_br_financial_payment_order/static/description/icon.png new file mode 100644 index 0000000..3a0328b Binary files /dev/null and b/l10n_br_financial_payment_order/static/description/icon.png differ diff --git a/l10n_br_financial_payment_order/views/bank_payment_line.xml b/l10n_br_financial_payment_order/views/bank_payment_line.xml new file mode 100644 index 0000000..4a47644 --- /dev/null +++ b/l10n_br_financial_payment_order/views/bank_payment_line.xml @@ -0,0 +1,56 @@ + + + + + + + + bank.payment.line.form (in l10n_br_financial_payment_order) + bank.payment.line + + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/l10n_br_financial_payment_order/views/financial_move.xml b/l10n_br_financial_payment_order/views/financial_move.xml new file mode 100644 index 0000000..d5231ba --- /dev/null +++ b/l10n_br_financial_payment_order/views/financial_move.xml @@ -0,0 +1,21 @@ + + + + + + + + financial.move in (l10n_br_financial_payment_order) + financial.move + + + + + + + + diff --git a/l10n_br_financial_payment_order/views/financial_retorno_bancario.xml b/l10n_br_financial_payment_order/views/financial_retorno_bancario.xml new file mode 100644 index 0000000..6f17f0e --- /dev/null +++ b/l10n_br_financial_payment_order/views/financial_retorno_bancario.xml @@ -0,0 +1,195 @@ + + + + + + cnab.retorno.tree + financial.retorno.bancario + + + + + + + + + + + + + + cnab.lote.tree + financial.retorno.bancario.lote + + + + + + + + + + + + + + + + + cnab.evento.tree + financial.retorno.bancario.evento + + + + + + + + + + + + + + + + + + + + + + cnab.retorno.evento.form.view + financial.retorno.bancario.evento + +
+
+ +
+ + + + + /> + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cnab.retorno.form.view + financial.retorno.bancario + +
+
+
+ + +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Retorno + ir.actions.act_window + financial.retorno.bancario + form + tree,form + + + + +
+
\ No newline at end of file diff --git a/l10n_br_financial_payment_order/views/hr_payslip.xml b/l10n_br_financial_payment_order/views/hr_payslip.xml new file mode 100644 index 0000000..b1a7683 --- /dev/null +++ b/l10n_br_financial_payment_order/views/hr_payslip.xml @@ -0,0 +1,40 @@ + + + + + + + + hr.payslip.form (in l10n_br_hr_payment_order) + hr.payslip + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/views/inherited_financial_document_type_view.xml b/l10n_br_financial_payment_order/views/inherited_financial_document_type_view.xml new file mode 100644 index 0000000..4e7c437 --- /dev/null +++ b/l10n_br_financial_payment_order/views/inherited_financial_document_type_view.xml @@ -0,0 +1,32 @@ + + + + + + + financial.document.type.form (in l10n_br_financial_payment_order) + financial.document.type + 2 + + + + + + + + + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/views/inherited_financial_move_debt_2pay_view.xml b/l10n_br_financial_payment_order/views/inherited_financial_move_debt_2pay_view.xml new file mode 100644 index 0000000..7069efa --- /dev/null +++ b/l10n_br_financial_payment_order/views/inherited_financial_move_debt_2pay_view.xml @@ -0,0 +1,28 @@ + + + + + + + financial.move.debt.2pay.form (in l10n_br_financial_payment_order) + financial.move + 2 + + + + + + + + + + + + + + + diff --git a/l10n_br_financial_payment_order/views/payment_line.xml b/l10n_br_financial_payment_order/views/payment_line.xml new file mode 100644 index 0000000..614fd83 --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_line.xml @@ -0,0 +1,55 @@ + + + + + + + + payment.line.form (in l10n_br_financial_payment_order) + payment.line + + + +
+ +
+
+
+
+ + + payment.line.search (in l10n_br_financial_payment_order) + payment.line + + + + + + + + payment.line.tree (in l10n_br_financial_payment_order) + payment.line + + + + + + + + Payment Line + payment.line + tree,form + [] + {} + + + + Payment Line + + + + + +
+
diff --git a/l10n_br_financial_payment_order/views/payment_menu.xml b/l10n_br_financial_payment_order/views/payment_menu.xml new file mode 100644 index 0000000..f367310 --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_menu.xml @@ -0,0 +1,21 @@ + + + + + + Integração bancária + + + + + + Integração bancária + + + + + + diff --git a/l10n_br_financial_payment_order/views/payment_mode/payment_mode_base_view.xml b/l10n_br_financial_payment_order/views/payment_mode/payment_mode_base_view.xml new file mode 100644 index 0000000..4e9d47d --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_mode/payment_mode_base_view.xml @@ -0,0 +1,135 @@ + + + + + + + + payment.mode.base.tree (in l10n_br_financial_payment_mode) + payment.mode + 9999 + primary + + + + + + + + + + + payment.mode.base.form (in l10n_br_financial_payment_order) + payment.mode + 9999 + primary + +
+ +

+ +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + payment.mode.base.search (in l10n_br_financial_payment_order) + payment.mode + 9999 + primary + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/l10n_br_financial_payment_order/views/payment_mode/payment_mode_cobranca_view.xml b/l10n_br_financial_payment_order/views/payment_mode/payment_mode_cobranca_view.xml new file mode 100644 index 0000000..44c6c3e --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_mode/payment_mode_cobranca_view.xml @@ -0,0 +1,55 @@ + + + + + + + + payment.mode.cobranca.form (in l10n_br_financial_payment_order) + payment.mode + primary + + + + + + + + + + + + + + + Cobrança + payment.mode + tree,form + [('tipo_pagamento', '=', 'boleto'), ('tipo_servico', '=', '01')] + {'default_tipo_pagamento': 'boleto', 'default_tipo_servico': '01'} + + + + Cobrança + + + + + + + + form + + + + + + + tree + + + + + + diff --git a/l10n_br_financial_payment_order/views/payment_mode/payment_mode_pagamento_view.xml b/l10n_br_financial_payment_order/views/payment_mode/payment_mode_pagamento_view.xml new file mode 100644 index 0000000..5d46b5d --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_mode/payment_mode_pagamento_view.xml @@ -0,0 +1,51 @@ + + + + + + + + payment.mode.pagamento.form (in l10n_br_financial_payment_order) + payment.mode + primary + + + + + + + + + + + Pagamento + payment.mode + tree,form + [('tipo_pagamento', '=', 'pagamento'), ('tipo_servico', '=', '03')] + {'default_tipo_pagamento': 'pagamento', 'default_tipo_servico': '03'} + + + + Pagamentos + + + + + + + + form + + + + + + + tree + + + + + + diff --git a/l10n_br_financial_payment_order/views/payment_mode_type.xml b/l10n_br_financial_payment_order/views/payment_mode_type.xml new file mode 100644 index 0000000..117090c --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_mode_type.xml @@ -0,0 +1,51 @@ + + + + + + + + payment.mode.type.form (in l10n_br_financial_payment_order) + payment.mode.type + + + + + + + + payment.mode.type.search (in l10n_br_financial_payment_order) + payment.mode.type + + + + + + + + payment.mode.type.tree (in l10n_br_financial_payment_order) + payment.mode.type + + + + + + + + Payment Mode Type + payment.mode.type + tree,form + [] + {} + + + + Payment Mode Type + + + + + + + diff --git a/l10n_br_financial_payment_order/views/payment_order/payment_order_base_view.xml b/l10n_br_financial_payment_order/views/payment_order/payment_order_base_view.xml new file mode 100644 index 0000000..69c9d9a --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_order/payment_order_base_view.xml @@ -0,0 +1,169 @@ + + + + + + + + payment.order.base.tree (in l10n_br_financial_payment_order) + payment.order + 9999 + primary + + + + + + + + + + + + + + + + + payment.order.base.form (in l10n_br_financial_payment_order) + payment.order + 9999 + primary + +
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+ + + payment.order.base.search (in l10n_br_financial_payment_order) + payment.order + 9999 + primary + + + + + + + + + + + + + + + + + +
+
diff --git a/l10n_br_financial_payment_order/views/payment_order/payment_order_cobranca_view.xml b/l10n_br_financial_payment_order/views/payment_order/payment_order_cobranca_view.xml new file mode 100644 index 0000000..b78d681 --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_order/payment_order_cobranca_view.xml @@ -0,0 +1,86 @@ + + + + + + + + payment.order.cobranca.form (in l10n_br_financial_payment_order) + payment.order + primary + + + + Cobrança + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Remessa de cobrança + payment.order + tree,form + [('tipo_pagamento', '=', 'boleto')] + {'default_tipo_pagamento': 'boleto'} + + + + + Remessa de cobrança + + + + + + + + + form + + + + + + + tree + + + + + + diff --git a/l10n_br_financial_payment_order/views/payment_order/payment_order_pagamento_view.xml b/l10n_br_financial_payment_order/views/payment_order/payment_order_pagamento_view.xml new file mode 100644 index 0000000..f11a394 --- /dev/null +++ b/l10n_br_financial_payment_order/views/payment_order/payment_order_pagamento_view.xml @@ -0,0 +1,86 @@ + + + + + + + + payment.order.pagamento.form (in l10n_br_financial_payment_order) + payment.order + primary + + + + Pagamento + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Remessa de pagamento + payment.order + tree,form + [('tipo_pagamento', '=', 'pagamento')] + {'default_tipo_pagamento': 'pagamento'} + + + + Remessa de pagamento + + + + + + + + form + + + + + + + tree + + + + + + diff --git a/l10n_br_financial_payment_order/wizards/__init__.py b/l10n_br_financial_payment_order/wizards/__init__.py new file mode 100644 index 0000000..b9f6613 --- /dev/null +++ b/l10n_br_financial_payment_order/wizards/__init__.py @@ -0,0 +1,3 @@ +from . import ordem_pagamento_holerite +from . import bank_payment_manual +from . import l10n_bank_payment_cnab_export \ No newline at end of file diff --git a/l10n_br_financial_payment_order/wizards/bank_payment_manual.py b/l10n_br_financial_payment_order/wizards/bank_payment_manual.py new file mode 100644 index 0000000..2f325a3 --- /dev/null +++ b/l10n_br_financial_payment_order/wizards/bank_payment_manual.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +"""This module contains a single "wizard" for confirming manual +bank transfers. +""" + +from openerp import models, api, workflow + + +class PaymentManual(models.TransientModel): + _inherit = 'payment.manual' + _description = 'Send payment order(s) manually' + + @api.multi + def button_ok(self): + for order_id in self.env.context.get('active_ids', []): + workflow.trg_validate(self.env.uid, 'payment.order', order_id, + 'generated', self.env.cr) + return {'type': 'ir.actions.act_window_close'} diff --git a/l10n_br_financial_payment_order/wizards/l10n_bank_payment_cnab_export.py b/l10n_br_financial_payment_order/wizards/l10n_bank_payment_cnab_export.py new file mode 100644 index 0000000..55c5c5f --- /dev/null +++ b/l10n_br_financial_payment_order/wizards/l10n_bank_payment_cnab_export.py @@ -0,0 +1,107 @@ +# coding: utf-8 +# ########################################################################### +# +# Author: Luis Felipe Mileo +# Fernando Marcato Rodrigues +# Daniel Sadamo Hirayama +# Copyright 2015 KMEE - www.kmee.com.br +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import base64 +import time + +from openerp import models, api, workflow, fields, _ +from openerp.exceptions import Warning as UserError +from ..febraban.cnab import Cnab + +import logging + +_logger = logging.getLogger(__name__) +try: + from cnab240.errors import (Cnab240Error) +except ImportError as err: + _logger.debug = err + + +class L10nPaymentCnab(models.TransientModel): + _name = 'payment.cnab' + _description = 'Export payment order(s) in cnab layout' + + name = fields.Char(string=u'Nome', size=255) + + cnab_file = fields.Binary(string='CNAB File', readonly=True) + + state = fields.Selection( + string='state', + selection=[('init', 'init'), ('done', 'done')], + default='init', + readonly=True + ) + + @api.multi + def export(self): + for order_id in self.env.context.get('active_ids', []): + + order = self.env['payment.order'].browse(order_id) + if not order.line_ids: + raise UserError( + _('Error'), + _('Adicione pelo menos uma linha na ordem de pagamento.')) + + # Criando instancia do CNAB a partir do código do banco + cnab = Cnab.get_cnab( + order.mode.bank_id.bank_bic, order.mode.type.code)() + + # Criando remessa de eventos + try: + remessa = cnab.remessa(order) + except Cnab240Error as e: + from openerp import exceptions + raise exceptions.ValidationError( + "Campo preenchido incorretamente \n\n{0}".format(e)) + + if order.mode.type.code == '240': + self.name = 'CB%s%s.REM' % ( + time.strftime('%d%m'), + str(order.mode.sequence_arquivo_proximo_numero)) + # elif order.mode.type.code == '400': + # self.name = 'CB%s%s.REM' % ( + # time.strftime('%d%m'), str(suf_arquivo)) + elif order.mode.type.code == '500': + self.name = 'PG%s%s.REM' % ( + time.strftime('%d%m'), + str(order.mode.sequence_arquivo_proximo_numero)) + self.state = 'done' + self.cnab_file = base64.b64encode(remessa) + order.cnab_file = base64.b64encode(remessa) + order.cnab_filename = self.name + + workflow.trg_validate( + self.env.uid, 'payment.order', order_id, 'generated', self.env.cr) + + return { + 'type': 'ir.actions.act_window', + 'res_model': self._name, + 'view_mode': 'form', + 'view_type': 'form', + 'res_id': self.id, + 'target': 'new', + } + + @api.multi + def done(self): + return {'type': 'ir.actions.act_window_close'} diff --git a/l10n_br_financial_payment_order/wizards/l10n_br_payment_cnab.xml b/l10n_br_financial_payment_order/wizards/l10n_br_payment_cnab.xml new file mode 100644 index 0000000..ae19e1e --- /dev/null +++ b/l10n_br_financial_payment_order/wizards/l10n_br_payment_cnab.xml @@ -0,0 +1,32 @@ + + + + + payment.cnab.form + payment.cnab + +
+ + + + + + + + + +
+
+
+
+ +
+
+
+
diff --git a/l10n_br_financial_payment_order/wizards/ordem_pagamento_holerite.py b/l10n_br_financial_payment_order/wizards/ordem_pagamento_holerite.py new file mode 100644 index 0000000..7b85fe2 --- /dev/null +++ b/l10n_br_financial_payment_order/wizards/ordem_pagamento_holerite.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from datetime import datetime + +from openerp import api, models, fields, _ +from openerp.addons.l10n_br_hr_payroll.models.hr_payslip import MES_DO_ANO + + +class PayslipPaymentCreateOrder(models.Model): + _name = "payslip.payment.order.create" + + mes_do_ano = fields.Selection( + selection=MES_DO_ANO, + string=u'Mês', + required=True, + default=datetime.now().month, + ) + + ano = fields.Integer( + strin="Ano", + default=datetime.now().year, + required=True, + ) + + entries = fields.Many2many( + comodel_name='hr.payslip', + rel='payorder_line_payslip_rel', + column1='pay_id', + column2='payslip_id', + string='Entries' + ) + + @api.multi + def _buscar_holerites_com_conta_bancaria_contrato(self, payslip_ids): + holerites = [] + for holerite in payslip_ids: + if holerite.contract_id.conta_bancaria_id: + holerites.append(holerite) + return holerites + + @api.model + def default_get(self, field_list): + res = super(PayslipPaymentCreateOrder, self).default_get(field_list) + context = self.env.context + if ('entries' in field_list and context.get('payslip_id') and + context.get('populate_results')): + res.update({'entries': context['payslip_id']}) + return res + + @api.multi + def buscar_linhas_holerites(self): + payment_order = self.env['payment.order'].browse( + self.env.context.get('active_id') + ) + payslip_obj = self.env['hr.payslip'] + payslip_ids = payslip_obj.search( + [ + ('tipo_de_folha', '=', payment_order.tipo_de_folha), + ('mes_do_ano', '=', self.mes_do_ano), + ('ano', '=', self.ano), + ('state', '=', 'verify') + ] + ) + payslips_partner_bank_id = \ + self._buscar_holerites_com_conta_bancaria_contrato(payslip_ids) + context = self.env.context.copy() + context['payslip_id'] = [] + if payslips_partner_bank_id: + context['payslip_id'] = [ + payslip.id for payslip in payslips_partner_bank_id + ] + context['populate_results'] = True + model_data_obj = self.env['ir.model.data'] + model_datas = model_data_obj.search( + [('model', '=', 'ir.ui.view'), + ('name', '=', 'payslip_payment_lines_create_order_view')]) + return {'name': _('Entry Lines'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'payslip.payment.order.create', + 'views': [(model_datas[0].res_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + } + + @api.multi + def _preparar_linha_do_holerite(self, payment, line): + self.ensure_one() + date_to_pay = False # no payment date => immediate payment + state = 'normal' + communication = 'Holerite: ' + line.display_name or '-' + amount_currency = line.total + res = { + 'amount_currency': amount_currency, + 'bank_id': line.contract_id.conta_bancaria_id.id, + 'order_id': payment.id, + 'partner_id': line.partner_id and line.partner_id.id or False, + # account banking + 'communication': communication, + 'state': state, + # end account banking + 'date': date_to_pay, + 'payslip_id': line.slip_id.id, + } + return res + + @api.multi + def _buscar_rubricas_a_pagar(self, payslip): + rubricas = [] + for line in payslip.line_ids: + if line.code in ['LIQUIDO', 'PENSAO_ALIMENTICIA']: + rubricas.append(line) + return rubricas + + @api.multi + def create_payment(self): + if not self.entries: + return {'type': 'ir.actions.act_window_close'} + context = self.env.context.copy() + context['default_payment_order_type'] = 'payment' + payment_line_obj = self.env['payment.line'] + payment = self.env['payment.order'].browse(context['active_id']) + # Populate the current payment with new lines: + for line in self.entries: + linha_rubrica = self._buscar_rubricas_a_pagar(line) + for rubrica in linha_rubrica: + vals = self._preparar_linha_do_holerite(payment, rubrica) + payment_line_obj.create(vals) + # Force reload of payment order view as a workaround for lp:1155525 + return {'name': _('Payment Orders'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'payment.order', + 'res_id': context['active_id'], + 'type': 'ir.actions.act_window'} diff --git a/l10n_br_financial_payment_order/wizards/ordem_pagamento_holerite_wizard.xml b/l10n_br_financial_payment_order/wizards/ordem_pagamento_holerite_wizard.xml new file mode 100644 index 0000000..17cb978 --- /dev/null +++ b/l10n_br_financial_payment_order/wizards/ordem_pagamento_holerite_wizard.xml @@ -0,0 +1,66 @@ + + + + + + payslip.payment.create.order.form + payslip.payment.order.create + +
+ + + + +
+
+
+
+
+ + + payment.order.populate.account.payslip.tree + hr.payslip + + + + + + + + + + + + + payslip.payment.line.create.order + payslip.payment.order.create + +
+
+
+ + + + + +
+ + + Buscar rubricas a serem pagas nos holerites + ir.actions.act_window + payslip.payment.order.create + form + form + {'record_id' : active_id} + + new + + +
+
diff --git a/l10n_br_financial_payment_order/workflows/hr_payroll_workflow.xml b/l10n_br_financial_payment_order/workflows/hr_payroll_workflow.xml new file mode 100644 index 0000000..0e64b7e --- /dev/null +++ b/l10n_br_financial_payment_order/workflows/hr_payroll_workflow.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + paid_order + + + diff --git a/l10n_br_financial_payment_order/workflows/payment_order_workflow.xml b/l10n_br_financial_payment_order/workflows/payment_order_workflow.xml new file mode 100644 index 0000000..c69cd5a --- /dev/null +++ b/l10n_br_financial_payment_order/workflows/payment_order_workflow.xml @@ -0,0 +1,107 @@ + + + + + + + waiting + + action_open() +write({'state':'waiting'}) + function + + + + waiting2 + + action_open() +write({'state':'waiting2'}) + function + + + + generated + + action_open() +write({'state':'generated'}) + function + + + + + + + open + nivel_aprovacao==0 + + + + + + + open + nivel_aprovacao>0 + + + + + + open + nivel_aprovacao>1 + + + + + + open + nivel_aprovacao==1 + + + + + + open + nivel_aprovacao==2 + + + + + + generated + tipo_exportacao=='BANKMAN' + + + + + + generated + tipo_exportacao<>'BANKMAN' + + + + + + done + + + + + + cancel + + + + + + cancel + + + + + + cancel + + + +