Wednesday, July 22, 2009

Validação NIF Português AS3

Tive necessidade de criar um pequeno validador de NIFs nacionais. Embora não tenha encontrado documentação oficial encontrei um grande número de sitios em que as regras supostas são:
- Tem que ter 9 dígitos
- O primeiro dígito tem que ser 1, 2, 5, 6, 8 ou 9
- A soma de controle dada por 9xd1+8xd2+7xd3+6xd4+5xd5+4xd6+3xd7+2xd8+d9 tem que ser múltipla de 11 (congruente com o módulo 11, isto é, dê resto 0 quando dividida por 11). d1 é o dígito mais à esquerda, e d9 o digito mais à direita (digito de controle).
- d9, em alguns casos, precisava de ter o valor 10, para que a soma de controle fosse divisível por 11. Neste caso d9 tomará o valor 0. Nitidamente uma decisão mal tomada, pois um dígito de controle igual a zero, poderá significar uma soma de controle correcta ou uma cujo resto da divisão por onze dá 1. O dígito de controle deveria ser, por exemplo, uma letra com os 11 possíveis valores de A a K. Por curiosidade, o mesmo erro, existe na validação dos BI.

Fica aqui source code exemplo em Flex:

<?xml version="1.0" encoding="utf-8"?>
<mx:canvas mx="http://www.adobe.com/2006/mxml" creationcomplete="_init()"
form="ui.form.*" jwolib="http://www.jwolib.com/2006/mxml">
<mx:script>
<![CDATA[
import mx.controls.Alert;

private function _init():void {

}

private function _validateNIF():void {
if ( tNIFToValidate.text.length < 9 ) {
Alert.show( 'O NIF deve conter 9 digitos!' );
return;
}
if ( _validateBegin( Number( tNIFToValidate.text.charAt( 0 ) ) ) ) {
var chkd:Number = _getCheckDigit( Number(
tNIFToValidate.text.substr( 0, 8 ) ) );
if ( chkd != Number( tNIFToValidate.text.charAt( 8 ) ) ) {
Alert.show( 'O Check-digit do NIF não é válido!' );
return;
}
} else {
Alert.show( 'O NIF não pode começar por 3,5 ou 7!' );
return;
}
Alert.show( 'NIF é válido!' );
}
private function _generateCheckDigit():void {
if ( tCode.text == '' || tCode.text.length < 8 ) {
Alert.show( 'Deve inserir o código totalmente para gerar o
Check-digit' );
return;
}
if ( ! _validateBegin( Number( tCode.text.charAt( 0 ) ) ) ) {
Alert.show( 'O NIF não pode começar por 3,5 ou 7!' );
return;
}
var chkd:Number = _getCheckDigit( Number( tCode.text ) );
tCheckDigit.text = String( chkd );
}

private function _validateBegin( startChar:Number ):Boolean {
if (startChar == 1 || startChar == 2 || startChar == 5 ||
startChar == 6 || startChar == 8 || startChar == 9) {
return true;
} else {
return false;
}
}
private function _getCheckDigit( code:Number ):Number {
var c:Number = Number( String( code ).charAt( 0 ) );
var checkDigit:Number = c * 9;
var i:Number = 0;
for( i = 2; i <= 8; i++ ){
checkDigit += Number( String( code ).charAt( i - 1 ) )
* ( 10 - i );
}
checkDigit = 11 - ( checkDigit % 11 );

if( checkDigit >= 10 ) checkDigit = 0;

return checkDigit;
}
private function _onChangeTCode():void {
if ( tCode.text.length == 8 ) {
_generateCheckDigit();
} else {
tCheckDigit.text = '';
}
}
]]>
</mx:Script>
<mx:vbox>
<jwolib:FieldSet title="Help" width="350"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:text text="Faz a validação de um NIF Português e gera o
check-digit." width="100%">
</jwolib:FieldSet>
<jwolib:FieldSet direction="vertical" title="Validador NIF" width="350"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:hbox>
<mx:label text="NIF" width="60">
<mx:textinput id="tNIFToValidate" restrict="[0-9]" maxchars="9"
width="85">
<mx:button label="Valida" click="_validateNIF()">
</mx:HBox>
<mx:hrule width="100%">
<mx:hbox>
<mx:label text="Gerador" width="60">
<mx:textinput id="tCode" restrict="[0-9]" width="75" maxchars="8"
change="_onChangeTCode()">
<mx:textinput id="tCheckDigit" editable="false" width="20"
maxchars="1">
<mx:button label="Gera Check-digit"
click="_generateCheckDigit()">
</mx:HBox>
</jwolib:FieldSet>
</mx:VBox>
</mx:Canvas>