segunda-feira, fevereiro 16, 2009

Mais um golpe

Aquela coisa que se diz governante da Venezuela conseguiu mais uma vez ludibriar o povo.
Com seu discurso populista e enganador, Chaves deu mais um golpe.

Pobres venezuelanos.

quinta-feira, fevereiro 12, 2009

Validar CPF e CNPJ juntos em Oracle PL/SQL

Precisava de uma rotina para validar CPF e CNPJ em Oracle PL/SQL.
Todas as dicas que encontrei mostram rotinas separadas.
Só encontrei uma, em Java, que utiliza o mesmo código para validar os dois identificadores.
Esse código faz parte do pacote BrazilUtils que, além de ter uma rotina única para validar os dois,
também apresenta rotinas separadas para cada um deles.

Pois bem, antes de exibir o código da função, lembremos como funciona a validação dos identificadores.

De acordo com o site da Receita Federal do Brasil o Cadastro de Pessoas Físicas - CPF é um banco de dados gerenciado pela Secretaria da Receita do Brasil - RFB que armazena informações cadastrais de contribuintes obrigados à inscrição no CPF, ou de cidadãos que se inscreveram voluntariamente. 

Já a WikiPedia trás algumas informações interessantes como o significado dos dígitos e o algoritmo de validação (em Pascal).
CNPJ é o cadastro administrado pela Receita Federal do Brasil que registra as informações cadastrais das pessoas jurídicas e de algumas entidades não caracterizadas como tais.

Os dois últimos dígitos do CPF são números de verificação: seguem um algoritmo de módulo 11,
baseado no valor dos outros dígitos, para possibilitar a verificação automática e prevenir erros de digitação.

O dígito anterior (isto é, o terceiro dígito da direita para a esquerda) revela a unidade federativa em que a pessoa

registrou-se pela primeira vez, dado que é proibido (em condições normais) trocar de número.

Vamos tomar como exemplo o número 123.456.789-09

• 1º Dígito Verificador
Primeiro calculamos a soma da multiplicação dos 9 primeiros dígitos por 10, 9, 8, ... , 3, 2, respectivamente. Ou seja:

Soma = (1*10) + (2*9) + ... + (8*3) + (9*2)

Em seguida, subtraimos 11 do resultado do módulo de 11 da soma.

Resultado = 11 - (Soma % 11)

Agora analisamos Resultado:

·      Se Resultado for igual ou maior que 10, então o 1º dígito verificador é 0;

·      Caso contrário, o 1º dígito verificador é o resultado.

• 2º Dígito Verificador
Primeiro calculamos a soma da multiplicação dos 9 primeiros dígitos por 11, 10, 9, ... , 4, 3, respectivamente e em seguida somamos com (Digito1*2), sendo que Digito1 é o valor encontrado para o 1º dígito verificador. Ou seja:

Soma = (1*11) + (2*10) + ... + (8*4) + (9*3) + (Digito1*2)

O resto é semelhante ao que foi feito anteriormente.

Resultado = 11 - (Soma % 11)

Agora analisamos Resultado:

·      Se Resultado for igual ou maior que 10, então o 2º dígito verificador é 0;

·      Caso contrário, o 2º dígito verificador é o resultado.

O código do BrasilUtils valida os dígitos informados conforme o tipo de identificador, CPF ou CNPJ, de acordo com

o tamanho do campo informado, em um único algoritmo. O CPF tem tamanho 11 e o CNPJ 14.
Esses valores são representam a quantidade de dígitos numéricos, já extraindo-se os caracteres para formatação
da máscara de exibição como “.”, “/” e “-‘.

A função pode receber como parâmetro o valor com os caracteres de máscara. Os mesmos serão removidos usando-se
expressão regular do SGBD.

Agora, vamos ao principal desse post, o código da função em PL/SQL.

CREATE OR REPLACE FUNCTION VALIDA_CPF_CNPJ(V_CPF_CNPJ VARCHAR2) RETURN BOOLEAN IS
  /*  Função para validar CPF/CNPJ
      Banco de Dados: Oracle 10g
      Data: 11/02/2008
      Autor: Rogério Alcântara Valente

  */ 

  TYPE ARRAY_DV IS VARRAY(2) OF PLS_INTEGER;
  V_ARRAY_DV ARRAY_DV := ARRAY_DV(0, 0);
  CPF_DIGIT  CONSTANT PLS_INTEGER := 11;
  CNPJ_DIGIT CONSTANT PLS_INTEGER := 14
  IS_CPF       BOOLEAN;
  IS_CNPJ      BOOLEAN;
  V_CPF_NUMBER VARCHAR2(20);
  TOTAL        NUMBER := 0;
  COEFICIENTE  NUMBER := 0;
  DV1    NUMBER := 0;
  DV2    NUMBER := 0;
  DIGITO NUMBER := 0;
  J      INTEGER;
  I      INTEGER;

