#!/usr/bin/perl use CGI qw(param); # LEITURA DE DADOS $barra=param("barra"); # não passar este parametro, este programa o fará sozinho. $logourl=param("logourl"); # url do logotipo da empresa que será impresso no boleto. $cedente=param("cedente") || param("nome_favorecido"); # nome do cedente $agencia=param("agencia") || param("numero_agencia"); # número da agência do cedente, SEM DV $cc=param("cc") || param("numero_conta"); # número da conta corrente do cedente, COM DV $vencimento=param("vencimento") || "À Vista"; # data de vencimento formato dd/mm/aaaa ou "À vista" ou "Contra apresentação" $sacado=param("sacado"); # nome do sacado na primeira linha, os demais dados nas seguintes $documento=param("documento"); # número do documento. Pode e costuma ser nulo. $nn=param("nn"); # nosso número SEM DV $quantidade=param("quantidade"); # pode e costuma ser nulo. $valor=param("valor"); # pode e costuma ser nulo $valor_documento=param("valor_documento"); # valor inicial sem descontos, sem multas, etc. $desconto=param("desconto") || "
"; # pode e costuma ser nulo $acrescimos=param("acrescimos"); # outros acréscimos $demonstrativo=param("demonstrativo"); # referente à compra de...? #$cobrado=param("cobrado"); # valor cobrado -> não posso passar esse valor, ele deve ser preenchido manualmente em caso de atraso de pgto $codigo_banco=param("codigo_banco"); # código do banco. Exemplo: 001 para BB, 341 para Itaú $local=param("local"); # local de pagamento $data_documento=param("data_documento") || today(); # data de emissão do boleto $aceite=param("aceite") || "N"; # não precisa passar como parâmetro $especie=param("especie") || "RC"; #não precisa passar como parâmetro $data_processamento=param("data_processamento") || $data_documento; #não precisa passar como parâmetro $uso_do_banco=param("uso_do_banco"); # deixe nulo $carteira=param("carteira"); # número da carteira $instrucoes=param("instrucoes") || "Sr. Caixa: não receber após o vencimento"; $multa=param("multa") || "
"; # formato 1234,56, deixar null caso a multa seja zero $total=param("total") || $valor_documento; # total a cobrar. $codigo_boleto=param("codigo_boleto"); # PARA HSBC = codigo do cedente / PARA UNIBANCO = CODIGO DE CLIENTE / PARA BB = CONVÊNIO / PARA CEF = "CÓDIGO DO CEDENTE" FORNECIDO PELO BANCO. $codigo_cedente=$cc; if ($codigo_banco eq "104") { $codigo_cedente=$codigo_boleto; } $width="640"; # largura do boleto em pixels $total=sprintf ("%.2f","$total"); $valor=sprintf ("%.2f","$valor") if $valor; $valor_documento=sprintf ("%.2f","$valor_documento") if $valor_documento; $acrescimos=sprintf ("%.2f","$acrescimos") if $acrescimos; $multa=sprintf ("%.2f","$multa") if ($multa!="
"); # SE RECEBO CÓDIGO DE BARRAS, IMPRIMO E FINALIZO EXECUÇÃO if ($barra) { # http://search.cpan.org/~kwitknr/GD-Barcode-1.15/Barcode/ITF.pm use GD::Barcode::ITF; binmode(STDOUT); print "Content-Type: image/png\n\n"; print GD::Barcode::ITF->new("$barra")->plot(NoText=>1, Height => 50)->png; # print GD::Barcode::ITF->new("$barra")->plot(NoText=>0, Height => 50)->png; exit; } print "Content-type: text/html\n\n"; # VAMOS ORGANIZAR OS NOMES DOS BANCOS SUPORTADOS $nome_banco{"341"}="Banco Itaú SA"; $nome_banco{"409"}="Unibanco"; $nome_banco{"237"}="Banco Bradesco SA"; $nome_banco{"001"}="Banco do Brasil"; $nome_banco{"104"}="Caixa Econômica Federal"; $nome_banco{"399"}="HSBC"; # SE NÃO RECEBO LOCAL DE PAGAMENTO, VOU DECLARÁ-LO if (!$local) { if ($codigo_banco eq "104") { $local="Pagável preferencialmente em casas lotéricas, agências da Caixa ou redes bancárias até o vencimento."; } elsif ( ($vencimento=~/Vista/i) || ($vencimento=~/apresenta/i) ) { $local="Pagável em qualquer banco."; } elsif ($vencimento=~/\//) { $local="Pagável em qualquer banco até a data de vencimento. Após o vencimento, pagável apenas no $nome_banco{$codigo_banco}."; } } # PREENCHENDO NOSSO NUMERO COM ZEROS À ESQUERDA if ($codigo_banco eq "341") { $length_nn = 8; } elsif ($codigo_banco eq "409") { $length_nn = 14; } elsif ($codigo_banco eq "237") { $length_nn = 11; } elsif ($codigo_banco eq "001") { # O TAMANHO DO NOSSO NÚMERO PODE VARIAR DE 11+1DV ATÉ 17+1DV $ok=0; # CONVÊNIO 6 posições ENTÃO NN 11 posições + 1 DV ETC if (length($codigo_boleto)==6 && length($nn)==11) { $ok=1; } # CONVÊNIO 6 POSIÇÕES - NN 17 POSIÇõES+DV - CARTEIRA 16 E 18 if (length($codigo_boleto)==6 && length($nn)==17 && ($carteira eq "16" || $carteira eq "18") ) { $ok=1; } # CONVÊNIO 7 posições - NN 17 posições + 1 DV - CARTEIRA 17 e 18 somente if (length($codigo_boleto)==7 && length($nn)==17 && ($carteira eq "17" || $carteira eq "18") ) { $ok=1; } if ( $codigo_boleto ne substr($nn,0,length($codigo_boleto)) && ($carteira eq "17" || $carteira eq "18") && length($codigo_boleto) ==7 ) { &erro("Erro: carteiras 17 e 18 do BB com nosso número de 17 dígitos, e número do convênio de 7 dígitos, devem ter número do convênio igual aos primeiros dígitos do Nosso Número. Exemplo: convênio 1234567, nosso número deve ser 1234567XXXXXXXXXX, onde X é qualquer dígito."); } if (!$ok) { &erro("Inválida combinação de Convênio $codigo_boleto / Nosso Número $nn / Carteira $carteira."); if (length($codigo_boleto)==7 && length($nn)<17 ) { &erro("Convênio de 7 dígitos requer nosso número com 17 dígitos, e carteira 17 ou 18."); } } } elsif ($codigo_banco eq "399") { $length_nn = 13; } elsif ($codigo_banco eq "104" && $carteira eq 'SR5') { $length_nn = 17; } elsif ($codigo_banco eq "104" && $carteira eq 'SR') { $length_nn = 15; } if ($codigo_banco ne "001" && length($nn) > $length_nn) { &erro("Nosso número possui " . length($nn) . " dígitos, enquanto deveria possuir " . $length_nn . " dígitos."); } if ($codigo_banco ne "001") { while (length($nn)<$length_nn) { $nn="0$nn"; } } # ARRUMANDO AS INFORMAÇÕES DO SACADO if ($sacado!~/
/i) { if ($sacado=~/\n/) { $sacado=~s/\n/
/g; $sacado=~s/\r//g; } } @linhas_sacado=split(/
/,$sacado); # ARRUMANDO O TOTAL A PAGAR $total=~s/\,/\./g; if ($total!~/\./) { $total.=".00"; } $total_digitavel=$total; $total_digitavel=~s/\.//; while (length($total_digitavel)<10) { $total_digitavel="0$total_digitavel"; } # ARRUMANDO O VENCIMENTO if ($vencimento=~/\//) { ($dia_vencimento,$mes_vencimento,$ano_vencimento)=split(/\//,$vencimento); $fator_vencimento=deltaDia(07,10,1997,$dia_vencimento,$mes_vencimento,$ano_vencimento); } else { $fator_vencimento="0000"; } # ARRUMANDO CONTA CORRENTE / AGÊNCIA $conta_corrente_sem_traco=$cc; $conta_corrente_sem_traco=~s/\-//g; $conta_corrente_sem_traco=~s/\.//g; ($cc_sem_dv,$lixo)=split(/-/,$cc); $agencia_sem_traco=$agencia; $agencia_sem_traco=~s/\-//g; $agencia_sem_traco=~s/\.//g; ($agencia_sem_dv,$lixo)=split(/-/,$agencia); # BANCOS SUPORTADOS: # -------------------------------------- ITAÚ ---------------------------------- if ($codigo_banco eq "341") { @carteiras_nao_suportadas=(126,131,146,150,168,198); foreach $tmp (@carteiras_nao_suportadas) { if ($carteira eq $tmp) { &erro("Carteira '$tmp' não suportada."); } } # VALIDANDO NÚMERO DA CONTA CORRENTE if (length($conta_corrente_sem_traco)>6) { &erro("Erro: conta corrente do Itaú com mais de 6 algarismos?!?!") } while (length($conta_corrente_sem_traco)<6) { $conta_corrente_sem_traco="0$conta_corrente_sem_traco"; } $dv_banco="7"; $nndv=&calcula_dv_nosso_numero_itau; $nn_texto="$carteira/$nn-$nndv"; # GERANDO A LINHA DIGITÁVEL $campo1=$codigo_banco . "9" . $carteira . substr($nn,0,2); $campo1.=&modulo10($campo1); $campo2=substr($nn,2,15) . $nndv . substr($agencia_sem_traco,0,3); $campo2.=&modulo10($campo2); $campo3=substr($agencia,3,4) . $conta_corrente_sem_traco . "000"; $campo3.=&modulo10($campo3); $dacCB=&daccb("$codigo_banco"."9"."$fator_vencimento$total_digitavel$carteira$nn$nndv$agencia_sem_traco$conta_corrente_sem_traco"."000"); $linha_digitavel = $campo1 . ' ' . $campo2 . ' ' . $campo3 . " " . $dacCB . " " . $fator_vencimento . $total_digitavel; # pag 44 Itaú - cobrança.doc agosto/2000 $barra="3419$dacCB$fator_vencimento$total_digitavel$carteira$nn$nndv$agencia_sem_traco$conta_corrente_sem_traco"."000"; } # ------------------------------ UNIBANCO --------------------------------- elsif ($codigo_banco eq "409") { =c Spe - Suporte Produto Eletronicos Tel.(11)3011-0288 / 0800-783310 =cut if (!$codigo_boleto) { &erro("Erro: para o UNIBANCO, é necessário passar o código de cliente, isto é, o número de cliente para o código de barras"); } if (uc($carteira) ne "ESP") { &erro("Carteira $carteira não suportada para o banco $nome_banco{409}."); } $codigo_boleto=~s/\-//g; $codigo_boleto=~s/\.//g; # VALIDANDO NÚMERO $codigo_boleto if (length($codigo_boleto)!=7) { &erro("Erro: código do cliente do Unibanco - $codigo_boleto - com mais de 7 algarismos?!?!") } while (length($codigo_boleto)<7) { $codigo_boleto="0$codigo_boleto"; } $dv_banco="0"; $nndv=modulo11("$nn"); $nn_texto="$nn-$nndv"; # GERANDO A LINHA DIGITÁVEL $campo1=$codigo_banco . "95" . substr($codigo_boleto,0,4); $campo1.=&modulo10($campo1); $campo2=substr($codigo_boleto,4,8) . "00" . substr($nn,0,5); $campo2.=&modulo10($campo2); $campo3=substr($nn,5,16) . $nndv; $campo3.=&modulo10($campo3); $dacCB=&daccb("4099"."$fator_vencimento$total_digitavel"."5"."$codigo_boleto"."00$nn$nndv"); $barra="4099" . $dacCB . "$fator_vencimento$total_digitavel"."5"."$codigo_boleto"."00" . "$nn$nndv"; } # --------------------------------- BRADESCO ------------------------------------- elsif ($codigo_banco eq "237") { if ($carteira ne "25" && $carteira ne "06" && $carteira ne "22") { &erro("Carteira $carteira não suportada para o banco $nome_banco{237}."); } $dv_banco="2"; $nndv=modulo11("$carteira$nn"); $nn_texto="$carteira/$nn-$nndv"; $agencia_sem_traco=substr($agencia_sem_traco,0,4); #necessário remover o DV da agência $conta_corrente_sem_traco=substr($conta_corrente_sem_traco,0,7); # e da conta tb $campo_livre="$agencia_sem_traco$carteira$nn$conta_corrente_sem_traco" . "0"; # GERANDO A LINHA DIGITÁVEL $campo1=$codigo_banco . "9" . substr($campo_livre,0,5); $campo1.=&modulo10($campo1); $campo2=substr($campo_livre,5,10); $campo2.=&modulo10($campo2); $campo3=substr($campo_livre,15,25); $campo3.=&modulo10($campo3); $dacCB=&daccb("2379"."$fator_vencimento$total_digitavel$campo_livre"); $barra="2379" . $dacCB . "$fator_vencimento$total_digitavel$campo_livre"; } # ----------------------- CEF -------------------------- # LINHA DIGITÁVEL TEM 47 DÍGITOS / CÓDIGO DE BARRAS TEM 44 DÍGITOS #CR - Cobrança Rápida #CS - Cobrança Simples #SAD - Cobrança SAD #SI - Cobrança Simplificada #SR - Cobrança Sem Registro #SR-14 - Cobrança Sem Registro Nosso Número 14 Dígitos #SR5 - SINCO - Sem Registro elsif ($codigo_banco eq "104") { $dv_banco="0"; if ($carteira eq "SR5") { # validação de dados if (length($codigo_boleto)!=6) { &erro("Carteira SR5 deve ter código do cedente com 6 posições"); } if (length($nn)!=17) # "Campo com 17 posições sempre iniciando com 9" { &erro("Nosso número deve possuir 17 dígitos. Nosso número informado: $nn"); } #if (substr($nn,0,1) ne "9") # "Campo com 17 posições sempre iniciando com 9" $nndv=modulo11("9$nn"); $nn_texto="9$nn-$nndv"; # OBS SOBRE NN: # PARA EXIBIÇÃO AO LADO DA DATA DE PROCESSAMENTO, DEVE TER 18 DÍGS + DV # 9ZZZZZZZZZZZZZZZZZ-D onde: # 9 - Constante # ZZZZZZZZZZZZZZZZ - Nosso Número do Cedente # D - Dígito verificador (Módulo 11 - incluindo o 9) # BARRA - o dv do nn não entra na barra $campo_livre="1" . $codigo_boleto . "9" . $nn; $dacCB=&daccb("1049"."$fator_vencimento$total_digitavel$campo_livre"); $dv_cod_barra=&daccb("1049"."$fator_vencimento$total_digitavel$campo_livre"); # certo $barra="1049" . $dv_cod_barra . $fator_vencimento . $total_digitavel . $campo_livre; # certo # LINHA DIGITÁVEL - certo $campo1="1049" . substr($barra,19,5); $campo1.=&modulo10($campo1); $campo2=substr($barra,24,10); $campo2.=&modulo10($campo2); $campo3=substr($barra,34,10); $campo3.=&modulo10($campo3); } elsif ($carteira eq 'SR') { =BEGIN 4.2.2.1 - Definição do campo livre (posições 20 a 44) Para as posições do Campo Livre, informar: XXXXXXD1NNNC1NNNC2NNNNNNNNND2 onde: XXXXXX Código do Cliente Cedente fornecido pela CAIXA D1 Dígito Verificador do Código do Cedente NNN 1ª parte do Nosso Número do cliente (3 posições) C1 Constante 1 para definição da carteira - (1-Registrada/2-Sem Registro) NNN 2ª parte do Nosso Número do cliente (3 posições) C2 Constante 2 para definição da impressão do bloqueto - (4-cedente) NNNNNNNNN 3ª parte do Nosso Número do Cliente (9 posições) D2 Dígito Verificador do Campo Livre =cut # VALIDAÇÃO DE DADOS if (length($codigo_boleto)!=7) { &erro("Carteira SR deve ter código do cedente com 6 posições + 1 dígito verificador, totalizando 7 algarismos."); } if (length($nn)!=15) # "Campo com 17 posições sempre iniciando com 9" { &erro("Nosso número deve possuir 15 dígitos. Nosso número informado: $nn"); } $campo_livre=$codigo_boleto . substr($nn,0,3) . '2' . substr($nn,3,3) . '4' . substr($nn,6,9) . $dv_campo_livre; $campo_livre.=&calcula_dv_campo_livre_cef_nn_15_posicoes($campo_livre); $dacCB=&daccb("1049"."$fator_vencimento$total_digitavel$campo_livre"); $nndv=modulo11("$nn"); $nn_texto="24$nn-$nndv"; $dv_cod_barra=&daccb("1049"."$fator_vencimento$total_digitavel$campo_livre"); # certo $barra="1049" . $dv_cod_barra . $fator_vencimento . $total_digitavel . $campo_livre; # certo # LINHA DIGITÁVEL $campo1="1049" . substr($barra,19,5); $campo1.=&modulo10($campo1); $campo2=substr($barra,24,10); $campo2.=&modulo10($campo2); $campo3=substr($barra,34,10); $campo3.=&modulo10($campo3); $codigo_cedente=substr($codigo_cedente,0,6) . '-' . substr($codigo_cedente,6,1); print "CEF, CARTEIRA SR - EM DESENVOLVIMENTO - NÃO LIBERE O SISTEMA PARA ENTRAR EM PRODUÇÃO EM SUA LOJA VIRTUAL"; } else { &erro("Carteira $carteira não suportada para o banco $nome_banco{104}."); } } # ---------------------------------------------- BB ------------------------------------------------- # SUPORTE TÉCNICO BB = 0800 729 0500 # GERENTE BB = ANA LUIZA 2572 7000 elsif ($codigo_banco eq "001") { $dv_banco="9"; $nn_texto="$nn-" . &modulo11($nn); # parece que é assim que se calcula, de acordo com o documento, mas que se foda porque o DV não entra nem no código de barras nem na linha digitável # VALIDANDO QUANTIDADE DE DÍGITOS DA AGÊNCIA / CC / CARTEIRA if (length($agencia_sem_dv)>4) { &erro("Agência do BB deve ter 4 dígitos sem o DV. Agência atual: $agencia_sem_dv"); } while (length($agencia_sem_dv)<4) { $agencia_sem_dv="0$agencia_sem_dv"; } if (length($cc_sem_dv)>8) { &erro("CC sem DV deve ter 8 algarismos. CC atual: $cc_sem_dv"); } while (length($cc_sem_dv)<8) { $cc_sem_dv="0$cc_sem_dv"; } if (length($carteira)!=2) { &erro("Cateira do BB deve ter 2 algarismos"); } if ( $codigo_boleto ne substr($nn,0,length($codigo_boleto)) && ($carteira eq "17" || $carteira eq "18") && length($codigo_boleto)>=7 ) { &erro("Erro: carteiras 17 e 18 do BB com nosso número de 17 dígitos, e número do convênio de 7 dígitos, devem ter número do convênio igual aos primeiros dígitos do Nosso Número.

Exemplo: convênio 1234567, nosso número deve ser 1234567XXXXXXXXXX, onde X é qualquer dígito."); } # GERANDO CAMPO LIVRE if ( length($codigo_boleto)==6 && length($nn)==11 ) # item 5 do doc { #$campolivre="$codigo_boleto$agencia_sem_dv$cc_sem_dv$carteira"; $campolivre="$nn$agencia_sem_dv$cc_sem_dv$carteira"; #print "$nn-$agencia_sem_dv-$cc_sem_dv-$carteira"; } if ( length($nn)==17 && ($carteira eq "16" || $carteira eq "18") && length($codigo_boleto)==6) #item 6 do doc { $campolivre="$codigo_boleto$nn"."21"; #print "$codigo_boleto-$nn-21---$fator_vencimento-$total_digitavel"; #print "
length campolivre=" . length($campolivre) . "
length nn=" . length($nn) . "
length conv=" . length($codigo_boleto) . '
'; } # item 7 do doc -> NN COM 27 POSICOES?! O SUPORTE MANDOU COLOCAR ZEROS NO CAMPO "COMPLEMENTO DO NOSSO NÚMERO" # esse é o caso do Ricardo: convenio 1179666 carteira 17 if ( ($carteira eq "17" || $carteira eq "18") && length($codigo_boleto)>=7 ) { $campolivre="000000" . $codigo_boleto . substr($nn,7,17) . $carteira; } #print "
convenio: $codigo_boleto
agencia: $agencia_sem_dv
CC: $cc_sem_dv
carteira $carteira
$fator vencimento: $fator_vencimento
total $total_digitavel
livre = $campolivre = " . length($campolivre) . " posicoes
nn=$nn

"; $tmp="0019"."$fator_vencimento$total_digitavel$campolivre"; $dacCB=&daccb($tmp); $campo1="0019" . substr($campolivre,0,5); # 5 primeiras posicoes do cpo livre $campo1.=&modulo10($campo1); $campo2=substr($campolivre,5,10); # posicoes 6 a 15 do cpo livre = 25 a 34 das barras $campo2.=&modulo10($campo2); $campo3=substr($campolivre,15,11); # posicoes 16 a 25 do cpo livre = 35 a 44 das barras $campo3.=&modulo10($campo3); $barra="0019" . $dacCB . "$fator_vencimento$total_digitavel$campolivre"; #print $barra; } elsif ($codigo_banco eq "399") { # "Antes da entrega dos bloquetos com código de barras aos sacados, é indispensável preparar uma massa de testes, e entregá-la à sua agência do HSBC, para que essa encaminhe-a à unidade regional responsável pela análise e homologação da emissão e leitura do código de barras" # validação de dados if ($carteira ne "CNR") { &erro("Carteira $carteira não suportada para o banco $nome_banco{399}. Utilize CNR."); } $local="Pagar preferencialmente em agência do HSBC"; $dv_banco="9"; #$nndv=modulo11("9$nn"); $nn_texto="$nn"; # ok $campo_livre=$codigo_boleto . $nn . "0000" . "2"; # troquei "data de vencimento em formato juliano" por "0000", conforme vi em boleto do HSBC # ok $dacCB=&daccb("3999"."$fator_vencimento$total_digitavel$campo_livre"); # OK $barra="3999" . $dacCB . $fator_vencimento . $total_digitavel . $campo_livre; # LINHA DIGITÁVEL - certo $campo1="3999" . substr($barra,19,5); $campo1.=&modulo10($campo1); $campo2=substr($barra,24,10); $campo2.=&modulo10($campo2); $campo3=substr($barra,34,10); $campo3.=&modulo10($campo3); } else { print "Banco não suportado"; exit; } $linha_digitavel = substr($campo1,0,5) . "." . substr($campo1,5,10) . ' ' . substr($campo2,0,5) . "." . substr($campo2,5,10) . ' ' . substr($campo3,0,5) . "." . substr($campo3,5,10) . " " . $dacCB . " " . $fator_vencimento . $total_digitavel; $total_print=$total if ($total != 0); ######################################################################################################### # DAQUI PRA BAIXO, SÓ CÓDIGO HTML E SUBROTINAS ######################################################################################################### # IMPRIMINDO O LOGO DA EMPRESA if ($logourl) { print "\n"; } # GERANDO A LINHA "CORTE AQUI" $corteaqui=qq {

}; print < Boleto bancário
Recibo do Sacado
Cedente
$cedente
Agência / Código Cedente
$agencia/$codigo_cedente
Vencimento
$vencimento
Sacado
$linhas_sacado[0]
Número do Documento
$documento
Nosso Número
$nn_texto
Espécie
R\$
Quantidade
$quantidade
(X) Valor
$valor
(=) Valor do Documento
$total_print
(-) Descontos/Abatimentos
$desconto
Demonstrativo (+) Outros Acréscimos
$acrescimos
(=) Valor Cobrado
 
