viernes, 14 de agosto de 2009

Validar RUC (SUNAT - PERU)

Para saber de que el RUC es valido se usa un algoritmo tambien llamado Modulo 11, esto nos permite hacer un calculo de los primeros 10 digitos y validarlo con el digito numero 11, de ser correcto se dice que el RUC es valido.

Aqui le adjunto la funcion que hace la validacion al RUC
Public Function ValidationRUC(ByVal ruc As String) As Boolean
Try

If Not IsNumeric(ruc) Then
Throw New Exception("El valor no es numerico")
End If

If ruc.Length <> 11 Then
Throw New Exception("Numero de digitos invalido")
End If

Dim dig01 As Integer = CInt(ruc.Substring(0, 1)) * 5
Dim dig02 As Integer = CInt(ruc.Substring(1, 1)) * 4
Dim dig03 As Integer = CInt(ruc.Substring(2, 1)) * 3
Dim dig04 As Integer = CInt(ruc.Substring(3, 1)) * 2
Dim dig05 As Integer = CInt(ruc.Substring(4, 1)) * 7
Dim dig06 As Integer = CInt(ruc.Substring(5, 1)) * 6
Dim dig07 As Integer = CInt(ruc.Substring(6, 1)) * 5
Dim dig08 As Integer = CInt(ruc.Substring(7, 1)) * 4
Dim dig09 As Integer = CInt(ruc.Substring(8, 1)) * 3
Dim dig10 As Integer = CInt(ruc.Substring(9, 1)) * 2
Dim dig11 As Integer = CInt(ruc.Substring(10, 1))

Dim suma As Integer = dig01 + dig02 + dig03 + dig04 + dig05 + dig06 + dig07 + dig08 + dig09 + dig10
Dim residuo As Integer = suma Mod 11
Dim resta As Integer = 11 - residuo

Dim digChk As Integer
If resta = 10 Then
digChk = 0
ElseIf resta = 11 Then
digChk = 1
Else
digChk = resta
End If

If dig11 = digChk Then
Return True
Else
Return False
End If

Catch ex As Exception
Throw ex
End Try
End Function
Ejm:
RUC = 10254824220
FACTOR = 5432765432

Se separa los 10 primeros digitos de la izquierda y se hace un calculo inividual
1 * 5 =5
0 * 4 = 0
2 * 3 = 6
5 * 2 = 10
4 * 7 = 28
8 * 6 = 48
2 * 5 = 10
4 * 4 = 16
2 * 3 = 6
2 * 2 = 4

Se suma el resultado de todas las multiplicaciones
SUMA = 133

Se calcula el residuo de la division por 11
133/ 11 = 1
RESIDUO = 1

Se resta 11 menos el residuo
11 - 1
RESTA = 10

digito de chequeo = RESTA
si resta = 10 entonces digito de cheque = 0
si resta = 11 entonces digito de cheque = 1

Por lo tanto el RUC 10254824220 es valido por que su digito numero 11 es 0 y el digito de chekeo es 0.

16 comentarios:

Unknown dijo...
Este comentario ha sido eliminado por el autor.
Unknown dijo...

Excelente explicacion, aqui lo transcribi en otro lenguaje como lo es PHP como funcion

function ValidRucPeru($ruc){
$factor= "5432765432";
$ruc= trim($ruc);

if ( (!is_numeric($ruc)) || (strlen($ruc) != 11) ){
return false;
}

$dig_verif= substr($ruc, 10, 1);

for ($i=0; $i < 10; $i++){
$arr[]= substr($ruc, $i, 1) * substr($factor, $i, 1);
}

$suma=0;
foreach($arr as $a){
$suma= $suma + $a;
}

//Calculamos el residuo
$residuo= round(($suma/11),1);
$residuo= substr($residuo, -1);
$resta= 11 - $residuo;
$dig_verif_aux= substr($resta, -1);

if ($dig_verif == $dig_verif_aux){
return true;
} else {
return false;
}
}

//ejecutamos la validacion
$ruc= "20372706288";
$isValidRuc= ValidRucPeru($ruc);
if ($isValidRuc){
echo "es valido";
} else {
echo "es invalido";
}

Unknown dijo...

Buenas eh descubierto una validacion mas leyendo unos powerpoint que encontre por la web ya me paso que ingreso como nro de RUC 29061992072 este numero y me sale como valido pero hay que tener en cuenta que los primeros 2 digitos deben ser de la siguiente manera:
10 Indica si se trata de una persona natural.
20 sociedad conyugal.
17 o 15 extranjeros

Por lo tanto al codigo en PHP que realice hay que agregarle lo siguiente:
//verificacion de los 2 digitos iniciales permitidos
$dig_valid= array("10", "20" ,"17", "15");
$dig=substr($ruc, 0, 2);
if (!in_array($dig, $dig_valid, true)) {
return false;
}

Saludos, Brian.

COCO dijo...

hola amigo no podrias compilar el codigo en un aplicativo.. seriaa de gran ayuda tu gran aporte.. gracias y saludos

