Saltar al contenido

Generador y Validador de CUIT/CUIL | Herramienta de Identificación Fiscal Argentina

Genere números de prueba válidos de CUIT/CUIL o valide los existentes. Herramienta en línea gratuita para desarrolladores que prueban sistemas de identificación fiscal y nómina con validación compatible con AFIP.

Generador de CUIT/CUIL

Ingrese un número de DNI de 8 dígitos o use el generador aleatorio

CUIT/CUIL Generado
20-28754232-2

Usando DNI generado aleatoriamente

Calculadora de carga...
📚

Documentación

Generador y Validador de CUIT/CUIL Argentino

Introducción

En los sistemas tributarios y laborales de Argentina, encontrará constantemente dos identificadores críticos: CUIT (Clave Única de Identificación Tributaria) y CUIL (Clave Única de Identificación Laboral). Considere el CUIT como el ID fiscal para empresas e individuos que pagan impuestos, mientras que el CUIL identifica a los trabajadores en el sistema de seguridad social. Ambos utilizan el mismo formato de 11 dígitos y algoritmo de verificación, lo que hace particularmente importante probar aplicaciones que manejan estos números.

Al desarrollar software para el mercado argentino, necesita datos de prueba válidos. Aquí es donde esta herramienta entra en juego. Puede generar números CUIT/CUIL matemáticamente correctos para pruebas sin usar información personal real, o validar números existentes para asegurar que se ajusten al algoritmo oficial de AFIP. Lo particularmente útil es que la herramienta maneja tanto el lado de generación (creando números válidos bajo demanda) como el lado de validación (detectando errores de formato, códigos de tipo inválidos y dígitos de verificación incorrectos antes de que causen problemas en producción).

Estructura y Cálculo de CUIT/CUIL

Comprendiendo el Formato

Un número CUIT/CUIL válido consta de 11 dígitos generalmente mostrados en el formato XX-XXXXXXXX-X. Así es como se desglosa:

  1. Código de Tipo (primeros 2 dígitos): Identifica el tipo de entidad

    • 20, 23, 24: Individuos masculinos (CUIL)
    • 27: Individuos femeninos (CUIL)
    • 30, 33, 34: Empresas y organizaciones (CUIT)
  2. Número de DNI (8 dígitos centrales): Para individuos, este es su número de documento nacional de identidad (DNI). Una trampa común: si el DNI real tiene menos de 8 dígitos, debe rellenarse con ceros a la izquierda. Por ejemplo, DNI 1234567 se convierte en 01234567 en el CUIT/CUIL. Las empresas reciben un número único asignado en su lugar.

  3. Dígito de Verificación (último dígito): Este dígito de control valida todo el número usando un algoritmo ponderado. Si este dígito no coincide con el cálculo, el CUIT/CUIL completo es inválido, algo que frecuentemente sorprende a los desarrolladores cuando construyen manualmente datos de prueba.

Cálculo del Dígito de Verificación

El dígito de verificación utiliza un algoritmo ponderado modulo-11. Así es como funciona:

  1. Tomar los primeros 10 dígitos del CUIT/CUIL (código de tipo + DNI)
  2. Multiplicar cada dígito por su peso correspondiente: 5, 4, 3, 2, 7, 6, 5, 4, 3, 2
  3. Sumar todos los productos
  4. Calcular: 11 menos (suma módulo 11)
  5. Manejar casos especiales: si el resultado es 11, usar 0; si es 10, usar 9

Lo que más confunde a la gente son esos casos especiales en los pasos 5. Al probar, ocasionalmente se obtiene un resultado de 10 o 11, y olvidar mapear estos a 9 y 0 respectivamente causa fallas de validación que pueden ser difíciles de depurar si no se conoce esta regla.

Matemáticamente, esto puede expresarse como:

VD=11((i=110di×wi)mod11)VD = 11 - ((\sum_{i=1}^{10} d_i \times w_i) \bmod 11)

