diff --git a/README.md b/README.md index b7aef636f..0842c8c5e 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ Criado pelo pessoal da [Akretion](http://www.akretion.com) muito TOP \o/ | 399 - HSBC | CNR, CSB - [Rafael DL](https://github.com/rafaeldl) | | | 748 - Sicredi | C (03) | | | 756 - Sicoob | Todas as carteiras presentes na documentação | | -| 756 - Unicred | 03 - [Marcelo J. Both](https://github.com/marceloboth) | | | 085 - AILOS | Todas as carteiras presentes na documentação - [Marcelo J. Both](https://github.com/marceloboth)| | +| 136 - Unicred | 21 - [Magno Costa](https://github.com/mbcosta) | | | 097 - CREDISIS | Todas as carteiras presentes na documentação - [Marcelo J. Both](https://github.com/marceloboth) | | | 745 - Citibank | 3 | | diff --git "a/docs/unicred/GR - COB136 - Composi\303\247\303\243o da Ficha de Compensa\303\247\303\243o 03DEZ2019.pdf" "b/docs/unicred/GR - COB136 - Composi\303\247\303\243o da Ficha de Compensa\303\247\303\243o 03DEZ2019.pdf" new file mode 100644 index 000000000..530701a29 Binary files /dev/null and "b/docs/unicred/GR - COB136 - Composi\303\247\303\243o da Ficha de Compensa\303\247\303\243o 03DEZ2019.pdf" differ diff --git a/docs/unicred/GR - COB136 - Layout CNAB 400 - Remessa.pdf b/docs/unicred/GR - COB136 - Layout CNAB 400 - Remessa.pdf new file mode 100644 index 000000000..59e6da298 Binary files /dev/null and b/docs/unicred/GR - COB136 - Layout CNAB 400 - Remessa.pdf differ diff --git a/docs/unicred/GR - COB136 - Layout CNAB 400 - Retorno.pdf b/docs/unicred/GR - COB136 - Layout CNAB 400 - Retorno.pdf new file mode 100644 index 000000000..3a7ae2b73 Binary files /dev/null and b/docs/unicred/GR - COB136 - Layout CNAB 400 - Retorno.pdf differ diff --git a/lib/brcobranca/boleto/unicred.rb b/lib/brcobranca/boleto/unicred.rb index 51e34f227..be91b342d 100755 --- a/lib/brcobranca/boleto/unicred.rb +++ b/lib/brcobranca/boleto/unicred.rb @@ -3,129 +3,104 @@ module Brcobranca module Boleto class Unicred < Base # Banco Unicred - # REQUERIDO: Código do posto da cooperativa de crédito - attr_accessor :posto - # REQUERIDO: Byte de identificação do cedente do bloqueto utilizado para compor o nosso número. - attr_accessor :byte_idt - - validates_length_of :agencia, maximum: 4, message: 'deve ser menor ou igual a 4 dígitos.' - validates_length_of :nosso_numero, maximum: 5, message: 'deve ser menor ou igual a 5 dígitos.' - validates_length_of :conta_corrente, maximum: 5, message: 'deve ser menor ou igual a 5 dígitos.' - # Carteira - # 1 – Com Registro - # 3 – Sem Registro - # Obs.: O Unicred não validará este campo. - validates_length_of :carteira, maximum: 1, message: 'deve ser menor ou igual a 1 dígitos.' - validates_length_of :posto, maximum: 2, message: 'deve ser menor ou igual a 2 dígitos.' - validates_length_of :byte_idt, is: 1, message: 'deve ser 1 se o numero foi gerado pela agencia ou 2-9 se foi gerado pelo beneficiário' - validates_length_of :convenio, maximum: 5, message: 'deve ser menor ou igual a 5 dígitos.' + validates_length_of :agencia, maximum: 4, message: + "deve ser menor ou igual a 4 dígitos." + validates_length_of :nosso_numero, maximum: 10, message: + "deve ser menor ou igual a 10 dígitos." + # validates_length_of :conta_corrente, maximum: 5, message: + # 'deve ser menor ou igual a 5 dígitos.' + # Carteira com 2(dois) caracteres ( SEMPRE 21 ) + validates_length_of :carteira, maximum: 2, message: + "deve ser menor ou igual a 2 dígitos." + validates_length_of :convenio, maximum: 10, message: + "deve ser menor ou igual a 10 dígitos." # Nova instancia do Unicred # @param (see Brcobranca::Boleto::Base#initialize) def initialize(campos = {}) - campos = { carteira: '3', - especie_documento: 'DM', - local_pagamento: 'PAGÁVEL PREFERENCIALMENTE NAS AGÊNCIAS DA UNICRED' + campos = { + carteira: "21", + local_pagamento: "PAGÁVEL PREFERENCIALMENTE NAS AGÊNCIAS DA UNICRED", + aceite: "N", }.merge!(campos) super(campos) end - # Codigo do banco emissor (3 dígitos sempre) + # Codigo do banco emissor 3 digitos sempre # - # @return [String] 3 caracteres numéricos. + # @return [String] 3 caracteres numericos. def banco - '748' - end - - # Carteira - # - # @return [String] 2 caracteres numéricos. - def carteira=(valor) - @carteira = valor.to_s.rjust(1, '0') if valor + "136" end - # Posto - # - # @return [String] 2 caracteres numéricos. - def posto=(valor) - @posto = valor.to_s.rjust(2, '0') if valor - end - - # Número da conta corrente - # @return [String] 5 caracteres numéricos. + # Numero da conta corrente + # @return [String] 9 caracteres numericos. def conta_corrente=(valor) - @conta_corrente = valor.to_s.rjust(5, '0') if valor + @conta_corrente = valor.to_s.rjust(9, "0") if valor end - # Código Beneficiário - # @return [String] 5 caracteres numéricos. + # Codigo Beneficiario + # @return [String] 5 caracteres numericos. def convenio=(valor) - @convenio = valor.to_s.rjust(5, '0') if valor + @convenio = valor.to_s.rjust(5, "0") if valor end - # Dígito verificador do banco + # Digito verificador do banco # @return [String] 1 caractere. def banco_dv - 'X' + "8" end - # Nosso número para exibir no boleto. - # O campo Nosso Número deve ser apresentado no formato AA/BXXXXX-D, onde: - # AA = Ano atual - # B = Byte que pode ser de 2 a 9. Somente será 1 se forem boletos pré-impressos. - # XXXXX = número sequencial - # D = dígito verificador calculado + # Nosso numero para exibir no boleto. Nosso Numero e formado com 11 onze + # caracteres, sendo 10 digitos para o nosso numero e um digito para o + # digito verificador. Ex.: 9999999999-D. Obs.: O Nosso Numero e um + # identificador do boleto, devendo ser atribuido Nosso Numero diferenciado + # para cada um. D = digito verificador calculado # @return [String] # @example - # boleto.nosso_numero_boleto #=> "14/200022-5" + # boleto.nosso_numero_boleto #=> "9999999999-D" def nosso_numero_boleto - "#{nosso_numero_with_byte_idt[0..1]}/#{nosso_numero_with_byte_idt[2..-1]}-#{nosso_numero_dv}" + "#{nosso_numero}-#{nosso_numero_dv}" end def nosso_numero_codigo_barra nosso_numero_boleto.gsub(/\D/, '') end - def nosso_numero_with_byte_idt - "#{data_processamento.strftime('%y')}#{byte_idt}#{nosso_numero}" - end - - # Número seqüencial utilizado para identificar o boleto. - # @return [String] 5 caracteres numéricos. + # Numero sequencial utilizado para identificar o boleto. + # @return [String] 10 caracteres numericos. def nosso_numero=(valor) - @nosso_numero = valor.to_s.rjust(5, '0') if valor + @nosso_numero = valor.to_s.rjust(10, '0') if valor end - # Dígito verificador do nosso número - # @return [Integer] 1 caracteres numéricos. + # Digito verificador do nosso numero + # @return [Integer] 1 caracteres numericos. def nosso_numero_dv - "#{agencia_posto_conta}#{nosso_numero_with_byte_idt}" - .modulo11(mapeamento: mapeamento_para_modulo_11) + "#{nosso_numero}".modulo11(mapeamento: mapeamento_para_modulo_11) end - def agencia_conta_boleto - "#{agencia}.#{posto}.#{convenio}" + def conta_corrente_codigo_barra + "#{conta_corrente}#{conta_corrente_dv}" end - def agencia_posto_conta - "#{agencia}#{posto}#{convenio}" + # AGENCIA / CODIGO DO BENEFICIARIO: devera ser preenchido com o codigo da + # agencia, contendo 4 quatro caracteres / Conta Corrente com 10 dez + # caracteres. Ex. 9999/999999999-9. Obs.: Preencher com zeros a direita + # quando necessario. + def agencia_conta_boleto + "#{agencia} / #{conta_corrente}-#{conta_corrente_dv}" end - # Segunda parte do código de barras. - # Posição Tamanho Conteúdo - # 20 – 20 01 Código numérico correspondente ao tipo de cobrança: “1” – Com Registro “3 – Sem Registro”. Obs.: O SICREDI não validará este campo. - # 21 – 21 01 Código numérico correspondente ao tipo de carteira: “1” - carteira simples - # 22 – 30 09 Nosso número - # 31 – 34 # 04 # Cooperativa de crédito/agência beneficiária - # 35 – 36 # 02 # Posto da cooperativa de crédito/agência beneficiária - # 37 – 41 # 05 # Código do beneficiário - # 42 – 42 # 01 # Será 1 (um) quando houver valor expresso no campo “valor do documento” - # 43 – 43 # 01 # Filler – zeros “0” - # 44 – 44 # 01 # DV do campo livre calculado por módulo 11 com aproveitamento total (resto igual a 0 ou 1 DV cai para 0) + # Segunda parte do codigo de barras. + # Posicao Tamanho Conteudo + # 20 - 23 04 Agencia BENEFICIARIO Sem o digito verificador, + # completar com zeros a esquerda quando necessario + # 24 - 33 10 Conta do BENEFICIARIO Com o digito verificador - + # Completar com zeros a esquerda quando necessario + # 34 – 44 11 Nosso Numero Com o digito verificador def codigo_barras_segunda_parte - campo_livre = "#{carteira}1#{nosso_numero_codigo_barra}#{agencia_posto_conta}10" - campo_livre + campo_livre.modulo11(mapeamento: mapeamento_para_modulo_11).to_s + "#{agencia}#{conta_corrente_codigo_barra}#{nosso_numero_codigo_barra}" end private diff --git a/lib/brcobranca/remessa/cnab400/unicred.rb b/lib/brcobranca/remessa/cnab400/unicred.rb index f4c8dab30..e22338373 100644 --- a/lib/brcobranca/remessa/cnab400/unicred.rb +++ b/lib/brcobranca/remessa/cnab400/unicred.rb @@ -3,94 +3,156 @@ module Brcobranca module Remessa module Cnab400 class Unicred < Brcobranca::Remessa::Cnab400::Base - attr_accessor :posto, :byte_idt - - # Codigo de transmissao fornecido pelo banco - attr_accessor :codigo_transmissao + # codigo da beneficiario (informado pelo Unicred no cadastramento) + attr_accessor :codigo_beneficiario validates_presence_of :agencia, :conta_corrente, :documento_cedente, - :digito_conta, :codigo_transmissao, message: 'não pode estar em branco.' + :digito_conta, :codigo_beneficiario, + message: "não pode estar em branco." - validates_length_of :agencia, maximum: 4, message: 'deve ter 4 dígitos.' - validates_length_of :conta_corrente, maximum: 5, message: 'deve ter 5 dígitos.' - validates_length_of :documento_cedente, minimum: 11, maximum: 14, message: 'deve ter entre 11 e 14 dígitos.' - validates_length_of :carteira, maximum: 2, message: 'deve ter 2 dígitos.' - validates_length_of :digito_conta, maximum: 1, message: 'deve ter 1 dígito.' - validates_length_of :codigo_transmissao, maximum: 20, message: 'deve ter 20 dígitos.' + validates_length_of :agencia, maximum: 4, + message: "deve ter 4 dígitos." + validates_length_of :conta_corrente, maximum: 5, + message: "deve ter 5 dígitos." + validates_length_of :documento_cedente, minimum: 11, maximum: 14, + message: "deve ter entre 11 e 14 dígitos." + validates_length_of :carteira, maximum: 2, + message: "deve ter 2 dígitos." + validates_length_of :digito_conta, maximum: 1, + message: "deve ter 1 dígito." - validates_inclusion_of :carteira, in: %w(01 03 04 05 06 07), message: 'não existente para este banco.' + validates_inclusion_of :carteira, in: %w(21), + message: "não existente para este banco." # Nova instancia do Unicred def initialize(campos = {}) campos = { - aceite: 'N' + aceite: "N" }.merge!(campos) super(campos) end def agencia=(valor) - @agencia = valor.to_s.rjust(4, '0') if valor + @agencia = valor.to_s.rjust(4, "0") if valor end def conta_corrente=(valor) - @conta_corrente = valor.to_s.rjust(5, '0') if valor + @conta_corrente = valor.to_s.rjust(5, "0") if valor end def carteira=(valor) - @carteira = valor.to_s.rjust(2, '0') if valor + @carteira = valor.to_s.rjust(2, "0") if valor end def cod_banco - '748' + "136" end def nome_banco - 'UNICRED'.ljust(15, ' ') + "UNICRED".ljust(15, " ") + end + + def identificador_complemento + " " + end + + # Numero sequencial utilizado para identificar o boleto. + # @return [String] 10 caracteres numericos. + def nosso_numero(nosso_numero) + nosso_numero.to_s.rjust(10, "0") + end + + # Digito verificador do nosso numero + # @return [Integer] 1 caracteres numericos. + def nosso_numero_dv(nosso_numero) + "#{nosso_numero}".modulo11(mapeamento: mapeamento_para_modulo_11) + end + + def nosso_numero_boleto(nosso_numero) + "#{nosso_numero(nosso_numero)}#{nosso_numero_dv(nosso_numero)}" end - # Informacoes da conta corrente do cedente + # Retorna o nosso numero # # @return [String] - # + def formata_nosso_numero(nosso_numero) + "#{nosso_numero_boleto(nosso_numero)}" + end + + def codigo_beneficiario=(valor) + @codigo_beneficiario = valor.to_s.rjust(20, "0") if valor + end + def info_conta - # CAMPO TAMANHO - # codigo da transmissao 20 - "#{codigo_transmissao}" + codigo_beneficiario end # Complemento do header - # (no caso do Unicred, sao apenas espacos em branco) # # @return [String] # def complemento - ''.rjust(294, ' ') + "codigo_beneficiario".rjust(277, " ") end - # Codigo da carteira de acordo com a documentacao do Unicred - # - # @return [String] - # - def codigo_carteira - codigo_carteira = carteira[1] + def sequencial_remessa=(valor) + @sequencial_remessa = valor.to_s.rjust(7, "0") if valor end - def identificador_complemento - " " + def digito_agencia + # utilizando a agencia com 4 digitos + # para calcular o digito + agencia.modulo11(mapeamento: { 10 => "X" }).to_s end - # Retorna o nosso numero + def digito_conta + # utilizando a conta corrente com 5 digitos + # para calcular o digito + conta_corrente.modulo11(mapeamento: { 10 => "0" }).to_s + end + + def mapeamento_para_modulo_11 + { + 10 => 0, + 11 => 0 + } + end + + # Header do arquivo remessa # # @return [String] - def formata_nosso_numero(nosso_numero) - nosso_numero.somente_numeros.rjust(20, ' ') + # + def monta_header + # CAMPO TAMANHO VALOR + # tipo do registro [1] 0 + # operacao [1] 1 + # literal remessa [7] REMESSA + # Codigo do serviço [2] 01 + # cod. servico [15] COBRANCA + # info. conta [20] + # empresa mae [30] + # cod. banco [3] + # nome banco [15] + # data geracao [6] formato DDMMAA + # branco [7] + # Codigo da Variacaoo carteira da UNICRED 003 + # Preencher com 000. [3] 000 + # Numero Sequencial do arquivo [7] + # complemento registro [277] + # num. sequencial [6] 000001 + header = "01REMESSA01COBRANCA #{info_conta}" + header << "#{empresa_mae.format_size(30)}#{cod_banco}" + header << "#{nome_banco}#{data_geracao} 000" + header << "#{sequencial_remessa}#{complemento}000001" + header end # Detalhe do arquivo # # @param pagamento [PagamentoCnab400] - # objeto contendo as informacoes referentes ao boleto (valor, vencimento, cliente) + # objeto contendo as informacoes referentes ao + # boleto (valor, vencimento, cliente) # @param sequencial # num. sequencial do registro no arquivo # @@ -99,43 +161,97 @@ def formata_nosso_numero(nosso_numero) def monta_detalhe(pagamento, sequencial) raise Brcobranca::RemessaInvalida, pagamento if pagamento.invalid? - detalhe = '1' # identificacao transacao 9[01] - detalhe << Brcobranca::Util::Empresa.new(documento_cedente).tipo # tipo de identificacao da empresa 9[02] - detalhe << documento_cedente.to_s.rjust(14, '0') # cpf/cnpj da empresa 9[14] - detalhe << codigo_transmissao # código da transmissao 9[20] - detalhe << pagamento.documento_ou_numero.to_s.ljust(25) # numero de controle do participante X[25] - detalhe << formata_nosso_numero(pagamento.nosso_numero) # nosso numero X[20] - detalhe << ''.rjust(25, ' ') # brancos X[25] - detalhe << codigo_carteira # codigo da carteira X[01] - detalhe << pagamento.identificacao_ocorrencia # identificacao ocorrencia 9[02] - detalhe << pagamento.numero.to_s.rjust(10, '0') # numero do documento X[10] - detalhe << pagamento.data_vencimento.strftime('%d%m%y') # data do vencimento 9[06] - detalhe << pagamento.formata_valor # valor do documento 9[13] - detalhe << cod_banco # codigo banco 9[03] - detalhe << ''.rjust(5, '0') # agencia cobradora - deixar zero 9[05] - detalhe << '01' # especie do titulo X[02] - detalhe << aceite # aceite (A/N) X[01] - detalhe << pagamento.data_emissao.strftime('%d%m%y') # data de emissao 9[06] - detalhe << "".rjust(4, "0") # instrucao 9[04] - detalhe << "0" # zero 9[01] - detalhe << pagamento.formata_valor_mora(12) # valor mora ao dia 9[12] - detalhe << pagamento.formata_data_desconto # data limite para desconto 9[06] - detalhe << pagamento.formata_valor_desconto # valor do desconto 9[13] - detalhe << pagamento.formata_valor_iof # valor do iof 9[13] - detalhe << pagamento.formata_valor_abatimento # valor do abatimento 9[13] - detalhe << pagamento.identificacao_sacado # identificacao do pagador 9[02] - detalhe << pagamento.documento_sacado.to_s.rjust(14, '0') # documento do pagador 9[14] - detalhe << pagamento.nome_sacado.format_size(40) # nome do pagador X[40] - detalhe << pagamento.endereco_sacado.format_size(40) # endereco do pagador X[40] - detalhe << pagamento.bairro_sacado.format_size(12) # bairro do pagador X[12] - detalhe << pagamento.cep_sacado # cep do pagador 9[08] - detalhe << pagamento.cidade_sacado.format_size(15) # cidade do pagador X[15] - detalhe << pagamento.uf_sacado # uf do pagador X[02] - detalhe << pagamento.nome_avalista.format_size(40) # nome do sacador/avalista X[40] - detalhe << pagamento.dias_protesto.rjust(2, '0') # numero de dias para proteste 9[02] - detalhe << "9" # moeda 9[01] - detalhe << sequencial.to_s.rjust(6, '0') # numero do registro no arquivo 9[06] + # identificacao transacao 9[01] + detalhe = "1" + # Agencia do BENEFICIARIO na UNICRED 9[05] 002 a 006 + detalhe << agencia.rjust(5, "0") + # Digito da Agencia 9[01] 007 a 007 + detalhe << digito_agencia + # Conta Corrente 9[12] 008 a 019 + detalhe << conta_corrente.rjust(12, "0") + # Digito da Conta 9[1] 020 a 020 + detalhe << digito_conta + # Zero 9[1] 021 a 021 + detalhe << "0" + # Codigo da Carteira 9[3] 022 a 024 + detalhe << carteira.rjust(3, "0") + # Zeros 9[13] 025 a 037 + detalhe << "".rjust(13, "0") + # No Controle do Participante Uso + # da empresa 9[25] 038 a 062 + detalhe << "".rjust(25, " ") + # Codigo do Banco na Camara de Compensacao 9[3] 063 a 065 + detalhe << cod_banco + # Zeros 9[2] 066 a 067 + detalhe << "00" + # Branco 9[25] 068 a 092 + detalhe << "".rjust(25, " ") + # Filler 9[01] 093 a 093 + detalhe << "0" + # Codigo da multa 9[1] 094 a 094 + detalhe << pagamento.codigo_multa + # Valor/Percentual da Multa 9[1] 095 a 104 + detalhe << pagamento.formata_percentual_multa(10) + # Tipo de Valor Mora 9[1] 105 a 105 + detalhe << pagamento.tipo_mora + # Identificacao de Titulo Descontavel 9[1] 106 a 106 + detalhe << "N" + # Branco 9[1] 107 a 108 + detalhe << " " + # Identificacao da Ocorrencia 9[2] 109 a 110 + detalhe << pagamento.identificacao_ocorrencia + # numero do documento X[10] 111 a 120 + detalhe << pagamento.numero.to_s.rjust(10, "0") + # data do vencimento 9[06] 121 a 126 + detalhe << pagamento.data_vencimento.strftime("%d%m%y") + # valor do documento 9[13] 127 a 139 + detalhe << pagamento.formata_valor + # Filler 9[10] 140 a 149 + detalhe << "".rjust(10, "0") + # Codigo do Desconto 9[1] 150 a 150 + detalhe << pagamento.cod_desconto + # data de emissao 9[06] 151 a 156 + detalhe << pagamento.data_emissao.strftime("%d%m%y") + # Filler 9[01] 157 a 157 + detalhe << "0" + # Codigo para Protesto 9[1] 158 a 158 + detalhe << pagamento.codigo_protesto + # numero de dias para protesto 9[02] 159 a 160 + detalhe << pagamento.dias_protesto.rjust(2, "0") + # valor mora ao dia 9[13] 161 a 173 + detalhe << pagamento.formata_valor_mora(13) + # data limite para desconto 9[06] 174 a 179 + detalhe << pagamento.formata_data_desconto + # valor do desconto 9[13] 180 a 192 + detalhe << pagamento.formata_valor_desconto + # nosso numero X[11] 193 a 203 + detalhe << formata_nosso_numero(pagamento.nosso_numero) + # Zeros 9[2] 204 a 205 + detalhe << "00" + # valor do abatimento 9[13] 206 a 218 + detalhe << pagamento.formata_valor_abatimento(13) + # Identificacao do Tipo de Inscricao do Pagador 9[2] 219 a 220 + detalhe << pagamento.identificacao_sacado + # documento do pagador 9[14] 221 a 234 + detalhe << pagamento.documento_sacado.to_s.rjust(14, "0") + # nome do pagador X[40] 235 a 274 + detalhe << pagamento.nome_sacado.format_size(40) + # endereco do pagador X[40] 275 a 314 + detalhe << pagamento.endereco_sacado.format_size(40) + # bairro do pagador X[12] 315 a 326 + detalhe << pagamento.bairro_sacado.format_size(12) + # cep do pagador 9[08] 327 a 334 + detalhe << pagamento.cep_sacado + # cidade do pagador X[15] 335 a 354 + detalhe << pagamento.cidade_sacado.format_size(20) + # uf do pagador X[02] 355 a 356 + detalhe << pagamento.uf_sacado + # nome do sacador/avalista X[38] 357 a 394 + detalhe << pagamento.nome_avalista.format_size(38) + # numero do registro no arquivo 9[06] 395 a 400 + detalhe << sequencial.to_s.rjust(6, "0") detalhe + end end end diff --git a/lib/brcobranca/retorno/cnab400/base.rb b/lib/brcobranca/retorno/cnab400/base.rb index 85deddff9..5a989c38f 100644 --- a/lib/brcobranca/retorno/cnab400/base.rb +++ b/lib/brcobranca/retorno/cnab400/base.rb @@ -29,6 +29,8 @@ def self.load_lines(file, options={}) Brcobranca::Retorno::Cnab400::Itau.load_lines(file, options) when "033", "353" Brcobranca::Retorno::Cnab400::Santander.load_lines(file, options) + when "136" + Brcobranca::Retorno::Cnab400::Unicred.load_lines(file, options) else Brcobranca::Retorno::RetornoCnab400.load_lines(file, options) end diff --git a/lib/brcobranca/retorno/cnab400/unicred.rb b/lib/brcobranca/retorno/cnab400/unicred.rb index 720c5cbdd..8f0745d21 100644 --- a/lib/brcobranca/retorno/cnab400/unicred.rb +++ b/lib/brcobranca/retorno/cnab400/unicred.rb @@ -5,11 +5,12 @@ module Brcobranca module Retorno module Cnab400 # Formato de Retorno CNAB 400 - class Unicred < Brcobranca::Retorno::Base + class Unicred < Brcobranca::Retorno::Cnab400::Base extend ParseLine::FixedWidth def self.load_lines(file, options = {}) - default_options = { except: [1] } # por padrao ignora a primeira linha que é header + # por padrao ignora a primeira linha que é header + default_options = { except: [1] } options = default_options.merge!(options) super file, options @@ -17,98 +18,101 @@ def self.load_lines(file, options = {}) fixed_width_layout do |parse| # Todos os campos descritos no documento em ordem - # :tipo_de_registro, 0..0 # identificacao do registro transacao + # :tipo_de_registro, 0..0 # identificacao do registro transacao - Fixo 1 parse.field :codigo_registro, 0..0 # :codigo_de_inscricao, 1..2 # identificacao do tipo de inscricao/empresa # :numero_de_inscricao, 3..16 # numero de inscricao da empresa (cpf/cnpj) - # :zeros, 17..19 # Identificacao da empresa no banco - # :zeros, 20..20 - # :carteira, 21..23 + # :agencia_com_dv, 17..21 + # :digito_agencia, 21..21 + # :cedente_com_dv, 22..29 parse.field :agencia_sem_dv, 17..20 - parse.field :cedente_com_dv, 21..28 - # :agencia_sem_dv, 24..28 - # :cedente_com_dv, 29..36 - - # :numero_controle_empresa, 37..61, # numero de controle da empresa - # :zeros, 62..69 - - # :nosso_numero, 62..69 # identificacao do titulo no banco - parse.field :nosso_numero, 62..69 + parse.field :cedente_com_dv, 22..30 + + # :codigo_beneficiario, 31..44 + # :nosso_numero, 45..61 # identificacao do titulo no banco + parse.field :nosso_numero, 45..61 + + # :FIXO, 62..72 BRANCOS* Este campo deve ser + # desconsiderado. Ele esta reservado para melhorias. + # :zeros, 73..73 + # :FIXO, 74..74 # 1 - SIMPLES + # :FIXO 75..84 BRANCOS* Este campo deve ser + # desconsiderado. Ele esta reservado para melhorias. + # :FIXO 85..87 # 019 + # :zeros 88..105 + # :FIXO 106..107 # 18 + + # :codigo_ocorrencia 108..109 + parse.field :codigo_ocorrencia, 108..109 - # :zeros, 82..91 # uso do banco - # :zeros, 92..103 # uso do banco - # :indicador_de_rateio, 104..104 # indicador de rateio de credito - # :zeros, 105..106 + # :data_credito, 110..115 # data de credito desta liquidacao + parse.field :data_credito, 110..115 - parse.field :carteira, 107 - parse.field :codigo_ocorrencia, 108..109 - parse.field :data_ocorrencia, 110..115 - # :n_do_documento, 116..125 # n umero do documento de cobranca (dupl, np etc) - # :nosso_numero, 126..133 # confirmacao do numero do titulo no banco - # :brancos, 134..145 # complemento de registro + # :FIXO 116..145 BRANCOS* Este campo deve ser + # desconsiderado. Ele está reservado para melhorias. # :vencimento, 146..151 # data de vencimento do titulo (ddmmaa) parse.field :data_vencimento, 146..151 - # :valor_do_titulo, 152..164 # valor nominal do titulo (ultimos 2 digitos, virgula decimal assumida) + # :valor_do_titulo, 152..164 # valor nominal do titulo + # (ultimos 2 digitos, virgula decimal assumida) parse.field :valor_titulo, 152..164 # :codigo_do_banco, 165..167 # numero do banco na camara de compensacao parse.field :banco_recebedor, 165..167 - # :agencia_cobradora, 168..171 # agencia cobradora, ag de liquidacao ou baixa - # :dac_ag_cobradora, 172..172 # dac da agencia cobradora + # :agencia_recebedora, 168..171 # agencia cobradora, + # ag de liquidacao ou baixa + # DV-PREFIXO AGENCIA RECEBEDORA, 172..172 # parse.field :agencia_recebedora_com_dv, 168..172 - # :especie, 173..174 # especie do titulo - parse.field :especie_documento, 173..174 + # :FIXO 173..174 BRANCOS* Este campo deve ser + # desconsiderado. Ele esta reservado para melhorias. - # :tarifa_de_cobranca, 175..187 # valor da despesa de cobranca (ultimos 2 digitos, virgula decimal assumida) - parse.field :valor_tarifa, 175..187 + # DATA PROGRAMADA PARA REPASSE + # :data, 175..180 - # :outras_despesas 188..200, # valor de outras despesas ou custos do protesto - # :juros_operacao_em_atraso, 201..213 # zeros? + # :tarifa_de_cobranca, 181..187 # valor da despesa de cobranca + # (ultimos 2 digitos, virgula decimal assumida) + parse.field :valor_tarifa, 181..187 - # :valor_do_iof, 214..226 # valor do iof a ser recolhido (ultimos 2 digitos, virgula decimal assumida) - parse.field :iof, 214..226 + # :FIXO 188..226 BRANCOS* Este campo deve ser + # desconsiderado. Ele está reservado para melhorias. - # :valor_abatimento, 227..239 # valor do abatimento concedido (ultimos 2 digitos, virgula decimal assumida) + # :valor_abatimento, 227..239 # valor do abatimento concedido + # (ultimos 2 digitos, virgula decimal assumida) parse.field :valor_abatimento, 227..239 - # :descontos, 240..252 # valor do desconto concedido (ultimos 2 digitos, virgula decimal assumida) + # :descontos, 240..252 # valor do desconto concedid + # o (ultimos 2 digitos, virgula decimal assumida) parse.field :desconto, 240..252 - # :valor_recebido, 253..265 # valor lancado em conta corrente (ultimos 2 digitos, virgula decimal assumida) + # :valor_recebido, 253..265 # valor lancado em conta corrente + # (ultimos 2 digitos, virgula decimal assumida) parse.field :valor_recebido, 253..265 - # :juros_mora, 266..278 # valor de mora e multa pagos pelo sacado (ultimos 2 digitos, virgula decimal assumida) + # :juros_mora, 266..278 # valor de mora e multa pagos pelo sacado + # (ultimos 2 digitos, virgula decimal assumida) parse.field :juros_mora, 266..278 - # :outros_creditos, 279..291 # valor de outros creditos (ultimos 2 digitos, virgula decimal assumida) - parse.field :outros_recebimento, 279..291 + # :numero_controle_empresa, 279..304, # numero de controle da empresa - # :brancos, 292..293 - # :motivo_do_codigo_de_ocorrencia, 294..294 + # : Valor Liquido, 305..317 Diferença entre: Valor Pago e Valor da + # Tarifa (Valor Pago – Valor da Tarifa) - # :data_credito, 295..300 # data de credito desta liquidacao - parse.field :data_credito, 295..300 - - # :origem_pagamento, 301..303 - # :brancos, 304..313 - # :cheque_bradesco, 314..317 - # :motivo_rejeicao, 318..327 - # :brancos, 328..367 - # :numero_do_cartorio, 368..369 - # :numero_do_protocolo, 370..379 - # :brancos, 380..393 - - parse.field :motivo_ocorrencia, 318..319, ->(motivos) do + # :Complemento do Movimento 318..325 + parse.field :motivo_ocorrencia, 318..325, ->(motivos) do motivos.scan(/.{2}/).reject(&:blank?).reject{|motivo| motivo == '00'} end + # :Tipo de Instrucao de Origem 326..327 + + # :FIXO 328..393 BRANCOS* Este campo deve ser + # desconsiderado. Ele está reservado para melhorias. + # :numero_sequencial, 394..399 # numero sequencial no arquivo parse.field :sequencial, 394..399 end diff --git a/spec/arquivos/CNAB400UNICRED.RET b/spec/arquivos/CNAB400UNICRED.RET index 4f03eb3cb..b5e899b81 100644 --- a/spec/arquivos/CNAB400UNICRED.RET +++ b/spec/arquivos/CNAB400UNICRED.RET @@ -1,3 +1,3 @@ 02RETORNO01COBRANCA 42056000156620925442CENTRAL DAS COOPERATIVAS DE CR001BANCO DO BRASIL0708131314759 000001 -100000000000000004205600015662092544221 3408928100000011600000116 506150515 00000000000010000001130515000000004440009042050010000000000160000000000000000000000000000000000000000000000000000000000000000000000000044400000000000000000000000000000001505150000000000000008920000000000000 0000000000000000000000000000000000000000000000000000000002 +10200000000000000420500600015660000000000000000000000000000116 01 0190000000000000000001806150515 130515000000004440009042050 1805150000160 0000000000000000000000000000000000444000000000000000 00000000438400000000001 000002 9201001 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000016 diff --git a/spec/brcobranca/boleto/unicred_spec.rb b/spec/brcobranca/boleto/unicred_spec.rb index ddbd202a8..78ee3a90d 100644 --- a/spec/brcobranca/boleto/unicred_spec.rb +++ b/spec/brcobranca/boleto/unicred_spec.rb @@ -17,36 +17,34 @@ conta_corrente: '61900', convenio: 12_345, nosso_numero: '00168', - posto: '1', - byte_idt: '7' } end it 'Criar nova instancia com atributos padrões' do boleto_novo = described_class.new - expect(boleto_novo.banco).to eql('748') + expect(boleto_novo.banco).to eql('136') expect(boleto_novo.especie_documento).to eql('DM') expect(boleto_novo.especie).to eql('R$') expect(boleto_novo.moeda).to eql('9') expect(boleto_novo.data_processamento).to eql(Date.current) expect(boleto_novo.data_vencimento).to eql(Date.current) - expect(boleto_novo.aceite).to eql('S') + expect(boleto_novo.aceite).to eql('N') expect(boleto_novo.quantidade).to be(1) expect(boleto_novo.valor).to eq(0.0) expect(boleto_novo.valor_documento).to eq(0.0) expect(boleto_novo.local_pagamento).to eql('PAGÁVEL PREFERENCIALMENTE NAS AGÊNCIAS DA UNICRED') - expect(boleto_novo.carteira).to eql('3') + expect(boleto_novo.carteira).to eql('21') end it 'Criar nova instancia com atributos válidos' do boleto_novo = described_class.new(@valid_attributes) - expect(boleto_novo.banco).to eql('748') + expect(boleto_novo.banco).to eql('136') expect(boleto_novo.especie_documento).to eql('DM') expect(boleto_novo.especie).to eql('R$') expect(boleto_novo.moeda).to eql('9') expect(boleto_novo.data_processamento).to eql(Date.parse('2012-01-18')) expect(boleto_novo.data_vencimento).to eql(Date.current) - expect(boleto_novo.aceite).to eql('S') + expect(boleto_novo.aceite).to eql('N') expect(boleto_novo.quantidade).to be(1) expect(boleto_novo.valor).to eq(0.0) expect(boleto_novo.valor_documento).to eq(0.0) @@ -55,28 +53,25 @@ expect(boleto_novo.documento_cedente).to eql('12345678912') expect(boleto_novo.sacado).to eql('Claudio Pozzebom') expect(boleto_novo.sacado_documento).to eql('12345678900') - expect(boleto_novo.conta_corrente).to eql('61900') + expect(boleto_novo.conta_corrente).to eql('000061900') expect(boleto_novo.agencia).to eql('4042') expect(boleto_novo.convenio).to eql('12345') - expect(boleto_novo.nosso_numero).to eql('00168') - expect(boleto_novo.carteira).to eql('3') + expect(boleto_novo.nosso_numero).to eql('0000000168') + expect(boleto_novo.carteira).to eql('21') end - it 'Montar código de barras para carteira número 03' do + it 'Montar código de barras para carteira número 21' do @valid_attributes[:valor] = 2952.95 @valid_attributes[:data_vencimento] = Date.parse('2012-01-24') @valid_attributes[:data_documento] = Date.parse('2012-01-19') @valid_attributes[:nosso_numero] = '13871' @valid_attributes[:conta_corrente] = '12345' @valid_attributes[:agencia] = '1234' - @valid_attributes[:carteira] = '3' - @valid_attributes[:posto] = '8' - @valid_attributes[:aceite] = 'N' - @valid_attributes[:byte_idt] = '2' + @valid_attributes[:carteira] = '21' boleto_novo = described_class.new(@valid_attributes) - expect(boleto_novo.codigo_barras.linha_digitavel).to eql('74893.11220 13871.212349 08123.451018 3 52220000295295') - expect(boleto_novo.codigo_barras_segunda_parte).to eql('3112213871212340812345101') + expect(boleto_novo.codigo_barras.linha_digitavel).to eql('13691.23409 00012.345500 00001.387117 1 52220000295295') + expect(boleto_novo.codigo_barras_segunda_parte).to eql('1234000012345500000138711') end it 'Não permitir gerar boleto com atributos inválido' do @@ -88,23 +83,20 @@ it 'Montar nosso_numero_boleto' do boleto_novo = described_class.new(@valid_attributes) - boleto_novo.byte_idt = '2' boleto_novo.agencia = '1234' - boleto_novo.posto = '18' boleto_novo.conta_corrente = '12345' boleto_novo.nosso_numero = '13871' - boleto_novo.carteira = '3' - expect(boleto_novo.nosso_numero_boleto).to eql('12/213871-5') - expect(boleto_novo.nosso_numero_dv).to be(5) + boleto_novo.carteira = '21' + expect(boleto_novo.nosso_numero_boleto).to eql('0000013871-1') + expect(boleto_novo.nosso_numero_dv).to be(1) end it 'Montar agencia_conta_boleto' do boleto_novo = described_class.new(@valid_attributes) boleto_novo.agencia = '1234' - boleto_novo.posto = '18' boleto_novo.conta_corrente = '12345' - expect(boleto_novo.agencia_conta_boleto).to eql('1234.18.12345') + expect(boleto_novo.agencia_conta_boleto).to eql('1234 / 000012345-5') end describe 'Busca logotipo do banco' do diff --git a/spec/brcobranca/remessa/cnab400/unicred_spec.rb b/spec/brcobranca/remessa/cnab400/unicred_spec.rb index a5d541b01..ae14b899f 100644 --- a/spec/brcobranca/remessa/cnab400/unicred_spec.rb +++ b/spec/brcobranca/remessa/cnab400/unicred_spec.rb @@ -5,26 +5,25 @@ let(:pagamento) do Brcobranca::Remessa::Pagamento.new(valor: 199.9, data_vencimento: Date.current, - nosso_numero: '072000031', - documento: 6969, + nosso_numero: '72000031', + documento: '1/01', documento_sacado: '12345678901', - nome_sacado: 'PABLO DIEGO JOSÉ FRANCISCO,!^.?\/@ DE PAULA JUAN NEPOMUCENO MARÍA DE LOS REMEDIOS CIPRIANO DE LA SANTÍSSIMA TRINIDAD RUIZ Y PICASSO', - endereco_sacado: 'RUA RIO GRANDE DO SUL,!^.?\/@ São paulo Minas caçapa da silva junior', - bairro_sacado: 'São josé dos quatro apostolos magros', + nome_sacado: 'AKRETION LTDA', + endereco_sacado: 'AVENIDA PAULISTA 1', + bairro_sacado: 'CENTRO', cep_sacado: '12345678', - cidade_sacado: 'Santa rita de cássia maria da silva', + cidade_sacado: 'SAO PAULO', uf_sacado: 'SP') end let(:params) do { - carteira: '03', + carteira: '21', agencia: '1234', conta_corrente: '12345', digito_conta: '1', empresa_mae: 'SOCIEDADE BRASILEIRA DE ZOOLOGIA LTDA', documento_cedente: '12345678910', - codigo_transmissao: '12345678901234567890', - byte_idt: '2', + codigo_beneficiario: '1234567890', pagamentos: [pagamento] } end @@ -102,24 +101,24 @@ end end - context '@codigo_transmissao' do + context '@codigo_beneficiario' do it 'deve ser inválido se não existir' do - object = subject.class.new(params.merge!(codigo_transmissao: nil)) + object = subject.class.new(params.merge!(codigo_beneficiario: nil)) expect(object.invalid?).to be true - expect(object.errors.full_messages).to include('Codigo transmissao não pode estar em branco.') + expect(object.errors.full_messages).to include('Codigo beneficiario não pode estar em branco.') end - it 'deve ser inválido quando não possuir até 20 dígitos' do - object = subject.class.new(params.merge!(codigo_transmissao: '123456789012345678901')) + it 'deve ser inválido quando maior que 10 dígitos' do + object = subject.class.new(params.merge!(codigo_beneficiario: '12345678901')) expect(object.invalid?).to be true - expect(object.errors.full_messages).to include('Codigo transmissao deve ter 20 dígitos.') + expect(object.errors.full_messages).to include('Codigo Beneficiario não deve ter mais que 10 dígitos.') end end end context 'formatacoes dos valores' do - it 'cod_banco deve ser 748' do - expect(unicred.cod_banco).to eq '748' + it 'cod_banco deve ser 136' do + expect(unicred.cod_banco).to eq '136' end it 'nome_banco deve ser UNICRED com 15 posicoes' do @@ -128,19 +127,19 @@ expect(nome_banco.strip).to eq 'UNICRED' end - it 'complemento deve retornar 294 caracteres' do - expect(unicred.complemento.size).to eq 294 + it 'complemento deve retornar 277 caracteres' do + expect(unicred.complemento.size).to eq 277 end - it 'info_conta deve retornar com 20 posicoes as informacoes da conta' do + it 'info_conta deve retornar com 10 posicoes as informacoes da conta' do info_conta = unicred.info_conta - expect(info_conta.size).to eq 20 - expect(info_conta[0..19]).to eq '12345678901234567890' + expect(info_conta.size).to eq 20 + expect(info_conta[0..19]).to eq '00000000001234567890' end it 'deve retornar o codigo da carteira de acordo com o tipo de emissão' do - unicred.carteira = '03' - expect(unicred.codigo_carteira).to eq '3' + unicred.carteira = '21' + expect(unicred.carteira).to eq '21' unicred.carteira = '09' expect(unicred.invalid?).to be true @@ -157,21 +156,21 @@ expect(header[1]).to eq '1' # tipo operacao (1 = remessa) expect(header[2..8]).to eq 'REMESSA' # literal da operacao expect(header[26..45]).to eq unicred.info_conta # informacoes da conta - expect(header[76..78]).to eq '748' # codigo do banco + expect(header[76..78]).to eq '136' # codigo do banco end end context 'detalhe' do it 'informacoes devem estar posicionadas corretamente no detalhe' do detalhe = unicred.monta_detalhe pagamento, 1 - expect(detalhe[37..61]).to eq "6969".ljust(25) # documento - expect(detalhe[62..81]).to eq '072000031'.rjust(20, ' ') # nosso numero + expect(detalhe[2..5]).to eq '1234' # Agencia + expect(detalhe[108..109]).to eq '01' # Instrução + expect(detalhe[110..119]).to eq "0000001/01" # documento expect(detalhe[120..125]).to eq Date.current.strftime('%d%m%y') # data de vencimento expect(detalhe[126..138]).to eq '0000000019990' # valor do titulo - expect(detalhe[142..145]).to eq '0000' # agência cobradora - expect(detalhe[156..159]).to eq '0000' # instrução + expect(detalhe[192..202]).to eq '72000031'.rjust(10, ' ') # nosso numero expect(detalhe[220..233]).to eq '00012345678901' # documento do pagador - expect(detalhe[234..263]).to eq 'PABLO DIEGO JOSE FRANCISCO DE ' # nome do pagador + expect(detalhe[234..263]).to eq 'AKRETION LTDA' # nome do pagador end end diff --git a/spec/brcobranca/retorno/cnab400/unicred_spec.rb b/spec/brcobranca/retorno/cnab400/unicred_spec.rb index 376fbf00d..84e425611 100644 --- a/spec/brcobranca/retorno/cnab400/unicred_spec.rb +++ b/spec/brcobranca/retorno/cnab400/unicred_spec.rb @@ -19,24 +19,19 @@ expect(pagamento.sequencial).to eql('000002') expect(pagamento.agencia_sem_dv).to eql('4205') - expect(pagamento.cedente_com_dv).to eql('60001566') - expect(pagamento.nosso_numero).to eql('00000116') - expect(pagamento.carteira).to eql('5') + expect(pagamento.cedente_com_dv).to eql('060001566') + expect(pagamento.nosso_numero).to eql('00000000000000116') expect(pagamento.data_vencimento).to eql('130515') expect(pagamento.valor_titulo).to eql('0000000044400') expect(pagamento.banco_recebedor).to eql('090') expect(pagamento.agencia_recebedora_com_dv).to eql('42050') - expect(pagamento.especie_documento).to eql('01') - expect(pagamento.valor_tarifa).to eql('0000000000160') - expect(pagamento.iof).to eql('0000000000000') + expect(pagamento.valor_tarifa).to eql('0000160') expect(pagamento.valor_abatimento).to eql('0000000000000') expect(pagamento.desconto).to eql('0000000000000') expect(pagamento.juros_mora).to eql('0000000000000') - expect(pagamento.outros_recebimento).to eql('0000000000000') expect(pagamento.codigo_ocorrencia).to eql('06') - expect(pagamento.data_ocorrencia).to eql('150515') expect(pagamento.valor_recebido).to eql('0000000044400') expect(pagamento.data_credito).to eql('150515') - expect(pagamento.motivo_ocorrencia).to eql(['20']) + expect(pagamento.motivo_ocorrencia).to eql(['00']) end end diff --git a/spec/fixtures/remessa/remessa-unicred-cnab400.rem b/spec/fixtures/remessa/remessa-unicred-cnab400.rem index 65955304e..c1af58187 100644 --- a/spec/fixtures/remessa/remessa-unicred-cnab400.rem +++ b/spec/fixtures/remessa/remessa-unicred-cnab400.rem @@ -1,3 +1,3 @@ -01REMESSA01COBRANCA 12345678901234567890SOCIEDADE BRASILEIRA DE ZOOLOG748UNICRED 140715 000001 -10100012345678910123456789012345678906969 072000031 301000000000014071500000000199907480000001N140715000000000000000000000000000000000000000000000000000000000000000100012345678901PABLO DIEGO JOSE FRANCISCO DE PAULA JUANRUA RIO GRANDE DO SUL SAO PAULO MINAS CASAO JOSE DOS12345678SANTA RITA DE CSP 009000002 +01REMESSA01COBRANCA 00000000001234567890SOCIEDADE BRASILEIRA DE ZOOLOG136UNICRED 140715 000001 +1012343000000012345100210000000000000 13600 0300000000005N 010000001/01140715000000001999000000000000140715020500000000002000000000000000000000000720000310000000000000000200012345678901AKRETION LTDA AVENIDA PAULISTA 1 CENTRO 12345678SAO PAULO SP 000002 9 000003