9 votes

How to validate a RUC from Peru

Question: How can I verify that the format of a RUC peruvian to be valid?

What is the RUC? The Single Registry of Taxpayers (RUC) is the computer record where they are registered taxpayers in all of Peru. Is the tax code for individuals and businesses issued by the SUNAT (Superintendency for National Customs and Tax Administration), with records since 1993, and regulated since 2004 [1].

Is a unique, permanent and mandatory for all natural or legal persons (national or foreign) [2]. The SUNAT maintains the registry of taxpayers, associating the RUC with the personal data [3].


Each taxpayer is identified with an 11-digit number. The first 2 digits identify the type of person, the following 8 are for the ID or the number assigned to the company, and the last is a check digit verifier [4][5].

2 ("10" Persona natural, "20" Persona jurídica) + 8 (DNI o número empresa) + 1 (dígito verificador)


What I tried: I Used the same code that uses the SUNAT on its website to validate a RUC. However, you agree RUCs incorrect and appear to have calculations redundant.

//Validación de SUNAT
function valruc(valor){
  valor = trim(valor)
  if ( esnumero( valor ) ) {
    if ( valor.length == 8 ){
      suma = 0
      for (i=0; i<valor.length-1;i++){
        digito = valor.charAt(i) - '0';
        if ( i==0 ) suma += (digito*2)
        else suma += (digito*(valor.length-i))
      }
      resto = suma % 11;
      if ( resto == 1) resto = 11;
      if ( resto + ( valor.charAt( valor.length-1 ) - '0' ) == 11 ){
        return true
      }
    } else if ( valor.length == 11 ){
      suma = 0
      x = 6
      for (i=0; i<valor.length-1;i++){
        if ( i == 4 ) x = 8
        digito = valor.charAt(i) - '0';
        x--
        if ( i==0 ) suma += (digito*x)
        else suma += (digito*x)
      }
      resto = suma % 11;
      resto = 11 - resto
      
      if ( resto >= 10) resto = resto - 10;
      if ( resto == valor.charAt( valor.length-1 ) - '0' ){
        return true
      }      
    }
  }
  return false
}
function trim(cadena){
  cadena2 = "";
  len = cadena.length;
  for ( var i=0; i <= len ; i++ )
    if (cadena.charAt(i) != " "){
      cadena2+=cadena.charAt(i);
    }
  return cadena2;
}
function esnumero(campo){
  return (!(isNaN( campo )));
}



//Prueba
var ruc    = '12345678903',
    valido = valruc(ruc);

console.log('El RUC', ruc,
            'es', (valido?'válido':'inválido'),
            'para SUNAT.');

Objective: I am interested in validating the format of a RUC entered by a user, which can accept characters such as hyphens or other punctuation marks between the digits. What would be used as a previous stage before submitting a form.
Additionally, if there's a way to check to see if the RUC exists and is active, it would be even better.

I'm testing in JavaScript, but can be in any popular language. What is important is the algorithm.