Unknown dijo...

pasa que en mi ejemplo es en PHP por lo tanto deberias copiar el codigo y correrlo con una pc con apache que levante PHP si a eso te referis.

r3xet dijo...

Gracias por los aportes, deberia compilarlo o tener una clase ya que es de gran utilidad y tomare en cuenta sus comentarios

Marcelo dijo...

Error al hallar el residuo :S cambiar:

$residuo= round(($suma/11),1);
$residuo= substr($residuo, -1);

por esto

$residuo = $suma%11;

El substraer el ultimo decimal no te da el residuo verdadero, por ejemplo prueba el RUC 101068886844 el residuo te daría 6 y no 7 ;) saludos

Anónimo dijo...

visiten C&J System
hay encontran un ejemplo del aplicativo

http://www.facebook.com/cjsystem

Anónimo dijo...

Aqui les mando una funcion en PHP que les puede servir para validar el número de ruc.

function isrucok($ruc){
$est=false;
if (preg_match('/^(10|20|15|17)[0-9]{9}$/',$ruc)) {
$suma = 0;
$x = 6;
for ($i=0; $i<10;$i++){
if ( $i == 4 ) $x = 8;
$digito = substr($ruc,$i,1);
$x--;
$suma+= ($digito*$x);
}
$resto = $suma % 11;
$resto = 11 - $resto;
if ( $resto >= 10) {
$resto = $resto - 10;
}
if ( $resto == substr($ruc,10,1)){
$est=true;
}
}
return $est;
}

Anónimo dijo...

El ultimo si valida correctamente

Marco Llapapasca dijo...

Gracias por el aporte,funciona muy bien en c#...

Sigue adelante

Anónimo dijo...

*
*//Aqui el codigo de validacion:
*edm
PARAMETERS __Ruc
IF INLIST(LEFT(__Ruc,2),"10","20","15","17")=.F.
RETURN .F.
ENDIF

_Factor = "5432765432"

DIMENSION _aFac[10]
DIMENSION _aRuc[10]

FOR _i = 1 TO 10
_aFac[_i]= VAL(SUBSTR(_Factor,_i,1))
NEXT
STORE 0 TO _aRuc, _xSum
_cRuc = __Ruc
FOR _i = 1 TO 10
_aRuc[_i]= VAL(SUBSTR(_cRuc,_i,1))
_xSum=_xSum+_aRuc[_i]*_aFac[_i]
NEXT

_xResta=11-MOD(_xSum,11)

DO CASE
CASE _xResta=10
_nCh=0
CASE _xResta=11
_nCh=1
OTHERWISE
_nCh=_xResta
ENDCASE

_xCh=STR(_nCh,1,0)
_Mca=IIF(_xCh # SUBSTR(_cRuc,11,1),.F.,.T.)

RETURN (_Mca)
*

Anónimo dijo...

la función esta en sunat en java

function valruc(valor){
valor = trim(valor)
if ( esnumero( valor ) ) {
if ( valor.length == 8 ){
suma = 0
for (i=0; i= 10) resto = resto - 10;
if ( resto == valor.charAt( valor.length-1 ) - '0' ){
return true
}
}
}
return false

Unknown dijo...

function valruc(valor){
valor = trim(valor)
if ( esnumero( valor ) ) {
if ( valor.length == 8 ){
suma = 0
for (i=0; i= 10) resto = resto - 10;
if ( resto == valor.charAt( valor.length-1 ) - '0' ){
return true
}
}
}
return false

Juan Carlos dijo...

El residuo no es más que el resto de la división, para eso se debe utilizar el símbolo %. Aquí les comparto esta funcionalidad hecha en javascript:

function IsNumeric(data){
return parseInt(data)==data;
}

function validarRUC(identificacion) {
if(!IsNumeric(identificacion) || identificacion.length != 11){
return false;
}

var dig01 = identificacion.substr(0, 1) * 5;
var dig02 = identificacion.substr(1, 1) * 4;
var dig03 = identificacion.substr(2, 1) * 3;
var dig04 = identificacion.substr(3, 1) * 2;
var dig05 = identificacion.substr(4, 1) * 7;
var dig06 = identificacion.substr(5, 1) * 6;
var dig07 = identificacion.substr(6, 1) * 5;
var dig08 = identificacion.substr(7, 1) * 4;
var dig09 = identificacion.substr(8, 1) * 3;
var dig10 = identificacion.substr(9, 1) * 2;
var dig11 = identificacion.substr(10, 1);

var suma = dig01 + dig02 + dig03 + dig04 + dig05 + dig06 + dig07 + dig08 + dig09 + dig10;

var residuo = suma % 11;
var resta = 11 - residuo;

var digChk;
if(resta == 10)
digChk = 0;
else if (resta == 11) {
digChk = 1;
} else {
digChk = resta;
}

if(dig11 == digChk) {
return true;
}
else{
return false;
}
}

Oskarin dijo...

Y para dni no habra una validacion similiar usando SOLO LOS 8 DIGITOS DEL DNI?