$demonstrativo
Autenticação Mecânica


$corteaqui

 $codigo_banco-$dv_banco  $linha_digitavel
Local de Pagamento
$local
Vencimento
$vencimento
Cedente
$cedente
Agência / Código Cedente
$agencia/$codigo_cedente
Data Documento
$data_documento
Número do Documento
$documento
Espécie Doc.
$especie
Aceite
$aceite
Data Processamento
$data_processamento
Nosso número
$nn_texto
Uso do Banco
$uso_do_banco
Carteira
$carteira
Espécie
R\$
Quantidade
$quantidade
(X) Valor
$valor
(=) Valor do Documento
$total_print
Instruções (Todas informações deste boleto são de responsabilidade do cedente)
$instrucoes
(-) Desconto
$desconto
(-) Outras deduções
 
(+) Mora/Multa
$multa
(+) Outros acréscimos
 
(=) Valor cobrado
 
Sacado
$sacado
Código de Baixa
$baixa

Autenticação mecânica - Ficha de compensação
$corteaqui END_HTML ############################################################################################### # # # S U B R O T I N A S # # # ############################################################################################### sub erro { print @_; exit; } #Contribuicao: calculo de intervalo de dias #autor: Carlos Angelim #tentativa de comparacao de datas em perl #a ideia eh fazer a verificacao baseada no mapeamento do numero de dias de cada mes #presentes em um hash; observar que se (ano % 4 == 0) => ano bissexto. #recebem (dia1,mes1,ano1),(dia2,mes2,ano2) e faz @2 - @1; #obs: delta_dia precisa saber se vai ou nao passar por ano bissexto... #ATENCAO: NAO FAZ VALIDACAO DE DATA!!!!!!!!!!!!!!!!!!!! sub deltaMes (\@\@) { my @data1 = ($_[0], $_[1], $_[2]); my @data2 = ($_[3], $_[4], $_[5]); my $dif_ano = $data2[2] - $data1[2]; my $dif_mes = 0; my $i; if ($dif_ano > 0) { for($i=0; $i < $dif_ano; $i++) { $dif_mes += 12; } }elsif($dif_ano < 0) { #data_inicio < data_fim encerra a funcao! return -1; } $dif_mes += $data2[1] - $data1[1]; #como a diferenca eh entre meses inteiros, vejo a diferenca de dias. if($data1[0] > $data2[0]) { #como nao completou o mes, a diferenca, em meses, eh reduzida. $dif_mes -= 1; } return $dif_mes; } sub ehAnoBissexto ($) { my $ano=$_[0]; if (($ano % 4) == 0) { return 1; } else { return 0; } } sub deltaDia (\@\@) { my @data1 = ($_[0], $_[1], $_[2]); my @data2 = ($_[3], $_[4], $_[5]); my $i=0; my %hash_ano = (1=>31, 2=>28, 3=>31, 4=>30, 5=>31, 6=>30, 7=>31, 8=>31, 9=>30, 10=>31, 11=>30, 12=>31); my $meses = &deltaMes(@data1, @data2); if($meses < 0) { #data inicio > data fim encerra a funcao! return -1; } if (&ehAnoBissexto($data1[2])==1) { $hash_ano{2} = 29; } else { $hash_ano{2} = 28; } #quando inicio $dias_contados, faco o calculo referente ao 1o mes ('mes quebrado') #porem, se os dias forem iguais, os meses serao inteiros if($data1[0] <= $data2[0]) { $meses--; } my $mes_inicio=$data1[1]; my $dias_contados = 0; my $ano_inicio=$data1[2]; if( ($data1[0] != $data2[0]) || ($data1[1] != $data2[1]) || ($data1[2] != $data2[2]) ) { $dias_contados = $hash_ano{$data1[1]} - $data1[0] + $data2[0]; } while($meses > 0) { #trata o mes e ano seguintes. if ($mes_inicio<12) { $mes_inicio++; } else { $mes_inicio = 1; $ano_inicio++; if (&ehAnoBissexto($ano_inicio)) { $hash_ano{2} = 29; } else { $hash_ano{2} = 28; } } $dias_contados += $hash_ano{$mes_inicio}; $meses--; } return $dias_contados; } sub calculaDiasMes(\@\$) { my @data1 = ($_[0], $_[1], $_[2]); my @data_fim = @data1; $data_fim[1] += $_[3]; if ($data_fim[1] > 12) { $data_fim[1] -= 12; $data_fim[2]++; } my $num_dias = deltaDia(@data1, @data_fim); return $num_dias; } ###Recebe um vetor (dd/mm/aaaa) e um numero. ###Devolve a nova data gerada a partir da soma. sub somaDias(\@\$) { my $dd=$_[0]; my $mm=$_[1]; my $aaaa=$_[2]; my $intervalo = $_[3]; my %hash_ano = (1=>31, 2=>28, 3=>31, 4=>30, 5=>31, 6=>30, 7=>31, 8=>31, 9=>30, 10=>31, 11=>30, 12=>31); if (&ehAnoBissexto($aaaa)) { $hash_ano{2} = 29; } else { $hash_ano{2} = 28; } my $diferenca = $hash_ano{$mm} - $dd + 1; while($intervalo > $diferenca) { $dd = 1; $intervalo -= $diferenca; $mm++; if($mm > 12) { $mm=1; $aaaa++; } if ( ($mm==2) && (&ehAnoBissexto($aaaa)) ) {$diferenca = 29;} else {$diferenca = $hash_ano{$mm}} } $dd += $intervalo; return "$dd/$mm/$aaaa"; } sub modulo10($) { my $sequencia=$_[0]; $p0 = substr($sequencia,-1,1); $p1 = substr($sequencia,-2,1); $p2 = substr($sequencia,-3,1); $p3 = substr($sequencia,-4,1); $p4 = substr($sequencia,-5,1); $p5 = substr($sequencia,-6,1); $p6 = substr($sequencia,-7,1); $p7 = substr($sequencia,-8,1); $p8 = substr($sequencia,-9,1); $p9 = substr($sequencia,-10,1); $p8n = $p8 * 2; $p6n = $p6 * 2; $p4n = $p4 * 2; $p2n = $p2 * 2; $p0n = $p0 * 2; while($p8n >= 10) { $p8na = substr($p8n,0,1); $p8nb = substr($p8n,1,1); $p8n = $p8na+$p8nb; } while($p6n >= 10) { $p6na = substr($p6n,0,1); $p6nb = substr($p6n,1,1); $p6n = $p6na+$p6nb; } while($p4n >= 10) { $p4na = substr($p4n,0,1); $p4nb = substr($p4n,1,1); $p4n = $p4na+$p4nb; } while($p2n >= 10) { $p2na = substr($p2n,0,1); $p2nb = substr($p2n,1,1); $p2n = $p2na+$p2nb; } while($p0n >= 10) { $p0na = substr($p0n,0,1); $p0nb = substr($p0n,1,1); $p0n = $p0na+$p0nb; } $somadigito = $p9+$p8n+$p7+$p6n+$p5+$p4n+$p3+$p2n+$p1+$p0n; $dezena = $somadigito / 10; ($parteinteira,$partedecimal)=(split(/\./,$dezena)); $dezenasuperior = ($parteinteira + 1) * 10; ## DVLD é o dígito verificador da linha digitável. $DVLD = $dezenasuperior - $somadigito; if ($DVLD == 10) {$DVLD = 0} return $DVLD; } #calcula o digito verificador modulo 11 para os campos #"nosso numero", "codigo do cedente" e "prefixo da agencia" # Cálculo do DAC do Código de Barras sub modulo11(\$) { my $sequencia=$_[0]; my $multiplicador=9; my $parte_inteira = $sequencia; my $parte_decimal; my $somadigito = 0; while( (length($parte_inteira) > 0) && ($parte_inteira != 0) ) { $parte_decimal = $parte_inteira % 10; $somadigito = $somadigito + ($multiplicador * $parte_decimal); $multiplicador--; if($multiplicador < 2) { $multiplicador = 9; } $parte_inteira = $parte_inteira / 10; ($parte_inteira,$lixo) = split(/\./,$parte_inteira); } $digito = $somadigito % 11; if ($digito == 10 && $codigo_banco eq "001") { $digito = 'X'; } elsif ( ($digito == 10) || ($digito==0) ) { $digito = '0'; } return $digito; } # bosta, a mesma função foi escritas duas vezes: essa e modulo11 sub daccb($) { my $multiplicador=shift; my $multiplicando="4329876543298765432987654329876543298765432"; if (length($multiplicador) != length($multiplicando)) { &erro("Erro no cálculo do DAC CB: length multiplicador=".length($multiplicador).", esperado ".length($multiplicando)); } my @produto=(); for ($i=0;$iSequencia=$sequencia
Sequencia=$sequencia2"); } my $soma=0; for (my $i=0;$i=10) { $tmp=substr($tmp,0,1) + substr($tmp,1,1); } $soma+=$tmp; } my $resto=$soma % 10; if ($resto == 0) { return 0; } else { return 10-$resto; } } sub today() { ( $day, $mon, $year ) = ( localtime(time) )[ 3, 4, 5 ]; $mon+=1; $year+=1900; return sprintf ("%02d/%02d/%4d", $day,$mon,$year); } sub calcula_dv_campo_livre_cef_nn_15_posicoes($) { my $cpo_livre=shift; my $multiplicadores="987654329876543298765432"; my $soma=0; if ( length($cpo_livre) ne length($multiplicadores) ) { &erro("Erro calculando DV do campo livre da CEF, para NN de 15 posições."); } for (my $i=0;$i 9); return $retornar; }