Evidence: I Found the following list of manufacturing companies in companies.regioncallao.gov. pe (

12voto

Mariano Points 21056

Code:

We use 3 functions (each call to the next if the result is valid):

  1. validarInput(input)

    • Deletes common punctuation marks and spaces
    • Verifies that it is a whole number
    • Displays the formatted result
  2. rucValido(ruc)

    • Accepts a RUC number
    • Verifies that start with 10, 15, 16, 17, or 20
    • Check that the digit verifier appropriate
  3. obtenerDatosSUNAT(ruc)

//Handler para el evento cuando cambia el input
//Elimina cualquier caracter espacio o signos habituales y comprueba validez
function validarInput(input) {
    var ruc       = input.value.replace(/[-.,[\]()\s]+/g,""),
        resultado = document.getElementById("resultado"),
        existente = document.getElementById("existente"),
        valido;
        
    existente.innerHTML = "";
    
    //Es entero?    
    if ((ruc = Number(ruc)) && ruc % 1 === 0
    	&& rucValido(ruc)) { // ⬅️ ⬅️ ⬅️ ⬅️ Acá se comprueba
    	valido = "Válido";
        resultado.classList.add("ok");
        obtenerDatosSUNAT(ruc);
    } else {
        valido = "No válido";
    	resultado.classList.remove("ok");
    }
        
    resultado.innerText = "RUC: " + ruc + "\nFormato: " + valido;
}

// Devuelve un booleano si es un RUC válido
// (deben ser 11 dígitos sin otro caracter en el medio)
function rucValido(ruc) {
    //11 dígitos y empieza en 10,15,16,17 o 20
    if (!(ruc >= 1e10 && ruc < 11e9
       || ruc >= 15e9 && ruc < 18e9
       || ruc >= 2e10 && ruc < 21e9))
        return false;
    
    for (var suma = -(ruc%10<2), i = 0; i<11; i++, ruc = ruc/10|0)
        suma += (ruc % 10) * (i % 7 + (i/7|0) + 1);
    return suma % 11 === 0;
    
}

//Buscar datos del RUC y si existe
function obtenerDatosSUNAT(ruc) {
    //Init
    var url = "https://cors-anywhere.herokuapp.com/wmtechnology.org/Consultar-RUC/?modo=1&btnBuscar=Buscar&nruc=" + ruc,
        existente = document.getElementById("existente"),
        xhr = false;
    if (window.XMLHttpRequest) //Crear XHR
        xhr = new XMLHttpRequest();
    else if (window.ActiveXObject)
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
    else return false;
    //handler para respuesta
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) { //200 OK
            var doc = document.implementation.createHTMLDocument()
                    .documentElement,
                res = "",
                txt, campos,
                ok = false;
                
            doc.innerHTML = xhr.responseText;
            //Sólo el texto de las clases que nos interesa
            campos = doc.querySelectorAll(".list-group-item");
            if (campos.length) {
                for (txt of campos)
                    res += txt.innerText + "\n";
                //eliminar blancos por demás
                res = res.replace(/^\s+\n*|(:) *\n| +$/gm,"$1");
                //buscar si está el texto "ACTIVO" en el estado
                ok = /^Estado: *ACTIVO *$/m.test(res);
            } else
                res = "RUC: " + ruc + "\nNo existe.";
                
            //mostrar el texto formateado
            if (ok)
                existente.classList.add("ok");
            else 
                existente.classList.remove("ok");
            existente.innerText = res;
        }
    } //falta verificar errores en conexión
    xhr.open("POST", url, true);
    xhr.send(null);
}
#resultado, #existente {
    background-color: red;
    color: white;
    font-weight: bold;
    margin-top: 20px;
}
#resultado.ok, #existente.ok {
    background-color: green;
}
<label>RUC:</label>
<input type="text" id="input_ruc" style="width:100%;"
       oninput="validarInput(this)"
       placeholder="Ingrese su RUC">
<pre id="resultado"></pre>
<pre id="existente"></pre>

Demo for mobile



Description:

The first step is to remove the characters that don't interest us (-.,[]() \t\r\n\f):

var ruc = input.value.replace(/[-.,[\]()\s]+/g,"");
  • within the brackets you can add any character you want to ignore.


Then, we check that we have remained a whole:

if ((ruc = Number(ruc)) && ruc % 1 === 0) {


And with the whole, call to the main function:

rucValido(ruc);


Inside the function, we see that are 11 digits and begin with 10, 15, 16, 17, or 20:

if (!(ruc >= 1e10 && ruc < 11e9
   || ruc >= 15e9 && ruc < 18e9
   || ruc >= 2e10 && ruc < 21e9)) {

And, if it meets all of the above, we can verify that the last digit (verifier) is correct.


How to validate the check digit verifier of a RUC?

SUNAT uses an adaptation of the method to the codes of so-called control Module 11 or ISBN 10. It is a widely used method in these cases to detect errors in a single digit, or exchanges, simple or double (essentially, typing errors). Consists of:

  1. Multiply each of the first 10 dígitoa by a fixed factor, according to its position (the first digit by 5, the second by 4, *3, *2, *7, *6, *5, *4, *3, *2).
  2. Add each of the results of the previous point.
  3. Calculate the remainder of dividing by 11 (suma % 11).
  4. Get the complement 11 (11 - resto).
  5. Check if the last digit of the previous point coincides with the last digit of the RUC (if (ruc % 10 == complemento % 10)).

Diagrama ejemplificando los pasos

That is to say, for each digit, we add the last digit of the RUC (ruc % 10) and multiply it by your factor (i % 7 + (i/7|0) + 1) -yes, this gives us 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, for each value of i.

In each iteration of i, we remove the last digit (ruc = ruc/10|0).

It should be noted that, to simplify operation even more, include the digit verifier in the same account (with factor 1 for i=0). We only need to adjust in the case that in step 4 obtain values higher than 9. If it is 10 or 11, it means that the last digit is 0 or 1, and in those cases you will subtract 1 to the total sum (suma = -(ruc%10<2)).

Then we have:

for (var suma = -(ruc%10<2), i = 0; i<11; i++, ruc = ruc/10|0)
    suma += (ruc % 10) * (i % 7 + (i/7|0) + 1);

And it checks when:

suma % 11 === 0;

If this last condition is true, it then checks the digit verifier, and the RUC is valid.

HolaDevs.com

HolaDevs is an online community of programmers and software lovers.
You can check other people responses or create a new question if you don't find a solution

Powered by:

X