BEGIN
  IF V_CPF_CNPJ IS NULL THEN
    RETURN FALSE;
  END IF

  /*
    Retira os caracteres não numéricos do CPF/CNPJ
    caso seja enviado para validação um valor com
    a máscara.
  */

  V_CPF_NUMBER := REGEXP_REPLACE(V_CPF_CNPJ, '[^0-9]'); 

  /*
    Verifica se o valor passado é um CPF através do
    número de dígitos informados. CPF = 11
  */

  IS_CPF := (LENGTH(V_CPF_NUMBER) = CPF_DIGIT); 

  /*
    Verifica se o valor passado é um CNPJ através do
    número de dígitos informados. CNPJ = 14
  */

  IS_CNPJ := (LENGTH(V_CPF_NUMBER) = CNPJ_DIGIT);

  IF (IS_CPF OR IS_CNPJ) THEN
    TOTAL := 0;
  ELSE
    RETURN FALSE;
  END IF;

   /*
    Armazena os valores de dígitos informados para
    posterior comparação com os dígitos verificadores calculados.
  */

  DV1 := TO_NUMBER(SUBSTR(V_CPF_NUMBER, LENGTH(V_CPF_NUMBER) - 1, 1));
  DV2 := TO_NUMBER(SUBSTR(V_CPF_NUMBER, LENGTH(V_CPF_NUMBER), 1)); 

  V_ARRAY_DV(1) := 0;
  V_ARRAY_DV(2) := 0

  /*
    Laço para cálculo dos dígitos verificadores.
    É utilizado módulo 11 conforme norma da Receita Federal.
  */

  FOR J IN 1 .. 2
  LOOP
    TOTAL := 0;
    COEFICIENTE := 2;

    FOR I IN REVERSE 1 .. ((LENGTH(V_CPF_NUMBER) - 3) + J)
    LOOP
      DIGITO := TO_NUMBER(SUBSTR(V_CPF_NUMBER, I, 1));
      TOTAL := TOTAL + (DIGITO * COEFICIENTE);   

      COEFICIENTE := COEFICIENTE + 1;
      IF (COEFICIENTE > 9AND IS_CNPJ THEN
        COEFICIENTE := 2;
      END IF;   

    END LOOP; --for i

    V_ARRAY_DV(J) := 11 - MOD(TOTAL, 11);
    IF (V_ARRAY_DV(J) >= 10) THEN
      V_ARRAY_DV(J) := 0;
    END IF

  END LOOP; --for j in 1..2

  /*
    Compara os dígitos calculados com os informados para informar resultado.
  */

  RETURN(DV1 = V_ARRAY_DV(1)) AND(DV2 = V_ARRAY_DV(2)); 

END VALIDA_CPF_CNPJ;


sexta-feira, fevereiro 06, 2009

Deputado Bolsonaro ataca ministros


O deputado federal Jair Bolsonaro (PP-RJ) atacou na tribuna da Câmara os ministros Tarso Genro e Dilma Russef.

Hino Nacional - 100 anos da letra de Duque Estrada

Recentemente o Jornal da Band exibiu matéria sobre os 100 anos da letra do nosso Hino. E como não podia deixar de acontecer em matéria sobre o hino, a reportagem foi às ruas verificar se as pessoas sabiam a letra. E, mais uma vez, como não podia deixar de ser, foi mostrado somente aquelas pessoas que não sabiam.

O repórter cometeu até o “pecado” de sugerir uma atualização da letra do hino, substituindo palavras em desuso por outras mais conhecidas da população. Ora bolas, a matéria deveria sugerir mais civismo, principalmente na educação de base, para as crianças crescerem com mais conhecimento, tanto da letra quanto do significado das palavras. Coisa que nenhum governo, até hoje, se preocupou em fazer, até porque, os governos “democráticos” que tivemos ultimamente devem ter em mente que civismo é coisa dos tempos dos militares. As vezes dá saudade desse tempo.

O comentarista Joelmir Beting sugeriu aos institutos de pesquisa que fizessem uma apuração para demonstrar quantas pessoas sabem a letra. Ele também brincou com os apresentadores – Ricardo Boechat e Ticiana Villas Boas – se eles topariam o desafio. O que foi prontamente negado. O Boechat até ficou vermelho. Não se sabe se foi de vergonha por não saber ou mesmo pela brincadeira do colega...

O interessante é que isso só se fala nas épocas de comemorações ou datas cívicas que estão, a cada dia, menos cívicas, menos importantes para o brasileiro.

Segue a letra do Hino retirada do site da Presidência da República.

HINO NACIONAL

Parte I

Ouviram do Ipiranga as margens plácidas
De um povo heróico o brado retumbante,
E o sol da liberdade, em raios fúlgidos,
Brilhou no céu da pátria nesse instante.

 

Se o penhor dessa igualdade
Conseguimos conquistar com braço forte,
Em teu seio, ó liberdade,
Desafia o nosso peito a própria morte!

 

Ó Pátria amada,
Idolatrada,
Salve! Salve!

 

Brasil, um sonho intenso, um raio vívido
De amor e de esperança à terra desce,
Se em teu formoso céu, risonho e límpido,
A imagem do Cruzeiro resplandece.

 

Gigante pela própria natureza,
És belo, és forte, impávido colosso,
E o teu futuro espelha essa grandeza.

 

Terra adorada,
Entre outras mil,
És tu, Brasil,
Ó Pátria amada!
Dos filhos deste solo és mãe gentil,
Pátria amada,
Brasil!

Parte II

Deitado eternamente em berço esplêndido,
Ao som do mar e à luz do céu profundo,
Fulguras, ó Brasil, florão da América,
Iluminado ao sol do Novo Mundo!

 

Do que a terra, mais garrida,
Teus risonhos, lindos campos têm mais flores;
"Nossos bosques têm mais vida",
"Nossa vida" no teu seio "mais amores."

 

Ó Pátria amada,
Idolatrada,
Salve! Salve!

 

Brasil, de amor eterno seja símbolo
O lábaro que ostentas estrelado,
E diga o verde-louro dessa flâmula
- "Paz no futuro e glória no passado."

 

Mas, se ergues da justiça a clava forte,
Verás que um filho teu não foge à luta,
Nem teme, quem te adora, a própria morte.

 

Terra adorada,
Entre outras mil,
És tu, Brasil,
Ó Pátria amada!
Dos filhos deste solo és mãe gentil,
Pátria amada,
Brasil!

Letra: Joaquim Osório Duque Estrada 
Música: Francisco Manuel da Silva

Atualizado ortograficamente em conformidade com Lei nº 5.765 de 1971, e com
art.3º da Convenção Ortográfica celebrada entre Brasil e Portugal. em 29.12.1943.

quarta-feira, fevereiro 04, 2009

Problema de quebra de linha em script Shell

O processo:

Gerar um arquivo texto formatado para carga em banco de dados utilizando o SQLLoader do SGBD Oracle. Cada linha desse arquivo deve conter: nome do arquivo, “0”, crc do arquivo, sequência do arquivo e o valor de uma linha de outro arquivo enviado por outro software, ou seja, para cada linha do arquivo enviado deve-se gerar uma nova linha com o formato descrito.

Script gerado:

for arquivo in $DIR_PROC/PCA*.REM ; do
  
 crc=`cksum $arquivo | cut -c1-10`
  
 nomearq=`echo $arquivo | cut -d\/ -f6`
  
 seqarq=`echo $arquivo | cut -d"_" -f2`
   for linha in `cat $arquivo`; do
      echo $nomearq ",0,"$crc","$seqarq","$linha  >> $DIR_PROC/arqPrepCartao.txt
   done
  `cp -f $arquivo $DIR_PROC/lidos_txt/$dia`
done

O problema:

O comando “echo”, utilizado para a criação da linha do novo arquivo, tem como padrão “quebrar” a linha sempre que encontra um espaço em branco na string utilizada. Como o arquivo original é formatado e, obviamente, tem vários espaços inseridos para colocar os valores na coluna esperada, o arquivo destino “arqPrepCartao.txt” fica totalmente desconfigurado. Com isso, a carga no banco de dados tem resultado completamente comprometido.

A solução:

A mais simples que encontrei foi gerar a linha substituindo-se o caractere espaço pelo caractere “#” no comando “cat” da linha do laço – “for” – e retornar com o espaço no lugar de “#” na linha do comando “echo”. Dessa forma o código do script fica assim:

for arquivo in $DIR_PROC/PCA*.REM ; do
  
 crc=`cksum $arquivo | cut -c1-10`
  
 nomearq=`echo $arquivo | cut -d\/ -f6`
  
 seqarq=`echo $arquivo | cut -d"_" -f2`
   for linha in `cat $arquivo | tr ' ' '#'`; do
      echo $nomearq ",0,"$crc","$seqarq","$linha | tr '#' ' '>> $DIR_PROC/arqPrepCartao.txt
  
 done 

  `cp -f $arquivo $DIR_PROC/lidos_txt/$dia`

done

Enquanto não encontrava a solução postei esse problema em uma thread com o título “Line break problem” no fórum do Ubuntu.  Uma das soluções propostas criava a nova linha sem quebras, porém, não mantinha o formato original.

A solução foi compartilhada com a comunidade no fórum.