Donde:

  • VDVD es el dígito de verificación
  • did_i es el ii-ésimo dígito de los primeros 10 dígitos
  • wiw_i es el peso correspondiente de la secuencia [5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
  • Casos especiales: si VD=11VD = 11 entonces VD=0VD = 0, si VD=10VD = 10 entonces VD=9VD = 9

Guía Paso a Paso

Usando el Generador

  1. Seleccione la pestaña "Generador" en la parte superior de la interfaz de la herramienta.

  2. Elija un Código de Tipo desde el menú desplegable:

    • 20: Masculino (CUIL)
    • 23: Empresa (CUIT)
    • 24: Empresa Temporal (CUIT)
    • 27: Femenino (CUIL)
    • 30: Corporación (CUIT)
    • 33: Asociación Civil (CUIT)
    • 34: Fundación (CUIT)
  3. Ingrese un Número de DNI (opcional):

    • Introduzca un número de DNI de 8 dígitos en el campo proporcionado
    • Si se deja vacío, la herramienta utilizará un DNI generado aleatoriamente
    • Si ingresa menos de 8 dígitos, el sistema completará con ceros a la izquierda
  4. Generar DNI Aleatorio (opcional):

    • Haga clic en el botón "Aleatorio" para generar un número de DNI aleatorio de 8 dígitos
  5. Ver el CUIT/CUIL Generado:

    • La herramienta muestra automáticamente un CUIT/CUIL válido basado en sus entradas
    • El formato será XX-XXXXXXXX-X con el dígito de verificación correcto
  6. Copiar el Resultado:

    • Haga clic en el icono de copiar para copiar el CUIT/CUIL generado al portapapeles
    • Aparecerá un mensaje de confirmación cuando se copie con éxito

Usando el Validador

  1. Seleccione la pestaña "Validador" en la parte superior de la interfaz de la herramienta.

  2. Ingrese el CUIT/CUIL a Validar:

    • Introduzca el CUIT/CUIL en el formato XX-XXXXXXXX-X
    • La herramienta formateará automáticamente su entrada con guiones mientras escribe
    • También puede ingresar el número sin guiones (XXXXXXXXXXX)
  3. Haga Clic en el Botón "Validar":

    • La herramienta verificará el formato, código de tipo y dígito de verificación
  4. Ver el Resultado de la Validación:

    • Para números CUIT/CUIL válidos, aparecerá un mensaje de éxito en verde
    • Para números inválidos, aparecerá un mensaje de error en rojo que explicará el problema:
      • Formato inválido (debe ser XX-XXXXXXXX-X)
      • Código de tipo inválido (debe ser uno de: 20, 23, 24, 27, 30, 33, 34)
      • Dígito de verificación inválido
  5. Información Adicional:

    • Para números válidos, la herramienta muestra un desglose de los componentes:
      • Código de tipo y su significado
      • Número de DNI
      • Dígito de verificación

Errores Comunes y Mejores Prácticas

Al trabajar con validación de CUIT/CUIL en sus aplicaciones, tenga cuidado con estas trampas frecuentes:

Problemas de Relleno con Ceros: El error más común que he encontrado involucra números de DNI con ceros iniciales. Cuando alguien ingresa DNI "1234567", su código necesita tratarlo como "01234567" para la construcción de CUIT/CUIL. Muchas implementaciones convierten a enteros para procesamiento, lo que elimina los ceros iniciales. Use operaciones de cadenas con relleno adecuado en su lugar.

Confusión de Código de Tipo: No todos los números de dos dígitos son códigos de tipo válidos. Solo 20, 23, 24, 27, 30, 33, 34 funcionan. He visto sistemas que aceptan cualquier prefijo de dos dígitos, lo que lleva a números como "21-12345678-X" que parecen válidos pero fallan en la validación de AFIP. Siempre valide el código de tipo antes de calcular el dígito de verificación.

Suposiciones de Género: Los códigos de tipo 20 (masculino) y 27 (femenino) no son intercambiables. Si está generando CUILs automáticamente basados en datos demográficos, asegúrese de que su código de tipo coincida con el género realmente registrado en RENAPER (registro nacional de Argentina). Los desajustes causan rechazo cuando las personas intentan usar estos números en servicios gubernamentales.

Manejo de Guiones: Algunas implementaciones requieren guiones mientras otras los rechazan. Mejor práctica: acepte ambos formatos en campos de entrada (con o sin guiones), elimine los guiones antes de la validación, almacene la versión sin guiones en bases de datos y agregue guiones solo para propósitos de visualización.

Verificación Faltante: La validación algorítmica detecta errores de formato pero no confirma que el CUIT/CUIL esté registrado. En producción, valide primero el formato (rápido), luego verifique contra la base de datos de AFIP (más lento pero autoritativo). Este enfoque de dos etapas detecta errores tipográficos instantáneamente mientras aún garantiza que el número sea real.

Prueba de Casos Límite: Siempre pruebe con dígitos de verificación 0 y 9, que resultan de casos especiales en el algoritmo. También pruebe DNIs que comiencen con ceros para asegurar que su lógica de relleno funcione correctamente.

Casos de Uso y Aplicaciones Prácticas

Desarrollo y Pruebas

Desarrollo de Software: Al construir aplicaciones para el mercado argentino, necesitará datos de prueba que pasen la validación sin usar información de usuarios reales. Aquí es donde esto se vuelve crítico:

  • Plataformas de comercio electrónico: Los procesadores de pagos y sistemas de facturación requieren números CUIT/CUIL válidos. Durante las pruebas de carga, podría necesitar miles de números válidos para simular registros de usuarios realistas.
  • Software contable: Los módulos de informes fiscales verifican el formato CUIT/CUIL antes de enviarlo a AFIP. Probar estas reglas de validación requiere números que pasen el algoritmo de dígito de verificación.
  • Sistemas de gestión de recursos humanos: El procesamiento de nómina y las contribuciones de seguridad social dependen de números CUIL válidos. Un escenario común: está probando flujos de incorporación de empleados y necesita verificar que los CUIL inválidos activen los mensajes de error apropiados.
  • Aplicaciones bancarias: Los procesos de KYC (Conoce a tu cliente) validan CUIT/CUIL como parte de la apertura de cuenta. En mi experiencia, los casos límite como discrepancias en el código de tipo a menudo surgen durante las pruebas de integración.

Población de Bases de Datos: Al sembrar bases de datos de prueba, usar números CUIT/CUIL válidos algorítmicamente garantiza que las restricciones y desencadenantes de su base de datos funcionen como se espera. Esto es particularmente importante al probar scripts de migración de datos o procesos ETL que validan números de identificación.

Pruebas de Validación de Formularios: Pruebe tanto el camino feliz como las condiciones de error. Genere números válidos para confirmar el envío exitoso, luego modifique el dígito de verificación para asegurarse de que la validación de su frontend y backend capture el error antes de que llegue a su base de datos.

Pruebas de API: Las pruebas de integración deben usar números CUIT/CUIL válidos en las cargas útiles de solicitud. Esto evita falsos negativos donde las pruebas fallan debido a datos de prueba inválidos en lugar de errores reales en la lógica de su API.

Automatización de QA: Las pruebas parametrizadas se benefician de la generación dinámica de CUIT/CUIL. En lugar de codificar valores de prueba que podrían entrar en conflicto entre ejecuciones de pruebas, genere números válidos nuevos para cada ejecución de prueba.

Propósitos Educativos

Aprendizaje de Algoritmos de Validación: El algoritmo de verificación de CUIT/CUIL demuestra la aplicación práctica de la aritmética modular y los dígitos de verificación ponderados. Este mismo patrón aparece en otros sistemas de identificación en todo el mundo: números de tarjetas de crédito (algoritmo de Luhn), códigos ISBN y números de IVA europeos utilizan enfoques similares de suma de verificación ponderada. Comprender cómo funciona la validación de CUIT/CUIL proporciona una idea de por qué existen estos algoritmos: detectan errores de transcripción como dígitos intercambiados o errores de un solo dígito.

Enseñanza de Validación de Datos: Al capacitar a desarrolladores junior en validación de entrada, el sistema CUIT/CUIL ofrece un ejemplo del mundo real más complejo que la validación de correo electrónico pero más simple que la verificación criptográfica. Demuestra el principio de defensa en profundidad: validación de formato (11 dígitos), validación de reglas de negocio (códigos de tipo válidos) y validación algorítmica (dígito de verificación).

Desarrollo Empresarial Internacional: Si está construyendo sistemas para mercados latinoamericanos, comprender CUIT/CUIL le ayuda a comprender sistemas similares en países vecinos. Brasil tiene CPF/CNPJ, Chile tiene RUT y Uruguay tiene RUT, todos utilizan algoritmos de dígito de verificación. Los patrones que aprenda aquí se transfieren a esos sistemas.

Alternativas y Consideraciones de Producción

Mientras que esta herramienta funciona bien para desarrollo y pruebas, los entornos de producción tienen requisitos diferentes:

Validación Oficial del Gobierno: Para aplicaciones en vivo, la validación algorítmica por sí sola no es suficiente, necesita verificar que el CUIT/CUIL esté realmente registrado con AFIP (Administración Federal de Ingresos Públicos). AFIP proporciona servicios web para validación en tiempo real, aunque necesitará registrarse y autenticarse para acceder a ellos. El truco: un número puede ser matemáticamente válido pero no asignado oficialmente, así que siempre implemente ambas capas de validación en producción.

Bibliotecas y Paquetes: Si está integrando la validación de CUIT/CUIL en su base de código, considere estas bibliotecas establecidas en lugar de crear la suya propia:

  • JavaScript: validar-cuit en npm maneja validación y formato
  • PHP: Biblioteca afip-php proporciona validación e integración de servicios web de AFIP
  • Python: py-cuit en PyPI implementa el algoritmo completo

Usar bibliotecas mantenidas reduce el riesgo de errores de implementación y a menudo incluye casos límite que podría pasar por alto en código personalizado.

Cálculo Manual: Con fines de aprendizaje o depuración, trabajar a través del algoritmo a mano ayuda a solidificar la comprensión. Agarre una calculadora y un CUIT/CUIL de muestra, luego siga el proceso de multiplicación ponderada paso a paso.

Servicios de Validación Empresarial: Las aplicaciones a gran escala podrían beneficiarse de API de validación de terceros que no solo verifican el formato, sino que también cruzan referencias con bases de datos comerciales. Estos servicios pueden marcar negocios inactivos, identificar entidades sancionadas o proporcionar metadatos adicionales sobre el titular del CUIT/CUIL.

Historia del Sistema CUIT/CUIL

El sistema de identificación CUIT/CUIL en Argentina ha evolucionado significativamente desde su creación:

Orígenes e Implementación

El CUIT (Clave Única de Identificación Tributaria) fue introducido por primera vez en Argentina en la década de 1970 como parte de los esfuerzos para modernizar el sistema de recaudación fiscal. La Administración Federal de Ingresos Públicos (AFIP) implementó este identificador único para rastrear contribuyentes de manera más eficiente y reducir la evasión fiscal.

El CUIL (Clave Única de Identificación Laboral) fue introducido posteriormente para identificar específicamente a los trabajadores en el sistema de seguridad social, creando una distinción entre la identificación fiscal y la identificación laboral, manteniendo un formato consistente.

Evolución y Digitalización

En la década de 1990, cuando Argentina atravesaba importantes reformas económicas, el sistema CUIT/CUIL se volvió cada vez más importante para rastrear la actividad económica. El sistema fue digitalizado aún más e implementó sistemas de verificación en línea.

A principios de los años 2000, se produjo la integración del sistema CUIT/CUIL con diversos servicios gubernamentales digitales, convirtiéndolo en un componente esencial de las iniciativas de gobierno electrónico de Argentina. Este período también vio la estandarización del algoritmo de verificación y el formato que se utiliza actualmente.

Desarrollos Recientes

En los últimos años, la AFIP ha mejorado los procesos de seguridad y verificación de los números CUIT/CUIL, implementando sistemas de validación más sofisticados e integrándolos con otras bases de datos gubernamentales. El sistema ahora juega un papel crucial en los esfuerzos de Argentina para combatir la evasión fiscal y formalizar la economía.

Actualmente, el CUIT/CUIL se utiliza no solo para fines fiscales y laborales, sino también para una amplia gama de actividades, incluyendo servicios bancarios, transacciones inmobiliarias, servicios públicos y compras en línea, convirtiéndolo en un identificador esencial para individuos y empresas que operan en Argentina.

Consideraciones de Implementación

Al implementar la validación de CUIT/CUIL en sus propios sistemas, considere estos aspectos técnicos:

Estabilidad del Algoritmo: El algoritmo de verificación de CUIT/CUIL actual se ha mantenido sin cambios desde su estandarización en la década de 1990. Según la documentación técnica de AFIP, el enfoque de dígito de verificación con módulo-11 ponderado está codificado en la Resolución General 2854/2010 y regulaciones posteriores. Esta estabilidad significa que las implementaciones rara vez necesitan actualizaciones, pero debe monitorear los anuncios de AFIP para cualquier cambio regulatorio.

Optimización de Rendimiento: El algoritmo de verificación es computacionalmente económico: solo 10 multiplicaciones, una adición y una operación de módulo. Para sistemas de alto rendimiento que procesan miles de validaciones por segundo, el cuello de botella es típicamente la latencia de red al verificar contra la base de datos de AFIP, no el algoritmo en sí. Considere almacenar en caché los resultados de verificación de AFIP con TTL apropiados (típicamente 24 horas) para equilibrar la actualidad con el rendimiento.

Codificación de Caracteres: Al procesar datos de CUIT/CUIL de fuentes externas (PDF, documentos escaneados, web scraping), preste atención a los problemas de codificación de caracteres. El guion puede aparecer como un guion largo (U+2014), guion corto (U+2013) o signo menos (U+2212) en lugar del guion estándar (U+002D). Normalice estos antes de la validación para prevenir falsos negativos.

Internacionalización: Si su aplicación atiende múltiples mercados latinoamericanos, tenga en cuenta que el CUIT/CUIL de Argentina usa módulo-11 con pesos específicos, mientras que el RUT de Chile usa módulo-11 con pesos diferentes, y el CPF/CNPJ de Brasil usa módulo-11 con otro patrón. No asuma que los algoritmos son idénticos: cada sistema de país tiene reglas distintas. Para una comprensión más amplia de los algoritmos de dígitos de verificación, consulte el estándar ISO/IEC 7064 que formaliza varios esquemas de verificación basados en módulo.

Almacenamiento en Base de Datos: Almacene números de CUIT/CUIL sin guiones como CHAR(11) de longitud fija o como BIGINT si su base de datos admite enteros de 11 dígitos sin pérdida de precisión. Agregue una restricción de verificación que valide el dígito de verificación a nivel de base de datos como red de seguridad contra datos corruptos. Cree índices en este campo para búsquedas eficientes cuando los usuarios busquen por CUIT/CUIL.

Ejemplos de Código

Python

1def calculate_verification_digit(type_code, dni):
2    # Convertir a cadena y asegurar que DNI tenga 8 dígitos con ceros a la izquierda
3    type_code_str = str(type_code)
4    dni_str = str(dni).zfill(8)
5    
6    # Combinar código de tipo y DNI
7    digits = type_code_str + dni_str
8    
9    # Pesos para cada posición
10    weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
11    
12    # Calcular suma de productos
13    sum_products = sum(int(digits[i]) * weights[i] for i in range(10))
14    
15    # Calcular dígito de verificación
16    verification_digit = 11 - (sum_products % 11)
17    
18    # Casos especiales
19    if verification_digit == 11:
20        verification_digit = 0
21    elif verification_digit == 10:
22        verification_digit = 9
23    
24    return verification_digit
25
26def generate_cuit_cuil(type_code, dni=None):
27    import random
28    
29    # Códigos de tipo válidos
30    valid_type_codes = [20, 23, 24, 27, 30, 33, 34]
31    
32    if type_code not in valid_type_codes:
33        raise ValueError(f"Código de tipo inválido. Debe ser uno de: {valid_type_codes}")
34    
35    # Generar DNI aleatorio si no se proporciona
36    if dni is None:
37        dni = random.randint(10000000, 99999999)
38    
39    # Calcular dígito de verificación
40    verification_digit = calculate_verification_digit(type_code, dni)
41    
42    # Formatear CUIT/CUIL
43    return f"{type_code}-{str(dni).zfill(8)}-{verification_digit}"
44
45def validate_cuit_cuil(cuit_cuil):
46    # Eliminar guiones si están presentes
47    cuit_cuil_clean = cuit_cuil.replace("-", "")
48    
49    # Verificar formato básico
50    if not cuit_cuil_clean.isdigit() or len(cuit_cuil_clean) != 11:
51        return False, "Formato inválido"
52    
53    # Extraer partes
54    type_code = int(cuit_cuil_clean[0:2])
55    dni = int(cuit_cuil_clean[2:10])
56    verification_digit = int(cuit_cuil_clean[10])
57    
58    # Validar código de tipo
59    valid_type_codes = [20, 23, 24, 27, 30, 33, 34]
60    if type_code not in valid_type_codes:
61        return False, "Código de tipo inválido"
62    
63    # Calcular y comparar dígito de verificación
64    calculated_digit = calculate_verification_digit(type_code, dni)
65    if calculated_digit != verification_digit:
66        return False, "Dígito de verificación inválido"
67    
68    return True, "CUIT/CUIL válido"
69
70# Ejemplo de uso
71print(generate_cuit_cuil(20, 12345678))  # Generar para DNI específico
72print(generate_cuit_cuil(27))  # Generar con DNI aleatorio
73print(validate_cuit_cuil("20-12345678-9"))  # Validar un CUIT/CUIL
74

JavaScript

1function calculateVerificationDigit(typeCode, dni) {
2  // Convertir a cadena y asegurar que DNI tenga 8 dígitos con ceros a la izquierda
3  const typeCodeStr = typeCode.toString();
4  const dniStr = dni.toString().padStart(8, '0');
5  
6  // Combinar código de tipo y DNI
7  const digits = typeCodeStr + dniStr;
8  
9  // Pesos para cada posición
10  const weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
11  
12  // Calcular suma de productos
13  let sumProducts = 0;
14  for (let i = 0; i < 10; i++) {
15    sumProducts += parseInt(digits[i]) * weights[i];
16  }
17  
18  // Calcular dígito de verificación
19  let verificationDigit = 11 - (sumProducts % 11);
20  
21  // Casos especiales
22  if (verificationDigit === 11) {
23    verificationDigit = 0;
24  } else if (verificationDigit === 10) {
25    verificationDigit = 9;
26  }
27  
28  return verificationDigit;
29}
30
31function generateCuitCuil(typeCode, dni) {
32  // Códigos de tipo válidos
33  const validTypeCodes = [20, 23, 24, 27, 30, 33, 34];
34  
35  if (!validTypeCodes.includes(typeCode)) {
36    throw new Error(`Código de tipo inválido. Debe ser uno de: ${validTypeCodes.join(', ')}`);
37  }
38  
39  // Generar DNI aleatorio si no se proporciona
40  if (dni === undefined) {
41    dni = Math.floor(Math.random() * 90000000) + 10000000;
42  }
43  
44  // Calcular dígito de verificación
45  const verificationDigit = calculateVerificationDigit(typeCode, dni);
46  
47  // Formatear CUIT/CUIL
48  return `${typeCode}-${dni.toString().padStart(8, '0')}-${verificationDigit}`;
49}
50
51function validateCuitCuil(cuitCuil) {
52  // Eliminar guiones si están presentes
53  const cuitCuilClean = cuitCuil.replace(/-/g, '');
54  
55  // Verificar formato básico
56  if (!/^\d{11}$/.test(cuitCuilClean)) {
57    return { isValid: false, errorMessage: 'Formato inválido' };
58  }
59  
60  // Extraer partes
61  const typeCode = parseInt(cuitCuilClean.substring(0, 2));
62  const dni = parseInt(cuitCuilClean.substring(2, 10));
63  const verificationDigit = parseInt(cuitCuilClean.substring(10, 11));
64  
65  // Validar código de tipo
66  const validTypeCodes = [20, 23, 24, 27, 30, 33, 34];
67  if (!validTypeCodes.includes(typeCode)) {
68    return { isValid: false, errorMessage: 'Código de tipo inválido' };
69  }
70  
71  // Calcular y comparar dígito de verificación
72  const calculatedDigit = calculateVerificationDigit(typeCode, dni);
73  if (calculatedDigit !== verificationDigit) {
74    return { isValid: false, errorMessage: 'Dígito de verificación inválido' };
75  }
76  
77  return { isValid: true };
78}
79
80// Ejemplo de uso
81console.log(generateCuitCuil(20, 12345678)); // Generar para DNI específico
82console.log(generateCuitCuil(27)); // Generar con DNI aleatorio
83console.log(validateCuitCuil("20-12345678-9")); // Validar un CUIT/CUIL
84

Java

1import java.util.Arrays;
2import java.util.List;
3import java.util.Random;
4
5public class CuitCuilUtils {
6    private static final List<Integer> VALID_TYPE_CODES = Arrays.asList(20, 23, 24, 27, 30, 33, 34);
7    private static final int[] WEIGHTS = {5, 4, 3, 2, 7, 6, 5, 4, 3, 2};
8    
9    public static int calculateVerificationDigit(int typeCode, int dni) {
10        // Convertir a cadena y asegurar que DNI tenga 8 dígitos con ceros a la izquierda
11        String typeCodeStr = String.valueOf(typeCode);
12        String dniStr = String.format("%08d", dni);
13        
14        // Combinar código de tipo y DNI
15        String digits = typeCodeStr + dniStr;
16        
17        // Calcular suma de productos
18        int sumProducts = 0;
19        for (int i = 0; i < 10; i++) {
20            sumProducts += Character.getNumericValue(digits.charAt(i)) * WEIGHTS[i];
21        }
22        
23        // Calcular dígito de verificación
24        int verificationDigit = 11 - (sumProducts % 11);
25        
26        // Casos especiales
27        if (verificationDigit == 11) {
28            verificationDigit = 0;
29        } else if (verificationDigit == 10) {
30            verificationDigit = 9;
31        }
32        
33        return verificationDigit;
34    }
35    
36    public static String generateCuitCuil(int typeCode, Integer dni) {
37        if (!VALID_TYPE_CODES.contains(typeCode)) {
38            throw new IllegalArgumentException("Código de tipo inválido. Debe ser uno de: " + VALID_TYPE_CODES);
39        }
40        
41        // Generar DNI aleatorio si no se proporciona
42        if (dni == null) {
43            Random random = new Random();
44            dni = 10000000 + random.nextInt(90000000);
45        }
46        
47        // Calcular dígito de verificación
48        int verificationDigit = calculateVerificationDigit(typeCode, dni);
49        
50        // Formatear CUIT/CUIL
51        return String.format("%d-%08d-%d", typeCode, dni, verificationDigit);
52    }
53    
54    public static ValidationResult validateCuitCuil(String cuitCuil) {
55        // Eliminar guiones si están presentes
56        String cuitCuilClean = cuitCuil.replace("-", "");
57        
58        // Verificar formato básico
59        if (!cuitCuilClean.matches("\\d{11}")) {
60            return new ValidationResult(false, "Formato inválido");
61        }
62        
63        // Extraer partes
64        int typeCode = Integer.parseInt(cuitCuilClean.substring(0, 2));
65        int dni = Integer.parseInt(cuitCuilClean.substring(2, 10));
66        int verificationDigit = Integer.parseInt(cuitCuilClean.substring(10, 11));
67        
68        // Validar código de tipo
69        if (!VALID_TYPE_CODES.contains(typeCode)) {
70            return new ValidationResult(false, "Código de tipo inválido");
71        }
72        
73        // Calcular y comparar dígito de verificación
74        int calculatedDigit = calculateVerificationDigit(typeCode, dni);
75        if (calculatedDigit != verificationDigit) {
76            return new ValidationResult(false, "Dígito de verificación inválido");
77        }
78        
79        return new ValidationResult(true, null);
80    }
81    
82    public static class ValidationResult {
83        private final boolean isValid;
84        private final String errorMessage;
85        
86        public ValidationResult(boolean isValid, String errorMessage) {
87            this.isValid = isValid;
88            this.errorMessage = errorMessage;
89        }
90        
91        public boolean isValid() {
92            return isValid;
93        }
94        
95        public String getErrorMessage() {
96            return errorMessage;
97        }
98    }
99    
100    public static void main(String[] args) {
101        // Ejemplo de uso
102        System.out.println(generateCuitCuil(20, 12345678)); // Generar para DNI específico
103        System.out.println(generateCuitCuil(27, null)); // Generar con DNI aleatorio
104        System.out.println(validateCuitCuil("20-12345678-9").isValid()); // Validar un CUIT/CUIL
105    }
106}
107

PHP

<?php function calculateVerificationDigit($typeCode, $dni) { // Convertir a cadena y asegurar que DNI tenga 8 dígitos con ceros a la izquierda $typeCodeStr = (string)$typeCode; $dniStr = str_pad((string)$dni, 8, '0', STR_PAD_LEFT); // Combinar código de tipo y DNI $digits = $typeCodeStr . $dniStr; // Pesos para cada posición $weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2]; // Calcular suma de productos $sumProducts = 0; for ($i = 0; $i < 10; $i++) { $sumProducts += (int)$digits[$i] * $weights[$i]; } // Calcular dígito de verificación $verificationDigit = 11 - ($sumProducts % 11); // Casos especiales if ($verificationDigit == 11) { $verificationDigit = 0; } else if ($verificationDigit == 10) { $verificationDigit = 9; } return $verificationDigit; } function generateCuitCuil($typeCode, $dni = null) { // Códigos de tipo válidos $validTypeCodes = [20, 23, 24, 27, 30, 33, 34]; if (!in_array($typeCode, $validTypeCodes)) { throw new Exception("Código de tipo inválido. Debe ser uno de: " . implode(', ', $validTypeCodes)); } // Generar DNI aleatorio si no se proporciona if ($dni === null) { $dni = rand(10000000, 99999999); } // Calcular dígito de verificación $verificationDigit = calculateVerificationDigit($typeCode, $dni); // Formatear CUIT/CUIL return sprintf("%d-%08d-%d", $typeCode, $dni, $verificationDigit); } function validateCuitCuil($cuitCuil) { // Eliminar guiones si están presentes $cuitCuilClean = str_replace('-', '', $cuitCuil); // Verificar formato básico if (!preg_match('/^\d{11}$/', $cuitCuilClean)) { return ['isValid' => false, 'errorMessage' => 'Formato inválido']; } // Extraer partes $typeCode = (int)substr($cuitCuilClean, 0, 2); $dni = (int)substr($cuitCuilClean, 2, 8); $verificationDigit = (int)substr($cuitCuilClean, 10, 1); // Validar código de tipo $validTypeCodes = [20, 23, 24, 27, 30, 33, 34]; if (!in_array($typeCode, $validTypeCodes)) { return ['isValid' => false, 'errorMessage' => 'Código de tipo inválido']; } // Calcular y comparar dígito de verificación $calculatedDigit = calculateVerificationDigit($typeCode, $dni); if ($calculatedDigit !== $verificationDigit) { return ['isValid' => false, 'errorMessage' => 'Dígito de verificación inválido']; } return ['isValid' => true]; } // Ejemplo de uso echo generateCuitCuil(20, 12345678) . "\n"; // Gen ## Preguntas Frecuentes ### ¿Cuál es la diferencia entre CUIT y CUIL? Aquí está la distinción práctica: **CUIT** (Clave Única de Identificación Tributaria) identifica contribuyentes, tanto individuos como empresas que presentan impuestos ante AFIP. **CUIL** (Clave Única de Identificación Laboral) identifica trabajadores en el sistema de seguridad social para empleo y jubilación. En la práctica, muchas personas tienen tanto un CUIL (de su primer trabajo) y podrían obtener posteriormente un CUIT (si se vuelven autónomos o inician un negocio). Los números utilizan un formato y reglas de cálculo idénticos, por lo que desde un punto de vista de validación, se manejan de la misma manera. La distinción importa para propósitos administrativos: los sistemas de nómina típicamente trabajan con CUIL, mientras que los sistemas de facturación e impuestos usan CUIT. ### ¿Qué códigos de tipo se usan para individuos y cuáles para empresas? Para individuos: - 20, 23, 24: Individuos masculinos (CUIL) - 27: Individuos femeninos (CUIL) Para empresas y organizaciones: - 30: Corporaciones (CUIT) - 33: Asociaciones Civiles (CUIT) - 34: Fundaciones (CUIT) ### ¿Cómo se calcula el dígito de verificación? El algoritmo usa multiplicación ponderada: toma cada uno de los primeros 10 dígitos, multiplica por los pesos **5, 4, 3, 2, 7, 6, 5, 4, 3, 2**, suma los productos, luego calcula 11 menos (suma módulo 11). Dos casos extremos confunden a la gente: cuando el cálculo da 11, se usa 0 como dígito de verificación; cuando da 10, se usa 9. Estos casos especiales existen porque el dígito de verificación debe ser un solo dígito (0-9). Este es un algoritmo de dígito de verificación módulo-11, similar al utilizado en códigos ISBN-10 y otros sistemas de identificación en todo el mundo. ### ¿Puedo usar esta herramienta para generar números CUIT/CUIL reales y oficiales? No, esta herramienta genera datos de prueba matemáticamente válidos, pero los números no están oficialmente registrados en AFIP. Piénselo como generar un número de tarjeta de crédito válido usando el algoritmo de Luhn: pasa la validación de formato, pero no está conectado a una cuenta real. Para el registro oficial de CUIT/CUIL, las personas necesitan visitar AFIP con su DNI, mientras que las empresas deben completar procedimientos de registro corporativo. La herramienta es estrictamente para desarrollo, pruebas y uso educativo donde se necesitan datos que parezcan válidos y que no entren en conflicto con números de identificación reales. ### ¿Por qué mi validación de CUIT/CUIL falla aunque el formato parezca correcto? Cuando la validación falla a pesar de tener un formato correcto, revise estos sospechosos habituales: 1. **Código de tipo inválido**: Solo 20, 23, 24, 27, 30, 33, 34 son válidos. Usar 21, 25 u otros números provocará un fallo. 2. **Dígito de verificación incorrecto**: El último dígito debe coincidir con el cálculo del algoritmo. Incluso cambiar un dígito en la parte del DNI requiere recalcular el dígito de verificación. 3. **Problemas de formato**: Debe tener exactamente 11gitos (XX-XXXXXXXX-X). Cuidado con espacios adicionales o ceros iniciales faltantes. 4. **Caracteres ocultos**: Copiar y pegar desde PDFs o sitios web a veces introduce caracteres Unicode invisibles que rompen la validación. Un consejo rápido de depuración: elimine el último dígito y recalcúlelo manualmente. Si no coincide, ese es su problema. ### ¿Son obligatorios los guiones en números CUIT/CUIL? Los guiones son solo para formato de visualización, no son parte del número para cálculos. Cuando ve **20-12345678-9**, el algoritmo solo se preocupa por los 11 dígitos: **20123456789**. La mayoría de las implementaciones de validación eliminan los guiones antes de procesar, por lo que nuestra herramienta acepta tanto **20-12345678-9** como **20123456789**. En API y bases de datos, normalmente se almacena la versión sin guiones y se añaden solo al mostrar a los usuarios. Este enfoque previene que las inconsistencias de formato causen fallos de validación. ### ¿Puede un número CUIT/CUIL tener menos de 8 dígitos en la parte de DNI? La parte de DNI debe tener siempre exactamente 8 dígitos, sin excepciones. Si el DNI real de alguien tiene menos dígitos (lo cual ocurre con DNIs antiguos de números más bajos), se rellena con ceros a la izquierda. Por ejemplo, DNI **1234567** se convierte en **01234567** en la estructura CUIT/CUIL. Esta es una fuente frecuente de errores al convertir entre formatos de DNI y CUIT/CUIL. He visto sistemas que fallan en la validación porque olvidaron rellenar, tratando **1234567** como un número de 7 dígitos en lugar de **01234567**. Siempre use funciones de relleno con ceros en su código en lugar de simple concatenación de cadenas. ### ¿Cómo puedo verificar si un CUIT/CUIL está oficialmente registrado en Argentina? Nuestra herramienta valida la corrección matemática: formato, código de tipo y dígito de verificación. Pero no puede decirle si el número está realmente registrado en AFIP o pertenece a una persona o empresa real. Para verificación oficial, use los [servicios web de AFIP](https://www.afip.gob.ar/) o su herramienta de búsqueda "Constancia de Inscripción". AFIP ofrece API para verificación automatizada, aunque necesitará registrarse como desarrollador y autenticarse. En entornos de producción, implemente ambas capas: primero ejecute validación algorítmica (rápida, detecta errores de escritura y de formato), luego verifique contra la base de datos de AFIP (más lenta, pero confirma que el número es real y activo). ### ¿Puedo usar esta herramienta en mi aplicación comercial? Sí, el algoritmo de validación de CUIT/CUIL es un estándar público definido por AFIP, por lo que puede implementarlo libremente en software comercial. Los ejemplos de código aquí proporcionados están destinados como implementaciones de referencia. Para uso en producción, considere estas mejores prácticas: implemente un manejo adecuado de errores para casos extremos, agregue registro para depurar fallos de validación, valide contra la base de datos oficial de AFIP (no solo validación algorítmica), y mantenga su implementación actualizada si AFIP cambia las reglas (aunque el algoritmo actual ha sido estable durante décadas). ### ¿La herramienta almacena los números CUIT/CUIL generados o validados? No, todo el procesamiento ocurre en su navegador (lado del cliente). Cuando genera o valida un CUIT/CUIL, el cálculo se ejecuta localmente usando JavaScript. Nada se envía a nuestros servidores, y no registramos, almacenamos ni rastreamos ningún número que ingrese o genere. Este enfoque del lado del cliente garantiza la privacidad y también significa que la herramienta funciona sin conexión una vez que la página se carga. Puede verificarlo abriendo las herramientas de desarrollador de su navegador y observando la pestaña de red, donde verá que no se envían solicitudes al generar o validar números. ## Referencias 1. AFIP (Administración Federal de Ingresos Públicos). "CUIT/CUIL/CDI." Sitio web oficial. [https://www.afip.gob.ar/](https://www.afip.gob.ar/) 2. Ministerio de Trabajo, Empleo y Seguridad Social. "CUIL - Clave Única de Identificación Laboral." [https://www.argentina.gob.ar/trabajo](https://www.argentina.gob.ar/trabajo) 3. ANSES (Administración Nacional de la Seguridad Social). "Obtener mi CUIL." [https://www.anses.gob.ar/](https://www.anses.gob.ar/) 4. Boletín Oficial de la República Argentina. "Resolución General AFIP 2854/2010: Procedimiento. Clave Única de Identificación Tributaria (C.U.I.T.)." 5. Código Fiscal de la República Argentina. "Identificación y Registro de Contribuyentes." --- Ya sea que esté construyendo un sistema de facturación, probando flujos de incorporación de empleados o aprendiendo sobre algoritmos de validación, esta herramienta proporciona la generación y validación de CUIT/CUIL que necesita. Genere datos de prueba que pasen la validación algorítmica, verifique números antes de que lleguen a su base de datos o explore cómo funciona el algoritmo de dígito de verificación en la práctica.