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;


Nenhum comentário:

Postar um comentário