71 lines
2.0 KiB
TypeScript
71 lines
2.0 KiB
TypeScript
import { ValidacionFiscalException } from '../exceptions/ValidacionFiscalException.js';
|
|
|
|
/**
|
|
* Value Object para el Número de Identificación Tributaria (NIT) en Colombia
|
|
* Incluye algoritmo de Módulo 11 oficial de la DIAN para cálculo y verificación del DV.
|
|
*/
|
|
export class Nit {
|
|
private readonly _numero: string;
|
|
private readonly _dv: string;
|
|
|
|
private static readonly PRIMOS_DIAN = [3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71];
|
|
|
|
constructor(numero: string, dv?: string) {
|
|
const cleanNumber = numero.replace(/\D/g, '');
|
|
if (!cleanNumber || cleanNumber.length < 5 || cleanNumber.length > 15) {
|
|
throw new ValidacionFiscalException(`El NIT suministrado "${numero}" no es válido. Debe contener entre 5 y 15 dígitos.`);
|
|
}
|
|
|
|
this._numero = cleanNumber;
|
|
const computedDv = Nit.calcularDigitoVerificacion(cleanNumber);
|
|
|
|
if (dv !== undefined && dv !== null && dv !== '') {
|
|
const cleanDv = dv.toString().trim();
|
|
if (cleanDv !== computedDv) {
|
|
throw new ValidacionFiscalException(
|
|
`Dígito de verificación inválido para el NIT ${cleanNumber}. Calculado: ${computedDv}, Proporcionado: ${cleanDv}`
|
|
);
|
|
}
|
|
this._dv = cleanDv;
|
|
} else {
|
|
this._dv = computedDv;
|
|
}
|
|
}
|
|
|
|
public static calcularDigitoVerificacion(nitLimpio: string): string {
|
|
let suma = 0;
|
|
const len = nitLimpio.length;
|
|
|
|
for (let i = 0; i < len; i++) {
|
|
const digito = parseInt(nitLimpio.charAt(len - 1 - i), 10);
|
|
suma += digito * Nit.PRIMOS_DIAN[i];
|
|
}
|
|
|
|
const residuo = suma % 11;
|
|
if (residuo === 0 || residuo === 1) {
|
|
return residuo.toString();
|
|
}
|
|
return (11 - residuo).toString();
|
|
}
|
|
|
|
public get numero(): string {
|
|
return this._numero;
|
|
}
|
|
|
|
public get dv(): string {
|
|
return this._dv;
|
|
}
|
|
|
|
public get nitCompleto(): string {
|
|
return `${this._numero}-${this._dv}`;
|
|
}
|
|
|
|
public toString(): string {
|
|
return this.nitCompleto;
|
|
}
|
|
|
|
public equals(otro: Nit): boolean {
|
|
return this._numero === otro._numero && this._dv === otro._dv;
|
|
}
|
|
}
|