diff --git a/.travis.yml b/.travis.yml index b50a925..a735fb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ install: - pip install git+https://github.com/aricaldeira/pybrasil.git - pip install pyboleto - pip install fixedwidth - - pip install https://github.com/kmee/cnab240/archive/master.zip + - pip install git+https://github.com/kmee/cnab240.git@feature/pagamento - travis_install_nightly before_script: diff --git a/l10n_br_account_banking_payment/__openerp__.py b/l10n_br_account_banking_payment/__openerp__.py index a63ab3a..4329ce4 100644 --- a/l10n_br_account_banking_payment/__openerp__.py +++ b/l10n_br_account_banking_payment/__openerp__.py @@ -32,7 +32,6 @@ 'website': 'https://github.com/odoo-brazil/odoo-brazil-banking', 'category': 'Banking addons', 'depends': [ - 'l10n_br_account', 'l10n_br_account', 'account_banking_payment_export', ], @@ -42,7 +41,7 @@ 'views/payment_mode.xml', 'views/payment_mode_type.xml', 'wizard/payment_order_create_view.xml', - 'data/payment_mode_type.xml', + # 'data/payment_mode_type.xml', ], 'demo': [ ], diff --git a/l10n_br_account_banking_payment/models/account_payment.py b/l10n_br_account_banking_payment/models/account_payment.py index cf4ca2a..29e1b39 100644 --- a/l10n_br_account_banking_payment/models/account_payment.py +++ b/l10n_br_account_banking_payment/models/account_payment.py @@ -26,6 +26,7 @@ from openerp import models, fields, api from openerp.addons import decimal_precision as dp from openerp.tools.float_utils import float_round as round +from openerp.exceptions import ValidationError class PaymentOrder(models.Model): @@ -41,6 +42,17 @@ class PaymentOrder(models.Model): def _compute_total(self): self.total = sum(self.mapped('line_ids.amount') or [0.0]) + @api.multi + def action_open(self): + """ + Validacao para nao confirmar ordem de pagamento vazia + """ + for record in self: + if not record.line_ids: + raise ValidationError("Impossivel confirmar linha vazia!") + res = super(PaymentOrder, self).action_open() + return res + class PaymentLine(models.Model): _inherit = 'payment.line' @@ -58,8 +70,8 @@ def _get_info_partner(self, cr, uid, partner_record, context=None): cntry = partner_record.country_id and \ partner_record.country_id.name or '' cnpj = partner_record.cnpj_cpf or '' - return partner_record.legal_name + "\n" + cnpj + "\n" + st + ", " \ - + n + " " + st1 + "\n" + zip_city + "\n" + cntry + return partner_record.legal_name or '' + "\n" + cnpj + "\n" + st \ + + ", " + n + " " + st1 + "\n" + zip_city + "\n" + cntry @api.one @api.depends('percent_interest', 'amount_currency') diff --git a/l10n_br_account_banking_payment/views/account_payment.xml b/l10n_br_account_banking_payment/views/account_payment.xml index f603877..59c507d 100644 --- a/l10n_br_account_banking_payment/views/account_payment.xml +++ b/l10n_br_account_banking_payment/views/account_payment.xml @@ -12,9 +12,6 @@ - - - diff --git a/l10n_br_account_banking_payment_bradesco_tributos/model/payment_mode.py b/l10n_br_account_banking_payment_bradesco_tributos/model/payment_mode.py index cbb1107..5e8faf4 100644 --- a/l10n_br_account_banking_payment_bradesco_tributos/model/payment_mode.py +++ b/l10n_br_account_banking_payment_bradesco_tributos/model/payment_mode.py @@ -26,10 +26,10 @@ class PaymentMode(models.Model): _inherit = "payment.mode" - payment_order_type = fields.Selection( - selection_add=[ - ('tax', u'Tributos'), - ]) + # payment_order_type = fields.Selection( + # selection_add=[ + # ('tax', u'Tributos'), + # ]) gnre_value_field = fields.Many2one( 'ir.model.fields', 'Value field', domain=[('model_id', '=', 'account.invoice')]) @@ -40,24 +40,24 @@ class PaymentModeType(models.Model): _inherit = 'payment.mode.type' _description = 'Payment Mode Type' - payment_order_type = fields.Selection( - selection_add=[ - ('tax', u'Tributos'), - ]) + # payment_order_type = fields.Selection( + # selection_add=[ + # ('tax', u'Tributos'), + # ]) class PaymentOrder(models.Model): _inherit = 'payment.order' - payment_order_type = fields.Selection( - selection_add=[ - ('tax', u'Tributos'), - ]) + # payment_order_type = fields.Selection( + # selection_add=[ + # ('tax', u'Tributos'), + # ]) class AccountMoveLine(models.Model): _inherit = 'account.move.line' - has_gnre = fields.Boolean( - related='stored_invoice_id.has_gnre', - string="Tem GNRE") + # has_gnre = fields.Boolean( + # related='stored_invoice_id.has_gnre', + # string="Tem GNRE") diff --git a/l10n_br_account_banking_payment_cnab/__openerp__.py b/l10n_br_account_banking_payment_cnab/__openerp__.py index d486b4a..c2b06d7 100644 --- a/l10n_br_account_banking_payment_cnab/__openerp__.py +++ b/l10n_br_account_banking_payment_cnab/__openerp__.py @@ -37,9 +37,9 @@ 'l10n_br_account_payment_boleto', 'l10n_br_account_payment_mode', 'l10n_br_account_product', - 'account_banking_payment_export', ], 'data': [ + 'security/cnab_cobranca_security.xml', 'view/l10n_br_payment_cnab.xml', 'view/payment_order.xml', 'view/l10n_br_cnab_sequence.xml', @@ -47,12 +47,18 @@ 'view/l10n_br_cobranca_cnab_lines.xml', 'view/account_move_line.xml', 'view/res_partner_bank.xml', + 'view/l10n_br_cnab_retorno_view.xml', 'view/payment_mode.xml', + 'view/payment_line.xml', + 'view/bank_payment_line.xml', 'data/l10n_br_payment_export_type.xml', - 'data/l10n_br_payment_mode.xml', + 'security/ir.model.access.csv', + ], + 'demo': [ + # 'demo/l10n_br_payment_mode.xml', ], 'test': [ - 'tests/invoice_create.yml' + # 'tests/invoice_create.yml' ], "installable": True, "auto_install": False, diff --git a/l10n_br_account_banking_payment_cnab/constantes.py b/l10n_br_account_banking_payment_cnab/constantes.py new file mode 100644 index 0000000..393ed67 --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/constantes.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- + +COBRANCA = '01' +BOLETO_PAGAMENTO_ELETRONICO = '03' +CONCILIACAO_BANCARIA = '04' +DEBITOS = '05' +CUSTODIA_CHEQUES = '06' +GESTAO_CAIXA = '07' +CONSULTA_INFORMACAO_MARGEM = '08' +AVERBACAO_CONSIGNACAO_RETENCAO = '09' +PAGAMENTO_DIVIDENDOS = '10' +MANUTENCAO_CONSIGNACAO = '11' +CONSIGNACAO_PARCELAS = '12' +GLOSA_CONSIGNACAO = '13' +CONSULTA_TRIBUTOS_PAGAR = '14' +PAGAMENTO_FORNECEDOR = '20' +PAGAMENTO_CONTAS_TRIBUTOS_IMPOSTOS = '22' +INTEROPERABILIDADE_CONTAS = '23' +COMPROR = '25' +COMPROR_ROTATIVO = '26' +ALEGACAO_PAGADOR = '29' +PAGAMENTO_SALARIOS = '30' +PAGAMENTO_HONORARIOS = '32' +PAGAMENTO_BOLSA_AUXILIO = '33' +PAGAMENTO_PREBENDA = '34' +VENDOR = '40' +VENDOR_TERMO = '41' +PAGAMENTO_SINISTROS_SEGURADOS = '50' +PAGAMENTO_DESPESAS_VIAJANTE = '60' +PAGAMENTO_AUTORIZADO = '70' +PAGAMENTO_CREDENCIADOS = '75' +PAGAMENTO_REMUNERACAO = '77' +PAGAMENTO_REPRESENTANTES = '80' +PAGAMENTO_BENEFICIOS = '90' +PAGAMENTOS_DIVERSOS = '98' + +TIPO_SERVICO = [ + (COBRANCA, COBRANCA + u' - Cobrança'), + (BOLETO_PAGAMENTO_ELETRONICO, BOLETO_PAGAMENTO_ELETRONICO + + u' - Boleto de Pagamento Eletrônico'), + (CONCILIACAO_BANCARIA, CONCILIACAO_BANCARIA + u' - Conciliação Bancária'), + (DEBITOS, DEBITOS + u' - Débitos'), + (CUSTODIA_CHEQUES, CUSTODIA_CHEQUES + u' - Custódia de Cheques'), + (GESTAO_CAIXA, GESTAO_CAIXA + u' - Gestão de Caixa'), + (CONSULTA_INFORMACAO_MARGEM, CONSULTA_INFORMACAO_MARGEM + + u' - Consulta/Informação Margem'), + (AVERBACAO_CONSIGNACAO_RETENCAO, AVERBACAO_CONSIGNACAO_RETENCAO + + u' - Averbação da Consignação/Retenção'), + (PAGAMENTO_DIVIDENDOS, PAGAMENTO_DIVIDENDOS + u' - Pagamento Dividendos'), + (MANUTENCAO_CONSIGNACAO, MANUTENCAO_CONSIGNACAO + + u' - Manutenção da Consignação'), + (CONSIGNACAO_PARCELAS, CONSIGNACAO_PARCELAS + + u' - Consignação de Parcelas'), + (GLOSA_CONSIGNACAO, GLOSA_CONSIGNACAO + + u' - Glosa da Consignação (INSS)'), + (CONSULTA_TRIBUTOS_PAGAR, CONSULTA_TRIBUTOS_PAGAR + + u' - Consulta de Tributos a pagar'), + (PAGAMENTO_FORNECEDOR, PAGAMENTO_FORNECEDOR + + u' - Pagamento Fornecedor'), + (PAGAMENTO_CONTAS_TRIBUTOS_IMPOSTOS, PAGAMENTO_CONTAS_TRIBUTOS_IMPOSTOS + + u' - Pagamento de Contas, Tributos e Impostos'), + (INTEROPERABILIDADE_CONTAS, INTEROPERABILIDADE_CONTAS + + u' - Interoperabilidade entre Contas de Instituições de Pagamentos'), + (COMPROR, COMPROR + u' - Compror'), + (COMPROR_ROTATIVO, COMPROR_ROTATIVO + u' - Compror Rotativo'), + (ALEGACAO_PAGADOR, ALEGACAO_PAGADOR + u' - Alegação do Pagador'), + (PAGAMENTO_SALARIOS, PAGAMENTO_SALARIOS + u' - Pagamento Salários'), + (PAGAMENTO_HONORARIOS, PAGAMENTO_HONORARIOS + + u' - Pagamento de honorários'), + (PAGAMENTO_BOLSA_AUXILIO, PAGAMENTO_BOLSA_AUXILIO + + u' - Pagamento de bolsa auxílio'), + (PAGAMENTO_PREBENDA, PAGAMENTO_PREBENDA + + u' - Pagamento de prebenda (remuneração a padres e sacerdotes)'), + (VENDOR, VENDOR + u' - Vendor'), + (VENDOR_TERMO, VENDOR_TERMO + u' - Vendor a Termo'), + (PAGAMENTO_SINISTROS_SEGURADOS, PAGAMENTO_SINISTROS_SEGURADOS + + u' - Pagamento Sinistros Segurados'), + (PAGAMENTO_DESPESAS_VIAJANTE, PAGAMENTO_DESPESAS_VIAJANTE + + u' - Pagamento Despesas Viajante em Trânsito'), + (PAGAMENTO_AUTORIZADO, PAGAMENTO_AUTORIZADO + u' - Pagamento Autorizado'), + (PAGAMENTO_CREDENCIADOS, PAGAMENTO_CREDENCIADOS + + u' - Pagamento Credenciados'), + (PAGAMENTO_REMUNERACAO, PAGAMENTO_REMUNERACAO + + u' - Pagamento de Remuneração'), + (PAGAMENTO_REPRESENTANTES, PAGAMENTO_REPRESENTANTES + + u' - Pagamento Representantes / Vendedores Autorizados'), + (PAGAMENTO_BENEFICIOS, PAGAMENTO_BENEFICIOS + u' - Pagamento Benefícios'), + (PAGAMENTOS_DIVERSOS, PAGAMENTOS_DIVERSOS + u' - Pagamentos Diversos'), +] + +CREDITO_CONTA_CORRENTE_SALARIO = ( + '01', u'01 - Crédito em Conta Corrente/Salário') +CHEQUE_PAGAMENTO_ADMINISTRATIVO = ( + '02', u'02 - Cheque Pagamento / Administrativo') +DOC_TED = ('03', u'03 - DOC/TED (1) (2)') +CARTAO_SALARIO = ( + '04', u'04 - Cartão Salário (somente para Tipo de Serviço = \'30\')') +CREDITO_CONTA_POUPANCA = ('05', u'05 - Crédito em Conta Poupança') +OP_A_DISPOSICAO = ('10', u'10 - OP à Disposição') +PAGAMENTO_CONTAS_TRIBUTOS_CODIGO_BARRAS = ( + '11', u'11 - Pagamento de Contas e Tributos com Código de Barras') +TRIBUTO_DARF_NORMAL = ('16', u'16 - Tributo - DARF Normal') +TRIBUTO_GPS = ('17', u'17 - Tributo - GPS (Guia da Previdência Social)') +TRIBUTO_DARF_SIMPLES = ('18', u'18 - Tributo - DARF Simples') +TRIBUTO_IPTU_PREFEITURAS = ('19', u'19 - Tributo - IPTU – Prefeituras') +PAGAMENTO_AUTENTICACAO = ('20', u'20 - Pagamento com Autenticação') +TRIBUTO_DARJ = ('21', u'21 - Tributo – DARJ') +TRIBUTO_GARE_SP_ICMS = ('22', u'22 - Tributo - GARE-SP ICMS') +TRIBUTO_GARE_SP_DR = ('23', u'23 - Tributo - GARE-SP DR') +TRIBUTO_GARE_SP_ITCMD = ('24', u'24 - Tributo - GARE-SP ITCMD') +TRIBUTO_IPVA = ('25', u'25 - Tributo - IPVA') +TRIBUTO_LICENCIAMENTO = ('26', u'26 - Tributo - Licenciamento') +TRIBUTO_DPVAT = ('27', u'27 - Tributo – DPVAT') +LIQUIDACAO_TITULOS_PROPRIO_BANCO = ( + '30', u'30 - Liquidação de Títulos do Próprio Banco') +PAGAMENTO_TITULOS_OUTROS_BANCOS = ( + '31', u'31 - Pagamento de Títulos de Outros Bancos') +EXTRATO_CONTA_CORRENTE = ('40', u'40 - Extrato de Conta Corrente') +TED_OUTRA_TITULARIDADE = ('41', u'41 - TED – Outra Titularidade (1)') +TED_MESMA_TITULARIDADE = ('43', u'43 - TED – Mesma Titularidade (1)') +TED_TRANSFERENCIA_CONTA_INVESTIMENTO = ( + '44', u'44 - TED para Transferência de Conta Investimento') +DEBITO_CONTA_CORRENTE = ('50', u'50 - Débito em Conta Corrente') +EXTRATO_GESTAO_CAIXA = ('70', u'70 - Extrato para Gestão de Caixa') +DEPOSITO_JUDICIAL_CONTA_CORRENTE = ( + '71', u'71 - Depósito Judicial em Conta Corrente') +DEPOSITO_JUDICIAL_POUPANCA = ('72', u'72 - Depósito Judicial em Poupança') +EXTRATO_CONTA_INVESTIMENTO = ('73', u'73 - Extrato de Conta Investimento') + +FORMA_LANCAMENTO = [ + CREDITO_CONTA_CORRENTE_SALARIO, + CHEQUE_PAGAMENTO_ADMINISTRATIVO, + DOC_TED, + CARTAO_SALARIO, + CREDITO_CONTA_POUPANCA, + OP_A_DISPOSICAO, + PAGAMENTO_CONTAS_TRIBUTOS_CODIGO_BARRAS, + TRIBUTO_DARF_NORMAL, + TRIBUTO_GPS, + TRIBUTO_DARF_SIMPLES, + TRIBUTO_IPTU_PREFEITURAS, + PAGAMENTO_AUTENTICACAO, + TRIBUTO_DARJ, + TRIBUTO_GARE_SP_ICMS, + TRIBUTO_GARE_SP_DR, + TRIBUTO_GARE_SP_ITCMD, + TRIBUTO_IPVA, + TRIBUTO_LICENCIAMENTO, + TRIBUTO_DPVAT, + LIQUIDACAO_TITULOS_PROPRIO_BANCO, + PAGAMENTO_TITULOS_OUTROS_BANCOS, + EXTRATO_CONTA_CORRENTE, + TED_OUTRA_TITULARIDADE, + TED_MESMA_TITULARIDADE, + TED_TRANSFERENCIA_CONTA_INVESTIMENTO, + DEBITO_CONTA_CORRENTE, + EXTRATO_GESTAO_CAIXA, + DEPOSITO_JUDICIAL_CONTA_CORRENTE, + DEPOSITO_JUDICIAL_POUPANCA, + EXTRATO_CONTA_INVESTIMENTO, +] + +CREDITO_EM_CONTA = ('01', u'01 - Crédito em Conta') +PAGAMENTO_ALUGUEL = ('02', u'02 - Pagamento de Aluguel/Condomínio') +PAGAMENTO_DUPLICATA_TITULOS = ('03', u'03 - Pagamento de Duplicata/Títulos') +PAGAMENTO_DIVIDENDOS_C = ('04', u'04 - Pagamento de Dividendos') +PAGAMENTO_MENSALIDADE_ESCOLAR = ( + '05', u'05 - Pagamento de Mensalidade Escolar') +PAGAMENTO_SALARIOS_C = ('06', u'06 - Pagamento de Salários') +PAGAMENTO_FORNECEDORES = ('07', u'07 - Pagamento a Fornecedores') +OPERACOES_CAMBIOS_FUNDOS_BOLSA = ( + '08', u'08 - Operações de Câmbios/Fundos/Bolsa de Valores') +REPASSE_ARRECADACAO = ( + '09', u'09 - Repasse de Arrecadação/Pagamento de Tributos') +TRANSFERECIA_INTERNACIONAL_EM_REAL = ( + '10', u'10 - Transferência Internacional em Real') +DOC_POUPANCA = ('11', u'11 - DOC para Poupança') +DOC_DEPOSITO_JUDICIAL = ('12', u'12 - DOC para Depósito Judicial') +OUTROS = ('13', u'13 - Outros') +PAGAMENTO_BOLSA_AUXILIO_C = ('16', u'16 - Pagamento de bolsa auxílio') +REMUNERACAO_COOPERADO = ('17', u'17 - Remuneração à cooperado') +PAGAMENTO_HONORARIOS_C = ('18', u'18 - Pagamento de honorários') +PAGAMENTO_PREBENDA_C = ( + '19', u'19 - Pagamento de prebenda (Remuneração a padres e sacerdotes)') + +COMPLEMENTO_TIPO_SERVICO = [ + CREDITO_EM_CONTA, + PAGAMENTO_ALUGUEL, + PAGAMENTO_DUPLICATA_TITULOS, + PAGAMENTO_DIVIDENDOS_C, + PAGAMENTO_MENSALIDADE_ESCOLAR, + PAGAMENTO_SALARIOS_C, + PAGAMENTO_FORNECEDORES, + OPERACOES_CAMBIOS_FUNDOS_BOLSA, + REPASSE_ARRECADACAO, + TRANSFERECIA_INTERNACIONAL_EM_REAL, + DOC_POUPANCA, + DOC_DEPOSITO_JUDICIAL, + OUTROS, + PAGAMENTO_BOLSA_AUXILIO_C, + REMUNERACAO_COOPERADO, + PAGAMENTO_HONORARIOS_C, + PAGAMENTO_PREBENDA_C, +] + +# 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 = [ + (' ', u'Padrão') +] + +NAO_EMITE_AVISO = ('0', u'0 - Não Emite Aviso') +EMITE_AVISO_REMETENTE = ('2', u'2 - Emite Aviso Somente para o Remetente') +EMITE_AVISO_FAVORECIDO = ('5', u'5 - Emite Aviso Somente para o Favorecido') +EMITE_AVISO_REMETENTE_FAVORECIDO = \ + ('6', u'6 - Emite Aviso para o Remetente e Favorecido') +EMITE_AVISO_FAVORECIDO_2_VIAS_REMETENTE = \ + ('7', u'7 - Emite Aviso para o Favorecido e 2 Vias para o Remetente') + +AVISO_FAVORECIDO = [ + NAO_EMITE_AVISO, + EMITE_AVISO_REMETENTE, + EMITE_AVISO_FAVORECIDO, + EMITE_AVISO_REMETENTE_FAVORECIDO, + EMITE_AVISO_FAVORECIDO_2_VIAS_REMETENTE, +] + +INDICATIVO_FORMA_PAGAMENTO = [ + ('01', u'01 - Débito em Conta Corrente'), + ('02', u'02 - Débito Empréstimo/Financiamento'), + ('03', u'03 - Débito Cartão de Crédito'), +] + +TIPO_MOVIMENTO = [ + ('0', u'0 - Indica INCLUSÃO'), + ('1', u'1 - Indica CONSULTA'), + ('2', u'2 - Indica SUSPENSÃO'), + ('3', u'3 - Indica ESTORNO (somente para retorno)'), + ('4', u'4 - Indica REATIVAÇÃO'), + ('5', u'5 - Indica ALTERAÇÃO'), + ('7', u'7 - Indica LIQUIDAÇAO'), + ('9', u'9 - Indica EXCLUSÃO'), +] + +CODIGO_INSTRUCAO_MOVIMENTO = [ + ('0', u'00 - Inclusão de Registro Detalhe Liberado'), + ('9', u'09 - Inclusão do Registro Detalhe Bloqueado'), + ('10', u'10 - Alteração do Pagamento Liberado para Bloqueado (Bloqueio)'), + ('11', u'11 - Alteração do Pagamento Bloqueado para Liberado (Liberação)'), + ('17', u'17 - Alteração do Valor do Título'), + ('19', u'19 - Alteração da Data de Pagamento'), + ('23', u'23 - Pagamento Direto ao Fornecedor - Baixar'), + ('25', u'25 - Manutenção em Carteira - Não Pagar'), + ('27', u'27 - Retirada de Carteira - Não Pagar'), + ('33', u'33 - Estorno por Devolução da Câmara Centralizadora ' + u'(somente para Tipo de Movimento = \'3\')'), + ('40', u'40 - Alegação do Pagador'), + ('99', u'99 - Exclusão do Registro Detalhe Incluído Anteriormente'), +] + +CODIGO_OCORRENCIAS = [ + ('00', u'00 - Crédito ou Débito Efetivado'), + ('01', u'01 - Insuficiência de Fundos - Débito Não Efetuado'), + ('02', u'02 - Crédito ou Débito Cancelado pelo Pagador/Credor'), + ('03', u'03 - Débito Autorizado pela Agência - Efetuado'), + ('AA', u'AA - Controle Inválido'), + ('AB', u'AB - Tipo de Operação Inválido'), + ('AC', u'AC - Tipo de Serviço Inválido'), + ('AD', u'AD - Forma de Lançamento Inválida'), + ('AE', u'AE - Tipo/Número de Inscrição Inválido'), + ('AF', u'AF - Código de Convênio Inválido'), + ('AG', u'AG - Agência/Conta Corrente/DV Inválido'), + ('AH', u'AH - Nº Seqüencial do Registro no Lote Inválido'), + ('AI', u'AI - Código de Segmento de Detalhe Inválido'), + ('AJ', u'AJ - Tipo de Movimento Inválido'), + ('AK', u'AK - Código da Câmara de Compensação do Banco' + u' Favorecido/Depositário Inválido'), + ('AL', u'AL - Código do Banco Favorecido, Instituição de Pagamento' + u' ou Depositário Inválido'), + ('AM', u'AM - Agência Mantenedora da Conta Corrente do' + u' Favorecido Inválida'), + ('AN', u'AN - Conta Corrente/DV/Conta de Pagamento do' + u' Favorecido Inválido'), + ('AO', u'AO - Nome do Favorecido Não Informado'), + ('AP', u'AP - Data Lançamento Inválido'), + ('AQ', u'AQ - Tipo/Quantidade da Moeda Inválido'), + ('AR', u'AR - Valor do Lançamento Inválido'), + ('AS', u'AS - Aviso ao Favorecido - Identificação Inválida'), + ('AT', u'AT - Tipo/Número de Inscrição do Favorecido Inválido'), + ('AU', u'AU - Logradouro do Favorecido Não Informado'), + ('AV', u'AV - Nº do Local do Favorecido Não Informado'), + ('AW', u'AW - Cidade do Favorecido Não Informada'), + ('AX', u'AX - CEP/Complemento do Favorecido Inválido'), + ('AY', u'AY - Sigla do Estado do Favorecido Inválida'), + ('AZ', u'AZ - Código/Nome do Banco Depositário Inválido'), + ('BA', u'BA - Código/Nome da Agência Depositária Não Informado'), + ('BB', u'BB - Seu Número Inválido'), + ('BC', u'BC - Nosso Número Inválido'), + ('BD', u'BD - Inclusão Efetuada com Sucesso'), + ('BE', u'BE - Alteração Efetuada com Sucesso'), + ('BF', u'BF - Exclusão Efetuada com Sucesso'), + ('BG', u'BG - Agência/Conta Impedida Legalmente'), + ('BH', u'BH - Empresa não pagou salário'), + ('BI', u'BI - Falecimento do mutuário'), + ('BJ', u'BJ - Empresa não enviou remessa do mutuário'), + ('BK', u'BK - Empresa não enviou remessa no vencimento'), + ('BL', u'BL - Valor da parcela inválida'), + ('BM', u'BM - Identificação do contrato inválida'), + ('BN', u'BN - Operação de Consignação Incluída com Sucesso'), + ('BO', u'BO - Operação de Consignação Alterada com Sucesso'), + ('BP', u'BP - Operação de Consignação Excluída com Sucesso'), + ('BQ', u'BQ - Operação de Consignação Liquidada com Sucesso'), + ('BR', u'BR - Reativação Efetuada com Sucesso'), + ('BS', u'BS - Suspensão Efetuada com Sucesso'), + ('CA', u'CA - Código de Barras - Código do Banco Inválido'), + ('CB', u'CB - Código de Barras - Código da Moeda Inválido'), + ('CC', u'CC - Código de Barras - Dígito Verificador Geral Inválido'), + ('CD', u'CD - Código de Barras - Valor do Título Inválido'), + ('CE', u'CE - Código de Barras - Campo Livre Inválido'), + ('CF', u'CF - Valor do Documento Inválido'), + ('CG', u'CG - Valor do Abatimento Inválido'), + ('CH', u'CH - Valor do Desconto Inválido'), + ('CI', u'CI - Valor de Mora Inválido'), + ('CJ', u'CJ - Valor da Multa Inválido'), + ('CK', u'CK - Valor do IR Inválido'), + ('CL', u'CL - Valor do ISS Inválido'), + ('CM', u'CM - Valor do IOF Inválido'), + ('CN', u'CN - Valor de Outras Deduções Inválido'), + ('CO', u'CO - Valor de Outros Acréscimos Inválido'), + ('CP', u'CP - Valor do INSS Inválido'), + ('HA', u'HA - Lote Não Aceito'), + ('HB', u'HB - Inscrição da Empresa Inválida para o Contrato'), + ('HC', u'HC - Convênio com a Empresa Inexistente/Inválido' + u' para o Contrato'), + ('HD', u'HD - Agência/Conta Corrente da Empresa Inexistente/Inválido' + u' para o Contrato'), + ('HE', u'HE - Tipo de Serviço Inválido para o Contrato'), + ('HF', u'HF - Conta Corrente da Empresa com Saldo Insuficiente'), + ('HG', u'HG - Lote de Serviço Fora de Seqüência'), + ('HH', u'HH - Lote de Serviço Inválido'), + ('HI', u'HI - Arquivo não aceito'), + ('HJ', u'HJ - Tipo de Registro Inválido'), + ('HK', u'HK - Código Remessa / Retorno Inválido'), + ('HL', u'HL - Versão de layout inválida'), + ('HM', u'HM - Mutuário não identificado'), + ('HN', u'HN - Tipo do beneficio não permite empréstimo'), + ('HO', u'HO - Beneficio cessado/suspenso'), + ('HP', u'HP - Beneficio possui representante legal'), + ('HQ', u'HQ - Beneficio é do tipo PA (Pensão alimentícia)'), + ('HR', u'HR - Quantidade de contratos permitida excedida'), + ('HS', u'HS - Beneficio não pertence ao Banco informado'), + ('HT', u'HT - Início do desconto informado já ultrapassado'), + ('HU', u'HU - Número da parcela inválida'), + ('HV', u'HV - Quantidade de parcela inválida'), + ('HW', u'HW - Margem consignável excedida para o mutuário dentro' + u' do prazo do contrato'), + ('HX', u'HX - Empréstimo já cadastrado'), + ('HY', u'HY - Empréstimo inexistente'), + ('HZ', u'HZ - Empréstimo já encerrado'), + ('H1', u'H1 - Arquivo sem trailer'), + ('H2', u'H2 - Mutuário sem crédito na competência'), + ('H3', u'H3 - Não descontado – outros motivos'), + ('H4', u'H4 - Retorno de Crédito não pago'), + ('H5', u'H5 - Cancelamento de empréstimo retroativo'), + ('H6', u'H6 - Outros Motivos de Glosa'), + ('H7', u'H7 - Margem consignável excedida para o mutuário acima' + u' do prazo do contrato'), + ('H8', u'H8 - Mutuário desligado do empregador'), + ('H9', u'H9 - Mutuário afastado por licença'), + ('IA', u'IA - Primeiro nome do mutuário diferente do primeiro nome' + u' do movimento do censo ou diferente da base de Titular' + u' do Benefício'), + ('IB', u'IB - Benefício suspenso/cessado pela APS ou Sisobi'), + ('IC', u'IC - Benefício suspenso por dependência de cálculo'), + ('ID', u'ID - Benefício suspenso/cessado pela inspetoria/auditoria'), + ('IE', u'IE - Benefício bloqueado para empréstimo pelo beneficiário'), + ('IF', u'IF - Benefício bloqueado para empréstimo por TBM'), + ('IG', u'IG - Benefício está em fase de concessão de PA ou desdobramento'), + ('IH', u'IH - Benefício cessado por óbito'), + ('II', u'II - Benefício cessado por fraude'), + ('IJ', u'IJ - Benefício cessado por concessão de outro benefício'), + ('IK', u'IK - Benefício cessado: estatutário transferido' + u' para órgão de origem'), + ('IL', u'IL - Empréstimo suspenso pela APS'), + ('IM', u'IM - Empréstimo cancelado pelo banco'), + ('IN', u'IN - Crédito transformado em PAB'), + ('IO', u'IO - Término da consignação foi alterado'), + ('IP', u'IP - Fim do empréstimo ocorreu durante período' + u' de suspensão ou concessão'), + ('IQ', u'IQ - Empréstimo suspenso pelo banco'), + ('IR', u'IR - Não averbação de contrato – quantidade de' + u' parcelas/competências informadas ultrapassou a data limite' + u' da extinção de cota do dependente titular de benefícios'), + ('TA', u'TA - Lote Não Aceito - Totais do Lote com Diferença'), + ('YA', u'YA - Título Não Encontrado'), + ('YB', u'YB - Identificador Registro Opcional Inválido'), + ('YC', u'YC - Código Padrão Inválido'), + ('YD', u'YD - Código de Ocorrência Inválido'), + ('YE', u'YE - Complemento de Ocorrência Inválido'), + ('YF', u'YF - Alegação já Informada'), + ('ZA', u'ZA - Agência / Conta do Favorecido Substituída'), + ('ZB', u'ZB - Divergência entre o primeiro e último nome do beneficiário' + u' versus primeiro e último nome na Receita Federal'), + ('ZC', u'ZC - Confirmação de Antecipação de Valor'), + ('ZD', u'ZD - Antecipação parcial de valor'), + ('ZE', u'ZE - Título bloqueado na base'), + ('ZF', u'ZF - Sistema em contingência' + u' – título valor maior que referência'), + ('ZG', u'ZG - Sistema em contingência – título vencido'), + ('ZH', u'ZH - Sistema em contingência – título indexado'), + ('ZI', u'ZI - Beneficiário divergente'), + ('ZJ', u'ZJ - Limite de pagamentos parciais excedido'), + ('ZK', u'ZK - Boleto já liquidado'), +] diff --git a/l10n_br_account_banking_payment_cnab/data/l10n_br_payment_export_type.xml b/l10n_br_account_banking_payment_cnab/data/l10n_br_payment_export_type.xml index 98952df..edbc317 100644 --- a/l10n_br_account_banking_payment_cnab/data/l10n_br_payment_export_type.xml +++ b/l10n_br_account_banking_payment_cnab/data/l10n_br_payment_export_type.xml @@ -3,16 +3,16 @@ + 240 Cnab240 True - cobranca - + payment + - + @@ -24,7 +24,7 @@ ref="l10n_br_account_banking_payment_cnab.model_payment_cnab"/> - + @@ -37,7 +37,7 @@ ref="l10n_br_account_banking_payment_cnab.model_payment_cnab"/> - + diff --git a/l10n_br_account_banking_payment_cnab/data/l10n_br_payment_mode.xml b/l10n_br_account_banking_payment_cnab/demo/l10n_br_payment_mode.xml similarity index 100% rename from l10n_br_account_banking_payment_cnab/data/l10n_br_payment_mode.xml rename to l10n_br_account_banking_payment_cnab/demo/l10n_br_payment_mode.xml diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab.py b/l10n_br_account_banking_payment_cnab/febraban/cnab.py index 9faec66..2a384e4 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab.py @@ -22,6 +22,8 @@ ############################################################################## # TODO: implement abc factory? +from __future__ import division, print_function, unicode_literals + class Cnab(object): diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/bb.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/bb.py new file mode 100644 index 0000000..5580359 --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/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_account_banking_payment_cnab/febraban/cnab_240/bancos/bradesco.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/bradesco.py index b6b4422..3dea8ad 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/bradesco.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/bradesco.py @@ -47,13 +47,13 @@ def _prepare_header(self): vals['servico_servico'] = 1 return vals - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: """ - vals = super(Bradesco240, self)._prepare_segmento(line) + vals = super(Bradesco240, self)._prepare_cobranca(line) vals['prazo_baixa'] = unicode(str( vals['prazo_baixa']), "utf-8") vals['desconto1_percentual'] = Decimal('0.00') diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/cef.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/cef.py index a6a7c05..14193fe 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/cef.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/cef.py @@ -57,13 +57,13 @@ def _prepare_header(self): return vals - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: """ - vals = super(Cef240, self)._prepare_segmento(line) + vals = super(Cef240, self)._prepare_cobranca(line) carteira, nosso_numero, digito = self.nosso_numero( line.move_line_id.transaction_ref) diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/itau.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/itau.py index 1fefd02..84c5706 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/itau.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/itau.py @@ -54,13 +54,13 @@ def _prepare_header(self): vals['cedente_agencia_dv']), return vals - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: """ - vals = super(Itau240, self)._prepare_segmento(line) + vals = super(Itau240, self)._prepare_cobranca(line) carteira, nosso_numero, digito = self.nosso_numero( line.move_line_id.transaction_ref) diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/santander.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/santander.py index bd4bbca..cd8a3a5 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/santander.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_240/bancos/santander.py @@ -49,11 +49,11 @@ def _prepare_header(self): del vals['arquivo_hora_de_geracao'] return vals - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: """ - vals = super(Santander240, self)._prepare_segmento(line) + vals = super(Santander240, self)._prepare_cobranca(line) return vals 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 0ccc091..b67d6b8 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 @@ -21,6 +21,8 @@ # ############################################################################## +from __future__ import division, print_function, unicode_literals + import datetime import logging import re @@ -35,14 +37,14 @@ _logger = logging.getLogger(__name__) try: - from cnab240.tipos import Arquivo + from cnab240.tipos import Arquivo, Lote except ImportError as err: _logger.debug = err class Cnab240(Cnab): """ - + CNAB240 """ def __init__(self): @@ -50,6 +52,12 @@ def __init__(self): @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 @@ -62,80 +70,180 @@ def get_bank(bank): elif bank == '033': from .bancos.santander import Santander240 return Santander240 + elif bank == '001': + from .bancos.bb import BB240 + return BB240 else: return Cnab240 - @property - def inscricao_tipo(self): + def get_inscricao_tipo(self, partner_id): # TODO: Implementar codigo para PIS/PASEP - if self.order.company_id.partner_id.is_company: + if partner_id.is_company: return 2 else: return 1 def _prepare_header(self): """ - - :param: - :return: + Preparar o header do arquivo do CNAB + :return: dict - Header do arquivo """ - return { + 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(), - # TODO: Número sequencial de arquivo + # 19.0 TODO: Número sequencial de arquivo 'arquivo_sequencia': int(self.get_file_numeration()), - 'cedente_inscricao_tipo': self.inscricao_tipo, - 'cedente_inscricao_numero': int(punctuation_rm( - self.order.company_id.cnpj_cpf)), - 'cedente_agencia': int( - self.order.mode.bank_id.bra_number), - 'cedente_conta': int(self.order.mode.bank_id.acc_number), - 'cedente_conta_dv': (self.order.mode.bank_id.acc_number_dig), - 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, - 'cedente_nome': self.order.company_id.legal_name, - # DV ag e conta - 'cedente_dv_ag_cc': (self.order.mode.bank_id.bra_acc_dig), - 'arquivo_codigo': 1, # Remessa/Retorno - 'servico_operacao': u'R', - 'nome_banco': unicode(self.order.mode.bank_id.bank_name), + # 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 } - def get_file_numeration(self): - numero = self.order.get_next_number() - if not numero: - numero = 1 - return numero + return header_arquivo - 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 _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 - def cep(self, format): - sulfixo = format[-3:] - prefixo = format[:5] - return prefixo, sulfixo + header_arquivo_lote = { - def sacado_inscricao_tipo(self, partner_id): - # TODO: Implementar codigo para PIS/PASEP - if partner_id.is_company: - return 2 - else: - return 1 + # CONTROLE + # 01.1 + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.1 Sequencia para o Arquivo + 'controle_lote': 1, + # 03.1 0- Header do Arquivo + 'controle_registro': 1, + + # SERVICO + # 04.1 # Header do lote sempre 'C' + 'servico_operacao': 'C', + # 05.1 + 'servico_servico': self.order.tipo_servico, + # 06.1 + 'servico_forma_lancamento': 1, + # 07.1 + 'servico_layout': 20, + # 08.1 + # CNAB - Uso Exclusivo da FEBRABAN/CNAB + + # EMPRESA CEDENTE + # 09.1 + 'empresa_inscricao_tipo': 2, + # self.get_inscricao_tipo(self.order.company_id.partner_id), + # 10.1 + 'empresa_inscricao_numero': punctuation_rm(empresa.cnpj_cpf), + # 11.1 + 'cedente_convenio': self.order.codigo_convenio, + # 12.1 + 'cedente_agencia': + int(self.order.mode.bank_id.bra_number), + # 13.1 + 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, + # 14.1 + 'cedente_conta': int(self.order.mode.bank_id.acc_number), + # 15.1 + 'cedente_conta_dv': self.order.mode.bank_id.acc_number_dig[0], + # 16.1 + 'cedente_agencia_conta_dv': + self.order.mode.bank_id.acc_number_dig[1] + if len(self.order.mode.bank_id.acc_number_dig) > 1 else '', + # 17.1 + 'cedente_nome': + self.order.mode.bank_id.partner_id.legal_name[:30], + # 18.1 + 'mensagem1': '', + + # ENDERECO + # 19.1 + 'empresa_logradouro': empresa.street, + # 20.1 + 'empresa_endereco_numero': empresa.number, + # 21.1 + 'empresa_endereco_complemento': empresa.street2, + # 22.1 + 'empresa_endereco_cidade': empresa.l10n_br_city_id.name, + # 23.1 + 'empresa_endereco_cep': self.get_cep('prefixo', empresa.zip), + # 24.1 + 'empresa_endereco_cep_complemento': + self.get_cep('sufixo', empresa.zip), + # 25.1 + 'empresa_endereco_estado': empresa.state_id.code, + + # 26.1 + 'indicativo_forma_pagamento': '', + # 27.1 + # CNAB - Uso Exclusivo FEBRABAN / CNAB + # 28.1 + 'ocorrencias': '', + } + return header_arquivo_lote - def rmchar(self, format): - return re.sub('[%s]' % re.escape(string.punctuation), '', - format or '') + def get_file_numeration(self): + # Função para retornar a numeração sequencial do arquivo + return 1 - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: """ - prefixo, sulfixo = self.cep(line.partner_id.zip) + # prefixo, sufixo = self.cep(line.partner_id.zip) aceite = u'N' if not self.order.mode.boleto_aceite == 'S': @@ -162,8 +270,6 @@ def _prepare_segmento(self, line): '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, - # DV ag e cc - 'cedente_dv_ag_cc': (self.order.mode.bank_id.bra_acc_dig), 'identificacao_titulo': u'0000000', # TODO 'identificacao_titulo_banco': u'0000000', # TODO 'identificacao_titulo_empresa': line.move_line_id.move_id.name, @@ -172,6 +278,7 @@ def _prepare_segmento(self, line): 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), @@ -185,15 +292,15 @@ def _prepare_segmento(self, line): 'juros_mora_taxa_dia': Decimal('0.00'), 'valor_abatimento': Decimal('0.00'), 'sacado_inscricao_tipo': int( - self.sacado_inscricao_tipo(line.partner_id)), + 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': int(prefixo), - 'sacado_cep_sufixo': int(sulfixo), + '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), @@ -204,31 +311,254 @@ def _prepare_segmento(self, line): 'cobranca_carteira': int(self.order.mode.boleto_carteira), } - def remessa(self, order): + 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 = { - :param order: - :return: + # SEGMENTO A + # CONTROLE + # 01.3A + 'controle_banco': int(self.order.mode.bank_id.bank_bic), + # 02.3A + 'controle_lote': 1, + # 03.3A - 3-Registros Iniciais do Lote + 'controle_registro': 3, + + # SERVICO + # 04.3A - Nº Seqüencial do Registro - Inicia em 1 em cada novo lote + # TODO: Contador para o sequencial do lote + 'servico_numero_registro': 1, + # 05.3A + # Segmento Código de Segmento do Reg.Detalhe + # 06.3A + 'servico_tipo_movimento': self.order.tipo_movimento, + # 07.3A + 'servico_codigo_movimento': self.order.codigo_instrucao_movimento, + + # FAVORECIDO + # 08.3A - 018-TED 700-DOC + 'favorecido_camara': 0, + # 09.3A + 'favorecido_banco': int(line.bank_id.bank_bic), + # 10.3A + 'favorecido_agencia': int(line.bank_id.bra_number), + # 11.3A + 'favorecido_agencia_dv': line.bank_id.bra_number_dig, + # 12.3A + 'favorecido_conta': punctuation_rm(line.bank_id.acc_number), + # 13.3A + 'favorecido_conta_dv': line.bank_id.acc_number_dig[0] + if line.bank_id.acc_number_dig else '', + # 14.3A + 'favorecido_dv': line.bank_id.acc_number_dig[1] + if len(line.bank_id.bra_number_dig or '') > 1 else '', + # 15.3A + 'favorecido_nome': line.partner_id.name, + + # CREDITO + # 16.3A - + 'credito_seu_numero': line.name, + # 17.3A + 'credito_data_pagamento': self.format_date(line.date), + # 18.3A + 'credito_moeda_tipo': line.currency.name, + # 19.3A + 'credito_moeda_quantidade': Decimal('0.00000'), + # 20.3A + 'credito_valor_pagamento': + Decimal(str(line.amount_currency)).quantize(Decimal('1.00')), + # 21.3A + # 'credito_nosLoteso_numero': '', + # 22.3A + # 'credito_data_real': '', + # 23.3A + # 'credito_valor_real': '', + + # INFORMAÇÔES + # 24.3A + # 'outras_informacoes': '', + # 25.3A + # 'codigo_finalidade_doc': line.codigo_finalidade_doc, + # 26.3A + 'codigo_finalidade_ted': line.codigo_finalidade_ted or '', + # 27.3A + 'codigo_finalidade_complementar': + line.codigo_finalidade_complementar or '', + # 28.3A + # CNAB - Uso Exclusivo FEBRABAN/CNAB + # 29.3A + # 'aviso_ao_favorecido': line.aviso_ao_favorecido, + 'aviso_ao_favorecido': 0, + # 'ocorrencias': '', + + # SEGMENTO B + # Preenchido no segmento A + # 01.3B + # 02.3B + # 03.3B + + # 04.3B + # 05.3B + # 06.3B + + # DADOS COMPLEMENTARES - FAVORECIDOS + # 07.3B + 'favorecido_tipo_inscricao': + self.get_inscricao_tipo(line.partner_id), + # 08.3B + 'favorecido_num_inscricao': + int(punctuation_rm(line.partner_id.cnpj_cpf)), + # 09.3B + 'favorecido_endereco_rua': line.partner_id.street or '', + # 10.3B + 'favorecido_endereco_num': int(line.partner_id.number) or 0, + # 11.3B + 'favorecido_endereco_complemento': line.partner_id.street2 or '', + # 12.3B + 'favorecido_endereco_bairro': line.partner_id.district or '', + # 13.3B + 'favorecido_endereco_cidade': + line.partner_id.l10n_br_city_id.name or '', + # 14.3B + # 'favorecido_cep': int(line.partner_id.zip[:5]) or 0, + 'favorecido_cep': self.get_cep('prefixo', line.partner_id.zip), + # 15.3B + 'favorecido_cep_complemento': + self.get_cep('sufixo', line.partner_id.zip), + # 16.3B + 'favorecido_estado': line.partner_id.state_id.code or '', + + # DADOS COMPLEMENTARES - PAGAMENTO + # 17.3B + 'pagamento_vencimento': 0, + # 18.3B + 'pagamento_valor_documento': Decimal('0.00'), + # 19.3B + 'pagamento_abatimento': Decimal('0.00'), + # 20.3B + 'pagamento_desconto': Decimal('0.00'), + # 21.3B + 'pagamento_mora': Decimal('0.00'), + # 22.3B + 'pagamento_multa': Decimal('0.00'), + # 23.3B + # TODO: Verificar se este campo é retornado no retorno + # 'cod_documento_favorecido': '', + # 24.3B - Informado No SegmentoA + # 'aviso_ao_favorecido': '0', + # 25.3B + # 'codigo_ug_centralizadora': '0', + # 26.3B + # 'codigo_ispb': '0', + } + return vals + + def _adicionar_evento(self, line): + """ + Adicionar o evento no arquivo de acordo com seu tipo """ - cobrancasimples_valor_titulos = 0 + # 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()) - for line in order.line_ids: - self.arquivo.incluir_cobranca(**self._prepare_segmento(line)) - self.arquivo.lotes[0].header.servico_servico = 1 + + 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')) + # 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') + 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_account_banking_payment_cnab/febraban/cnab_400/bancos/bradesco.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_400/bancos/bradesco.py index 6317ed9..fa3cf04 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_400/bancos/bradesco.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_400/bancos/bradesco.py @@ -48,13 +48,13 @@ def _prepare_header(self): vals['servico_servico'] = 1 return vals - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: """ - vals = super(Bradesco400, self)._prepare_segmento(line) + vals = super(Bradesco400, self)._prepare_cobranca(line) vals['prazo_baixa'] = unicode(str( vals['prazo_baixa']), "utf-8") vals['desconto1_percentual'] = Decimal('0.00') diff --git a/l10n_br_account_banking_payment_cnab/febraban/cnab_400/cnab_400.py b/l10n_br_account_banking_payment_cnab/febraban/cnab_400/cnab_400.py index 09c49c6..cb1e3d8 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/cnab_400/cnab_400.py +++ b/l10n_br_account_banking_payment_cnab/febraban/cnab_400/cnab_400.py @@ -136,8 +136,6 @@ def _prepare_header(self): 'cedente_conta_dv': (self.order.mode.bank_id.acc_number_dig), 'cedente_agencia_dv': self.order.mode.bank_id.bra_number_dig, 'cedente_nome': self.order.company_id.legal_name, - # DV ag e conta - 'cedente_dv_ag_cc': (self.order.mode.bank_id.bra_acc_dig), 'arquivo_codigo': 1, # Remessa/Retorno 'servico_operacao': u'R', 'nome_banco': unicode(self.order.mode.bank_id.bank_name), @@ -176,7 +174,7 @@ def rmchar(self, format): def codificar(self, texto): return texto.encode('utf-8') - def _prepare_segmento(self, line): + def _prepare_cobranca(self, line): """ :param line: :return: @@ -236,8 +234,6 @@ def _prepare_segmento(self, line): '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, - # DV ag e cc - 'cedente_dv_ag_cc': (self.order.mode.bank_id.bra_acc_dig), 'identificacao_titulo': u'0000000', # TODO 'identificacao_titulo_banco': u'0000000', # TODO 'identificacao_titulo_empresa': line.move_line_id.move_id.name, @@ -303,7 +299,7 @@ def remessa(self, order): self.order = order self.arquivo = ArquivoCobranca400(self.bank, **self._prepare_header()) for line in order.line_ids: - self.arquivo.incluir_cobranca(**self._prepare_segmento(line)) + self.arquivo.incluir_cobranca(**self._prepare_cobranca(line)) self.arquivo.trailer.num_seq_registro = self.controle_linha remessa = unicode(self.arquivo) diff --git a/l10n_br_account_banking_payment_cnab/febraban/pag_for/bancos/bradesco.py b/l10n_br_account_banking_payment_cnab/febraban/pag_for/bancos/bradesco.py index 9b4cb40..1edd242 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/pag_for/bancos/bradesco.py +++ b/l10n_br_account_banking_payment_cnab/febraban/pag_for/bancos/bradesco.py @@ -45,13 +45,13 @@ def _prepare_header(self): vals['codigo_comunicacao'] = int(self.order.mode.boleto_convenio) return vals - def _prepare_segmento(self, line, vals): + def _prepare_cobranca(self, line, vals): """ :param line: :return: """ - vals = super(BradescoPagFor, self)._prepare_segmento(line, vals) + 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( diff --git a/l10n_br_account_banking_payment_cnab/febraban/pag_for/pag_for500.py b/l10n_br_account_banking_payment_cnab/febraban/pag_for/pag_for500.py index 472fca8..3666832 100644 --- a/l10n_br_account_banking_payment_cnab/febraban/pag_for/pag_for500.py +++ b/l10n_br_account_banking_payment_cnab/febraban/pag_for/pag_for500.py @@ -249,7 +249,7 @@ def sacado_inscricao_tipo(self, partner_id): def rmchar(self, format): return re.sub('[%s]' % re.escape(string.punctuation), '', format or '') - def _prepare_segmento(self, line, vals): + def _prepare_cobranca(self, line, vals): """ :param line: @@ -436,7 +436,7 @@ def lancamento_credito_bradesco(self, line): 'informacoes_complementares': u'', } - return self._prepare_segmento(line, vals) + return self._prepare_cobranca(line, vals) def lancamento_ted(self, line): # TODO: @@ -488,14 +488,14 @@ def lancamento_ted(self, line): } - return self._prepare_segmento(line, vals) + return self._prepare_cobranca(line, vals) def lancamento_doc(self): # TODO: vals = {} - return self._prepare_segmento(vals) + return self._prepare_cobranca(vals) def lancamento_titulos_terceiros(self, line): # TODO: @@ -520,7 +520,7 @@ def lancamento_titulos_terceiros(self, line): } - return self._prepare_segmento(vals) + return self._prepare_cobranca(vals) def adiciona_digitos_num_pag(self, campo): num_digitos = 16 diff --git a/l10n_br_account_banking_payment_cnab/model/__init__.py b/l10n_br_account_banking_payment_cnab/model/__init__.py index 28ef5a5..c630028 100644 --- a/l10n_br_account_banking_payment_cnab/model/__init__.py +++ b/l10n_br_account_banking_payment_cnab/model/__init__.py @@ -7,3 +7,7 @@ from . import payment_mode from . import res_partner_bank from . import res_partner +from .. import constantes +from . import 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 new file mode 100644 index 0000000..ddd64c9 --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/model/bank_payment_line.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +from openerp import models, fields, api +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' + + @api.model + def default_get(self, fields_list): + res = super(BankPaymentLine, self).default_get(fields_list) + mode = self.env['payment.order'].browse( + self.env.context.get('order_id')).mode + if mode.codigo_finalidade_doc: + res.update({ + 'codigo_finalidade_doc': mode.codigo_finalidade_doc}) + if mode.codigo_finalidade_ted: + res.update({ + 'codigo_finalidade_ted': mode.codigo_finalidade_ted + }) + if mode.codigo_finalidade_complementar: + res.update({ + 'codigo_finalidade_complementar': + mode.codigo_finalidade_complementar + }) + if mode.aviso_ao_favorecido: + res.update({ + 'aviso_ao_favorecido': mode.aviso_ao_favorecido + }) + return res + + codigo_finalidade_doc = fields.Selection( + selection=COMPLEMENTO_TIPO_SERVICO, + string=u'Complemento do Tipo de Serviço', + help=u'Campo P005 do CNAB' + ) + codigo_finalidade_ted = fields.Selection( + selection=CODIGO_FINALIDADE_TED, + string=u'Código Finalidade da TED', + help=u'Campo P011 do CNAB' + ) + codigo_finalidade_complementar = fields.Char( + size=2, + string=u'Código de finalidade complementar', + help=u'Campo P013 do CNAB' + ) + aviso_ao_favorecido = fields.Selection( + selection=AVISO_FAVORECIDO, + string=u'Aviso ao Favorecido', + help=u'Campo P006 do CNAB', + default='0', + ) + abatimento = fields.Float( + digits=(13, 2), + string=u'Valor do Abatimento', + help=u'Campo G045 do CNAB', + default=0.00 + ) + desconto = fields.Float( + digits=(13, 2), + string=u'Valor do Desconto', + help=u'Campo G046 do CNAB', + default=0.00 + ) + mora = fields.Float( + digits=(13, 2), + string=u'Valor da Mora', + help=u'Campo G047 do CNAB', + default=0.00 + ) + multa = fields.Float( + digits=(13, 2), + string=u'Valor da Multa', + 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", + inverse_name="bank_payment_line_id", + readonly=True + ) + codigo_finalidade_complementar = fields.Char( + size=2, + string=u'Código de finalidade complementar', + help=u'Campo P013 do CNAB', + ) diff --git a/l10n_br_account_banking_payment_cnab/model/l10n_br_cnab.py b/l10n_br_account_banking_payment_cnab/model/l10n_br_cnab.py new file mode 100644 index 0000000..d16929d --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/model/l10n_br_cnab.py @@ -0,0 +1,304 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 KMEE - Luiz Felipe do Divino Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +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 +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 L10nBrHrCnab(models.Model): + _name = "l10n.br.cnab" + _rec_name = "display_name" + + @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( + u"Este não é um arquivo de retorno!" + ) + 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] + ) + self.bank_account_id = self.env['res.partner.bank'].search( + [('acc_number', '=', arquivo_parser.header.cedente_conta)]).id + self.num_lotes = arquivo_parser.trailer.totais_quantidade_lotes + self.num_eventos = arquivo_parser.trailer.totais_quantidade_registros + for lote in arquivo_parser.lotes: + 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['l10n.br.cnab.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] + ) + 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 + favorecido_partner = self.env['res.partner.bank'].search( + [('owner_name', 'ilike', evento.favorecido_nome)] + ) + favorecido_partner = favorecido_partner[0].partner_id.id \ + if favorecido_partner else False + bank_payment_line_id = self.env['bank.payment.line'].search( + [ + ('name', '=', evento.credito_seu_numero) + ] + ) + ocorrencias_dic = dict(CODIGO_OCORRENCIAS) + ocorrencias = [ + evento.ocorrencias[0:2], + evento.ocorrencias[2:4], + evento.ocorrencias[4:6], + evento.ocorrencias[6:8], + evento.ocorrencias[8:10] + ] + vals_evento = { + 'data_real_pagamento': data_evento, + 'segmento': evento.servico_segmento, + 'favorecido_nome': favorecido_partner, + 'favorecido_conta_bancaria': 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, + } + self.env['l10n.br.cnab.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(L10nBrHrCnab, self).create(vals) + + arquivo_retorno = fields.Binary(string='Arquivo Retorno') + data = fields.Date( + string="Data CNAB", + required=True, + default=datetime.now() + ) + name = fields.Char( + string="Name", + ) + lote_id = fields.One2many( + string="Lotes", + comodel_name="l10n.br.cnab.lote", + inverse_name="cnab_id" + ) + state = fields.Selection( + string=u"Estágio", + selection=STATE, + default="draft", + ) + data_arquivo = fields.Datetime( + string="Data Criação no Banco", + ) + bank_account_id = fields.Many2one( + string="Conta cedente", + comodel_name="res.partner.bank", + ) + num_lotes = fields.Integer( + string=u"Número de Lotes", + ) + num_eventos = fields.Integer( + string=u"Número de Eventos", + ) + + +class L10nBrHrCnabLote(models.Model): + _name = "l10n.br.cnab.lote" + + account_bank_id = fields.Many2one( + string=u"Conta Bancária", + comodel_name="res.partner.bank", + ) + 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") + evento_id = fields.One2many( + string="Eventos", + comodel_name="l10n.br.cnab.evento", + inverse_name="lote_id", + ) + cnab_id = fields.Many2one( + string="CNAB", + comodel_name="l10n.br.cnab" + ) + state = fields.Selection( + string="State", + related="cnab_id.state", + selection=STATE, + default="draft", + ) + + +class L10nBrHrCnabEvento(models.Model): + _name = "l10n.br.cnab.evento" + + data_real_pagamento = fields.Datetime(string="Data Real do Pagamento") + segmento = fields.Char(string="Segmento") + favorecido_nome = fields.Many2one( + string="Favorecido", + comodel_name="res.partner" + ) + favorecido_conta_bancaria = fields.Many2one( + string=u"Conta Bancária", + comodel_name="res.partner.bank", + ) + 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') + bank_payment_line_id = fields.Many2one( + string="Bank Payment Line", + comodel_name="bank.payment.line", + ) + lote_id = fields.Many2one( + string="Lote", + comodel_name="l10n.br.cnab.lote", + ) + state = fields.Selection( + string="State", + related="lote_id.state", + selection=STATE, + default="draft", + ) diff --git a/l10n_br_account_banking_payment_cnab/model/payment_line.py b/l10n_br_account_banking_payment_cnab/model/payment_line.py new file mode 100644 index 0000000..0c66474 --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/model/payment_line.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +from openerp import models, fields, api +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' + + @api.model + def default_get(self, fields_list): + res = super(PaymentLine, self).default_get(fields_list) + mode = self.env['payment.order'].browse( + self.env.context.get('order_id')).mode + if mode.codigo_finalidade_doc: + res.update({ + 'codigo_finalidade_doc': mode.codigo_finalidade_doc}) + if mode.codigo_finalidade_ted: + res.update({ + 'codigo_finalidade_ted': mode.codigo_finalidade_ted + }) + if mode.codigo_finalidade_complementar: + res.update({ + 'codigo_finalidade_complementar': + mode.codigo_finalidade_complementar + }) + if mode.aviso_ao_favorecido: + res.update({ + 'aviso_ao_favorecido': mode.aviso_ao_favorecido + }) + return res + + seu_numero = fields.Char( + string=u'Seu Número', + size=20, + help=u'Campo G064' + ) + codigo_finalidade_doc = fields.Selection( + selection=COMPLEMENTO_TIPO_SERVICO, + string=u'Complemento do Tipo de Serviço', + help=u'Campo P005 do CNAB', + ) + codigo_finalidade_ted = fields.Selection( + selection=CODIGO_FINALIDADE_TED, + string=u'Código Finalidade da TED', + help=u'Campo P011 do CNAB', + ) + codigo_finalidade_complementar = fields.Char( + size=2, + string=u'Código de finalidade complementar', + help=u'Campo P013 do CNAB', + ) + aviso_ao_favorecido = fields.Selection( + selection=AVISO_FAVORECIDO, + string=u'Aviso ao Favorecido', + help=u'Campo P006 do CNAB', + default='0', + ) + abatimento = fields.Float( + digits=(13, 2), + string=u'Valor do Abatimento', + help=u'Campo G045 do CNAB', + default=0.00 + ) + desconto = fields.Float( + digits=(13, 2), + string=u'Valor do Desconto', + help=u'Campo G046 do CNAB', + default=0.00 + ) + mora = fields.Float( + digits=(13, 2), + string=u'Valor da Mora', + help=u'Campo G047 do CNAB', + default=0.00 + ) + multa = fields.Float( + digits=(13, 2), + string=u'Valor da Multa', + 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/model/payment_mode.py b/l10n_br_account_banking_payment_cnab/model/payment_mode.py index b6eec56..18de555 100644 --- a/l10n_br_account_banking_payment_cnab/model/payment_mode.py +++ b/l10n_br_account_banking_payment_cnab/model/payment_mode.py @@ -22,6 +22,8 @@ from openerp import models, fields from openerp.addons import decimal_precision as dp +from ..constantes import TIPO_SERVICO, FORMA_LANCAMENTO, \ + COMPLEMENTO_TIPO_SERVICO, CODIGO_FINALIDADE_TED, AVISO_FAVORECIDO class PaymentMode(models.Model): @@ -34,5 +36,42 @@ class PaymentMode(models.Model): cnab_percent_interest = fields.Float(string=u"Percentual de Juros", digits=dp.get_precision('Account')) comunicacao_2 = fields.Char("Comunicação para o sacador avalista") + tipo_servico = fields.Selection( + selection=TIPO_SERVICO, + string=u'Tipo de Serviço', + help=u'Campo G025 do CNAB' + ) + forma_lancamento = fields.Selection( + selection=FORMA_LANCAMENTO, + string=u'Forma Lançamento', + help=u'Campo G029 do CNAB' + ) + codigo_convenio = fields.Char( + size=20, + string=u'Código do Convênio no Banco', + help=u'Campo G007 do CNAB', + default=u'0001222130126', + ) + codigo_finalidade_doc = fields.Selection( + selection=COMPLEMENTO_TIPO_SERVICO, + string=u'Complemento do Tipo de Serviço', + help=u'Campo P005 do CNAB' + ) + codigo_finalidade_ted = fields.Selection( + selection=CODIGO_FINALIDADE_TED, + string=u'Código Finalidade da TED', + help=u'Campo P011 do CNAB' + ) + codigo_finalidade_complementar = fields.Char( + size=2, + string=u'Código de finalidade complementar', + help=u'Campo P013 do CNAB', + ) + aviso_ao_favorecido = fields.Selection( + selection=AVISO_FAVORECIDO, + string=u'Aviso ao Favorecido', + help=u'Campo P006 do CNAB', + default=0, + ) # A exportação CNAB não se encaixa somente nos parâmetros de # débito e crédito. diff --git a/l10n_br_account_banking_payment_cnab/model/payment_order.py b/l10n_br_account_banking_payment_cnab/model/payment_order.py index d1c7d01..6a191ea 100644 --- a/l10n_br_account_banking_payment_cnab/model/payment_order.py +++ b/l10n_br_account_banking_payment_cnab/model/payment_order.py @@ -1,65 +1,65 @@ # -*- coding: utf-8 -*- -# ############################################################################# -# -# -# Copyright (C) 2012 KMEE (http://www.kmee.com.br) -# @author Fernando Marcato Rodrigues -# -# 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 . -# -############################################################################## +# Copyright 2012 KMEE - Fernando Marcato Rodrigues +# Copyright 2017 KMEE - Hendrix Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import api, models, fields +from __future__ import division, print_function, unicode_literals -# TODO: funcao a ser chamada por ação automatizada para resetar o sufixo -# diariamente +from openerp import models, fields + +from ..constantes import TIPO_SERVICO, FORMA_LANCAMENTO, \ + INDICATIVO_FORMA_PAGAMENTO, TIPO_MOVIMENTO, CODIGO_INSTRUCAO_MOVIMENTO class PaymentOrder(models.Model): - _inherit = 'payment.order' + _inherit = b'payment.order' + + file_number = fields.Integer( + string=u'Número sequencial do arquivo', + ) - file_number = fields.Integer(u'Número sequencial do arquivo') - # TODO adicionar domain para permitir o modo de pagamento correspondente - # ao mode - serie_id = fields.Many2one( - 'l10n_br_cnab.sequence', u'Sequencia interna') - sufixo_arquivo = fields.Integer(u'Sufixo do arquivo') - serie_sufixo_arquivo = fields.Many2one( - 'l10n_br_cnab_file_sufix.sequence', u'Série do Sufixo do arquivo') + cnab_file = fields.Binary( + string='CNAB File', + readonly=True, + ) - @api.multi - def get_next_number(self): - for ord in self: - sequence = self.env['ir.sequence'] - # sequence_read = sequence.read( - # cr, uid, ord.serie_id.internal_sequence_id.id, - # ['number_next']) - seq_no = sequence.get_id(ord.serie_id.internal_sequence_id.id) - ord.write({'file_number': seq_no}) - return seq_no + cnab_filename = fields.Char("CNAB Filename") - @api.multi - def get_next_sufixo(self): - for ord in self: - sequence = self.env['ir.sequence'] - # sequence_read = sequence.read( - # cr, uid, ord.serie_id.internal_sequence_id.id, - # ['number_next']) - seq_no = sequence.get_id( - ord.serie_sufixo_arquivo.internal_sequence_id.id) - ord.write({'sufixo_arquivo': seq_no}) - return seq_no + tipo_servico = fields.Selection( + selection=TIPO_SERVICO, + string=u'Tipo de Serviço', + help=u'Campo G025 do CNAB', + default='30', + ) + forma_lancamento = fields.Selection( + selection=FORMA_LANCAMENTO, + string=u'Forma Lançamento', + help=u'Campo G029 do CNAB' + ) + codigo_convenio = fields.Char( + size=20, + string=u'Código do Convênio no Banco', + help=u'Campo G007 do CNAB', + default=u'0001222130126', + ) + indicativo_forma_pagamento = fields.Selection( + selection=INDICATIVO_FORMA_PAGAMENTO, + string=u'Indicativo de Forma de Pagamento', + help='Campo P014 do CNAB', + default='01' + ) + tipo_movimento = fields.Selection( + selection=TIPO_MOVIMENTO, + string='Tipo de Movimento', + help='Campo G060 do CNAB', + default='0', + ) + codigo_instrucao_movimento = fields.Selection( + selection=CODIGO_INSTRUCAO_MOVIMENTO, + string='Código da Instrução para Movimento', + help='Campo G061 do CNAB', + default='0', + ) # @api.multi # def set_to_draft(self, *args): diff --git a/l10n_br_account_banking_payment_cnab/model/res_partner_bank.py b/l10n_br_account_banking_payment_cnab/model/res_partner_bank.py index e21c9ce..0892a46 100644 --- a/l10n_br_account_banking_payment_cnab/model/res_partner_bank.py +++ b/l10n_br_account_banking_payment_cnab/model/res_partner_bank.py @@ -1,24 +1,7 @@ # -*- coding: utf-8 -*- -# ############################################################################# -# -# -# Copyright (C) 2012 KMEE (http://www.kmee.com.br) -# @author Fernando Marcato Rodrigues -# -# 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 . -# -############################################################################## +# Copyright 2012 KMEE - Fernando Marcato Rodrigues +# Copyright 2017 KMEE - Hendrix Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from openerp import models, fields @@ -28,18 +11,27 @@ class ResPartnerBank(models.Model): bancárias no Brasil.""" _inherit = 'res.partner.bank' - bra_acc_dig = fields.Char(u'Digito Verificador Agência/Conta', size=1) codigo_da_empresa = fields.Integer( - u'Código da empresa', size=20, + u'Código da empresa', + size=20, help=u"Será informado pelo banco depois do cadastro do beneficiário " - u"na agência") + u"na agência" + ) + tipo_de_conta = fields.Selection( - [('01', u'Conta corrente individual'), - ('02', u'Conta poupança individual'), - ('03', u'Conta depósito judicial/Depósito em consignação individual'), - ('11', u'Conta corrente conjunta'), - ('12', u'Conta poupança conjunta'), - ('13', u'Conta depósito judicial/Depósito em consignação conjunta') - ], - u'Tipo de Conta', default='01' + selection=[ + ('01', u'Conta corrente individual'), + ('02', u'Conta poupança individual'), + ('03', u'Conta depósito judicial/Depósito em consignação ' + u'individual'), + ('11', u'Conta corrente conjunta'), + ('12', u'Conta poupança conjunta'), + ('13', u'Conta depósito judicial/Depósito em consignação ' + u'conjunta')], + string=u'Tipo de Conta', + default='01' + ) + + bra_number = fields.Char( + size=5, ) diff --git a/l10n_br_account_banking_payment_cnab/security/cnab_cobranca_security.xml b/l10n_br_account_banking_payment_cnab/security/cnab_cobranca_security.xml new file mode 100644 index 0000000..42a6a0c --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/security/cnab_cobranca_security.xml @@ -0,0 +1,11 @@ + + + + + + CNAB Cobranca + + + + + \ No newline at end of file diff --git a/l10n_br_account_banking_payment_cnab/security/ir.model.access.csv b/l10n_br_account_banking_payment_cnab/security/ir.model.access.csv new file mode 100644 index 0000000..8ed4b5e --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/security/ir.model.access.csv @@ -0,0 +1,6 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +access_l10n_br_cnab,access_l10n_br_cnab,model_l10n_br_cnab,,1,0,0,0 +access_l10n_br_cnab_lote,access_l10n_br_cnab_lote,model_l10n_br_cnab_lote,,1,0 +access_l10n_br_cnab_evento,access_l10n_br_cnab_evento,model_l10n_br_cnab_evento,,1,0,0,0 +access_l10n_br_cnab_sequence,access_l10n_br_cnab_sequence,model_l10n_br_cnab_sequence,,1,0,0,0 +access_l10n_br_cnab_file_sufix_sequence,access_l10n_br_cnab_file_sufix_sequence,model_l10n_br_cnab_file_sufix_sequence,,1,0,0,0 diff --git a/l10n_br_account_banking_payment_cnab/tests/invoice_create.yml b/l10n_br_account_banking_payment_cnab/tests/invoice_create.yml deleted file mode 100644 index aeffa3d..0000000 --- a/l10n_br_account_banking_payment_cnab/tests/invoice_create.yml +++ /dev/null @@ -1,207 +0,0 @@ -- - Create a sale customer invoice from SP to SP fiscal contributor -- - !record {model: account.invoice, id: account_invoice_customer_sp_sp_banking, view: l10n_br_account_product.l10n_br_account_product_invoice_form}: - partner_id: l10n_br_base.res_partner_cliente1_sp - fiscal_category_id: l10n_br_account_product.fc_78df616ab31e95ee46c6a519a2ce9e12 - reference_type: none - payment_mode_id: l10n_br_account_banking_payment_cnab.payment_mode_cobranca_bradesco240 - name: 'NFe Invoice Test' - date_due: 2017-03-05 - invoice_line: - - product_id: product.product_product_18 - fiscal_category_id: l10n_br_account_product.fc_78df616ab31e95ee46c6a519a2ce9e12 - quantity: 1.0 - price_unit: 1000.00 -- - I check if found fisal position and CFOP, document type and document serie -- - !assert {model: account.invoice, id: account_invoice_customer_sp_sp_banking}: - - fiscal_position != False - - fiscal_document_id.id == company_id.product_invoice_id.id - - document_serie_id.fiscal_document_id.id == fiscal_document_id.id - - invoice_line[0].fiscal_position.id == ref('l10n_br_account_product.fp_78df616ab31e95ee46c6a519a2ce9e12_internal_demo') - - invoice_line[0].cfop_id.code == '5101' - -- - I check that Initially customer invoice is in the "Draft" state -- - !assert {model: account.invoice, id: account_invoice_customer_sp_sp_banking}: - - state == 'draft' -- - I create invoice by clicking on Create button -- - !workflow {model: account.invoice, action: invoice_validate, ref: account_invoice_customer_sp_sp_banking} -- - I check that the invoice state is "sefaz_export" -- - !assert {model: account.invoice, id: account_invoice_customer_sp_sp_banking}: - - state == 'sefaz_export' -- - I set the state of invoice to "open" state -- - !workflow {model: account.invoice, action: invoice_open, ref: account_invoice_customer_sp_sp_banking} -- - I check that the invoice state is "open" -- - !assert {model: account.invoice, id: account_invoice_customer_sp_sp_banking}: - - state == 'open' -- - I check if the invoice has a related move that is receivable -- - !assert {model: account.invoice, id: account_invoice_customer_sp_sp_banking}: - - move_id.line_id[0].date_maturity != False - - move_id.line_id[0].account_id.type == 'receivable' -- - I update the main company bank bradesco account digit -- - !record {model: res.partner.bank, id: l10n_br_account_payment_mode.main_company_bank_bradesco}: - bra_acc_dig: '0' -- - I create the payment mode for pagamento -- - !record {model: payment.mode, id: payment_mode_pagamento}: - name: u'Pagamento' - bank_id: l10n_br_account_payment_mode.main_company_bank_bradesco - active: True - payment_order_type: 'payment' - sale_ok: True - journal: account.bank_journal - company_id: base.main_company - type: account_banking_payment_export.manual_bank_tranfer - purchase_ok: False, - type_sale_payment: '99' -- - I create the cnab internal sequence -- - !record {model: ir.sequence, id: cnab_internal_sequence}: - name: u'Sequência interna de cobrança' - number_next: 1 - number_next_actual: 1 -- - I create the cnab sufix internal sequence -- - !record {model: ir.sequence, id: cnab_sufix_internal_sequence}: - name: u'Sequência interna do sufixo da cobrança' - number_next: 1 - number_next_actual: 1 -- - I create the cnab sequence -- - !record {model: l10n_br_cnab.sequence, id: cnab_sequence}: - code: 'Cob' - name: u'Sequência da Cobrança' - internal_sequence_id: cnab_internal_sequence - parent_payment_mode: payment_mode_pagamento -- - I create the cnab sufix sequence -- - !record {model: l10n_br_cnab_file_sufix.sequence, id: cnab_sufix_sequence}: - code: 'CobSuf' - name: u'Sequência do sufixo da Cobrança' - internal_sequence_id: cnab_sufix_internal_sequence - parent_payment_mode_suf: payment_mode_pagamento -- - I create the cobrança (payment.order) -- - !record {model: payment.order, id: cobranca}: - user_id: 1 - mode: l10n_br_account_banking_payment_cnab.payment_mode_cobranca_bradesco240 - date_prefered: 'due' - serie_id: cnab_sequence - serie_sufixo_arquivo: cnab_sufix_sequence -- - I confirm the cobrança (payment order) -- - !workflow {model: payment.order, action: open, ref: cobranca} -- - I check that cobranca(payment order) is now "Confirmed". -- - !assert {model: payment.order, id: cobranca, severity: error, string: Payment Order should be 'Confirmed'.}: - - state == 'open' -- - !record {model: payment.order.create, id: wizard_cobranca}: - duedate: 2017-03-05 -- - I search for the invoice entries to make the payment. -- - !python {model: payment.order.create}: | - self.search_entries(cr, uid, [ref("wizard_cobranca")], { - "active_model": "payment.order", "active_ids": [ref("cobranca")], - "active_id": ref("cobranca"), }) -- - I create payment lines entries. -- - !python {model: payment.order.create}: | - invoice = self.pool.get('account.invoice').browse(cr, uid, ref("account_invoice_customer_sp_sp_banking")) - move_line = invoice.move_id.line_id[0] - self.write(cr, uid, [ref("wizard_cobranca")], {'entries': [(6,0,[move_line.id])]}) - self.create_payment(cr, uid, [ref("wizard_cobranca")], { - "active_model": "payment.order", "active_ids": [ref("cobranca")], - "active_id": ref("cobranca")}) -- - I check that payment line is created with proper data. -- - !python {model: payment.order}: | - invoice = self.pool.get('account.invoice').browse(cr, uid, ref("account_invoice_customer_sp_sp_banking")) - payment = self.browse(cr, uid, ref("cobranca")) - payment_line = payment.line_ids[0] - # rename the payment line because we can't test if the generated file get dinamic information (payment line get the by ir.sequence) - payment_line.name = '001' - payment_line.move_line_id.move_id.name = 1 - - assert payment_line.move_line_id, "move line is not created in payment line." - assert invoice.move_id.name == payment_line.ml_inv_ref.number, "invoice reference number is not same created." - assert invoice.partner_id == payment_line.partner_id, "Partner is not correct." - assert invoice.date_due == payment_line.ml_maturity_date, "Due date is not correct." - assert invoice.amount_total == payment_line.amount, "Payment amount is not correct." - assert payment_line.move_line_id.amount_to_pay > 0, "Move line paid" - assert len(self.pool("account.move.line").search(cr, uid, - [('amount_to_pay', '>', 0), ('id', '=', payment_line.move_line_id.id)])) == 0, \ - "No payment order found for this move line" -- - I generate the .REM file and compare it with a test file -- - !python {model: payment.order, id: cobranca}: | - import base64 - import time - assert self.mode.type.ir_model_id.model == 'payment.cnab', "Modelo de wizard errado, deveria ser payment.cnab porem o selecionado foi: %s" %self.mode.type.ir_model_id.model - wizard = self.env['payment.cnab'].create({}) - wizard.with_context(active_ids=[self.env.ref("l10n_br_account_banking_payment_cnab.cobranca").id]).export() - generated_file = base64.b64decode(str(wizard.cnab_file)) - - # fixing dates to have the same date as the test_file - def change(string, interval, what): - start = interval[0] - end = interval[1] - length = end - start - if len(what) + + + + bank.payment.line.form + bank.payment.line + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+
+ + +
+ \ No newline at end of file diff --git a/l10n_br_account_banking_payment_cnab/view/l10n_br_cnab_retorno_view.xml b/l10n_br_account_banking_payment_cnab/view/l10n_br_cnab_retorno_view.xml new file mode 100644 index 0000000..7604f01 --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/view/l10n_br_cnab_retorno_view.xml @@ -0,0 +1,173 @@ + + + + + + + + cnab.retorno.tree + l10n.br.cnab + + + + + + + + + + + + + + + cnab.lote.tree + l10n.br.cnab.lote + + + + + + + + + + + + + + + + + cnab.evento.tree + l10n.br.cnab.evento + + + + + + + + + + + + + + + + + + + + + cnab.retorno.evento.form.view + l10n.br.cnab.evento + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + cnab.retorno.lote.form.view + l10n.br.cnab.lote + +
+
+ +
+ + + + + + + + + + + + + + + + + +
+
+
+ + + cnab.retorno.form.view + l10n.br.cnab + +
+
+
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + CNAB Retorno + ir.actions.act_window + l10n.br.cnab + form + tree,form + + + + +
+
\ No newline at end of file diff --git a/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab.xml b/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab.xml index 2e314d1..981c640 100644 --- a/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab.xml +++ b/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab.xml @@ -20,7 +20,7 @@ Crie ordens de cobrança CNAB 240. - + payment.order.form diff --git a/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab_lines.xml b/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab_lines.xml index e5890de..c809942 100644 --- a/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab_lines.xml +++ b/l10n_br_account_banking_payment_cnab/view/l10n_br_cobranca_cnab_lines.xml @@ -87,7 +87,7 @@ Lista das linhas cnab 400. - + diff --git a/l10n_br_account_banking_payment_cnab/view/payment_line.xml b/l10n_br_account_banking_payment_cnab/view/payment_line.xml new file mode 100644 index 0000000..bf79e1d --- /dev/null +++ b/l10n_br_account_banking_payment_cnab/view/payment_line.xml @@ -0,0 +1,37 @@ + + + + payment.order.form + + payment.order + + + {'order_id': active_id or False, + 'default_mode': mode} + + + + + + + + + + + + + + + payment.line.form + payment.line + + + +
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/l10n_br_account_banking_payment_cnab/view/payment_mode.xml b/l10n_br_account_banking_payment_cnab/view/payment_mode.xml index e0c7cb8..abec16c 100644 --- a/l10n_br_account_banking_payment_cnab/view/payment_mode.xml +++ b/l10n_br_account_banking_payment_cnab/view/payment_mode.xml @@ -15,6 +15,17 @@
+ + + + + + + + + + +
diff --git a/l10n_br_account_banking_payment_cnab/view/payment_order.xml b/l10n_br_account_banking_payment_cnab/view/payment_order.xml index c601651..d71dc0b 100644 --- a/l10n_br_account_banking_payment_cnab/view/payment_order.xml +++ b/l10n_br_account_banking_payment_cnab/view/payment_order.xml @@ -6,22 +6,23 @@ payment.order.form.sequence payment.order + ref="account_banking_payment_export.view_payment_order_form"/> - + + + + + + + - - - - - - - - + + + + + - diff --git a/l10n_br_account_banking_payment_cnab/view/res_partner_bank.xml b/l10n_br_account_banking_payment_cnab/view/res_partner_bank.xml index 3e47645..88e7551 100644 --- a/l10n_br_account_banking_payment_cnab/view/res_partner_bank.xml +++ b/l10n_br_account_banking_payment_cnab/view/res_partner_bank.xml @@ -10,14 +10,22 @@ + + + + + + {'required': True} + + + + {'required': True} + + - - - - diff --git a/l10n_br_account_banking_payment_cnab/wizard/l10n_bank_payment_cnab_export.py b/l10n_br_account_banking_payment_cnab/wizard/l10n_bank_payment_cnab_export.py index 6e21f5b..b951042 100644 --- a/l10n_br_account_banking_payment_cnab/wizard/l10n_bank_payment_cnab_export.py +++ b/l10n_br_account_banking_payment_cnab/wizard/l10n_bank_payment_cnab_export.py @@ -24,50 +24,72 @@ import base64 import time -from openerp import models, api, workflow, fields - +from openerp import models, api, workflow, fields, _ +from openerp.exceptions import Warning as UserError from ..febraban.cnab import Cnab +import logging -# TODO Server action para a cada dia retornar o sufixo do arquivo para zero +_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(u'Nome', size=255) - cnab_file = fields.Binary('CNAB File', readonly=True) + name = fields.Char(string=u'Nome', size=255) + + cnab_file = fields.Binary(string='CNAB File', readonly=True) + state = fields.Selection( - [('init', 'init'), - ('done', 'done')], - 'state', + string='state', + selection=[('init', 'init'), ('done', 'done')], default='init', - readonly=True) + 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) - cnab = Cnab.get_cnab(order.mode.bank_id.bank_bic, - order.mode.type.code)() - remessa = cnab.remessa(order) - suf_arquivo = order.get_next_sufixo() + 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.file_number)) - elif order.mode.type.code == '400': - self.name = 'CB%s%s.REM' % ( - time.strftime('%d%m'), str(suf_arquivo)) + # 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.file_number)) self.state = 'done' self.cnab_file = base64.b64encode(remessa) - workflow.trg_validate(self.env.uid, 'payment.order', order_id, - 'done', self.env.cr) + order.cnab_file = base64.b64encode(remessa) + order.cnab_filename = self.name + + workflow.trg_validate( + self.env.uid, 'payment.order', order_id, 'done', self.env.cr) return { 'type': 'ir.actions.act_window', diff --git a/l10n_br_account_payment_boleto/demo/payment_demo.xml b/l10n_br_account_payment_boleto/demo/payment_demo.xml index 94e0f0c..26d9d2c 100644 --- a/l10n_br_account_payment_boleto/demo/payment_demo.xml +++ b/l10n_br_account_payment_boleto/demo/payment_demo.xml @@ -20,7 +20,7 @@ 18 DM 29 - S + 03 DM 19 - N + @@ -65,7 +65,7 @@ CNR PD - N + @@ -87,7 +87,7 @@ 109 DM - N + 102 DM - N + @@ -132,7 +132,7 @@ SR - N + SR - N + diff --git a/l10n_br_account_payment_mode/__openerp__.py b/l10n_br_account_payment_mode/__openerp__.py index 24c78be..1d58a49 100644 --- a/l10n_br_account_payment_mode/__openerp__.py +++ b/l10n_br_account_payment_mode/__openerp__.py @@ -8,14 +8,13 @@ 'version': '8.0.1.0.0', 'category': 'Banking addons', 'license': 'AGPL-3', - 'summary': '', 'author': "KMEE, Odoo Community Association (OCA)", "website": "https://odoo-community.org/", 'depends': [ - 'l10n_br_account', 'l10n_br_data_base', 'account_due_list_payment_mode', - 'account_banking_payment_export' + 'account_banking_payment_export', + 'l10n_br_account_banking_payment', ], 'data': [ 'views/payment_mode_view.xml', diff --git a/l10n_br_account_payment_mode/models/payment_mode.py b/l10n_br_account_payment_mode/models/payment_mode.py index 16e1946..a27a4fd 100644 --- a/l10n_br_account_payment_mode/models/payment_mode.py +++ b/l10n_br_account_payment_mode/models/payment_mode.py @@ -39,16 +39,6 @@ class PaymentMode(models.Model): ('99', u'99 - Outros')], string='Tipo SPED', required=True, default='99') - type_purchase_payment = fields.Selection( - [('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'), - ] - ) internal_sequence_id = fields.Many2one('ir.sequence', u'Sequência') instrucoes = fields.Text(u'Instruções de cobrança') invoice_print = fields.Boolean( diff --git a/l10n_br_account_payment_mode/views/payment_mode_view.xml b/l10n_br_account_payment_mode/views/payment_mode_view.xml index 8ace235..da9cc2b 100644 --- a/l10n_br_account_payment_mode/views/payment_mode_view.xml +++ b/l10n_br_account_payment_mode/views/payment_mode_view.xml @@ -16,7 +16,8 @@ - + - - - + + diff --git a/l10n_br_cnab400_import/__openerp__.py b/l10n_br_cnab400_import/__openerp__.py index bfc0c1a..d0e1974 100644 --- a/l10n_br_cnab400_import/__openerp__.py +++ b/l10n_br_cnab400_import/__openerp__.py @@ -40,7 +40,7 @@ 'data/l10n_br_res_partner_bank_type.xml', ], 'active': False, - "installable": True, + "installable": False, "auto_install": False, 'description': """ Allows to import CNAB 400 (Centro Nacional de Automação Bancária) diff --git a/l10n_br_cnab400_import/models/__init__.py b/l10n_br_cnab400_import/models/__init__.py index d0a4b42..3c3f5f6 100644 --- a/l10n_br_cnab400_import/models/__init__.py +++ b/l10n_br_cnab400_import/models/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -#from . import account_bank_statement_line +# from . import account_bank_statement_line from . import account_move_line from . import account_bank_statement_import from . import l10n_br_cnab_move diff --git a/l10n_br_cnab400_import/models/account_bank_statement.py b/l10n_br_cnab400_import/models/account_bank_statement.py index 309e471..fc38fe8 100644 --- a/l10n_br_cnab400_import/models/account_bank_statement.py +++ b/l10n_br_cnab400_import/models/account_bank_statement.py @@ -28,11 +28,11 @@ class AccountBankStatementLine(models.Model): @api.model def get_reconcile_lines_from_cnab_move(self, this, excluded_ids=None): """return move.line to reconcile with statement line""" - move_lines = self.env['account.move.line'].search( - [('transaction_ref', '=', this.name), - ('name', '=', this.ref), - ('company_id', '=', self.env.user.company_id.id) - ]) + move_lines = self.env['account.move.line'].search([ + ('transaction_ref', '=', this.name), + ('name', '=', this.ref), + ('company_id', '=', self.env.user.company_id.id) + ]) try: assert len(move_lines) <= 1 except Exception, e: