Jump to content

Algoritmo de validação de NIF (PT)


nunopicado

Recommended Posts

nunopicado

Já aqui anda no fórum algo do género, mas creio que não em Delphi/Pascal.

Este é um algoritmo para validar um NIF (Nº de contribuinte) segundo as regras portuguesas.

É em Delphi, mas com pouco trabalho se pode adaptar a Pascal, ou mesmo a qualquer outra linguagem.

function ValidaNIF(NIF:String):Boolean;
var
  i:byte;
  Control:Integer;
begin
    // Testa o tamanho do NIF (Obrigatório 9 digitos)
    Result:=Length(NIF)=9;

    // Testa o NIF por tipo de caracteres (apenas númerico é aceite)
    try
       Control:=StrToInt(NIF);
    except
       Result:=False;
    end;

    // Testa se o digito inicial é válido (1, 2, 5, 6, 7, 8 ou 9)
    Result:=Result AND (Pos(NIF[1],'1256789')>0);

    // Calcula o CheckDigit do número e valida-o contra o último algarismo (algarismo de controle) pelo método Módulo 11
    if Result
       then begin
                 Control:=StrToInt(NIF[1])*9;
                 for i:=2 to 8 do
                     Control:=Control+(10-i)*StrToInt(NIF[i]);
                 Control:=11-(Control Mod 11);
                 if Control>=10 then Control:=0;
                 Result:=Control = StrToInt(NIF[9]);
            end;
end;
Edited by nunopicado
Adicionado o algarismo 7 como possível começo de um NIF

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to post
Share on other sites
nunopicado

:) Nunca usei tal. Tenho de olhar bem para isso. Regular Expressions ainda é mundo novo para mim! :(

Mas sem duvida, fica melhor!

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to post
Share on other sites

Usas muito o if Result. Não gosto de ver.

begin
Result := false;

// testa condição... se não dá:
exit;

// mais testes...

// se tudo deu certo, mudas o valor no fim:
Result := true;
end;

    // Testa o NIF por tipo de caracteres (apenas númerico é aceite)
    try
       Control:=StrToInt(NIF);
    except
       Result:=False;
    end;

Se se puder evitar o Try, evita-se. Neste caso, nem é preciso criar mais variáveis do que aquelas que já tens:

Val(NIF, Control, i);
if boolean(i) then exit;

Knowledge is free!

Link to post
Share on other sites

Só há um pormenor que está a falhar - também podem começar por 7 (aprendi isso da pior maneira no mês passado).

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to post
Share on other sites
nunopicado

:) Eu gosto do Try... Nada contra algo que me dá controle sobre o que estou a fazer.

A ideia dos IF's todos é mostrar os varios passos da validação. Tirando o checkdigit, podia ficar tudo numa condição só, mas quis simplificar ao máximo a percepção dos passos da validação!

Só há um pormenor que está a falhar - também podem começar por 7 (aprendi isso da pior maneira no mês passado).

Por 7?? Olha, essa desconhecia!

Sabes em que situações pode acontecer?

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to post
Share on other sites
Por 7?? Olha, essa desconhecia!

Sabes em que situações pode acontecer?

Acho que são NIF usados para processos de partilhas, é do conjunto dos herdeiros.

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to post
Share on other sites
nunopicado

Coisa esquisita, nunca ouvi falar! Mas pronto, se for o caso é só adicionar lá em cima! :)

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to post
Share on other sites
nunopicado

heheheh Como te compreendo...

Aqui está o link para a portaria que estabelece essa regra: http://www.igf.min-financas.pt/inflegal/bd_igf/bd_legis_geral/leg_geral_docs/PORTARIA_0386_98.htm

  • Vote 1

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to post
Share on other sites

Boas!!

Tenho um cliente a queixar-se de que inseriu um nif errado e o programa nao se queixou :S

O algoritmo basicamente é este:

Validar tamanho (9 digitos)

O primeiro dígito tem que ser 1, 2, 5, 6, 7, 8 ou 9

A soma de controle é dada por 9xd1 + 8xd2 + 7xd3 + 6xd4 + 5xd5 + 4xd6 + 3xd7 + 2xd8 + d9

Faz-se divisão por 11

Se o resto for inferior a 2, o check digit é 0

Caso contrario é 11 menos o resto

Se o valor for igual ao ultimo do NIF, então é valido, senão não

Estou a falhar nalguma coisa??

Link to post
Share on other sites
// class para validar Numero de Contribuinte
unit UValidaN;

interface

uses sysutils, classes;

type
// CalssObj Pascal Para validação de, NIF, BI, NISS
// fcarvalho98@gmail.com

TValidaNumeros=class
 protected
  FNumero : string;
  function Get_isValidoNIF:boolean;
  function Get_isValidoNISS:boolean;
  function Get_isValidoBI:boolean;
 public
  constructor create;
  property Numero:string read FNumero write FNumero;
  property isValidoNIF: boolean read Get_isValidoNIF;
  property isValidoNISS: boolean read Get_isValidoNISS;
  property isValidoBI: boolean read Get_isValidoBI;
  function IsNumero(s: string): Boolean;
end;

implementation

function TValidaNumeros.IsNumero(s: string): Boolean;
var
 i: Integer;
begin
 Result := False;
 for i := 1 to Length(s) do
case s[i] of '0'..'9':;
 else Exit;
end;
 Result := True;
end;

// Função para validar Nº idenf. Fiscal
function TValidaNumeros.Get_isValidoNIF:boolean;
var
 checkdigito, i : integer;
begin
 result := false;
 if (length(FNumero) = 9) and (isNumero(FNumero)) then
  begin
if (FNumero[1] in ['1','2','5','6','8','9'])  then
 begin
	 checkdigito := strtoint(FNumero[1]) * 9;
	for i := 3 to 9 do
	 checkdigito := checkdigito + (strtoint(FNumero[i-1])  * (11 - i));
	 checkdigito := 11 - (checkDigito mod 11);
	if (checkDigito >= 10) then checkDigito := 0;
	if (checkDigito = strtoint(FNumero[9])) then result := True;
  end;
end
  else
result := false;
end;

// Função para validar Nº idenf. Seg social
function TValidaNumeros.Get_isValidoNISS:boolean;
const
factor : array[1..10] of byte = (29,23,19,17,13,11,7,5,3,2);
var
soma, i : integer;
begin
 result := false;
 soma := 0;
 if (length(FNumero) = 11) and (isNumero(FNumero)) then
  begin
if (FNumero[1] in ['1','2'] ) then
 begin
	for i := 1 to 10 do
	 soma  := soma + ((strtoint(FNumero[i])  * factor[i]));
	 If (strtoint(FNumero[11]) = (9 - (soma mod 10))) then result := True;
  end;
end
  else
result := false;
end;

// Valida
constructor TValidaNumeros.create;
begin
FNumero := '123456789';
end;

function TValidaNumeros.Get_isValidoBI:boolean;
var
 soma : integer;
 TamanhoBI, i, cont : byte;
begin
 soma := 0;
 result := false;
 TamanhoBI := length(FNumero);
 if ((tamanhoBI > 6) and (TamanhoBI < 11)) and (isNumero(FNumero)) then
  begin
	cont := 0;
	for i := TamanhoBI downto 1 do
	 begin
	  inc(cont);
	  soma  := soma + ((strtoint(FNumero[i])  * cont));
	 end;
	 if ((Soma mod 11 = 0) or (soma mod 11 = 10)) then result := True;
end
  else
result := false;
end;


end.
Edited by nunopicado
Adicionadas tags GeShi
Link to post
Share on other sites

Boas!!

Tenho um cliente a queixar-se de que inseriu um nif errado e o programa nao se queixou :S

O algoritmo basicamente é este:

Validar tamanho (9 digitos)

O primeiro dígito tem que ser 1, 2, 5, 6, 7, 8 ou 9

A soma de controle é dada por 9xd1 + 8xd2 + 7xd3 + 6xd4 + 5xd5 + 4xd6 + 3xd7 + 2xd8 + d9

Faz-se divisão por 11

Se o resto for inferior a 2, o check digit é 0

Caso contrario é 11 menos o resto

Se o valor for igual ao ultimo do NIF, então é valido, senão não

Estou a falhar nalguma coisa??

Esse algoritmo tem uma falha.

Na soma de controlo não se adiciona o digito 9 pois este é apenas o check digit.

Fiz uma implementação desse algoritmo em Java e cometi o mesmo erro.

O algoritmo correcto será :

Validar tamanho (9 digitos)

O primeiro dígito tem que ser 1, 2, 5, 6, 7, 8 ou 9

A soma de controle é dada por 9xd1 + 8xd2 + 7xd3 + 6xd4 + 5xd5 + 4xd6 + 3xd7 + 2xd8

Faz-se divisão por 11

Se o resto for inferior a 2, o check digit é 0

Caso contrario é 11 menos o resto

Link to post
Share on other sites
Icepick.pt

Aqui fica o código para validação com Javascript


function validaContribuinte(contribuinte){
// algoritmo de validação do NIF de acordo com
// http://pt.wikipedia.org/wiki/N%C3%BAmero_de_identifica%C3%A7%C3%A3o_fiscal

var temErro=0;

if (
contribuinte.substr(0,1) != '1' && // pessoa singular
contribuinte.substr(0,1) != '2' && // pessoa singular
contribuinte.substr(0,1) != '3' && // pessoa singular
contribuinte.substr(0,2) != '45' && // pessoa singular não residente
contribuinte.substr(0,1) != '5' && // pessoa colectiva
contribuinte.substr(0,1) != '6' && // administração pública
contribuinte.substr(0,2) != '70' && // herança indivisa
contribuinte.substr(0,2) != '71' && // pessoa colectiva não residente
contribuinte.substr(0,2) != '72' && // fundos de investimento
contribuinte.substr(0,2) != '77' && // atribuição oficiosa
contribuinte.substr(0,2) != '79' && // regime excepcional
contribuinte.substr(0,1) != '8' && // empresário em nome individual (extinto)
contribuinte.substr(0,2) != '90' && // condominios e sociedades irregulares
contribuinte.substr(0,2) != '91' && // condominios e sociedades irregulares
contribuinte.substr(0,2) != '98' && // não residentes
contribuinte.substr(0,2) != '99' // sociedades civis

) { temErro=1;}
var check1 = contribuinte.substr(0,1)*9;
var check2 = contribuinte.substr(1,1)*8;
var check3 = contribuinte.substr(2,1)*7;
var check4 = contribuinte.substr(3,1)*6;
var check5 = contribuinte.substr(4,1)*5;
var check6 = contribuinte.substr(5,1)*4;
var check7 = contribuinte.substr(6,1)*3;
var check8 = contribuinte.substr(7,1)*2;

var total= check1 + check2 + check3 + check4 + check5 + check6 + check7 + check8;
var divisao= total / 11;
var modulo11=total - parseInt(divisao)*11;
if ( modulo11==1 || modulo11==0){ comparador=0; } // excepção
else { comparador= 11-modulo11;}


var ultimoDigito=contribuinte.substr(8,1)*1;
if ( ultimoDigito != comparador ){ temErro=1;}

if (temErro==1){ alert('O numero de contribuinte parece estar errado' ); }

}
  • Vote 1
Link to post
Share on other sites
nunopicado
1 hora atrás, FranciscoS disse:

Tentei usar o seu código em Pascalzim porém continha alguns erros de sintaxe e "Result não esperado na linha 18 pode me ajudar a resolver?

Abraço!

PascalZim suporta apenas um subconjunto das capacidades da linguagem Pascal. 

Por outro lado, o código deste tópico está feito em Object Pascal, um supraconjunto da linguagem. 

Neste sentido há com certeza muita coisa no código que o PascalZim não suporta, e não admira. A ideia por trás do PascalZim é ter apenas o básico para propósitos de ensino. 

É possível adaptar o código para correr em PascalZim, mas se a ideia for usar todo o poder da linguagem pascal, o ideal é passar a usar um compilador capaz, com suporte a todas as funcionalidades da linguagem. Um bom exemplo gratuito é o FreePascal. 

 

 

Para o caso específico do "Result", este é um alias para o nome da função. Pode ser substituído pelo nome da função em que o result está a ser usado (neste caso, 'ValidaNIF') 

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.