unit uValidacionUtils;

interface

function EsNIFCIF(Cif : String) : Boolean;
function DarDC(const Entidad,Sucursal,Cuenta: Variant): String;

implementation

uses
  SysUtils, Variants;

function Letra(Numero: Integer): string;
begin
  Result:= copy('TRWAGMYFPDXBNJZSQVHLCKET',1 + numero mod 23,1);
end;

function EsNif(NIF: String): Boolean;
var
  Numero: Integer;
begin
  Result:= FALSE;
  if TryStrToInt(Copy(NIF,1,Length(NIF)-1),Numero) then
     Result:= Uppercase(Copy(NIF,Length(NIF),1)) = Letra(Numero);
end;

function EsNumero(Num: Char): Boolean;
begin
  try
    StrToInt(Num);
    Result:=True;
  Except
    result:=False;
  end;
end;

{Cambiar un carácter por otro en una cadena.}
function CadCambioCar(Cadena, CarOrig, CarCambio : String) : String;
var
  i : Integer;
  Temp : String;
begin
  Temp := '';
  for i := 1 to Length(Cadena) do
      if Copy(Cadena, i, 1) = CarOrig then
         Temp := Temp + CarCambio
      else
         Temp := Temp + Copy(Cadena, i, 1);
  Result := Temp;
end;


{ Validar si un CIF introducido es correcto}
function EsNIFCIF(Cif : String) : Boolean;
var
  Suma, Control : Integer;
  n : Byte;
begin
  Result := False;

  {Se pasa todo a mayúsculas limpio de espacios y de caracteres especiales}
  Cif := UpperCase(Trim(Cif));

  {Se limpia de los caracteres '-' y '/'. }
  Cif := CadCambioCar(Cif,'-','');
  Cif := CadCambioCar(Cif,'/','');

  {El cif debe ser de 9 cifras}
  if Length(Cif) = 9 then
  begin
    {Comprobamos que sea un NIF}
    if EsNumero(Cif[1]) then
       Result := EsNif(Cif)
    else
      {Se comprueba que la letra que designa el tipo de cif sea correcta}
      if (Pos(Cif[1], 'ABCDEFGHPQSKLMX') = 0) then
         Result := False
      else
        {Se comprueba si es un extranjero, en ese caso se calcula el nif, cambiando la X, por 0}
        if Cif[1] = 'X' then
           Result := EsNif('0'+Copy(Cif,2,8))
        else
        begin
          Suma:= StrToInt(Cif[3])+StrToInt(Cif[5])+StrToInt(Cif[7]);
          for n := 1 to 4 do
              Suma := Suma + ((2*StrToInt(Cif[2*n])) mod 10)+((2*StrToInt(Cif[2*n])) div 10);
          Control := 10 - (Suma mod 10);
          {Se comprueba si es de tipo 'P' o 'S', es decir, Corporaciones Locales (Ayuntamientos, etc.)
           y Organismos públicos.}
          if Pos(Cif[1],'PS')<>0 then
           {Control tipo letra}
             Result := (Cif[9] = Chr(64+Control))
          else
           {Resto de tipos de CIF}
          begin
          {Control tipo número}
            if Control = 10 then
               Control := 0;
            Result:= ( StrToInt(Cif[9]) = Control);
          end;
        end;
  end;
end;

function CCC(cTemp : String) : Integer;
var
  K,I,nNum,nSum : Integer;
  cPesos,cNum  : String;
begin
  cPesos := '06030709100508040201';
  nSum := 0;
  for I := 1 TO length(cTemp) DO
  begin
    cNum := Copy(cTemp, length(cTemp) - I + 1, 1);
    nNum := StrToInt(cNum);
    nSum := nSum + (nNum * StrToInt(Copy(cPesos, ((i - 1) * 2) + 1, 2)));
  end;

  K := 11 -  (nSum MOD 11);

  Case K OF
    10:Result := 1;
    11:Result := 0;
    Else Result := K;
  end;
end;


function DarDC(const Entidad,Sucursal,Cuenta: Variant): String;
var
DC1,DC2: String;
begin
  if VarIsNull(Entidad)
  or VarIsNull(Sucursal)
  or VarIsNull(Cuenta) then
    Result := ''
  else
  begin
    DC1 := IntToStr(CCC(VarToStr(Entidad) + VarToStr(Sucursal))) ;
    DC2 := IntToStr(CCC(VarToStr(Cuenta)));
    Result := Dc1 + Dc2;
  end;
end; 



end.
