{ Invokable implementation File for TwsFactura which implements IwsFactura }
unit wsFacturaImpl;

interface

uses InvokeRegistry, Types, XSBuiltIns, wsFacturaIntf, xmldom, XMLIntf, msxmldom, XMLDoc,
      FIBDatabase,pFIBDatabase, DB, FIBDataSet, pFIBDataSet,SysUtils,uDataModule,
      Controls, Estados, Cliente, NuevoCliente, FacturasCli, NuevaDireccion, CHILKATMAILLib2_TLB,
      IniFiles, IdSSLOpenSSL,IdHTTP,Utils, Sello, Classes, StdCtrls, TimbrarCD, DateUtils,
      cfdv32,cfdv22,  Windows, Messages, Variants, Graphics, Forms, Dialogs, ShellAPI, StrUtils,
      FIBQuery, pFIBQuery, pFIBStoredProc,  SBCustomCertStorage, SBUtils,
      SBConstants, SBEncoding, SBTypes, Buttons, ExtCtrls,SBPublicKeyCrypto, SBCryptoProv,
      DirCliente, frxFIBComponents, frxClass, Hasp_Unit, SBX509;

      {SBASCommon}

type

  { TwsFactura }
  TwsFactura = class(TInvokableClass, IwsFactura)
  public

    //procedure GET_CONFIG( StrConexion:String; out NuevoCliente,NuevoConsig,SolicitarFactura, ValidaClave, EmailAlterno:Boolean; AgregarImpuesto, ListaLugares, Error:String); stdcall;
    procedure GET_CONFIG( StrConexion:String; out NuevoCliente, NuevoConsig, SolicitarFactura, ValidaClave, EmailAlterno:Boolean; out AgregarImpuesto, SujetoIEPS, ListaLugares, NoValidarImporte:String; out Error:String); stdcall;
    function VERIFICA_USUARIO(StrConexion:String; RFC,PASSWORD:String; out Error:String):Integer; stdcall;
    function RECUPERA_PASSWORD(StrConexion:String; RFC:String; Out Error:String):Boolean; stdcall;
    function GET_ESTADOS(StrConexion:String; Out Error:String ):WideString; stdcall;
    function REGISTRA_CLIENTE(StrConexion:String; NuevoCliente:WideString; out Error:String):Integer; stdcall;
    function GET_CLIENTE(StrConexion:String; ClienteId:Integer; out Error:String):WideString; stdcall;
    function VERIFICA_TICKET(StrConexion:String; Folio:String; out Error:String; TotalPagar : Double):Integer; stdcall;
    function GENERA_FACTURA(StrConexion:String; NumTicket:String;ConsigId : Integer; EmailAlterno:String; LugarExp:Integer; VUsoCFDI:String; out  Error:String):Boolean; stdcall;
    //function GENERA_FACTURA(StrConexion:String; NumTicket:String;ConsigId : Integer; EmailAlterno:String; LugarExp:Integer; out  Error:String):Boolean; stdcall; //GENERA_FACTURA(StrConexion:String; NumTicket:String;ConsigId : Integer; EmailAlterno:String; out  Error:String):Boolean; stdcall;
    function REGISTRA_DIRECCION(StrConexion:String; NuevaDireccion:WideString; out Error:String):Integer; stdcall;
    function GET_FACTURAS_CLI(StrConexion:String; ClienteId:Integer; out Error:String ):WideString; stdcall;
    function GET_PDF_XML(StrConexion:String; DoctoPvId:Integer; TipoArchivo:String; var Error:String) : WideString; stdcall;
    function GET_DIRECCION(StrConexion:String; DirCliId:Integer; Var Error:String):WideString; stdcall;
    function FACTURA_POR_MAIL(StrConexion:String; DOCTO_PV_ID:Integer; EmailAlterno:String; Var Error:String ):Boolean;  stdcall;

    // descarga y envio de notas de credito Josue 27/11/2017
    function GET_PDF_XML_CREDITO(StrConexion:String; DoctoPvId:Integer; TipoArchivo:String; var Error:String) : WideString; stdcall;
    function GET_NOTASCRED_CLI(StrConexion:String; ClienteId:Integer; out Error:String ):WideString; stdcall;
    function NOTASC_POR_MAIL(StrConexion:String; DOCTO_PV_ID:Integer; EmailAlterno:String; Var Error:String ):Boolean;  stdcall;

    //Cambio Josué 02/03/2018
    function GET_LUGARES_EXP(StrConexion:String; out Error:String):WideString; stdcall;

     //Cambio Josué 27/03/2018
    function GET_USOS_CFDI(StrConexion:String; out Error:String):WideString; stdcall;

    //Cambio Josué Octubre 2018 se listan los pagos que pueda tener una factura o todos los pagos de un cliente
    function GET_PAGOS_FAC_CLI(StrConexion, FolioVenta:String; ClienteId:Integer; out Error:String ):WideString; stdcall;
    function GET_PDF_XML_PAGOS(StrConexion:String; DoctoCCID:Integer; TipoArchivo:String; var Error:String) : WideString; stdcall;
    function PAGO_POR_MAIL(StrConexion:String; DoctoCCID:Integer; EmailAlterno:String; Var Error:String ):Boolean;  stdcall;

    function GetVersionDLL():String;  stdcall;
     //Candado
    function LeerCandado( var VersionCan,NumSuc:Integer):String;
    function Versiones(Var Error:String) : Integer;
    procedure ReadLicense(Var Error:String);
    function Conecta_Hasp(feature:integer; Var Error:String):integer;
    function ByteToString( var Value: array of byte ): String;
    function Errores_Hasp(estatus:hasp_status_t; Var Error:String):Integer;

  private
    handle  : hasp_handle_t;    // Para el candado
    status  : hasp_status_t;    // Para el candado
    FDataFile: string;


const
      AES_MIN_DATA_LEN      = 16; { the minimum data length for AES encryption/decryption }
      MAX_MEMORY            = 128; { the maximum memory size to be handled here }
      CUSTOM_FEATURE        = 42;
      DEMO_MEMBUFFER_SIZE   = 128;
      gVersionApp = 18;
      VersionMicrosip = 1135;  // Primera 2015

      vendor_code : AnsiString =
'XUD2y9qZN7MrT8pWw9zUtf5XvGDC2o8UosgXQPyP3sKV0k4cAmb+Ktsg7DPH7lBhO8kwaB1gTKD7McrE'+
'++V9I5C9WRRZZIJVglSLmWjk0hLf6vSwGACdK3+7TBXPYfHkoS1jP1SzKwrhdrKjtfClbE6ii0ylY8qP'+
'ZwHGL9BDToOCu4zH65FG+kcmQvD0voMZ9QY09BJoK82r8XQ4Rkne7XO0qGNNSJhqLQlOgUUFKztmXL5A'+
'2dTaE+mPx6het0LrQJfW3fhGYnO4ZfwE9mqO10hIkcTQLKrVcN+xe4qqOp2AdcgK4vntf/i5wjFDvwC6'+
'a4SPteYUfIP8qnt5tInFxNSj4S65onTl4NHK/BIjtLAPsN3T0xzPKpAPK2MWSvxFYYd1bdLZ0qshRifF'+
'eSOGJkLLu7uYYmpC/t+oA8jBgFx6xRuyUPumJcuednkfYn1JNnjbuG32wQ39j/ANdRxeHNR3BjVdEHix'+
'lMSzZLuMfQpnCsxkQ54kDHOpO3gtVYmSvIXoXdKlPEy4GVQR8J5pOcm0CR7bJG4TtzYxJCdnww2njYgG'+
'vdcj6SwVaY1Lwrq5TqwQOL2hBlN5LdhZNS9GMGEjoCSpFslRNfRnLbzo0De7wPTB3RLVmj6vcpL7KU/M'+
'eU8/2xBoO9KhEwtfv+BIrSKj0dcmH1TJqQ25kLDW2xbHVSFVCiu5PDeJoLPQpomm246gkgsWBXZtnc6N'+
'0RLiLnAAcjuv2DQzFTgZ2Qn0FSflQ9CskgxP/yrSAqplk640ZLJfQTwAhSmerdb2xTF0qMZEiqMQ3xP1'+
'HmQ1/NGU5VXLc8Th59Mp/KjS9P4bm/uyliJddKJUIC+wI3LpCIbuwhwdR1LUNLqI7nagfun9R2T2yNmR'+
'/qvaot0YRINED/mTbybS/KpfhkkQhSv8EJ5oRnkETJULBYi2imqWCnlAHtg=';

   var
     dm: TfrmDataModule;
     CatEstados : IXMLEstadosType;
     Cliente : IXMLClienteType;
     NuevoCli : IXMLNuevoClienteType;
     FacturasCliente : IXMLFacturasType;
     NuevaDir : IXMLNuevaDireccionType;
     DirCliente : IXMLDireccionType;

     data : array[0..16] of byte ;   // para el uso de lectura del candado

     membuffer : array [0..DEMO_MEMBUFFER_SIZE] of byte;  // para el uso de lectura del candado

     HANDLE1,HDTRN:Integer;    // para el uso de lectura del candado
     ParametrosArray: array[0..25] of String;   // para el uso de lectura del candado
     gNumSuc,gVersion : Integer;
end;

implementation

  { TwsFacturador }

{$REGION 'Versión de DLL'}
function TwsFactura.GetVersionDLL():String;  stdcall;
Var Folio,Modulo :String;
begin
 ///  Se agregó la función para obtener la versión de la dll
 ///  Desde 24/04/2014

 GetVersionDLL := '1.4.3';

end;
{$ENDREGION}



{$REGION 'Candado'}

function TwsFactura.Errores_Hasp(estatus:hasp_status_t; Var Error : String):Integer;
begin
Result := -1;
  case estatus of
    HASP_STATUS_OK:Result := 0;
    HASP_HASP_NOT_FOUND : Error := 'HASP_HASP_NOT_FOUND';
    HASP_MEM_RANGE : Error := 'Request exceeds memory range of a HASP file';
    HASP_INV_PROGNUM_OPT : Error := 'Legacy HASP HL Run-time API: Unknown/Invalid Feature ID option';
    HASP_INSUF_MEM : Error := 'System is out of memory';
    HASP_TMOF : Error := 'Too many open Features/login sessions';
    HASP_ACCESS_DENIED : Error := 'Access to Feature, HASP protection key or functionality denied';
    HASP_INCOMPAT_FEATURE : Error := 'Legacy decryption function cannot work on Feature';
    HASP_TOO_SHORT : Error := 'Encrypted/decrypted data length too short to execute function call';
    HASP_INV_HND : Error := 'Invalid login handle passed to function';
    HASP_INV_FILEID : Error := 'Specified File ID not recognized by API';
    HASP_OLD_DRIVER : Error := 'Installed driver or daemon too old to execute function';
    HASP_NO_TIME : Error := 'Real-time clock (rtc) not available';
    HASP_SYS_ERR : Error := 'SYSTEM ERROR';
    HASP_NO_DRIVER : Error := 'Required driver not installed';
    HASP_INV_FORMAT : Error := 'Unrecognized file format for update';
    HASP_REQ_NOT_SUPP : Error := 'Unable to execute function in this context';
    HASP_INV_UPDATE_OBJ : Error := 'Binary data passed to function does not contain valid update';
    HASP_KEYID_NOT_FOUND : Error := 'HASP protection key not found';
    HASP_INV_UPDATE_DATA : Error := 'Required XML tags not found; Contents in binary data are missing';
    HASP_INV_UPDATE_NOTSUPP : Error := 'UPDATE NOT SUPPORT';
    HASP_INV_UPDATE_CNTR : Error := 'Update counter set incorrectly';
    HASP_INV_VCODE : Error := 'Invalid Vendor Code passed';
    HASP_ENC_NOT_SUPP : Error := 'HASP SRM protection key does not support encryption type';
    HASP_INV_TIME : Error := 'Passed time value outside supported value range';
    HASP_NO_BATTERY_POWER : Error := 'Real-time clock battery out of power';
    HASP_NO_ACK_SPACE : Error := 'Acknowledge data requested by update, but ack_data parameter is null';
    HASP_TS_DETECTED : Error := 'Program running on a terminal server';
    HASP_FEATURE_TYPE_NOT_IMPL : Error := 'Requested Feature type not implemented';
    HASP_UNKNOWN_ALG : Error := 'Unknown algorithm used in H2R/V2C file';
    HASP_INV_SIG : Error := 'Signature verification operation failed';
    HASP_FEATURE_NOT_FOUND:Result := 0;//MessageDlg('Requested Feature not available';
    HASP_NO_LOG : Error := 'Access log not enabled';
    HASP_LOCAL_COMM_ERR : Error := 'Communication error between API and local HASP License Manager';
    HASP_UNKNOWN_VCODE : Error := 'Vendor Code not recognized by API';
    HASP_INV_SPEC : Error := 'Invalid XML specification';
    HASP_INV_SCOPE : Error := 'Invalid XML scope';
    HASP_TOO_MANY_KEYS : Error := 'Too many HASP SRM protection keys currently connected';
    HASP_TOO_MANY_USERS : Error := 'Too many concurrent user sessions currently connected';
    HASP_BROKEN_SESSION : Error := 'Session been interrupted';
    HASP_REMOTE_COMM_ERR : Error := 'Communication error between local and remote HASP License Managers';
    HASP_FEATURE_EXPIRED : Error := 'Feature expired';
    HASP_OLD_LM : Error := 'HASP License Manager version too old';
    HASP_DEVICE_ERR : Error := 'Input/Output error occured';
    HASP_UPDATE_BLOCKED : Error := 'Update installation not permitted; This update was already applied';
    HASP_TIME_ERR : Error := 'System time has been tampered with';
    HASP_SCHAN_ERR : Error := 'Communication error occurred in secure channel';
    HASP_STORAGE_CORRUPT : Error := 'Corrupt data exists in secure storage area of HASP SL protection key';
    HASP_NO_VLIB : Error := 'Unable to find Vendor library';
    HASP_INV_VLIB : Error := 'Unable to load Vendor library';
    HASP_SCOPE_RESULTS_EMPTY : Error := 'Unable to locate any Feature matching scope';
    HASP_VM_DETECTED : Error := 'Program running on a virtual machine';
    HASP_HARDWARE_MODIFIED : Error := 'HASP SL key incompatible';
    HASP_USER_DENIED : Error := 'USER DINI';
    HASP_UPDATE_TOO_OLD : Error := 'Ya se aplico esta actualización.';
    HASP_UPDATE_TOO_NEW : Error := 'Update to old';
    HASP_OLD_VLIB : Error := 'Old vlib';
    HASP_UPLOAD_ERROR : Error := 'Upload via ACC failed, e.g. because of illegal format';
    HASP_INV_RECIPIENT : Error := 'Invalid XML "recipient" parameter';
    HASP_INV_DETACH_ACTION : Error := 'Invalid XML "action" parameter';
    HASP_TOO_MANY_PRODUCTS : Error := 'scope does not specify a unique Product';
    HASP_INV_PRODUCT : Error := 'Invalid Product information';
    HASP_UNKNOWN_RECIPIENT : Error := 'Unknown Recipient';
    HASP_INV_DURATION : Error := 'Invalid Duration ';
    HASP_NO_API_DYLIB : Error := 'API dispatcher: API for this Vendor Code was not found ';
    HASP_INV_API_DYLIB : Error := 'API dispatcher: Unable to load API; DLL possibly corrupt? ';
    HASP_INVALID_OBJECT : Error := 'C++ API: Object incorrectly initialized ';
    HASP_INVALID_PARAMETER : Error := 'C++ API: Invalid function parameter ';
    HASP_ALREADY_LOGGED_IN : Error := 'C++ API: Logging in twice to the same object ';
    HASP_ALREADY_LOGGED_OUT : Error := 'C++ API: Logging out twice of the same object ';
    else result := 1;
  end;
end;

function TwsFactura.LeerCandado(var VersionCan,NumSuc:Integer):String;
Var Error : String;
begin
  gVersion := 0;
  gNumSuc := 0;
  Result := '';

  Versiones(Error);

  VersionCan := gVersion;
  NumSuc := gNumSuc;
  Result := Error;

end;

function TwsFactura.Versiones(Var Error:String) : Integer;
begin
Result := 1;
  try
    ReadLicense(Error);
    Result := 0;
  except on e : exception do
  begin
   Error := e.Message;
   Result := 1;
  end;
end;
end;

procedure TwsFactura.ReadLicense(Var Error:String);
var EstatusHasp:Integer;
Memoria, Version, NoAdendas: String;
begin

try
begin
  if Conecta_Hasp(0,Error) = 0 then
  begin
  
     EstatusHasp := hasp_read(handle, HASP_FILEID_RO, 0, 96, membuffer);
     EstatusHasp := hasp_logout(handle);
     MEMORIA := ByteToString(membuffer);
     VERSION := Copy(MEMORIA,33,2);
     NoAdendas := Copy(MEMORIA,35,2); //Solo para Adendas

     if trim( NoAdendas ) = '' then
     begin
         gNumSuc := 0;
     end else
         gNumSuc := StrToInt(NoAdendas);

     if trim(VERSION) = '' then begin Version := '2011'; gVersion := 2011; end;

       if MEMORIA = '' then
       BEGIN
        if Conecta_Hasp(32,Error) = 0 then
        begin
           EstatusHasp := hasp_read(handle, HASP_FILEID_RO, 0, 96, membuffer);
           EstatusHasp := hasp_logout(handle);
           MEMORIA := ByteToString(membuffer);
           VERSION := Copy(MEMORIA,33,2);//9,4);
           NoAdendas := Copy(MEMORIA,35,2);//,13,2); //Solo para Adendas
           if trim(VERSION) = '' then begin  Version := '2011'; gVersion := 2011; end;
           if trim( NoAdendas ) = '' then
              gNumSuc := 0
           else
             gNumSuc := StrToInt(NoAdendas);
        end
       END;
  end
  else
  begin
      raise exception.Create(Error);
  end;

     if trim(VERSION) = '' then
     begin
        Version := '0';
        gVersion := 0;
     end;

     if trim( NoAdendas ) = '' then
              gNumSuc := 0
           else
              gNumSuc := StrToInt(NoAdendas);
     //lblVersion Se tiene que agregar a cada proyecto
     //fmConfigConexion.lblVersion.Caption := 'Versión: '+ VERSION + ' NoAdendas: '+ NoAdendas; //Solo para Adendas

     try
       gVersion := StrToInt(VERSION);
     finally
     end;
     if gVersion = 0 then
     begin
       Error := 'Necesita activar en su candado el módulo.';
     end else
     begin
     if gVersion < gVersionApp then
     begin
       Error := 'La versión '+ IntToStr(gVersionApp)+' del programa es superior a la versión '+Version+' de su candado. ';
       //Application.Terminate;
     end;
     end;

     //gVersion := VersionNumero;
     gNumSuc := StrToInt(NoAdendas);

 end
except on e :exception do
 begin
   Error := e.Message;
   gVersion := 0;
   gNumSuc := 0;
 end;
end;

end;

function TwsFactura.Conecta_Hasp(feature:integer; Var Error:String):integer;
begin
Result := 1;
status := hasp_login(feature, @vendor_code[1], handle);
  case status of
    HASP_STATUS_OK:Result := 0;
  else
  begin
    if Errores_Hasp(status,Error) = 1 then
       MessageDlg('Ha sucedido un error. No es posible continuar.', mtError, [mbOk], 0);
  end;
  end;
end;

function TwsFactura.ByteToString( var Value: array of byte ): String;
var  I: integer;
    S : String;
    Letra: char;
begin
    S := '';
    for I := Length(Value)-1 Downto 0 do
    begin
        letra := Char(Value[I]);
        S := letra + S;
    end;
    Result := S;
end;

{$ENDREGION}

//Enviar factura por mail
function TwsFactura.FACTURA_POR_MAIL(StrConexion:String; DOCTO_PV_ID:Integer; EmailAlterno:String; Var Error:String ):Boolean;  stdcall;
Var Folio,Modulo :String;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
     if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);

     if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
     dm.trTrans.StartTransaction;

     folio := '';
     Error := '';

     dm.IBQuery.Close;
     dm.IBQuery.SelectSQL.Clear;
     dm.IBQuery.SelectSQL.Add('SELECT IIF( B.SERIE = ''@'','''',B.SERIE)||A.FOLIO FOLIO, A.SISTEMA ');
     dm.IBQuery.SelectSQL.Add('FROM USOS_FOLIOS_FISCALES A ');
     dm.IBQuery.SelectSQL.Add('INNER JOIN FOLIOS_FISCALES B ON ( A.FOLIOS_FISCALES_ID = B.FOLIOS_FISCALES_ID ) ');
     dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_ID = :DOCTO_VE_ID ');
     dm.IBQuery.ParamByName('DOCTO_VE_ID').AsInteger := DOCTO_PV_ID;
     dm.IBQuery.Open;

     folio := dm.IBQuery.FieldByName('FOLIO').AsString;

     if folio = '' then
         raise exception.Create('No existe el documento indicado.');

     Modulo := dm.IBQuery.FieldByName('SISTEMA').AsString;

     Result := dm.EnviaFacturas(DOCTO_PV_ID,Folio,Modulo,EmailAlterno,Error);

     if Error <> '' then
            raise exception.Create(Error);

    end
	  except on e : exception do
     begin
       Error := e.Message;
       Result := False;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

// Obtiene las preferencias.
//procedure TwsFactura.GET_CONFIG( StrConexion:String; out NuevoCliente,NuevoConsig,SolicitarFactura, ValidaClave, EmailAlterno:Boolean; AgregarImpuesto, ListaLugares, Error:String); stdcall;
procedure TwsFactura.GET_CONFIG( StrConexion:String; out NuevoCliente, NuevoConsig, SolicitarFactura, ValidaClave, EmailAlterno:Boolean; out AgregarImpuesto, SujetoIEPS, ListaLugares, NoValidarImporte:String; out Error:String); stdcall;
Var Valor:String;
 NuevoCli,ConsigNuevo:Boolean;
 VersionCan,NumSuc:Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      Error := '';

      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

    {$REGION ' Nuevo cliente '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''CrearNuevoCli'' ');
      dm.IBQuery.Open;
      Valor := dm.IBQuery.FieldByName('VALOR').AsString;
      if Valor = 'S' then
        NuevoCliente := True
      else
        NuevoCliente := False;
    {$ENDREGION}

    {$REGION ' Nueva dirección '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''CrearNuevaDir'' ');
      dm.IBQuery.Open;
      Valor := dm.IBQuery.FieldByName('VALOR').AsString;
      if Valor = 'S' then
        NuevoConsig := True
      else
        NuevoConsig := False;
    {$ENDREGION}

    {$REGION ' Solicitar factura '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''SolicitarFactura'' ');
      dm.IBQuery.Open;
      Valor := dm.IBQuery.FieldByName('VALOR').AsString;
      if Valor = 'S' then
        SolicitarFactura := True
      else
        SolicitarFactura := False;
    {$ENDREGION}

     {$REGION ' Validar clave de acceso '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''PassWeb'' ');
      dm.IBQuery.Open;
      Valor := dm.IBQuery.FieldByName('VALOR').AsString;
      if Valor = 'S' then
        ValidaClave := True
      else
        ValidaClave := False;
    {$ENDREGION}

    {$REGION ' utilizar email alterno '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''CorreoAlterno'' ');
      dm.IBQuery.Open;
      Valor := dm.IBQuery.FieldByName('VALOR').AsString;
      if Valor = 'S' then
        EmailAlterno := True
      else
        EmailAlterno := False;
    {$ENDREGION}

    {$REGION ' retener impuesto '}
      AgregarImpuesto := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''RetieneImpto'' ');
      dm.IBQuery.Open;
      AgregarImpuesto := dm.IBQuery.FieldByName('VALOR').AsString;

    {$ENDREGION}

     {$REGION ' lugares de expedición  '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''ListaLugares'' ');
      dm.IBQuery.Open;
      ListaLugares := dm.IBQuery.FieldByName('VALOR').AsString;
    {$ENDREGION}

    //NoValidarImporte
    {$REGION ' lugares de expedición  '}
      Valor := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''NoValidarImporte'' ');
      dm.IBQuery.Open;
      NoValidarImporte := dm.IBQuery.FieldByName('VALOR').AsString;
    {$ENDREGION}
//SujetoIEPS

    {$REGION 'Sujeto IEPS '}
      SujetoIEPS := '';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''SujetoIEPS'' ');
      dm.IBQuery.Open;
      SujetoIEPS := dm.IBQuery.FieldByName('VALOR').AsString;
    {$ENDREGION}

    Error := LeerCandado(VersionCan,NumSuc);
    if Error <> '' then
    begin
      NuevoCliente := False;
      NuevoConsig := False;
      SolicitarFactura := False;
      if Error = 'HASP_HASP_NOT_FOUND' then
         raise Exception.Create('Versión demostrativa.' )
      else
         raise Exception.Create(Error);
    end;


    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;

end;

//Verifica que el cliente exista en la base de datos
function TwsFactura.VERIFICA_USUARIO(StrConexion:String; RFC,PASSWORD:String; out Error:String):Integer; stdcall;
Var ClienteId:Integer;
Pass,Estatus:String;
NumSuc,VersionCan : Integer;
ValidaClave:String;
EsRFC:String;
begin
Result := 0;
    sysutils.decimalseparator:='.';
    SysUtils.ThousandSeparator := ',';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      // Verifica candado exsim
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      Error := LeerCandado(VersionCan,NumSuc);

      if (VersionCan < gVersionApp) and (VersionCan<> 0) then
          Raise Exception.Create('La versión '+IntToStr(gVersionApp)+' del programa es superior a la versión '+
                                 IntToStr(VersionCan)+' de su candado.');

      if (RFC = 'XEXX010101000') then
          Raise Exception.Create('Si es un cliente extranjero, debe iniciar sesión con su correo electrónico.');

      EsRFC := '';
      if Ansipos(trim('@'),trim(RFC))<>0 then
        EsRFC := 'N'
      else
        EsRFC := 'S';

      //Raise Exception.Create('Valor EsRFC: '+EsRFC);

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''PassWeb'' ');
      dm.IBQuery.Open;
      ValidaClave  := dm.IBQuery.FieldByName('VALOR').AsString;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''ConfigOK'' ');
      dm.IBQuery.Open;

      if dm.IBQuery.FieldByName('VALOR').AsString = 'S' then
      begin
      ClienteId := 0;
      {Esta consulta regresaba valor que no se ven el configurador
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.CLIENTE_ID,B."PASSWORD",B.ESTATUS ');
      dm.IBQuery.SelectSQL.Add('FROM DIRS_CLIENTES A ');
      dm.IBQuery.SelectSQL.Add('LEFT JOIN MGFACTURA_USUARIOS B ON (A.CLIENTE_ID = B.CLIENTE_ID) ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN DIRS_CLIENTES C ON ( A.DIR_CLI_ID = C.DIR_CLI_ID ) ');
      dm.IBQuery.SelectSQL.Add('WHERE REPLACE( REPLACE(UPPER(A.RFC_CURP),'' '',''''),''-'','''') = :RFC AND C.ES_DIR_PPAL = ''S'' ');
      dm.IBQuery.ParamByName('RFC').AsString := dm.ValidaCadena(AnsiUpperCase(RFC));
      dm.IBQuery.Open;
      }

      if EsRFC = 'S' then
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT B.CLIENTE_ID,A."PASSWORD",A.ESTATUS ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURA_USUARIOS A ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN CLIENTES B ON ( A.CLIENTE_ID = B.CLIENTE_ID ) ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN DIRS_CLIENTES C ON ( A.CLIENTE_ID = C.CLIENTE_ID ) ');
        dm.IBQuery.SelectSQL.Add('WHERE C.ES_DIR_PPAL = ''S'' AND B.ESTATUS = ''A'' ');
        dm.IBQuery.SelectSQL.Add('AND REPLACE( REPLACE(UPPER(C.RFC_CURP),'' '',''''),''-'','''') = :RFC  ');
        dm.IBQuery.ParamByName('RFC').AsString := dm.ValidaCadena(AnsiUpperCase(RFC));
        dm.IBQuery.Open;
      end;

      if EsRFC = 'N' then
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT B.CLIENTE_ID,A."PASSWORD",A.ESTATUS ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURA_USUARIOS A ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN CLIENTES B ON ( A.CLIENTE_ID = B.CLIENTE_ID ) ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN DIRS_CLIENTES C ON ( A.CLIENTE_ID = C.CLIENTE_ID ) ');
        dm.IBQuery.SelectSQL.Add('WHERE C.ES_DIR_PPAL = ''S'' AND B.ESTATUS = ''A'' ');
        dm.IBQuery.SelectSQL.Add('AND UPPER(C.EMAIL) = UPPER(:RFC)  ');
        dm.IBQuery.ParamByName('RFC').AsString := RFC;
        dm.IBQuery.Open;
      end;

      ClienteId := dm.IBQuery.FieldByName('CLIENTE_ID').AsInteger;
      {if dm.IBQuery.FieldByName('PASSWORD').AsString <> '' then
         Pass := dm.descifrarTexto(Trim(dm.IBQuery.FieldByName('PASSWORD').AsString))
      else
         Pass := '';}
      Pass := dm.IBQuery.FieldByName('PASSWORD').AsString;
      Estatus := dm.IBQuery.FieldByName('ESTATUS').AsString;

     if ClienteId = 0 then
      begin
        Error := 'El cliente no existe, verifique su información.';
        Result := 0;
        PASSWORD := '';
        RFC := '';

      end else
      begin
        //////
        if Pass = '' then
        begin
           if ValidaClave <> 'S' then
           begin
             Error := 'El cliente no está configurado correctamente.';
             Result := 0;
             PASSWORD := '';
             RFC := '';
           end else
           begin
               if Estatus <> 'A' then
               begin
                  Error := 'Esta cuenta está desactivada.';
                  Result := 0;
                  PASSWORD := '';
                  RFC := '';
                end else
                begin
                  Error := '';
                  Result := ClienteId;
                  PASSWORD := Pass;
                end;
           end;
        end else
        begin
          if ValidaClave <> 'S' then
          begin
            if (trim(Pass) <> trim(PASSWORD)) or (trim(Pass)='') then
            begin
              Error := 'El password no es correcto, verifique su información.';
              Result := 0;
              PASSWORD := '';
              RFC := '';

            end else
            begin
              if Estatus <> 'A' then
              begin
                Error := 'Esta cuenta está desactivada.';
                Result := 0;
                PASSWORD := '';
                RFC := '';
              end else
              begin
                Error := '';
                Result := ClienteId;
                PASSWORD := Pass;
              end;
            end;
          end else// if ValidaClave <> 'S' then
          begin
               if Estatus <> 'A' then
                begin
                  Error := 'Esta cuenta está desactivada.';
                  Result := 0;
                  PASSWORD := '';
                  RFC := '';
                end else
                begin
                  Error := '';
                  Result := ClienteId;
                  PASSWORD := Pass;
                end;
          end;
        end
        /////////
      end;
      end else
      begin
        Error := 'El módulo no se ha configurado correctamente.';
        Result := 0;
      end;

    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

//Envía un correo con el password del cliente
function TwsFactura.RECUPERA_PASSWORD(StrConexion:String; RFC:String; Out Error:String):Boolean; stdcall;
Var Smtp,Usuario,Pass,EnviadoPor,PuertoMail,Asunto,Mensaje,Email,NombreCli:String;
ErrorEnvio,NombreEmpresa,PDF,XML,SSL,TLS:String;
ClienteId : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
          dm.trTrans.Rollback;

      dm.trTrans.StartTransaction;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT NOMBRE FROM DATOS_EMPRESA ');
      dm.IBQuery.Open;
      NombreEmpresa := dm.IBQuery.FieldByName('NOMBRE').AsString;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''ConfigOK'' ');
      dm.IBQuery.Open;

      if dm.IBQuery.FieldByName('VALOR').AsString = 'S' then
      begin

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT A.CLIENTE_ID ');
        dm.IBQuery.SelectSQL.Add('FROM DIRS_CLIENTES A ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN DIRS_CLIENTES C ON ( A.DIR_CLI_ID = C.DIR_CLI_ID ) ');
        dm.IBQuery.SelectSQL.Add('WHERE UPPER(A.RFC_CURP) = :RFC AND C.ES_DIR_PPAL = ''S'' ');
        dm.IBQuery.ParamByName('RFC').AsString := AnsiUpperCase(RFC);
        dm.IBQuery.Open;
        ClienteId := dm.IBQuery.FieldByName('CLIENTE_ID').AsInteger;

        dm.IBQuery4.Close;
        dm.IBQuery4.SelectSQL.Clear;
        dm.IBQuery4.SelectSQL.Add('SELECT A.CLIENTE_ID,B."PASSWORD",A.EMAIL,C.NOMBRE ');
        dm.IBQuery4.SelectSQL.Add('FROM DIRS_CLIENTES A ');
        dm.IBQuery4.SelectSQL.Add('LEFT JOIN MGFACTURA_USUARIOS B ON ( B.CLIENTE_ID = A.CLIENTE_ID ) ');
        dm.IBQuery4.SelectSQL.Add('INNER JOIN CLIENTES C ON ( C.CLIENTE_ID = A.CLIENTE_ID ) ');
        dm.IBQuery4.SelectSQL.Add('WHERE A.CLIENTE_ID = :CLIENTE_ID ');
        dm.IBQuery4.SelectSQL.Add('AND A.NOMBRE_CONSIG = ''Dirección principal'' ');
        dm.IBQuery4.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
        dm.IBQuery4.Open;

        {$REGION 'Validaciones'}
        if RFC = '' then
              Raise Exception.Create('Debe indicar un R.F.C..');
        if dm.IBQuery4.FieldByName('CLIENTE_ID').AsInteger = 0 then
              Raise Exception.Create('El cliente no está registrado.');
        if dm.IBQuery4.FieldByName('PASSWORD').AsString = '' then
              Raise Exception.Create('El cliente no está configurado correctamente.');
        if dm.IBQuery4.FieldByName('EMAIL').AsString = '' then
              Raise Exception.Create('El cliente no tiene configurado el email para la recuperación de la contraseña.');
        {$ENDREGION}

        {$REGION 'Obtención de datos'}
        NombreCli := dm.IBQuery4.FieldByName('NOMBRE').AsString;
        Pass := dm.IBQuery4.FieldByName('PASSWORD').AsString;
                //dm.descifrarTexto(dm.IBQuery4.FieldByName('PASSWORD').AsString);
        Email := dm.IBQuery4.FieldByName('EMAIL').AsString;
        Asunto := dm.GetPrefer('AsuntoMailPass');
        Mensaje := dm.GetPrefer('MensajeMailPass');

        Asunto := dm.ReemplazaPalabrasReservadas(Asunto,NombreCli,Pass,NombreEmpresa,'');
        Mensaje := dm.ReemplazaPalabrasReservadas(Mensaje,NombreCli,Pass,NombreEmpresa,'');

        Smtp := dm.GetPrefer('SMPT');
        Usuario := dm.GetPrefer('UsuarioMail');
        Pass := dm.GetPrefer('PassMail');
        EnviadoPor := dm.GetPrefer('EnviadoPorMail');
        PuertoMail := dm.GetPrefer('PuertoMail');
        SSL := dm.GetPrefer('SslMail');
        TLS := dm.GetPrefer('TlsMail');
        {$ENDREGION}

        PDF := '';
        XML := '';

        if not dm.EnvioMail(Smtp,Usuario,Pass,EnviadoPor,PuertoMail,Asunto,Mensaje,Email,PDF,XML,SSL,TLS,ErrorEnvio) then
        begin
           Error := ErrorEnvio;
           Result := False;
        end else
        begin
           Error := '';
           Result := True;
        end;


      end else
      begin
        Error := 'No se ha configurado correctamente el módulo.';
        Result := False;
      end;
      
    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

function TwsFactura.GET_DIRECCION(StrConexion:String; DirCliId:Integer; Var Error:String):WideString; stdcall;
Var I : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);

	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.DIR_CLI_ID,A.NOMBRE_CONSIG,A.NOMBRE_CALLE,A.NUM_EXTERIOR,A.NUM_INTERIOR, ');
      dm.IBQuery.SelectSQL.Add('A.COLONIA,A.POBLACION,A.CODIGO_POSTAL,A.EMAIL,B.NOMBRE CIUDAD,C.NOMBRE ESTADO, ');
      dm.IBQuery.SelectSQL.Add('D.NOMBRE PAIS,A.TELEFONO1,A.REFERENCIA ');
      dm.IBQuery.SelectSQL.Add('FROM DIRS_CLIENTES A ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN CIUDADES B ON ( A.CIUDAD_ID = B.CIUDAD_ID ) ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN ESTADOS C ON ( C.ESTADO_ID = B.ESTADO_ID ) ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN PAISES D ON ( D.PAIS_ID = C.PAIS_ID ) ');
      dm.IBQuery.SelectSQL.Add('WHERE A.DIR_CLI_ID = :DIR_CLI_ID ');
      dm.IBQuery.ParamByName('DIR_CLI_ID').AsInteger := DirCliId;
      dm.IBQuery.Open;

      if not dm.IBQuery.IsEmpty then
      begin

        dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Direccion></Direccion>';
        dm.xmlWebservice.Active := True;

        DirCliente := GetDireccion(dm.xmlWebservice);
        I := 0;
        with DirCliente do
        begin
          DireccionId := dm.IBQuery.FieldByName('DIR_CLI_ID').AsInteger;
          NombreDireccion := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CONSIG').AsString);
          Calle := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CALLE').AsString);
          NumExterior := AnsiLowerCase(dm.IBQuery.FieldByName('NUM_EXTERIOR').AsString);
          NumInterior := AnsiLowerCase(dm.IBQuery.FieldByName('NUM_INTERIOR').AsString);
          Colonia := AnsiLowerCase(dm.IBQuery.FieldByName('COLONIA').AsString);
          Poblacion := AnsiLowerCase(dm.IBQuery.FieldByName('POBLACION').AsString);
          Ciudad := AnsiLowerCase(dm.IBQuery.FieldByName('CIUDAD').AsString);
          Estado := AnsiLowerCase(dm.IBQuery.FieldByName('ESTADO').AsString);
          Pais := AnsiLowerCase(dm.IBQuery.FieldByName('PAIS').AsString);
          CodigoPostal := AnsiLowerCase(dm.IBQuery.FieldByName('CODIGO_POSTAL').AsString);
          Telefono := AnsiLowerCase(dm.IBQuery.FieldByName('TELEFONO1').AsString);
          Referencia := AnsiLowerCase(dm.IBQuery.FieldByName('REFERENCIA').AsString);
          Email := AnsiLowerCase(dm.IBQuery.FieldByName('EMAIL').AsString);
        end;

        dm.xmlWebservice.Active := True;
        Result := dm.xmlWebservice.XML.Text;

      end else
      begin
        Error := 'El cliente indicado no existe.';
        Result := '';
      end;


    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

function TwsFactura.GET_PDF_XML(StrConexion:String; DoctoPvId:Integer; TipoArchivo:String; var Error:String) : WideString; stdcall;
Var TOTAL_LETRA,Folio,PdfPath,XmlPath,Modulo,ModalidadFact : String;
TotalPagar : Double;
   VerSML, RutaReportes:String;
begin
Error := '';
Result := '';
try
 begin
  sysutils.decimalseparator:='.';
  dm := TfrmDataModule.Create (nil);

  if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
    raise Exception.Create(Error);
  if dm.trTrans.InTransaction then
    dm.trTrans.Rollback;
  dm.trTrans.StartTransaction;

  Error := '';
  Result := '';
  TOTAL_LETRA := '';                  Folio := '';
  PdfPath := '';                      XmlPath := '';
  Modulo := '';                       ModalidadFact := '';
  TotalPagar := 0;
  dm.gVERCFDI := '';
  dm.gVERCFDI := dm.GetPrefer('VERCFDI');

  dm.IBQuery.Close;
  dm.IBQuery.SelectSQL.Clear;
  dm.IBQuery.SelectSQL.Add('SELECT A.SISTEMA,A.XML ');
  dm.IBQuery.SelectSQL.Add('FROM USOS_FOLIOS_FISCALES A ');
  dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_ID = :DOCTO_ID ');
  DM.IBQuery.ParamByName('DOCTO_ID').ASINTEGER := DoctoPvId;
  dm.IBQuery.Open;
  Modulo := dm.IBQuery.FieldByName('SISTEMA').AsString;

  if (dm.IBQuery.FieldByName('XML').AsString = '') then
     raise exception.create('No existe el XML del documento indicado.');

  if (Modulo = 'VE') then
  begin
    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT TOTAL_A_PAGAR FROM CALC_TOTALES_DOCTO_VE (:DOCTO_VE_ID, ''S'' ) ');
    dm.IBQuery.ParamByName('DOCTO_VE_ID').ASINTEGER := DoctoPvId;
    dm.IBQuery.Open;
    TotalPagar := dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat;
    TOTAL_LETRA := dm.NUMLET(dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat,1,1);

    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_VE_ID,B.XML,A.FOLIO,A.MODALIDAD_FACTURACION ');
    dm.IBQuery.SelectSQL.Add('FROM DOCTOS_VE A ');
    dm.IBQuery.SelectSQL.Add('INNER JOIN USOS_FOLIOS_FISCALES B ON ( A.DOCTO_VE_ID = B.DOCTO_ID ) ');
    dm.IBQuery.SelectSQL.Add('WHERE A.TIPO_DOCTO = ''F'' AND A.DOCTO_VE_ID = :DOCTO_VE_ID ');
    dm.IBQuery.ParamByName('DOCTO_VE_ID').AsInteger := DoctoPvId;
    dm.IBQuery.Open;
    Folio :=  dm.IBQuery.FieldByName('FOLIO').AsString;
    ModalidadFact := dm.IBQuery.FieldByName('MODALIDAD_FACTURACION').AsString;
    dm.xmlTimbre.XML.Text := dm.IBQuery.FieldByName('XML').AsString;
    dm.xmlTimbre.Active := True;
  end;

  if (Modulo = 'PV') then
  begin
    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT TOTAL_A_PAGAR FROM CALC_TOTALES_DOCTO_PV(:DOCTO_PV_ID, ''S'',''N'',0 ) ');
    dm.IBQuery.ParamByName('DOCTO_PV_ID').ASINTEGER := DoctoPvId;
    dm.IBQuery.Open;
    TotalPagar := dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat;
    TOTAL_LETRA := dm.NUMLET(dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat,1,1);

    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_PV_ID,B.XML,A.FOLIO,A.MODALIDAD_FACTURACION ');
    dm.IBQuery.SelectSQL.Add('FROM DOCTOS_PV A ');
    dm.IBQuery.SelectSQL.Add('INNER JOIN USOS_FOLIOS_FISCALES B ON ( A.DOCTO_PV_ID = B.DOCTO_ID ) ');
    dm.IBQuery.SelectSQL.Add('WHERE A.TIPO_DOCTO = ''F'' AND A.DOCTO_PV_ID = :DOCTO_PV_ID ');
    dm.IBQuery.ParamByName('DOCTO_PV_ID').AsInteger := DoctoPvId;
    dm.IBQuery.Open;
    Folio :=  dm.IBQuery.FieldByName('FOLIO').AsString;
    dm.xmlTimbre.XML.Text := dm.IBQuery.FieldByName('XML').AsString;
    dm.xmlTimbre.Active := True;
    ModalidadFact := dm.IBQuery.FieldByName('MODALIDAD_FACTURACION').AsString;
  end;

  VerSML := dm.VensionXML(dm.IBQuery.FieldByName('XML').AsString);

  RutaReportes :=  dm.GetPrefer('CarpetaArchivos');

  if (AnsiUpperCase(TipoArchivo) = 'PDF') then
  begin



    if VerSML = '3.3' then
    begin
        dm.ObtenerDatosFact33();
    end else
        dm.ObtenerDatosFact();



    Result := dm.GeneraPDF(Folio,TOTAL_LETRA,Modulo,ModalidadFact,TotalPagar,DoctoPvId);//dm.GeneraPDF('AA48','mucho dinero', 'PV', 'CFDI', 382.80, 52071);

    //Error := 'pasa_pdf_:_'+PdfPath;


    { if FileExists(PdfPath) then
         Result := dm.CodificaPDF(PdfPath);
     if not FileExists(PdfPath) then
      Result := ''; }    

   // DeleteFile(PAnsiChar(pdfpath));
  end;

  if (AnsiUpperCase(TipoArchivo) = 'XML') then
  begin
    XmlPath := dm.GetPrefer('CarpetaArchivos')+'\'+Folio+'.xml';
    dm.xmlTimbre.xml.savetofile(XmlPath);
    Result := dm.CodificaPDF(XmlPath);
    DeleteFile(PAnsiChar(XmlPath));
  end;           

 end
except on e : exception do
 begin
  Result := '1';
  Error := 'Mensaje: '+e.Message+' - '+VerSML+'/-/- '+RutaReportes;
  if dm.trTrans.InTransaction then
    dm.trTrans.Rollback;
  dm.Free;
 end;
end;

end;

//Lista en un XML los estados con su país
function TwsFactura.GET_ESTADOS(StrConexion:String; Out Error:String):WideString; stdcall;
Var I : Integer;
begin
    Result := '';
    Error := '';
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.ESTADO_ID,A.NOMBRE ESTADO, B.NOMBRE PAIS ');
      dm.IBQuery.SelectSQL.Add('FROM ESTADOS A ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN PAISES B ON ( B.PAIS_ID = A.PAIS_ID ) ');
      dm.IBQuery.Open;

      dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Estados></Estados>';
      dm.xmlWebservice.Active := True;

      CatEstados := GetEstados(dm.xmlWebservice);
      I := 0;
      with CatEstados do
      begin
        while not dm.IBQuery.Eof do
        begin
          with CatEstados.add do
          begin
            Estado[I].Row := I;
            Estado[I].Id := dm.IBQuery.FieldByName('ESTADO_ID').AsInteger;
            Estado[I].Nombre := AnsiLowerCase(dm.IBQuery.FieldByName('ESTADO').AsString);
            Estado[I].Pais := AnsiLowerCase(dm.IBQuery.FieldByName('PAIS').AsString);
            Inc(I);
          end;
          dm.IBQuery.Next;
        end;
      end;

      Result := dm.xmlWebservice.XML.Text;
      Error := '';
    end
	  except on e : exception do
     begin
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

//Registra un nuevo cliente
function TwsFactura.REGISTRA_CLIENTE(StrConexion:String; NuevoCliente:WideString; out Error:String):Integer; stdcall;
Var ClienteId,MonedaId,TipoClienteId,CondPagoId,DirCliId,CiudadId,PaisId,UserWebId:Integer;
Res,CalleDirCli,RfcCorrecto,TienePassWeb,CliExis, RETIENE_IMPUESTOS:String;
SujetoIEPS, RetieneImpto, ValidaClave:String;
paso:String;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin

      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;
      paso := '1';
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''ConfigOK'' ');
      dm.IBQuery.Open;

      if dm.IBQuery.FieldByName('VALOR').AsString = 'S' then
      begin
        {$REGION 'Valores default'}
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''MonedaId'' ');
        dm.IBQuery.Open;

        if dm.IBQuery.FieldByName('VALOR').AsString <> '' then
            MonedaId := StrToInt(dm.IBQuery.FieldByName('VALOR').AsString)
        else MonedaId := 0;

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''TipoClienteId'' ');
        dm.IBQuery.Open;

        if dm.IBQuery.FieldByName('VALOR').AsString <> '' then
            TipoClienteId := StrToInt(dm.IBQuery.FieldByName('VALOR').AsString)
        else TipoClienteId := 0;

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''CondPagoId'' ');
        dm.IBQuery.Open;

        if dm.IBQuery.FieldByName('VALOR').AsString <> '' then
            CondPagoId := StrToInt(dm.IBQuery.FieldByName('VALOR').AsString)
        else CondPagoId := 0;

        {$REGION 'Sujeto IEPS '}
          SujetoIEPS := '';
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''SujetoIEPS'' ');
          dm.IBQuery.Open;
          SujetoIEPS := dm.IBQuery.FieldByName('VALOR').AsString;
        {$ENDREGION}
        {$REGION 'Sujeto IEPS '}
          RetieneImpto := '';
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''RetieneImpto'' ');
          dm.IBQuery.Open;
          RetieneImpto := dm.IBQuery.FieldByName('VALOR').AsString;
        {$ENDREGION}
          paso := '2';
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''PassWeb'' ');
          dm.IBQuery.Open;
          ValidaClave := dm.IBQuery.FieldByName('VALOR').AsString;
          paso := '3';

        {$ENDREGION}

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('INSERT INTO CLIENTES (CLIENTE_ID, NOMBRE, CONTACTO1, CONTACTO2, ESTATUS, CAUSA_SUSP, ');
        dm.IBQuery.SelectSQL.Add('FECHA_SUSP, COBRAR_IMPUESTOS, RETIENE_IMPUESTOS, SUJETO_IEPS, GENERAR_INTERESES, EMITIR_EDOCTA, ');
        dm.IBQuery.SelectSQL.Add('LIMITE_CREDITO, MONEDA_ID, COND_PAGO_ID, TIPO_CLIENTE_ID, ZONA_CLIENTE_ID, COBRADOR_ID, ');
        dm.IBQuery.SelectSQL.Add('VENDEDOR_ID, NOTAS, CUENTA_CXC, CUENTA_ANTICIPOS, FORMATOS_EMAIL, RECEPTOR_CFD, ');
        dm.IBQuery.SelectSQL.Add('NUM_PROV_CLIENTE, CAMPOS_ADDENDA, USUARIO_CREADOR, FECHA_HORA_CREACION, USUARIO_AUT_CREACION, ');
        dm.IBQuery.SelectSQL.Add('USUARIO_ULT_MODIF, FECHA_HORA_ULT_MODIF, USUARIO_AUT_MODIF) VALUES ');
        dm.IBQuery.SelectSQL.Add('( :CLIENTE_ID, :NOMBRE, :CONTACTO1, :CONTACTO2, :ESTATUS, :CAUSA_SUSP, ');
        dm.IBQuery.SelectSQL.Add(':FECHA_SUSP, :COBRAR_IMPUESTOS, :RETIENE_IMPUESTOS, :SUJETO_IEPS, :GENERAR_INTERESES, :EMITIR_EDOCTA, ');
        dm.IBQuery.SelectSQL.Add(':LIMITE_CREDITO, :MONEDA_ID, :COND_PAGO_ID, :TIPO_CLIENTE_ID, :ZONA_CLIENTE_ID, :COBRADOR_ID, ');
        dm.IBQuery.SelectSQL.Add(':VENDEDOR_ID, :NOTAS, :CUENTA_CXC, :CUENTA_ANTICIPOS, :FORMATOS_EMAIL, :RECEPTOR_CFD, ');
        dm.IBQuery.SelectSQL.Add(':NUM_PROV_CLIENTE, :CAMPOS_ADDENDA, :USUARIO_CREADOR, :FECHA_HORA_CREACION, :USUARIO_AUT_CREACION, ');
        dm.IBQuery.SelectSQL.Add(':USUARIO_ULT_MODIF, :FECHA_HORA_ULT_MODIF, :USUARIO_AUT_MODIF ) ');

        dm.xmlWebservice.XML.Text := NuevoCliente;
        NuevoCli := GetNuevoCliente(DM.xmlWebservice);

        with NuevoCli do
        begin

        {$REGION 'Validaciones'}
          Res := '';
          RfcCorrecto := dm.ValidaCadena(RFC);

          Res := dm.ValidarRFC(RfcCorrecto);

          if Res <> '' then
              Raise Exception.Create(Res);

          //Cambio noviembre apartir de la configuracion se valida o no la contraseña de usuario
          if ValidaClave <> 'S' then
          begin
            if Trim(Contrasena) = '' then
                Raise Exception.Create('Debe indicar una contraseña.');
          end;
          paso := '4';

          if Trim(Nombre) = '' then
              Raise Exception.Create('Debe indicar un nombre.');


         { if Trim(Contacto) = '' then
              Raise Exception.Create('Debe indicar un contacto.');   }

         // Cambio noviembre la direcion y cp no son obligatorios
         {
          if Trim(Calle) = '' then
              Raise Exception.Create('Debe indicar la calle.');   }
         { if Trim(NumExt) = '' then
              Raise Exception.Create('Debe indicar el número exterior.');  }
        {  if Trim(Colonia) = '' then
              Raise Exception.Create('Debe indicar la colonia.');  }
         { if Trim(Ciudad) = '' then
              Raise Exception.Create('Debe indicar la ciudad.');  }
         { if IdEstado = 0 then
              Raise Exception.Create('Debe indicar un estado.');  }
         { if Trim(CodigoPostal) = '' then
              Raise Exception.Create('Debe indicar el código postal.');  }
         { if Trim(Telefono) = '' then
              Raise Exception.Create('Debe indicar el teléfono.');  }
          if Trim(Email) = '' then
              Raise Exception.Create('Debe indicar el correo electrónico.');
          if Trim(RFC) = '' then
              Raise Exception.Create('Debe indicar el R.F.C..');

          paso := '5';
          if IdEstado > 0 then
          begin
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('SELECT * FROM ESTADOS WHERE ESTADO_ID = :ESTADO_ID ');
            dm.IBQuery4.ParamByName('ESTADO_ID').AsInteger := IdEstado;
            dm.IBQuery4.Open;
            if dm.IBQuery4.IsEmpty then
              Raise Exception.Create('El estado indicado no existe.');
          end;
        {$ENDREGION}
          paso := '6';
        {$REGION 'Validaciones de longitud'}
        if ValidaClave <> 'S' then
        begin
          if length(dm.cifrarTexto(Trim(Contrasena))) > 100  then
              Raise Exception.Create('La contraseña excede el tamaño máximo.');
        end;
        
          if length(Trim(Nombre)) > 200 then
              Raise Exception.Create('El nombre excede el tamaño máximo.');
          if length(Trim(Contacto)) > 50 then
              Raise Exception.Create('El contacto excede el tamaño máximo.');
          if length(Trim(Calle)) > 100 then
              Raise Exception.Create('La calle excede el tamaño máximo.');
          if length(Trim(NumExt)) > 10 then
              Raise Exception.Create('El número exterior excede el tamaño máximo.');
          if length(Trim(NumInt)) > 10 then
              Raise Exception.Create('El número interior excede el tamaño máximo.');
          if length(Trim(Colonia)) > 100 then
              Raise Exception.Create('La colonia excede el tamaño máximo.');
          if length(Trim(Ciudad)) > 50 then
              Raise Exception.Create('La ciudad excede el tamaño máximo.');
          if length(Trim(CodigoPostal)) > 10 then
              Raise Exception.Create('El código postal excede el tamaño máximo.');
          if length(Trim(Telefono)) > 35 then
              Raise Exception.Create('El teléfono excede el tamaño máximo.');
          if length(Trim(Email)) > 200 then
              Raise Exception.Create('El correo electrónico excede el tamaño máximo');
          if length(Trim(RFC)) > 18 then
              Raise Exception.Create('El R.F.C. excede el tamaño máximo.');
        {$ENDREGION}
         paso := '7';
          ClienteId := 0;
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('SELECT A.CLIENTE_ID ');
          dm.IBQuery4.SelectSQL.Add('FROM DIRS_CLIENTES A ');
          dm.IBQuery4.SelectSQL.Add('WHERE UPPER( REPLACE( (REPLACE(A.RFC_CURP,'' '','''')),''-'','''')) = :RFC_CURP ');
          dm.IBQuery4.SelectSQL.Add('GROUP BY A.CLIENTE_ID ');
         // dm.IBQuery4.SelectSQL.Add('AND A.NOMBRE_CONSIG = ''Dirección principal'' ');
          dm.IBQuery4.ParamByName('RFC_CURP').AsString := dm.ValidaCadena(AnsiUpperCase(RfcCorrecto));
          dm.IBQuery4.Open;
          ClienteId := dm.IBQuery4.FieldByName('CLIENTE_ID').AsInteger;

          if dm.ValidaCadena(AnsiUpperCase(RfcCorrecto)) = 'XEXX010101000' then
             ClienteId := 0;
         paso := '8';

          if ClienteId = 0 then
          begin
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('SELECT A.CLIENTE_ID FROM CLIENTES A WHERE UPPER(A.NOMBRE) = :NOMBRE ');
            dm.IBQuery4.ParamByName('NOMBRE').AsString := AnsiUpperCase(Nombre);
            dm.IBQuery4.Open;
            ClienteId := dm.IBQuery4.FieldByName('CLIENTE_ID').AsInteger;
            if ClienteId > 0 then
                 Raise Exception.Create('Ya existe un cliente con el nombre: '+AnsiUpperCase(Nombre)+' y diferente RFC.');
          end;
          paso := '9';
          TienePassWeb := 'N';
          if ClienteId > 0 then
          begin
            CliExis := 'S';
            //TienePassWeb := 'N';
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('SELECT USUARIO_ID,"PASSWORD", ESTATUS ');
            dm.IBQuery4.SelectSQL.Add('FROM MGFACTURA_USUARIOS ');
            dm.IBQuery4.SelectSQL.Add('WHERE CLIENTE_ID = :CLIENTE_ID ');
            dm.IBQuery4.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
            dm.IBQuery4.Open;
            if (dm.IBQuery4.Fieldbyname('PASSWORD').ASSTRING = '') then
                TienePassWeb := 'N'
            else
                TienePassWeb := 'S';
            UserWebId := dm.IBQuery4.Fieldbyname('USUARIO_ID').ASinteger;
          end else
                CliExis := 'N';

          if TienePassWeb = 'S' then
          begin
            {
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('SELECT A.CLIENTE_ID FROM CLIENTES A WHERE A.NOMBRE = :NOMBRE ');
            dm.IBQuery4.ParamByName('NOMBRE').AsString := Nombre;
            dm.IBQuery4.Open;

            if dm.IBQuery4.FieldByName('CLIENTE_ID').AsInteger > 0 then
            }
              Raise Exception.Create('Ya existe un cliente con el rfc: '+AnsiUpperCase(RfcCorrecto)+'.');
          end;
           paso := '10';
          if TienePassWeb = 'S' then
          begin
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('SELECT A.CLIENTE_ID FROM CLIENTES A WHERE UPPER(A.NOMBRE) = :NOMBRE ');
            dm.IBQuery4.ParamByName('NOMBRE').AsString := AnsiUpperCase(Nombre);
            dm.IBQuery4.Open;
            if dm.IBQuery4.FieldByName('CLIENTE_ID').AsInteger > 0 then
                 Raise Exception.Create('Ya existe un cliente con el nombre: '+AnsiUpperCase(Nombre)+'.');
          end;

        if CliExis = 'N' then
        begin
          {$REGION 'Clientes'}
          ClienteId := 0;
          dm.spGenCatId.execproc;
          ClienteId := dm.spGenCatId.fieldbyname('CATALOGO_ID').asinteger;

          if clienteId = 0 then
          begin
            dm.spGenCatId.execproc;
            ClienteId := dm.spGenCatId.fieldbyname('CATALOGO_ID').asinteger;
          end;
           paso := '11';
          dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery.ParamByName('NOMBRE').AsString := AnsiUpperCase(NuevoCli.ChildNodes.Nodes['Nombre'].NodeValue);

          try
            begin
              if Trim(NuevoCli.ChildNodes.Nodes['Contacto'].NodeValue) <> '' then
                dm.IBQuery.ParamByName('CONTACTO1').AsString := AnsiUpperCase(NuevoCli.ChildNodes.Nodes['Contacto'].NodeValue)
              else
                dm.IBQuery.ParamByName('CONTACTO1').Clear;
            end;
          except
             begin
                dm.IBQuery.ParamByName('CONTACTO1').Clear;
             end;
          end;



          dm.IBQuery.ParamByName('CONTACTO2').Clear;
          dm.IBQuery.ParamByName('ESTATUS').AsString := 'A';
          dm.IBQuery.ParamByName('CAUSA_SUSP').Clear;
          dm.IBQuery.ParamByName('FECHA_SUSP').Clear;
          dm.IBQuery.ParamByName('COBRAR_IMPUESTOS').AsString := 'S';

          if RetieneImpto = 'S' then
             dm.IBQuery.ParamByName('RETIENE_IMPUESTOS').AsString := 'S';

          if RetieneImpto = 'N' then
             dm.IBQuery.ParamByName('RETIENE_IMPUESTOS').AsString := 'N';

          if RetieneImpto = 'O' then
             dm.IBQuery.ParamByName('RETIENE_IMPUESTOS').AsString := NuevoCli.ChildNodes.Nodes['RetImpto'].NodeValue;



          if SujetoIEPS = 'S' then
             dm.IBQuery.ParamByName('SUJETO_IEPS').AsString := 'S';

          if SujetoIEPS = 'N' then
             dm.IBQuery.ParamByName('SUJETO_IEPS').AsString := 'N';

          if SujetoIEPS = 'O' then
             dm.IBQuery.ParamByName('SUJETO_IEPS').AsString := NuevoCli.ChildNodes.Nodes['RetIEPS'].NodeValue;

          dm.IBQuery.ParamByName('GENERAR_INTERESES').AsString := 'S';
          dm.IBQuery.ParamByName('EMITIR_EDOCTA').AsString := 'S';
          dm.IBQuery.ParamByName('LIMITE_CREDITO').AsFloat := 0;
          dm.IBQuery.ParamByName('MONEDA_ID').AsInteger := MonedaId;
          dm.IBQuery.ParamByName('COND_PAGO_ID').AsInteger := CondPagoId;
          dm.IBQuery.ParamByName('TIPO_CLIENTE_ID').AsInteger := TipoClienteId;
          dm.IBQuery.ParamByName('ZONA_CLIENTE_ID').Clear;
          dm.IBQuery.ParamByName('COBRADOR_ID').Clear;
          dm.IBQuery.ParamByName('VENDEDOR_ID').Clear;
          dm.IBQuery.ParamByName('NOTAS').Clear;
          dm.IBQuery.ParamByName('CUENTA_CXC').Clear;
          dm.IBQuery.ParamByName('CUENTA_ANTICIPOS').Clear;
          dm.IBQuery.ParamByName('FORMATOS_EMAIL').Clear;
          dm.IBQuery.ParamByName('RECEPTOR_CFD').AsString := 'GENERICO';
          dm.IBQuery.ParamByName('NUM_PROV_CLIENTE').Clear;
          dm.IBQuery.ParamByName('CAMPOS_ADDENDA').Clear;
          dm.IBQuery.ParamByName('USUARIO_CREADOR').AsString := AnsiUpperCase(dm.IBDatabase1.ConnectParams.UserName);
          dm.IBQuery.ParamByName('FECHA_HORA_CREACION').AsDateTime := dm.IBDatabase1.GetServerTime;
          dm.IBQuery.ParamByName('USUARIO_AUT_CREACION').Clear;
          dm.IBQuery.ParamByName('USUARIO_ULT_MODIF').Clear;
          dm.IBQuery.ParamByName('FECHA_HORA_ULT_MODIF').Clear;
          dm.IBQuery.ParamByName('USUARIO_AUT_MODIF').Clear;
          dm.IBQuery.Open;
          {$ENDREGION}
           paso := '12';
          {$REGION 'Dirección principal'}
          dm.IBQuery2.Close;
          dm.IBQuery2.SelectSQL.Clear;
          dm.IBQuery2.SelectSQL.Add('INSERT INTO DIRS_CLIENTES (DIR_CLI_ID, CLIENTE_ID, NOMBRE_CONSIG, ');
          dm.IBQuery2.SelectSQL.Add('CALLE, NOMBRE_CALLE, NUM_EXTERIOR, NUM_INTERIOR, COLONIA, POBLACION, ');
          dm.IBQuery2.SelectSQL.Add('REFERENCIA, CIUDAD_ID, ESTADO_ID, CODIGO_POSTAL, PAIS_ID, TELEFONO1, ');
          dm.IBQuery2.SelectSQL.Add('TELEFONO2, FAX, EMAIL, RFC_CURP, CONTACTO, VIA_EMBARQUE_ID, ES_DIR_PPAL, ');
          dm.IBQuery2.SelectSQL.Add('USAR_PARA_ENVIOS, USAR_PARA_FACTURAR, GLN) VALUES ');
          dm.IBQuery2.SelectSQL.Add('( :DIR_CLI_ID, :CLIENTE_ID, :NOMBRE_CONSIG, ');
          dm.IBQuery2.SelectSQL.Add(':CALLE, :NOMBRE_CALLE, :NUM_EXTERIOR, :NUM_INTERIOR, :COLONIA, :POBLACION, ');
          dm.IBQuery2.SelectSQL.Add(':REFERENCIA, :CIUDAD_ID, :ESTADO_ID, :CODIGO_POSTAL, :PAIS_ID, :TELEFONO1, ');
          dm.IBQuery2.SelectSQL.Add(':TELEFONO2, :FAX, :EMAIL, :RFC_CURP, :CONTACTO, :VIA_EMBARQUE_ID, :ES_DIR_PPAL, ');
          dm.IBQuery2.SelectSQL.Add(':USAR_PARA_ENVIOS, :USAR_PARA_FACTURAR, :GLN ); ');
          dm.spGenCatId.ExecProc;
          DirCliId := dm.spGenCatId.FieldByName('CATALOGO_ID').AsInteger;

          {$REGION 'Obtener datos importantes'}
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('SELECT CIUDAD_ID FROM CIUDADES WHERE UPPER( NOMBRE ) = :NOMBRE ');
          dm.IBQuery4.ParamByName('NOMBRE').AsString := AnsiUpperCase(Ciudad);
          dm.IBQuery4.Open;
          CiudadId := dm.IBQuery4.FieldByName('CIUDAD_ID').AsInteger;
          if CiudadId = 0 then
          begin


            if AnsiUpperCase(Ciudad) <> '' then
            begin
            dm.spGenCatId.ExecProc;
            CiudadId := dm.spGenCatId.FieldByName('CATALOGO_ID').AsInteger;
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('INSERT INTO CIUDADES (CIUDAD_ID, NOMBRE, ES_PREDET, ESTADO_ID, ');
            dm.IBQuery4.SelectSQL.Add('USUARIO_CREADOR, FECHA_HORA_CREACION, USUARIO_AUT_CREACION, ');
            dm.IBQuery4.SelectSQL.Add('USUARIO_ULT_MODIF, FECHA_HORA_ULT_MODIF, USUARIO_AUT_MODIF) VALUES ');
            dm.IBQuery4.SelectSQL.Add('(:CIUDAD_ID, :NOMBRE, :ES_PREDET, :ESTADO_ID, ');
            dm.IBQuery4.SelectSQL.Add(':USUARIO_CREADOR, :FECHA_HORA_CREACION, :USUARIO_AUT_CREACION, ');
            dm.IBQuery4.SelectSQL.Add(':USUARIO_ULT_MODIF, :FECHA_HORA_ULT_MODIF, :USUARIO_AUT_MODIF); ');
            dm.IBQuery4.ParamByName('CIUDAD_ID').AsInteger := CiudadId;
            dm.IBQuery4.ParamByName('NOMBRE').AsString := AnsiUpperCase(Ciudad);
            dm.IBQuery4.ParamByName('ES_PREDET').AsString := 'N';
            dm.IBQuery4.ParamByName('ESTADO_ID').AsInteger := IdEstado;
            dm.IBQuery4.ParamByName('USUARIO_CREADOR').AsString := AnsiUpperCase(dm.IBDatabase1.ConnectParams.UserName);
            dm.IBQuery4.ParamByName('FECHA_HORA_CREACION').AsDateTime := dm.IBDatabase1.GetServerTime;
            dm.IBQuery4.ParamByName('USUARIO_AUT_CREACION').Clear;
            dm.IBQuery4.ParamByName('USUARIO_ULT_MODIF').Clear;
            dm.IBQuery4.ParamByName('FECHA_HORA_ULT_MODIF').Clear;
            dm.IBQuery4.ParamByName('USUARIO_AUT_MODIF').Clear;
            dm.IBQuery4.Open;
            end;
          end;
           paso := '13';
          if IdEstado > 0 then
          begin
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('SELECT PAIS_ID FROM ESTADOS WHERE UPPER( ESTADO_ID ) = :ESTADO_ID ');
          dm.IBQuery4.ParamByName('ESTADO_ID').AsInteger := IdEstado;
          dm.IBQuery4.Open;
          PaisId := dm.IBQuery4.FieldByName('PAIS_ID').AsInteger;
          end else
              PaisId := 0;

          {$ENDREGION}
           paso := '14';
          CalleDirCli := '';
          
          CalleDirCli := Calle+' '+NumExt;

          if NumInt <> '' then
              CalleDirCli := CalleDirCli+' '+NumInt;

          CalleDirCli := CalleDirCli+#13+Colonia;  

          if Poblacion <> '' then
              CalleDirCli := CalleDirCli+' '+Poblacion;
              
          if Referencia <> '' then
              CalleDirCli := CalleDirCli+#13+Referencia;  
          
          dm.IBQuery2.ParamByName('DIR_CLI_ID').AsInteger := DirCliId;
          dm.IBQuery2.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery2.ParamByName('NOMBRE_CONSIG').AsString := 'Dirección principal';
          dm.IBQuery2.ParamByName('CALLE').AsString := AnsiUpperCase(CalleDirCli);
          dm.IBQuery2.ParamByName('NOMBRE_CALLE').AsString := AnsiUpperCase(Calle);
          dm.IBQuery2.ParamByName('NUM_EXTERIOR').AsString := AnsiUpperCase(NumExt);
          dm.IBQuery2.ParamByName('NUM_INTERIOR').AsString := AnsiUpperCase(NumInt);
          dm.IBQuery2.ParamByName('COLONIA').AsString := AnsiUpperCase(Colonia);
          dm.IBQuery2.ParamByName('POBLACION').AsString := AnsiUpperCase(Poblacion);
          dm.IBQuery2.ParamByName('REFERENCIA').AsString := AnsiUpperCase(Referencia);
          dm.IBQuery2.ParamByName('CIUDAD_ID').AsInteger := CiudadId;
          dm.IBQuery2.ParamByName('ESTADO_ID').AsInteger := IdEstado;
          dm.IBQuery2.ParamByName('CODIGO_POSTAL').AsString := CodigoPostal;
          dm.IBQuery2.ParamByName('PAIS_ID').AsInteger := PaisId;
          dm.IBQuery2.ParamByName('TELEFONO1').AsString := Telefono;
          dm.IBQuery2.ParamByName('TELEFONO2').Clear;
          dm.IBQuery2.ParamByName('FAX').Clear;
          dm.IBQuery2.ParamByName('EMAIL').AsString := Email;
          dm.IBQuery2.ParamByName('RFC_CURP').AsString := RfcCorrecto;
          dm.IBQuery2.ParamByName('CONTACTO').AsString := '';;
          dm.IBQuery2.ParamByName('VIA_EMBARQUE_ID').Clear;
          dm.IBQuery2.ParamByName('ES_DIR_PPAL').AsString := 'S';
          dm.IBQuery2.ParamByName('USAR_PARA_ENVIOS').AsString := 'S';
          dm.IBQuery2.ParamByName('USAR_PARA_FACTURAR').AsString := 'S';
          dm.IBQuery2.Open;
          {$ENDREGION}
           paso := '14';
          {$REGION 'Registra usuario web'}

          dm.IBQuery3.Close;
          dm.IBQuery3.SelectSQL.Clear;
          dm.IBQuery3.SelectSQL.Add('SELECT USUARIO_ID FROM MGFACTURA_USUARIOS WHERE CLIENTE_ID = :CLIENTE_ID ');
          dm.IBQuery3.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery3.Open;
           paso := '15';
          if dm.IBQuery3.fIELDBYNAME('USUARIO_ID').ASINTEGER = 0 then
          BEGIN
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('INSERT INTO MGFACTURA_USUARIOS (USUARIO_ID, CLIENTE_ID, "PASSWORD", ESTATUS ) ');
            dm.IBQuery4.SelectSQL.Add('VALUES (:USUARIO_ID, :CLIENTE_ID, :PASS, :ESTATUS ); ');
            dm.spGenCatId.execproc;
            dm.IBQuery4.ParamByName('USUARIO_ID').AsInteger := dm.spGenCatId.fieldbyname('CATALOGO_ID').asinteger;
            dm.IBQuery4.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
            dm.IBQuery4.ParamByName('PASS').AsString := Contrasena;//dm.cifrarTexto(Contrasena);
            dm.IBQuery4.ParamByName('ESTATUS').AsString := 'A';
            dm.IBQuery4.Open;
          END;
           paso := '16';
          if dm.IBQuery3.fIELDBYNAME('USUARIO_ID').ASINTEGER > 0 then
          BEGIN
            dm.IBQuery4.Close;
            dm.IBQuery4.SelectSQL.Clear;
            dm.IBQuery4.SelectSQL.Add('UPDATE MGFACTURA_USUARIOS SET ');
            dm.IBQuery4.SelectSQL.Add('"PASSWORD" = :PASSWORD, ESTATUS = :ESTATUS ');
            dm.IBQuery4.SelectSQL.Add('WHERE ( USUARIO_ID = :USUARIO_ID ); ');
            dm.spGenCatId.execproc;
            dm.IBQuery4.ParamByName('USUARIO_ID').AsInteger := dm.IBQuery3.FIELDBYNAME('USUARIO_ID').ASINTEGER;
            dm.IBQuery4.ParamByName('PASSWORD').AsString := Contrasena;//dm.cifrarTexto(Contrasena);
            dm.IBQuery4.ParamByName('ESTATUS').AsString := 'A';
            dm.IBQuery4.Open;
          END;
            paso := '17';

          {$ENDREGION}

        end else
        begin
          if UserWebId = 0 then
          begin
            {$REGION 'Registra usuario web'}
             paso := '18';
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('INSERT INTO MGFACTURA_USUARIOS (USUARIO_ID, CLIENTE_ID, "PASSWORD", ESTATUS ) ');
          dm.IBQuery4.SelectSQL.Add('VALUES (:USUARIO_ID, :CLIENTE_ID, :PASS, :ESTATUS ); ');
          dm.spGenCatId.execproc;
          dm.IBQuery4.ParamByName('USUARIO_ID').AsInteger := dm.spGenCatId.fieldbyname('CATALOGO_ID').asinteger;
          dm.IBQuery4.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery4.ParamByName('PASS').AsString := Contrasena;//dm.cifrarTexto(Contrasena);
          dm.IBQuery4.ParamByName('ESTATUS').AsString := 'A';
          dm.IBQuery4.Open;
          {$ENDREGION}
             paso := '19';
          end else
          begin
           if TienePassWeb = 'N' then
           begin
            {$REGION 'Actualiza usuario web'}
            paso := '20';
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('UPDATE MGFACTURA_USUARIOS SET "PASSWORD" = :PASS, ESTATUS = ''A'' ');
          dm.IBQuery4.SelectSQL.Add('WHERE (USUARIO_ID = :USUARIO_ID ); ');
          dm.spGenCatId.execproc;
          dm.IBQuery4.ParamByName('USUARIO_ID').AsInteger := UserWebId;
          dm.IBQuery4.ParamByName('PASS').AsString := Contrasena;//dm.cifrarTexto(Contrasena);
          dm.IBQuery4.Open;
          paso := '21';
          {$ENDREGION}
           end;
          end;
        end;


          if dm.trTrans.InTransaction then
             dm.trTrans.Commit;

          Result := ClienteId;

        end;
      end else
      begin
        Error := 'No se ha configurado correctamente.';
        Result := 0;
      end;
    end;
	  except on e : exception do
     begin
        if dm.trTrans.InTransaction then
             dm.trTrans.Rollback;
       Error := e.Message+' paso:'+paso;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

//Obtiene los datos del cliente
function TwsFactura.GET_CLIENTE(StrConexion:String; ClienteId:Integer; out Error:String):WideString; stdcall;
Var I : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.CLIENTE_ID,A.NOMBRE,A.CONTACTO1,B.RFC_CURP,C."PASSWORD" ');
      dm.IBQuery.SelectSQL.Add('FROM CLIENTES A ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN DIRS_CLIENTES B ON (A.CLIENTE_ID = B.CLIENTE_ID) ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN MGFACTURA_USUARIOS C ON ( A.CLIENTE_ID = C.CLIENTE_ID ) ');
      dm.IBQuery.SelectSQL.Add('WHERE A.CLIENTE_ID = :CLIENTE_ID AND B.NOMBRE_CONSIG = ''Dirección principal'' ');
      dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
      dm.IBQuery.Open;

      if not dm.IBQuery.IsEmpty then
      begin

        dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Cliente></Cliente>';
        dm.xmlWebservice.Active := True;

        Cliente := GetCliente(dm.xmlWebservice);
        I := 0;
        with Cliente do
        begin
          Cliente.ClienteId := dm.IBQuery.FieldByName('CLIENTE_ID').AsInteger;
          Cliente.Nombre := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE').AsString);
          Cliente.Contacto := AnsiLowerCase(dm.IBQuery.FieldByName('CONTACTO1').AsString);
          Cliente.Rfc := AnsiLowerCase(dm.IBQuery.FieldByName('RFC_CURP').AsString);
          Cliente.Contrasena := AnsiLowerCase(dm.IBQuery.FieldByName('PASSWORD').AsString);

          dm.IBQuery3.Close;
          dm.IBQuery3.SelectSQL.Clear;
          dm.IBQuery3.SelectSQL.Add('SELECT A.DIR_CLI_ID,A.NOMBRE_CONSIG ');
          dm.IBQuery3.SelectSQL.Add('FROM DIRS_CLIENTES A ');
          dm.IBQuery3.SelectSQL.Add('WHERE A.CLIENTE_ID = :CLIENTE_ID ');
          dm.IBQuery3.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery3.Open;

          if not dm.IBQuery3.IsEmpty then
          begin
            Cliente.AddChild('Direcciones',5);

            while not dm.IBQuery3.Eof do
            begin
                with Direcciones.add do
                begin
                  DireccionId := dm.IBQuery3.FieldByName('DIR_CLI_ID').AsInteger;
                  NombreDireccion := AnsiLowerCase(dm.IBQuery3.FieldByName('NOMBRE_CONSIG').AsString);
                  Inc(I);
                  dm.IBQuery3.Next;
                end;
            end;
          end;
        end; 

        //dm.xmlWebservice.Active := True;

        Result := dm.xmlWebservice.XML.Text;

      end else
      begin
        Error := 'El cliente indicado no existe.';
        Result := '';
      end;


    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

//Verifica el ticket
function TwsFactura.VERIFICA_TICKET(StrConexion:String; Folio:String; out Error:String; TotalPagar : Double ):Integer; stdcall;
Var IdTicket:Integer;
NoValidarImporte:String;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
     if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
     if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
     dm.trTrans.StartTransaction;


     //NoValidarImporte
    {$REGION ' lugares de expedición  '}
      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT A.VALOR FROM MGFACTURA_CONFIG A WHERE A.NOMBRE = ''NoValidarImporte'' ');
      dm.IBQuery.Open;
      NoValidarImporte := '';
      NoValidarImporte := dm.IBQuery.FieldByName('VALOR').AsString;
    {$ENDREGION}


     Error := '';
     IdTicket := 0;

     dm.IBQuery.Close;
     dm.IBQuery.SelectSQL.Clear;
     dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_PV_ID,B.TOTAL_A_PAGAR ');
     dm.IBQuery.SelectSQL.Add('FROM DOCTOS_PV A ');
     dm.IBQuery.SelectSQL.Add('LEFT JOIN CALC_TOTALES_DOCTO_PV( A.DOCTO_PV_ID , ''S'', ''N'',0 ) B ON ( A.DOCTO_PV_ID = B.DOCTO_PV_ID ) ');
     dm.IBQuery.SelectSQL.Add('WHERE A.TIPO_DOCTO = ''V'' AND A.FOLIO = :FOLIO '); //AND B.TOTAL_A_PAGAR = :TOTAL_A_PAGAR
     dm.IBQuery.ParamByName('FOLIO').AsString := dm.Rellena(Folio);
     dm.IBQuery.Open;
     IdTicket := dm.IBQuery.FieldByName('DOCTO_PV_ID').AsInteger;

     if IdTicket > 0 then
     begin
       //Cambio Josue 17/04/2018 No validar el importe del ticket (Se agrega If de validación)
      if NoValidarImporte <> 'S' then
      begin
        if dm.IBQuery.FieldByName('TOTAL_A_PAGAR').Asfloat <> TotalPagar then
         begin
            IdTicket := 0;
            Raise Exception.Create('El importe no coincide con el importe del ticket '+UpperCase(Folio)+'.');
         end;
      end;
     end;

     if IdTicket = 0 then
        Raise Exception.Create('El documento '+UpperCase(Folio)+' no existe.');

     IdTicket := dm.ValidacionesTicket(dm.Rellena(Folio),Error);
     
     if (( IdTicket = 0) or ( Error <> '' )) then
     begin
       Raise Exception.Create(Error);
     end;

     rESULT := IdTicket;

    end
	  except on e : exception do
     begin
       Error := e.Message;
       rESULT := 0;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

//Genera la factura
function TwsFactura.GENERA_FACTURA(StrConexion:String; NumTicket:String;ConsigId : Integer; EmailAlterno:String; LugarExp:Integer; VUsoCFDI:String; out  Error:String):Boolean; stdcall;
Var ClienteId,FolioN,DoctoPvId,IdTicket,CliTicket:Integer;
    FolioL,NombreCli,ClaveCli:String;
    TipoCambio,DsctoImpte,DsctoPctje : Double;
    CajaId,MonedaId,ClientePublicoId : Integer;
    Fecha : Tdate;
    MGFACTURA_USO_CFDI_ID:Integer;
    Resultado:String;
    MetodoPagoSAT:String;
begin
    Result := False;
    ClienteId := 0;
    DoctoPvId := 0;
    FolioN := 0;
    IdTicket := 0;
    FolioL := '';
    MetodoPagoSAT := '';

    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
       if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
         raise Exception.Create(Error);
       if dm.trTrans.InTransaction then
         dm.trTrans.Rollback;
       dm.trTrans.StartTransaction;

      {$REGION '  Validaciones del documento'}
      Error := '';
      IdTicket := 0;
      IdTicket := dm.ValidacionesTicket(NumTicket,Error);
      if (( IdTicket = 0) or ( Error <> '' )) then
      begin
        Raise Exception.Create('Error al validar el ticket, error: '+Error);
      end;

      //VUsoCFDI
      dm.IBQuery.Close;
      dm.IBQuery.SelectSql.Clear;
      dm.IBQuery.selectSql.Add('SELECT MGFACTURA_USO_CFDI_ID ');
      dm.IBQuery.selectSql.Add('FROM MGFACTURA_USO_CFDI ');
      dm.IBQuery.selectSql.Add('WHERE UPPER(USO_CFDI) = UPPER(:USO_CFDI) ');
      dm.IBQuery.ParamByName('USO_CFDI').AsString := VUsoCFDI;
      dm.IBQuery.Open;
      MGFACTURA_USO_CFDI_ID := 0;
      MGFACTURA_USO_CFDI_ID := dm.IBQuery.FieldByName('MGFACTURA_USO_CFDI_ID').asinteger;

      if MGFACTURA_USO_CFDI_ID = 0 then
      begin
          Raise Exception.Create('El uso CFDI seleccionado no es un valido, verifique su información.');
      end;

      {$ENDREGION}
        
      {$REGION 'Validaciones'}

    //   Raise Exception.Create('despues de preferencias. Resultado 111 :'+  Resultado);

      dm.IBQuery.Close;
      dm.IBQuery.SelectSql.Clear;
      dm.IBQuery.selectSql.Add('SELECT A.VALOR ');
      dm.IBQuery.selectSql.Add('FROM REGISTRY A ');
      dm.IBQuery.selectSql.Add('WHERE A.NOMBRE = ''CLIENTE_EVENTUAL_PV_ID'' ');
      dm.IBQuery.Open;
      ClientePublicoId := 0;
      ClientePublicoId := dm.IBQuery.FieldByName('VALOR').asinteger;

       //VERCFDI
       dm.gVERCFDI := ''; 
       dm.gVERCFDI := dm.GetPrefer('VERCFDI');

      if dm.gVERCFDI = '' then
          Raise Exception.Create('No se ha configurado la Versión de CFDI.');


      if  dm.GetPrefer('ConfigOK') = 'S' then
      begin



        gUrlTimbrado := dm.GetPrefer('DirTimbre');
        if gurltimbrado = '' then
            Raise Exception.Create('No se ha configurado correctamente.');

        if NumTicket = '' then
            Raise Exception.Create('Debe indicar un ticket.');
        if ConsigId = 0 then
            Raise Exception.Create('Debe indicar una dirección válida.');

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT DOCTO_PV_ID,CLIENTE_ID,ESTATUS FROM DOCTOS_PV WHERE FOLIO = :FOLIO AND TIPO_DOCTO = ''V'' ');
        dm.IBQuery.ParamByName('FOLIO').AsString := dm.Rellena(NumTicket);
        dm.IBQuery.Open;
        IdTicket := dm.IBQuery.FieldByName('DOCTO_PV_ID').AsInteger;
        if IdTicket = 0 then
           Raise Exception.Create('El ticket indicado no es válido');

        CliTicket := dm.IBQuery.FieldByName('CLIENTE_ID').AsInteger;

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT B.ESTATUS,B.CLIENTE_ID,B.NOMBRE FROM DIRS_CLIENTES A ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN CLIENTES B ON ( A.CLIENTE_ID = B.CLIENTE_ID ) ');
        dm.IBQuery.SelectSQL.Add('WHERE A.DIR_CLI_ID = :DIR_CLI_ID ');
        dm.IBQuery.ParamByName('DIR_CLI_ID').AsInteger := ConsigId;
        dm.IBQuery.Open;
        NombreCli := dm.IBQuery.FieldByName('NOMBRE').AsString;
        if dm.IBQuery.FieldByName('ESTATUS').AsString = 'B' then
          Raise Exception.Create('El cliente está dado de baja.');
        if dm.IBQuery.FieldByName('ESTATUS').AsString = 'V' then
          Raise Exception.Create('El cliente está suspendido de ventas.');
        if dm.IBQuery.FieldByName('ESTATUS').AsString = 'C' then
          Raise Exception.Create('El cliente está suspendido de créditos.');

        ClienteId := dm.IBQuery.FieldByName('CLIENTE_ID').AsInteger;

        Error := '';
        if ClientePublicoId = CliTicket then
        begin
             ConsigId := dm.AgregaConsig(ConsigId,ClientePublicoId,Error);
             ClienteId := ClientePublicoId;
        end;
        if (Error <> '') or (ConsigId = 0) then
          Raise Exception.Create('Error al crear al consignatario.'+'Error: '+Error);


        if CliTicket <> ClienteId then
          Raise Exception.Create('El ticket no pertenece al cliente '+NombreCli+'.');

        Error := '';
        Error := dm.ValidarDatosCliente(ConsigId);
        if Error <> '' then
          Raise Exception.Create(Error);

      {$ENDREGION}

        ///  Este procedimiento obtiene las rutas de los certificados y contraseña
        ///  También obtiene el link, usuario y contraseña para el servicio de timbrado
        dm.GetDatosFac();

      //  Raise Exception.Create('Antes de abrir sellos.');

        Error:='';
        if not dm.AbrirSellos(dm.gPathCertificado,dm.gPathLlave,dm.gContrasena,Error) then
          Raise Exception.Create(Error);
        {
        Error := '';
        if (dm.GetSaldoTimbres(dm.gUsuarioTimbre,dm.gPassTimbre,Error) < 1) or (Error<>'') then
        begin
            if (Error <> '') then
                Raise Exception.Create('Error al verificar el saldo de los timbres: '+Error)
            else
                Raise Exception.Create('Saldo de timbres insuficiente.');
        end;
        }

        {$REGION 'Obtiene datos encabezado'}
        dm.dsdoctofte.Close;
        dm.dsdoctofte.parambyname('DOCTO_PV_ID').asinteger := IdTicket;
        dm.dsdoctofte.CloseOpen(False);
        ClaveCli := dm.dsdoctoFte.fieldbyname('CLAVE_CLIENTE').ASSTRING;
        TipoCambio := dm.dsdoctofte.fieldbyname('TIPO_CAMBIO').ASfloat;
        DsctoImpte := dm.dsdoctofte.fieldbyname('DSCTO_IMPORTE').ASfloat;
        DsctoPctje := dm.dsdoctofte.fieldbyname('DSCTO_PCTJE').ASfloat;
        CajaId := dm.dsdoctofte.fieldbyname('CAJA_ID').AsInteger;
        MonedaId := dm.dsdoctofte.fieldbyname('MONEDA_ID').AsInteger;
        Fecha := dm.IBDatabase1.getservertime;
        {$ENDREGION}
        //IdTicket

        FolioL := dm.GetPrefer('Serie');

        Error := '';
        ///   función para generar el encabezado de una factura de punto de venta
        Fecha := DM.IBDatabase1.GETSERVERTIME;


        //Cambio Josue Octubre se agrego el metodo de pago SAT MetodoPagoSAT
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT COUNT(*) CONT_FORMAS ');
        dm.IBQuery.SelectSQL.Add('FROM DOCTOS_PV_COBROS A ');
        dm.IBQuery.SelectSQL.Add('LEFT JOIN FORMAS_COBRO B ON ( A.FORMA_COBRO_ID = B.FORMA_COBRO_ID ) ');
        dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_PV_ID = :DOCTO_PV_ID ');
        dm.IBQuery.SelectSQL.Add('AND B.TIPO = ''R'' ');
        dm.IBQuery.ParamByName('DOCTO_PV_ID').AsInteger := IdTicket;
        dm.IBQuery.Open;

        if dm.IBQuery.FieldByName('CONT_FORMAS').AsInteger > 0 then
          MetodoPagoSAT :='PPD'
        else
          MetodoPagoSAT :='PUE';
        



        //DoctoPvId := dm.NuevaFacturaPv(FolioL,'',ClaveCli,'P','N',VUsoCFDI,TipoCambio,DsctoImpte,DsctoPctje,ClienteId,ConsigId,CajaId,MonedaId,LugarExp,Fecha,Error);
        //Cambio Josue Octubre se agrego el metodo de pago SAT MetodoPagoSAT
        DoctoPvId := dm.NuevaFacturaPv(MetodoPagoSAT,FolioL,'',ClaveCli,'P','N',VUsoCFDI,TipoCambio,DsctoImpte,DsctoPctje,ClienteId,ConsigId,CajaId,MonedaId,LugarExp,Fecha,Error);
        if (DoctoPvId = 0) or (Error <> '') then
          Raise Exception.Create('Ocurrió un error al momento de generar la factura. '+#13+
                                ' Error: '+Error);


        Error := '';
        ///   Copia el detalle de un documento a otro en punto de venta
        if not dm.CopiarDetallePv(IdTicket,DoctoPvId,'N',Error) then
          Raise Exception.Create(' Error: '+Error);

        Error := '';

        //Formas de cobro   IdTicket    DoctoPvId
        if not dm.FormasCobroPV(IdTicket,DoctoPvId,Error) then
          Raise exception.create('Error: '+Error);


        ///   esta función calcula los totales del documento y lo aplica
        if not dm.AplicaDoctoPv(DoctoPvId,'N','N',Error) then
          Raise exception.create('Error: '+Error);

        Error := '';
        if dm.gVERCFDI = 'CFDI 3.3' then
        begin
          if (dm.GeneraXmlPv33(DoctoPvId,'F',Error) = '') or (Error <> '') then
                Raise Exception.Create('Ocurrió un error al momento de generar la factura electrónica. '+#13+' Error: '+Error);
        end;

        if dm.gVERCFDI = 'CFDI 3.2' then
        begin
         // Raise Exception.Create('Entro 3.2');
                //GeneraXmlPv32   GeneraXmlPv
         if (dm.GeneraXmlPv33(DoctoPvId,'F',Error) = '') or (Error <> '') then
              Raise Exception.Create('Ocurrió un error al momento de generar la factura electrónica. '+#13+' Error: '+Error);

        end;


        {$REGION 'Obtener Folio'}
        dm.IBQuery.close;
        dm.IBQuery.selectsql.clear;
        dm.IBQuery.selectsql.add('SELECT A.FOLIO ');
        dm.IBQuery.selectsql.add('FROM USOS_FOLIOS_FISCALES A ');
        dm.IBQuery.Selectsql.add('WHERE A.DOCTO_ID = :DOCTO_ID AND A.SISTEMA = ''PV'' ');
        dm.IBQuery.ParamByName('DOCTO_ID').ASINTEGER := DoctoPvId;
        dm.IBQuery.open;
        FolioN := dm.IBQuery.FieldByName('FOLIO').ASINTEGER;
        {$ENDREGION}

        if dm.trTrans.InTransaction then
          dm.trTrans.Commit;

        dm.trTrans.StartTransaction;

        Error := '';
        //Función para timbrar la factura.     TimbrarFac33
        if dm.gVERCFDI = 'CFDI 3.3' then
        begin
          if (not dm.TimbrarFac33(DoctoPvId,dm.gUrlTimbre,dm.gUsuarioTimbre,dm.gPassTimbre,FolioL+IntToStr(FolioN),Error) ) or (Error <> '') then
             Raise Exception.Create('Error: La factura se generó correctamente, pero no se timbró mas tarde se le enviará. '+Error);
        end;


        if dm.gVERCFDI = 'CFDI 3.2' then
        begin
         //TimbrarFac32
          if (not dm.TimbrarFac33(DoctoPvId,dm.gUrlTimbre,dm.gUsuarioTimbre,dm.gPassTimbre,FolioL+IntToStr(FolioN),Error) ) or (Error <> '') then
             Raise Exception.Create('Error: La factura se generó correctamente, pero no se timbró mas tarde se le enviará. '+Error);
        end;




        if dm.trTrans.InTransaction then
          dm.trTrans.Commit;

        dm.trTrans.StartTransaction;
        //Función para el envío de facturas
        if (not dm.EnviaFacturas(DoctoPvId,FolioL+IntToStr(FolioN),'PV',EmailAlterno,Error)) or (Error <> '') then
           Raise Exception.Create('Ocurrió un error al momento enviar la factura: '+Error);

         Result := True;
         Error := '';

      end else
      begin
        Result := False;
        Raise Exception.Create('No se ha configurado correctamente.');
      end;

    end
	  except on e : exception do
     begin
       Error := e.Message;
       Result := False;
       if dm.trTrans.InTransaction then
          dm.trTrans.Rollback;
	     dm.Free;
     end;
	  end;
end;


//Registra nuevo consignatario
function TwsFactura.REGISTRA_DIRECCION(StrConexion:String; NuevaDireccion:WideString; out Error:String):Integer; stdcall;
Var DirCliId, CiudadId, PaisId : Integer;
CalleDirCli,RfcCorrecto,Res:String;
begin
Result := 0;
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      dm.xmlWebservice.XML.Text := NuevaDireccion;
      NuevaDir := GetNuevaDireccion(dm.xmlWebservice);

      with NuevaDir do
      begin

         {$REGION 'Validaciones'}
           dm.IBQuery.Close;
           dm.IBQuery.SelectSQL.Clear;
           dm.IBQuery.SelectSQL.Add('SELECT A.DIR_CLI_ID FROM DIRS_CLIENTES A ');
           dm.IBQuery.SelectSQL.Add('WHERE A.NOMBRE_CONSIG = :NOMBRE_CONSIG AND A.CLIENTE_ID = :CLIENTE_ID ');
           dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
           dm.IBQuery.ParamByName('NOMBRE_CONSIG').AsString := Nombre;
           dm.IBQuery.Open;

           if dm.IBQuery.FieldByName('DIR_CLI_ID').AsInteger <> 0 then
             Raise Exception.Create('Este consignatario ya se encuentra registrado.');

           dm.IBQuery.Close;
           dm.IBQuery.SelectSQL.Clear;
           dm.IBQuery.SelectSQL.Add('SELECT CLIENTE_ID FROM CLIENTES WHERE CLIENTE_ID = :CLIENTE_ID ');
           dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
           dm.IBQuery.Open;

           if dm.IBQuery.FieldByName('CLIENTE_ID').AsInteger = 0 then
              Raise Exception.Create('El cliente indicado no existe.');

           if Nombre = '' then
              Raise Exception.Create('No se indicó el nombre.');

          RfcCorrecto := dm.ValidaCadena(RFC);

          Res := dm.ValidarRFC(RfcCorrecto);
          if Res <> '' then
              Raise Exception.Create(Res);

           if Trim(RfcCorrecto) = '' then
              Raise Exception.Create('No se indicó el RFC.');
           {// Cambio Noviembre: No son campos requeridos para la creacion de factura
           if Trim(Calle) = '' then
              Raise Exception.Create('No se indicó la calle.');

           if Trim(NumExt) = '' then
              Raise Exception.Create('No se indicó el número exterior.');

           if Trim(Colonia) = '' then
              Raise Exception.Create('No se indicó la colonia.');

           if Trim(Ciudad) = '' then
              Raise Exception.Create('No se indicó la ciudad.');
           }
           dm.IBQuery.Close;
           dm.IBQuery.SelectSQL.Clear;
           dm.IBQuery.SelectSQL.Add('SELECT ESTADO_ID FROM ESTADOS WHERE ESTADO_ID = :ESTADO_ID ');
           dm.IBQuery.ParamByName('ESTADO_ID').AsInteger := IdEstado;
           dm.IBQuery.Open;

           {// Cambio Noviembre: No son campos requeridos para la creacion de factura
           if dm.IBQuery.FieldByName('ESTADO_ID').AsInteger = 0 then
              Raise Exception.Create('No existe el estado indicado.');

           if Trim(CodigoPostal) = '' then
              Raise Exception.Create('No se indicó el código postal.');

           if Trim(Telefono) = '' then
              Raise Exception.Create('No se indicó el teléfono.');
            }  

           if Trim(Email) = '' then
              Raise Exception.Create('No se indicó el correo electrónico.');

         {$ENDREGION}

         {$REGION 'Validacion longitud'}
           if (length(trim(Nombre)) > 200)  then
               Raise Exception.Create('El nombre excede el tamaño máximo.');
           if (length(Trim(Contacto))>50) then
               Raise Exception.Create('El contacto excede el tamaño máximo.');
           if (length(Trim(RFC))>18) then
               Raise Exception.Create('El R.F.C. excede el tamaño máximo.');
           if (length(Trim(Calle)) > 100) then
               Raise Exception.Create('La calle excede el tamaño máximo.');
           if (length(Trim(NumExt))>10) then
               Raise Exception.Create('El número exterior excede el tamaño máximo.');
           if (length(Trim(NumInt))>10) then
               Raise Exception.Create('El número interior excede el tamaño máximo.');
           if (length(Trim(Colonia))>100) then
               Raise Exception.Create('La colonia excede el tamaño máximo.');
           if (length(Trim(Poblacion))>100) then
               Raise Exception.Create('La población excede el tamaño máximo.');
           if (length(Trim(Referencia))>100) then
               Raise Exception.Create('La referencia excede el tamaño máximo.');
           if (length(Trim(Ciudad))>50) then
               Raise Exception.Create('La ciudad excede el tamaño máximo.');
           if (length(Trim(CodigoPostal))>10) then
               Raise Exception.Create('El código postal excede el tamaño máximo.');
           if (length(Trim(Telefono))>35) then
               Raise Exception.Create('El teléfono excede el tamaño máximo.');
           if (length(Trim(Email))>200) then
               Raise Exception.Create('El correo electrónico excede el tamaño máximo.');
         {$ENDREGION}

          {$REGION 'Obtener datos importantes'}
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('SELECT CIUDAD_ID FROM CIUDADES WHERE UPPER( NOMBRE ) = :NOMBRE ');
          dm.IBQuery4.ParamByName('NOMBRE').AsString := AnsiUpperCase(Ciudad);
          dm.IBQuery4.Open;
          CiudadId := dm.IBQuery4.FieldByName('CIUDAD_ID').AsInteger;
          if CiudadId = 0 then
          begin
            if AnsiUpperCase(Ciudad) <> '' then
            begin
              dm.spGenCatId.ExecProc;
              CiudadId := dm.spGenCatId.FieldByName('CATALOGO_ID').AsInteger;

              dm.IBQuery4.Close;
              dm.IBQuery4.SelectSQL.Clear;
              dm.IBQuery4.SelectSQL.Add('INSERT INTO CIUDADES (CIUDAD_ID, NOMBRE, ES_PREDET, ESTADO_ID, ');
              dm.IBQuery4.SelectSQL.Add('USUARIO_CREADOR, FECHA_HORA_CREACION, USUARIO_AUT_CREACION, ');
              dm.IBQuery4.SelectSQL.Add('USUARIO_ULT_MODIF, FECHA_HORA_ULT_MODIF, USUARIO_AUT_MODIF) VALUES ');
              dm.IBQuery4.SelectSQL.Add('(:CIUDAD_ID, :NOMBRE, :ES_PREDET, :ESTADO_ID, ');
              dm.IBQuery4.SelectSQL.Add(':USUARIO_CREADOR, :FECHA_HORA_CREACION, :USUARIO_AUT_CREACION, ');
              dm.IBQuery4.SelectSQL.Add(':USUARIO_ULT_MODIF, :FECHA_HORA_ULT_MODIF, :USUARIO_AUT_MODIF); ');
              dm.IBQuery4.ParamByName('CIUDAD_ID').AsInteger := CiudadId;
              dm.IBQuery4.ParamByName('NOMBRE').AsString := AnsiUpperCase(Ciudad);
              dm.IBQuery4.ParamByName('ES_PREDET').AsString := 'N';
              dm.IBQuery4.ParamByName('ESTADO_ID').AsInteger := IdEstado;
              dm.IBQuery4.ParamByName('USUARIO_CREADOR').AsString := AnsiUpperCase(dm.IBDatabase1.ConnectParams.UserName);
              dm.IBQuery4.ParamByName('FECHA_HORA_CREACION').AsDateTime := dm.IBDatabase1.GetServerTime;
              dm.IBQuery4.ParamByName('USUARIO_AUT_CREACION').Clear;
              dm.IBQuery4.ParamByName('USUARIO_ULT_MODIF').Clear;
              dm.IBQuery4.ParamByName('FECHA_HORA_ULT_MODIF').Clear;
              dm.IBQuery4.ParamByName('USUARIO_AUT_MODIF').Clear;
              dm.IBQuery4.Open;
            end;
          end;

          if IdEstado > 0 then
          begin
          dm.IBQuery4.Close;
          dm.IBQuery4.SelectSQL.Clear;
          dm.IBQuery4.SelectSQL.Add('SELECT PAIS_ID FROM ESTADOS WHERE UPPER( ESTADO_ID ) = :ESTADO_ID ');
          dm.IBQuery4.ParamByName('ESTADO_ID').AsInteger := IdEstado;
          dm.IBQuery4.Open;
          PaisId := dm.IBQuery4.FieldByName('PAIS_ID').AsInteger;
          end else
             PaisId := 0;
          {$ENDREGION}

          {$REGION 'Dirección'}
          dm.IBQuery2.Close;
          dm.IBQuery2.SelectSQL.Clear;
          dm.IBQuery2.SelectSQL.Add('INSERT INTO DIRS_CLIENTES (DIR_CLI_ID, CLIENTE_ID, NOMBRE_CONSIG, ');
          dm.IBQuery2.SelectSQL.Add('CALLE, NOMBRE_CALLE, NUM_EXTERIOR, NUM_INTERIOR, COLONIA, POBLACION, ');
          dm.IBQuery2.SelectSQL.Add('REFERENCIA, CIUDAD_ID, ESTADO_ID, CODIGO_POSTAL, PAIS_ID, TELEFONO1, ');
          dm.IBQuery2.SelectSQL.Add('TELEFONO2, FAX, EMAIL, RFC_CURP, CONTACTO, VIA_EMBARQUE_ID, ES_DIR_PPAL, ');
          dm.IBQuery2.SelectSQL.Add('USAR_PARA_ENVIOS, USAR_PARA_FACTURAR, GLN) VALUES ');
          dm.IBQuery2.SelectSQL.Add('( :DIR_CLI_ID, :CLIENTE_ID, :NOMBRE_CONSIG, ');
          dm.IBQuery2.SelectSQL.Add(':CALLE, :NOMBRE_CALLE, :NUM_EXTERIOR, :NUM_INTERIOR, :COLONIA, :POBLACION, ');
          dm.IBQuery2.SelectSQL.Add(':REFERENCIA, :CIUDAD_ID, :ESTADO_ID, :CODIGO_POSTAL, :PAIS_ID, :TELEFONO1, ');
          dm.IBQuery2.SelectSQL.Add(':TELEFONO2, :FAX, :EMAIL, :RFC_CURP, :CONTACTO, :VIA_EMBARQUE_ID, :ES_DIR_PPAL, ');
          dm.IBQuery2.SelectSQL.Add(':USAR_PARA_ENVIOS, :USAR_PARA_FACTURAR, :GLN ); ');
          dm.spGenCatId.ExecProc;
          DirCliId := dm.spGenCatId.FieldByName('CATALOGO_ID').AsInteger;

          CalleDirCli := '';
          
          CalleDirCli := Calle+' '+NumExt;

          if NumInt <> '' then
              CalleDirCli := CalleDirCli+' '+NumInt;

          CalleDirCli := CalleDirCli+#13+Colonia;  

          if Poblacion <> '' then
              CalleDirCli := CalleDirCli+' '+Poblacion;
              
          if Referencia <> '' then
              CalleDirCli := CalleDirCli+#13+Referencia;                
          
          dm.IBQuery2.ParamByName('DIR_CLI_ID').AsInteger := DirCliId;
          dm.IBQuery2.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery2.ParamByName('NOMBRE_CONSIG').AsString := AnsiUpperCase(Nombre);
          dm.IBQuery2.ParamByName('CALLE').AsString := AnsiUpperCase(CalleDirCli);
          dm.IBQuery2.ParamByName('NOMBRE_CALLE').AsString := AnsiUpperCase(Calle);
          dm.IBQuery2.ParamByName('NUM_EXTERIOR').AsString := AnsiUpperCase(NumExt);
          dm.IBQuery2.ParamByName('NUM_INTERIOR').AsString := AnsiUpperCase(NumInt);
          dm.IBQuery2.ParamByName('COLONIA').AsString := AnsiUpperCase(Colonia);
          dm.IBQuery2.ParamByName('POBLACION').AsString := AnsiUpperCase(Poblacion);
          dm.IBQuery2.ParamByName('REFERENCIA').AsString := AnsiUpperCase(Referencia);
          dm.IBQuery2.ParamByName('CIUDAD_ID').AsInteger := CiudadId;
          dm.IBQuery2.ParamByName('ESTADO_ID').AsInteger := IdEstado;
          dm.IBQuery2.ParamByName('CODIGO_POSTAL').AsString := AnsiUpperCase(CodigoPostal);
          dm.IBQuery2.ParamByName('PAIS_ID').AsInteger := PaisId;
          dm.IBQuery2.ParamByName('TELEFONO1').AsString := AnsiUpperCase(Telefono);
          dm.IBQuery2.ParamByName('TELEFONO2').Clear;
          dm.IBQuery2.ParamByName('FAX').Clear;
          dm.IBQuery2.ParamByName('EMAIL').AsString := Email;
          dm.IBQuery2.ParamByName('RFC_CURP').AsString := AnsiUpperCase(RfcCorrecto);

          if Contacto <> '' then
            dm.IBQuery2.ParamByName('CONTACTO').AsString := AnsiUpperCase(Contacto)
          else
            dm.IBQuery2.ParamByName('CONTACTO').Clear;

          dm.IBQuery2.ParamByName('VIA_EMBARQUE_ID').Clear;
          dm.IBQuery2.ParamByName('ES_DIR_PPAL').AsString := 'N';
          dm.IBQuery2.ParamByName('USAR_PARA_ENVIOS').AsString := 'S';
          dm.IBQuery2.ParamByName('USAR_PARA_FACTURAR').AsString := 'S';
          dm.IBQuery2.Open;
          {$ENDREGION}

          Result := DirCliId;

          if dm.trTrans.InTransaction then
             dm.trTrans.Commit;

        // end;
      end;
    end
	  except on e : exception do
     begin
       Error := e.Message;
       if dm.trTrans.InTransaction then
             dm.trTrans.Rollback;
       Result := 0;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;

//Lista en un XML las facturas del cliente
function TwsFactura.GET_FACTURAS_CLI(StrConexion:String; ClienteId:Integer; out Error:String ):WideString; stdcall;
Var
Integ_Ve_CC,Integ_Pv_Pv,SoloLiq:String;
VersionCan,NumSuc : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      Error := '';
      Result := '';
      dm.xmlWebservice.XML.Text := '';

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT VALOR FROM REGISTRY WHERE NOMBRE = ''INTEG_CC_PV'' ');
      dm.IBQuery.Open;
      Integ_Pv_Pv := dm.IBQuery.FieldByName('VALOR').AsString;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT VALOR FROM REGISTRY WHERE NOMBRE = ''INTEG_CC'' ');
      dm.IBQuery.Open;
      Integ_Ve_CC := dm.IBQuery.FieldByName('VALOR').AsString;

      SoloLiq := dm.GetPrefer('SoloFactLiquidadas');
      if (SoloLiq = '') then
        SoloLiq := 'N';

      Error := LeerCandado(VersionCan,NumSuc);
      if VersionCan = 0 then
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT FIRST 1 A.DOCTO_ID,A.ESTATUS,A.FOLIO,A.FECHA,A.IMPORTE_NETO, ');
        dm.IBQuery.SelectSQL.Add('A.IMPORTE_DONATIVO,A.TOTAL_IMPUESTOS,A.TOTAL_DSCTO_PPAG, ');
        dm.IBQuery.SelectSQL.Add('A.NOMBRE_CLIENTE,A.ALMACEN_ID ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURAS_GET_FACTURAS_CLI( :CLIENTE_ID , :SOLO_LIQUIDADAS ) A ');
        dm.IBQuery.SelectSQL.Add('ORDER BY A.FECHA DESC,A.FOLIO DESC ');
        dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
        dm.IBQuery.ParamByName('SOLO_LIQUIDADAS').AsString := SoloLiq;
        dm.IBQuery.open;

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('DOCTO_ID').AsInteger;
              Cliente := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CLIENTE').AsString);
              Folio := dm.IBQuery.FieldByName('FOLIO').AsString;
              Fecha := FormatDateTime('DD/MM/YYYY',dm.IBQuery.FieldByName('FECHA').AsDateTime);
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

        Error := '';
      end else
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_ID,A.ESTATUS,A.FOLIO,A.FECHA,A.IMPORTE_NETO, ');
        dm.IBQuery.SelectSQL.Add('A.IMPORTE_DONATIVO,A.TOTAL_IMPUESTOS,A.TOTAL_DSCTO_PPAG, ');
        dm.IBQuery.SelectSQL.Add('A.NOMBRE_CLIENTE,A.ALMACEN_ID ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURAS_GET_FACTURAS_CLI( :CLIENTE_ID , :SOLO_LIQUIDADAS ) A ');
        dm.IBQuery.SelectSQL.Add('ORDER BY A.FECHA DESC,A.FOLIO DESC ');
        dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
        dm.IBQuery.ParamByName('SOLO_LIQUIDADAS').AsString := SoloLiq;
        dm.IBQuery.open;

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('DOCTO_ID').AsInteger;
              Cliente := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CLIENTE').AsString);
              Folio := dm.IBQuery.FieldByName('FOLIO').AsString;
              Fecha := FormatDateTime('DD/MM/YYYY',dm.IBQuery.FieldByName('FECHA').AsDateTime);
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

        Error := '';
      end;

      if dm.xmlWebservice.XML.Text = '' then
      begin
        Error := 'El cliente no tiene facturas.';
        Result := '';
      end;

      Error := '';
      Result := '';
      Result := dm.xmlWebservice.XML.Text;

    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;


function TwsFactura.GET_PDF_XML_CREDITO(StrConexion:String; DoctoPvId:Integer; TipoArchivo:String; var Error:String) : WideString; stdcall;
Var TOTAL_LETRA,Folio,PdfPath,XmlPath,Modulo,ModalidadFact : String;
TotalPagar : Double;
   VerSML:String;
begin
Error := '';
Result := '';
try
 begin
  sysutils.decimalseparator:='.';
  dm := TfrmDataModule.Create (nil);

  if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
    raise Exception.Create(Error);
  if dm.trTrans.InTransaction then
    dm.trTrans.Rollback;
  dm.trTrans.StartTransaction;

  Error := '';
  Result := '';
  TOTAL_LETRA := '';                  Folio := '';
  PdfPath := '';                      XmlPath := '';
  Modulo := '';                       ModalidadFact := '';
  TotalPagar := 0;
  dm.gVERCFDI := '';
  dm.gVERCFDI := dm.GetPrefer('VERCFDI');

  dm.IBQuery.Close;
  dm.IBQuery.SelectSQL.Clear;
  dm.IBQuery.SelectSQL.Add('SELECT A.SISTEMA,A.XML ');
  dm.IBQuery.SelectSQL.Add('FROM USOS_FOLIOS_FISCALES A ');
  dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_ID = :DOCTO_ID ');
  DM.IBQuery.ParamByName('DOCTO_ID').ASINTEGER := DoctoPvId;
  dm.IBQuery.Open;
  Modulo := dm.IBQuery.FieldByName('SISTEMA').AsString;

  if (dm.IBQuery.FieldByName('XML').AsString = '') then
     raise exception.create('No existe el XML del documento indicado.');

  if (Modulo = 'VE') then
  begin
    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT TOTAL_A_PAGAR FROM CALC_TOTALES_DOCTO_VE (:DOCTO_VE_ID, ''S'' ) ');
    dm.IBQuery.ParamByName('DOCTO_VE_ID').ASINTEGER := DoctoPvId;
    dm.IBQuery.Open;
    TotalPagar := dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat;
    TOTAL_LETRA := dm.NUMLET(dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat,1,1);

    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_VE_ID,B.XML,A.FOLIO,A.MODALIDAD_FACTURACION ');
    dm.IBQuery.SelectSQL.Add('FROM DOCTOS_VE A ');
    dm.IBQuery.SelectSQL.Add('INNER JOIN USOS_FOLIOS_FISCALES B ON ( A.DOCTO_VE_ID = B.DOCTO_ID ) ');
    dm.IBQuery.SelectSQL.Add('WHERE A.TIPO_DOCTO = ''D'' AND A.DOCTO_VE_ID = :DOCTO_VE_ID ');
    dm.IBQuery.ParamByName('DOCTO_VE_ID').AsInteger := DoctoPvId;
    dm.IBQuery.Open;
    Folio :=  dm.IBQuery.FieldByName('FOLIO').AsString;
    ModalidadFact := dm.IBQuery.FieldByName('MODALIDAD_FACTURACION').AsString;
    dm.xmlTimbre.XML.Text := dm.IBQuery.FieldByName('XML').AsString;
    dm.xmlTimbre.Active := True;
  end;

  if (Modulo = 'PV') then
  begin
    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT TOTAL_A_PAGAR FROM CALC_TOTALES_DOCTO_PV(:DOCTO_PV_ID, ''S'',''N'',0 ) ');
    dm.IBQuery.ParamByName('DOCTO_PV_ID').ASINTEGER := DoctoPvId;
    dm.IBQuery.Open;
    TotalPagar := dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat;
    TOTAL_LETRA := dm.NUMLET(dm.IBQuery.FieldByName('TOTAL_A_PAGAR').asfloat,1,1);

    dm.IBQuery.Close;
    dm.IBQuery.SelectSQL.Clear;
    dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_PV_ID,B.XML,A.FOLIO,A.MODALIDAD_FACTURACION ');
    dm.IBQuery.SelectSQL.Add('FROM DOCTOS_PV A ');
    dm.IBQuery.SelectSQL.Add('INNER JOIN USOS_FOLIOS_FISCALES B ON ( A.DOCTO_PV_ID = B.DOCTO_ID ) ');
    dm.IBQuery.SelectSQL.Add('WHERE A.TIPO_DOCTO = ''C'' AND A.DOCTO_PV_ID = :DOCTO_PV_ID ');
    dm.IBQuery.ParamByName('DOCTO_PV_ID').AsInteger := DoctoPvId;
    dm.IBQuery.Open;
    Folio :=  dm.IBQuery.FieldByName('FOLIO').AsString;
    dm.xmlTimbre.XML.Text := dm.IBQuery.FieldByName('XML').AsString;
    dm.xmlTimbre.Active := True;
    ModalidadFact := dm.IBQuery.FieldByName('MODALIDAD_FACTURACION').AsString;
  end;

  VerSML := dm.VensionXML(dm.IBQuery.FieldByName('XML').AsString);

  if (AnsiUpperCase(TipoArchivo) = 'PDF') then
  begin

  //raise exception.create('Antes de PDF1.'+' ID:'+IntToStr(DoctoPvId)+' Sistema:'+Modulo);

    if VerSML = '3.3' then
    begin
        dm.ObtenerDatosFact33();
    end else
        dm.ObtenerDatosFact();



    Result := dm.GeneraPDF(Folio,TOTAL_LETRA,Modulo,ModalidadFact,TotalPagar,DoctoPvId);//dm.GeneraPDF('AA48','mucho dinero', 'PV', 'CFDI', 382.80, 52071);

    //Error := 'pasa_pdf_:_'+PdfPath;


    { if FileExists(PdfPath) then
         Result := dm.CodificaPDF(PdfPath);
     if not FileExists(PdfPath) then
      Result := ''; }    

   // DeleteFile(PAnsiChar(pdfpath));
  end;

  if (AnsiUpperCase(TipoArchivo) = 'XML') then
  begin
    XmlPath := dm.GetPrefer('CarpetaArchivos')+'\'+Folio+'.xml';
    dm.xmlTimbre.xml.savetofile(XmlPath);
    Result := dm.CodificaPDF(XmlPath);
    DeleteFile(PAnsiChar(XmlPath));
  end;           

 end
except on e : exception do
 begin
  Result := '1';
  Error := 'Mensaje: '+e.Message;
  if dm.trTrans.InTransaction then
    dm.trTrans.Rollback;
  dm.Free;
 end;
end;

end;

function TwsFactura.GET_NOTASCRED_CLI(StrConexion:String; ClienteId:Integer; out Error:String ):WideString; stdcall;
Var
Integ_Ve_CC,Integ_Pv_Pv,SoloLiq:String;
VersionCan,NumSuc : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      Error := '';
      Result := '';
      dm.xmlWebservice.XML.Text := '';

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT VALOR FROM REGISTRY WHERE NOMBRE = ''INTEG_CC_PV'' ');
      dm.IBQuery.Open;
      Integ_Pv_Pv := dm.IBQuery.FieldByName('VALOR').AsString;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT VALOR FROM REGISTRY WHERE NOMBRE = ''INTEG_CC'' ');
      dm.IBQuery.Open;
      Integ_Ve_CC := dm.IBQuery.FieldByName('VALOR').AsString;

      SoloLiq := dm.GetPrefer('SoloFactLiquidadas');
      if (SoloLiq = '') then
        SoloLiq := 'N';

      Error := LeerCandado(VersionCan,NumSuc);
      if VersionCan = 0 then
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT FIRST 1 A.DOCTO_ID,A.ESTATUS,A.FOLIO,A.FECHA,A.IMPORTE_NETO, ');
        dm.IBQuery.SelectSQL.Add('A.IMPORTE_DONATIVO,A.TOTAL_IMPUESTOS,A.TOTAL_DSCTO_PPAG, ');
        dm.IBQuery.SelectSQL.Add('A.NOMBRE_CLIENTE,A.ALMACEN_ID ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURAS_GET_NOTASCRED_CLI( :CLIENTE_ID , :SOLO_LIQUIDADAS ) A ');
        dm.IBQuery.SelectSQL.Add('ORDER BY A.FECHA DESC,A.FOLIO DESC ');
        dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
        dm.IBQuery.ParamByName('SOLO_LIQUIDADAS').AsString := SoloLiq;
        dm.IBQuery.open;

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('DOCTO_ID').AsInteger;
              Cliente := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CLIENTE').AsString);
              Folio := dm.IBQuery.FieldByName('FOLIO').AsString;
              Fecha := FormatDateTime('DD/MM/YYYY',dm.IBQuery.FieldByName('FECHA').AsDateTime);
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

        Error := '';
      end else
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_ID,A.ESTATUS,A.FOLIO,A.FECHA,A.IMPORTE_NETO, ');
        dm.IBQuery.SelectSQL.Add('A.IMPORTE_DONATIVO,A.TOTAL_IMPUESTOS,A.TOTAL_DSCTO_PPAG, ');
        dm.IBQuery.SelectSQL.Add('A.NOMBRE_CLIENTE,A.ALMACEN_ID ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURAS_GET_NOTASCRED_CLI( :CLIENTE_ID , :SOLO_LIQUIDADAS ) A ');
        dm.IBQuery.SelectSQL.Add('ORDER BY A.FECHA DESC,A.FOLIO DESC ');
        dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
        dm.IBQuery.ParamByName('SOLO_LIQUIDADAS').AsString := SoloLiq;
        dm.IBQuery.open;

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('DOCTO_ID').AsInteger;
              Cliente := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CLIENTE').AsString);
              Folio := dm.IBQuery.FieldByName('FOLIO').AsString;
              Fecha := FormatDateTime('DD/MM/YYYY',dm.IBQuery.FieldByName('FECHA').AsDateTime);
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

        Error := '';
      end;

      if dm.xmlWebservice.XML.Text = '' then
      begin
        Error := 'El cliente no tiene facturas.';
        Result := '';
      end;

      Error := '';
      Result := '';
      Result := dm.xmlWebservice.XML.Text;

    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;


function TwsFactura.NOTASC_POR_MAIL(StrConexion:String; DOCTO_PV_ID:Integer; EmailAlterno:String; Var Error:String ):Boolean;  stdcall;
Var Folio,Modulo :String;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
     if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);

     if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
     dm.trTrans.StartTransaction;

     folio := '';
     Error := '';

     dm.IBQuery.Close;
     dm.IBQuery.SelectSQL.Clear;
     dm.IBQuery.SelectSQL.Add('SELECT IIF( B.SERIE = ''@'','''',B.SERIE)||A.FOLIO FOLIO, A.SISTEMA ');
     dm.IBQuery.SelectSQL.Add('FROM USOS_FOLIOS_FISCALES A ');
     dm.IBQuery.SelectSQL.Add('INNER JOIN FOLIOS_FISCALES B ON ( A.FOLIOS_FISCALES_ID = B.FOLIOS_FISCALES_ID ) ');
     dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_ID = :DOCTO_VE_ID ');
     dm.IBQuery.ParamByName('DOCTO_VE_ID').AsInteger := DOCTO_PV_ID;
     dm.IBQuery.Open;

     folio := dm.IBQuery.FieldByName('FOLIO').AsString;

     if folio = '' then
         raise exception.Create('No existe el documento indicado.');

     Modulo := dm.IBQuery.FieldByName('SISTEMA').AsString;

     Result := dm.EnviaNotasCredito(DOCTO_PV_ID,Folio,Modulo,EmailAlterno,Error);

     if Error <> '' then
            raise exception.Create(Error);

    end
	  except on e : exception do
     begin
       Error := e.Message;
       Result := False;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;


//Cambio Josué -- Obtiene los lugares de expedición si se activa la opción 
function TwsFactura.GET_LUGARES_EXP(StrConexion:String; out Error:String):WideString; stdcall;
Var I, Conteo : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT COUNT(B.LUGAR_EXPEDICION_ID) CONTEO ');
      dm.IBQuery.SelectSQL.Add('FROM MGFACTURA_LUGARES_EXPEDICION A ');
      dm.IBQuery.SelectSQL.Add('INNER JOIN LUGARES_EXPEDICION B ON (A.LUGAR_EXPEDICION_ID = B.LUGAR_EXPEDICION_ID) ');
      dm.IBQuery.Open;
      Conteo := 0;
      Conteo := dm.IBQuery.FieldByName('CONTEO').AsInteger;

      if Conteo > 0 then
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT B.LUGAR_EXPEDICION_ID, B.NOMBRE ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURA_LUGARES_EXPEDICION A ');
        dm.IBQuery.SelectSQL.Add('INNER JOIN LUGARES_EXPEDICION B ON (A.LUGAR_EXPEDICION_ID = B.LUGAR_EXPEDICION_ID) ');
        dm.IBQuery.SelectSQL.Add('WHERE A.ESTATUS = ''A'' ');
        dm.IBQuery.SelectSQL.Add('ORDER BY B.NOMBRE ');
        dm.IBQuery.Open;
      end else
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT B.LUGAR_EXPEDICION_ID, B.NOMBRE ');
        dm.IBQuery.SelectSQL.Add('FROM LUGARES_EXPEDICION B ON (A.LUGAR_EXPEDICION_ID = B.LUGAR_EXPEDICION_ID) ');
        dm.IBQuery.SelectSQL.Add('ORDER BY B.NOMBRE ');
        dm.IBQuery.Open;
      end;


        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('LUGAR_EXPEDICION_ID').AsInteger;
              Cliente := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE').AsString);
              Folio := '';
              Fecha := '';
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

      {

        dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Cliente></Cliente>';
        dm.xmlWebservice.Active := True;

        Cliente := GetCliente(dm.xmlWebservice);
        I := 0;
        with Cliente do
        begin
          Cliente.ClienteId := 0;
          Cliente.Nombre := 'Valor';
          Cliente.Contacto := 'Valor';
          Cliente.Rfc := 'Valor';
          Cliente.Contrasena := 'Valor';


          if Conteo > 0 then
          begin
            dm.IBQuery3.Close;
            dm.IBQuery3.SelectSQL.Clear;
            dm.IBQuery3.SelectSQL.Add('SELECT B.LUGAR_EXPEDICION_ID, B.NOMBRE ');
            dm.IBQuery3.SelectSQL.Add('FROM MGFACTURA_LUGARES_EXPEDICION A ');
            dm.IBQuery3.SelectSQL.Add('INNER JOIN LUGARES_EXPEDICION B ON (A.LUGAR_EXPEDICION_ID = B.LUGAR_EXPEDICION_ID) ');
            dm.IBQuery3.SelectSQL.Add('WHERE A.ESATUS = ''A'' ');
            dm.IBQuery3.Open;

            if not dm.IBQuery3.IsEmpty then
            begin
              Cliente.AddChild('Direcciones',5);
              while not dm.IBQuery3.Eof do
              begin
                  with Direcciones.add do
                  begin
                    DireccionId := dm.IBQuery3.FieldByName('LUGAR_EXPEDICION_ID').AsInteger;
                    NombreDireccion := AnsiLowerCase(dm.IBQuery3.FieldByName('NOMBRE').AsString);
                    Inc(I);
                    dm.IBQuery3.Next;
                  end;
              end;
            end;
          end; //if Conteo > 0 then

          if Conteo = 0 then
          begin
            dm.IBQuery3.Close;
            dm.IBQuery3.SelectSQL.Clear;
            dm.IBQuery3.SelectSQL.Add('SELECT B.LUGAR_EXPEDICION_ID, B.NOMBRE ');
            dm.IBQuery3.SelectSQL.Add('FROM LUGARES_EXPEDICION B ');
            dm.IBQuery3.Open;

            if not dm.IBQuery3.IsEmpty then
            begin
              Cliente.AddChild('Direcciones',5);
              while not dm.IBQuery3.Eof do
              begin
                  with Direcciones.add do
                  begin
                    DireccionId := dm.IBQuery3.FieldByName('LUGAR_EXPEDICION_ID').AsInteger;
                    NombreDireccion := AnsiLowerCase(dm.IBQuery3.FieldByName('NOMBRE').AsString);
                    Inc(I);
                    dm.IBQuery3.Next;
                  end;
              end;
            end;
          end; //if Conteo > 0 then

        end;

        //dm.xmlWebservice.Active := True;

        Result := dm.xmlWebservice.XML.Text;
      }
    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;


//Cambio Josué -- Obtiene los lugares de expedición si se activa la opción 
function TwsFactura.GET_USOS_CFDI(StrConexion:String; out Error:String):WideString; stdcall;
Var I, Conteo : Integer;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      dm.IBQuery.Close;
      dm.IBQuery.SelectSQL.Clear;
      dm.IBQuery.SelectSQL.Add('SELECT COUNT(*) CONTEO');
      dm.IBQuery.SelectSQL.Add('FROM MGFACTURA_USO_CFDI ');
      dm.IBQuery.SelectSQL.Add('WHERE ESTATUS = ''A'' ');
      dm.IBQuery.Open;
      Conteo := 0;
      Conteo := dm.IBQuery.FieldByName('CONTEO').AsInteger;

      if Conteo > 0 then
      begin
        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT MGFACTURA_USO_CFDI_ID, USO_CFDI, ESTATUS, NOMBRE ');
        dm.IBQuery.SelectSQL.Add('FROM MGFACTURA_USO_CFDI ');
        dm.IBQuery.SelectSQL.Add('WHERE ESTATUS = ''A'' ');
        dm.IBQuery.Open;

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('MGFACTURA_USO_CFDI_ID').AsInteger;
              Cliente := dm.IBQuery.FieldByName('NOMBRE').AsString;
              Folio := dm.IBQuery.FieldByName('USO_CFDI').AsString;
              Fecha := '';
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

      end else
      begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin

            with FacturasCliente.Add do
            begin
              DoctoPvId := 2;
              Cliente := 'Gastos en general';
              Folio := 'G03';
              Fecha := '';
            end;

          end;
          Result := dm.xmlWebservice.XML.Text;

      end;





    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;



function TwsFactura.GET_PAGOS_FAC_CLI(StrConexion, FolioVenta:String; ClienteId:Integer; out Error:String ):WideString; stdcall;
Var
VersionCan,NumSuc : Integer;
DOCTO_CC_ID:Integer;
FolioVentaPV:String;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
      if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);
      if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
      dm.trTrans.StartTransaction;

      Error := '';
      Result := '';
      dm.xmlWebservice.XML.Text := '';
      DOCTO_CC_ID := 0;
      if FolioVenta <> 'T' then
      begin
        FolioVenta := dm.Rellena(FolioVenta);

        dm.IBQuery.Close;
        dm.IBQuery.SelectSQL.Clear;
        dm.IBQuery.SelectSQL.Add('SELECT DOCTO_CC_ID ');
        dm.IBQuery.SelectSQL.Add('FROM DOCTOS_CC ');
        dm.IBQuery.SelectSQL.Add('WHERE FACTURA_MOSTRADOR = :FACTURA_MOSTRADOR ');
        dm.IBQuery.ParamByName('FACTURA_MOSTRADOR').AsString := FolioVenta;
        dm.IBQuery.Open;
        DOCTO_CC_ID := dm.IBQuery.FieldByName('DOCTO_CC_ID').AsInteger;

        if DOCTO_CC_ID = 0 then
        begin
           dm.IBQuery.Close;
           dm.IBQuery.SelectSQL.Clear;
           dm.IBQuery.SelectSQL.Add('SELECT DOCTO_DEST_ID ');
           dm.IBQuery.SelectSQL.Add('FROM DOCTOS_VE A ');
           dm.IBQuery.SelectSQL.Add('INNER JOIN DOCTOS_ENTRE_SIS B ON (A.DOCTO_VE_ID = B.DOCTO_FTE_ID) ');
           dm.IBQuery.SelectSQL.Add('WHERE A.FOLIO = :FOLIO ');
           dm.IBQuery.SelectSQL.Add('AND CLAVE_SIS_DEST = ''CC'' ');
           dm.IBQuery.ParamByName('FOLIO').AsString := FolioVenta;
           dm.IBQuery.Open;
           DOCTO_CC_ID := dm.IBQuery.FieldByName('DOCTO_DEST_ID').AsInteger;
        end;

      end;

      Error := LeerCandado(VersionCan,NumSuc);
      if VersionCan = 0 then
      begin
        if FolioVenta = 'T' then
        begin
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT FIRST 1 A.DOCTO_CC_ID, B.FECHA, B.FOLIO, D.UUID, D.USO_FOLIO_ID, D.FOLIOS_FISCALES_ID ');
          dm.IBQuery.SelectSQL.Add('FROM IMPORTES_DOCTOS_CC A ');
          dm.IBQuery.SelectSQL.Add('JOIN DOCTOS_CC B ON (A.DOCTO_CC_ID = B.DOCTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN CONCEPTOS_CC C ON (B.CONCEPTO_CC_ID = C.CONCEPTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN USOS_FOLIOS_FISCALES D ON (B.DOCTO_CC_ID = D.DOCTO_ID) ');
          dm.IBQuery.SelectSQL.Add('WHERE B.CLIENTE_ID = :CLIENTE_ID ');
          dm.IBQuery.SelectSQL.Add('AND C.TIPO = ''P'' ');
          dm.IBQuery.SelectSQL.Add('AND A.CANCELADO = ''N'' ');
          dm.IBQuery.SelectSQL.Add('AND A.APLICADO = ''S'' ');
          dm.IBQuery.SelectSQL.Add('AND D.UUID IS NOT NULL ');
          dm.IBQuery.SelectSQL.Add('ORDER BY B.FECHA DESC, B.FOLIO DESC ');
          dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery.open;
        end else
        begin
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT FIRST 1  A.DOCTO_CC_ID, B.FECHA, B.FOLIO, D.UUID, D.USO_FOLIO_ID, D.FOLIOS_FISCALES_ID ');
          dm.IBQuery.SelectSQL.Add('FROM IMPORTES_DOCTOS_CC A ');
          dm.IBQuery.SelectSQL.Add('JOIN DOCTOS_CC B ON (A.DOCTO_CC_ID = B.DOCTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN CONCEPTOS_CC C ON (B.CONCEPTO_CC_ID = C.CONCEPTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN USOS_FOLIOS_FISCALES D ON (B.DOCTO_CC_ID = D.DOCTO_ID) ');
          dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_CC_ACR_ID = :V_CARGO_ID ');
          dm.IBQuery.SelectSQL.Add('AND B.CLIENTE_ID = :CLIENTE_ID ');
          dm.IBQuery.SelectSQL.Add('AND C.TIPO = ''P'' ');
          dm.IBQuery.SelectSQL.Add('AND A.CANCELADO = ''N'' ');
          dm.IBQuery.SelectSQL.Add('AND A.APLICADO = ''S'' ');
          dm.IBQuery.SelectSQL.Add('AND D.UUID IS NOT NULL ');
          dm.IBQuery.SelectSQL.Add('ORDER BY B.FECHA DESC, B.FOLIO DESC ');
          dm.IBQuery.ParamByName('V_CARGO_ID').AsInteger := DOCTO_CC_ID;
          dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery.open;
        end;

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('DOCTO_ID').AsInteger;
              Cliente := AnsiLowerCase(dm.IBQuery.FieldByName('NOMBRE_CLIENTE').AsString);
              Folio := dm.IBQuery.FieldByName('FOLIO').AsString;
              Fecha := FormatDateTime('DD/MM/YYYY',dm.IBQuery.FieldByName('FECHA').AsDateTime);
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

        Error := '';
      end else
      begin

        if FolioVenta = 'T' then
        begin
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_CC_ID, B.FECHA, B.FOLIO, D.UUID, D.USO_FOLIO_ID, D.FOLIOS_FISCALES_ID, A.DOCTO_CC_ACR_ID ');
          dm.IBQuery.SelectSQL.Add('FROM IMPORTES_DOCTOS_CC A ');
          dm.IBQuery.SelectSQL.Add('JOIN DOCTOS_CC B ON (A.DOCTO_CC_ID = B.DOCTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN CONCEPTOS_CC C ON (B.CONCEPTO_CC_ID = C.CONCEPTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN USOS_FOLIOS_FISCALES D ON (B.DOCTO_CC_ID = D.DOCTO_ID) ');
          dm.IBQuery.SelectSQL.Add('WHERE B.CLIENTE_ID = :CLIENTE_ID ');
          dm.IBQuery.SelectSQL.Add('AND C.TIPO = ''P'' ');
          dm.IBQuery.SelectSQL.Add('AND A.CANCELADO = ''N'' ');
          dm.IBQuery.SelectSQL.Add('AND A.APLICADO = ''S'' ');
          dm.IBQuery.SelectSQL.Add('AND D.UUID IS NOT NULL ');
          dm.IBQuery.SelectSQL.Add('ORDER BY B.FECHA DESC, B.FOLIO DESC ');
          dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery.open;
        end else
        begin
          dm.IBQuery.Close;
          dm.IBQuery.SelectSQL.Clear;
          dm.IBQuery.SelectSQL.Add('SELECT A.DOCTO_CC_ID, B.FECHA, B.FOLIO, D.UUID, D.USO_FOLIO_ID, D.FOLIOS_FISCALES_ID, A.DOCTO_CC_ACR_ID ');
          dm.IBQuery.SelectSQL.Add('FROM IMPORTES_DOCTOS_CC A ');
          dm.IBQuery.SelectSQL.Add('JOIN DOCTOS_CC B ON (A.DOCTO_CC_ID = B.DOCTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN CONCEPTOS_CC C ON (B.CONCEPTO_CC_ID = C.CONCEPTO_CC_ID) ');
          dm.IBQuery.SelectSQL.Add('JOIN USOS_FOLIOS_FISCALES D ON (B.DOCTO_CC_ID = D.DOCTO_ID) ');
          dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_CC_ACR_ID = :V_CARGO_ID ');
          dm.IBQuery.SelectSQL.Add('AND B.CLIENTE_ID = :CLIENTE_ID ');
          dm.IBQuery.SelectSQL.Add('AND C.TIPO = ''P'' ');
          dm.IBQuery.SelectSQL.Add('AND A.CANCELADO = ''N'' ');
          dm.IBQuery.SelectSQL.Add('AND A.APLICADO = ''S'' ');
          dm.IBQuery.SelectSQL.Add('AND D.UUID IS NOT NULL ');
          dm.IBQuery.SelectSQL.Add('ORDER BY B.FECHA DESC, B.FOLIO DESC ');
          dm.IBQuery.ParamByName('V_CARGO_ID').AsInteger := DOCTO_CC_ID;
          dm.IBQuery.ParamByName('CLIENTE_ID').AsInteger := ClienteId;
          dm.IBQuery.open;
        end;

        

        if not dm.IBQuery.IsEmpty then
        begin
          dm.xmlWebservice.XML.Text := '<?xml version="1.0" encoding="UTF-8" ?><Facturas></Facturas>';
          dm.xmlWebservice.Active := True;
          FacturasCliente := GetFacturas(dm.xmlWebservice);
          with FacturasCliente do
          begin
           while not dm.IBQuery.Eof do
           begin
            with FacturasCliente.Add do
            begin
              DoctoPvId := dm.IBQuery.FieldByName('DOCTO_CC_ID').AsInteger;
              if FolioVenta <> 'T' then
              begin
                  Cliente := FolioVenta;
              end else
              begin
                FolioVentaPV := '';
                dm.IBQuery2.Close;
                dm.IBQuery2.SelectSQL.Clear;
                dm.IBQuery2.SelectSQL.Add('SELECT FACTURA_MOSTRADOR ');
                dm.IBQuery2.SelectSQL.Add('FROM DOCTOS_CC ');
                dm.IBQuery2.SelectSQL.Add('WHERE DOCTO_CC_ID = :DOCTO_CC_ID ');
                dm.IBQuery2.ParamByName('DOCTO_CC_ID').AsInteger := dm.IBQuery.FieldByName('DOCTO_CC_ACR_ID').AsInteger;
                dm.IBQuery2.Open;
                FolioVentaPV := dm.IBQuery2.FieldByName('FACTURA_MOSTRADOR').AsString;

                if FolioVentaPV = '' then
                begin
                   dm.IBQuery2.Close;
                   dm.IBQuery2.SelectSQL.Clear;
                   dm.IBQuery2.SelectSQL.Add('SELECT A.FOLIO ');
                   dm.IBQuery2.SelectSQL.Add('FROM DOCTOS_VE A ');
                   dm.IBQuery2.SelectSQL.Add('INNER JOIN DOCTOS_ENTRE_SIS B ON (A.DOCTO_VE_ID = B.DOCTO_FTE_ID) ');
                   dm.IBQuery2.SelectSQL.Add('WHERE B.DOCTO_DEST_ID = :DOCTO_CC_ID ');
                   dm.IBQuery2.SelectSQL.Add('AND CLAVE_SIS_DEST = ''CC'' ');
                   dm.IBQuery2.ParamByName('DOCTO_CC_ID').AsInteger := dm.IBQuery.FieldByName('DOCTO_CC_ACR_ID').AsInteger;
                   dm.IBQuery2.Open;
                   FolioVentaPV := dm.IBQuery2.FieldByName('FOLIO').AsString;
                end;
                Cliente := FolioVentaPV;
              end;
              Folio := dm.IBQuery.FieldByName('FOLIO').AsString;
              Fecha := FormatDateTime('DD/MM/YYYY',dm.IBQuery.FieldByName('FECHA').AsDateTime);
            end;
            dm.IBQuery.Next;
           end;
          end;
          Result := dm.xmlWebservice.XML.Text;
        end;

        Error := '';
      end;

      if dm.xmlWebservice.XML.Text = '' then
      begin
        Error := 'El cliente no tiene pagos.';
        Result := '';
      end;

      Error := '';
      Result := '';
      Result := dm.xmlWebservice.XML.Text;

    end
	  except on e : exception do
     begin
       Error := e.Message;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;


function TwsFactura.GET_PDF_XML_PAGOS(StrConexion:String; DoctoCCID:Integer; TipoArchivo:String; var Error:String) : WideString; stdcall;
Var TOTAL_LETRA,Folio,PdfPath,XmlPath,Modulo,ModalidadFact : String;
TotalPagar : Double;
   VerSML:String;
begin
Error := '';
Result := '';
try
 begin
  sysutils.decimalseparator:='.';
  dm := TfrmDataModule.Create (nil);

  if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
    raise Exception.Create(Error);
  if dm.trTrans.InTransaction then
    dm.trTrans.Rollback;
  dm.trTrans.StartTransaction;

  Error := '';
  Result := '';
  TOTAL_LETRA := '';                  Folio := '';
  PdfPath := '';                      XmlPath := '';
  Modulo := '';                       ModalidadFact := '';
  TotalPagar := 0;
  dm.gVERCFDI := '';
  dm.gVERCFDI := dm.GetPrefer('VERCFDI');

  dm.IBQuery.Close;
  dm.IBQuery.SelectSQL.Clear;
  dm.IBQuery.SelectSQL.Add('SELECT A.SISTEMA,A.XML ');
  dm.IBQuery.SelectSQL.Add('FROM USOS_FOLIOS_FISCALES A ');
  dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_ID = :DOCTO_ID ');
  DM.IBQuery.ParamByName('DOCTO_ID').ASINTEGER := DoctoCCID;
  dm.IBQuery.Open;
  Modulo := dm.IBQuery.FieldByName('SISTEMA').AsString;

  if (dm.IBQuery.FieldByName('XML').AsString = '') then
     raise exception.create('No existe el XML del documento indicado.');



  dm.IBQuery.Close;
  dm.IBQuery.SelectSQL.Clear;
  dm.IBQuery.SelectSQL.Add('SELECT A.FOLIO, B.IMPORTE, C.SISTEMA, C.XML ');
  dm.IBQuery.SelectSQL.Add('FROM DOCTOS_CC A ');
  dm.IBQuery.SelectSQL.Add('INNER JOIN IMPORTES_DOCTOS_CC B ON (A.DOCTO_CC_ID = B.DOCTO_CC_ID) ');
  dm.IBQuery.SelectSQL.Add('INNER JOIN USOS_FOLIOS_FISCALES C ON (A.DOCTO_CC_ID = C.DOCTO_ID) ');
  dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_CC_ID = :DOCTO_ID ');
  dm.IBQuery.ParamByName('DOCTO_ID').AsInteger := DoctoCCID;
  dm.IBQuery.Open;
  TotalPagar := dm.IBQuery.FieldByName('IMPORTE').asfloat;

  Folio :=  dm.IBQuery.FieldByName('FOLIO').AsString;
  ModalidadFact := 'CFDI';
  dm.xmlTimbre.XML.Text := dm.IBQuery.FieldByName('XML').AsString;
  dm.xmlTimbre.Active := True;
  VerSML := dm.VensionXML(dm.IBQuery.FieldByName('XML').AsString);
  
  dm.IBQuery.Close;
  dm.IBQuery.SelectSQL.Clear;
  dm.IBQuery.SelectSQL.Add('SELECT A.FOLIO, B.NOMBRE AS CONCEPTO, D.NOMBRE AS CLIENTE, CALLE, F.NOMBRE AS CIUDAD, ');
  dm.IBQuery.SelectSQL.Add(' G.NOMBRE AS ESTADO, G.NOMBRE_ABREV AS ESTADO_ABREV, E.CODIGO_POSTAL, E.NUM_EXTERIOR, ');
  dm.IBQuery.SelectSQL.Add(' E.NUM_INTERIOR, E.COLONIA, E.POBLACION, E.RFC_CURP, SUM(C.IMPORTE) IMPORTE ');
  dm.IBQuery.SelectSQL.Add('FROM DOCTOS_CC A ');
  dm.IBQuery.SelectSQL.Add('INNER JOIN CONCEPTOS_CC B ON (A.CONCEPTO_CC_ID = B.CONCEPTO_CC_ID) ');
  dm.IBQuery.SelectSQL.Add('INNER JOIN IMPORTES_DOCTOS_CC C ON (A.DOCTO_CC_ID = C.DOCTO_CC_ID) ');
  dm.IBQuery.SelectSQL.Add('INNER JOIN CLIENTES D ON (A.CLIENTE_ID = D.CLIENTE_ID) ');
  dm.IBQuery.SelectSQL.Add('INNER JOIN DIRS_CLIENTES E ON (D.CLIENTE_ID = E.CLIENTE_ID) ');
  dm.IBQuery.SelectSQL.Add('LEFT JOIN CIUDADES F ON (F.CIUDAD_ID = E.CIUDAD_ID) ');
  dm.IBQuery.SelectSQL.Add('LEFT JOIN ESTADOS G ON (G.ESTADO_ID = E.ESTADO_ID) ');
  dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_CC_ID = :DOCTO_ID ');
  dm.IBQuery.SelectSQL.Add('AND E.NOMBRE_CONSIG = ''Dirección principal'' ');
  dm.IBQuery.SelectSQL.Add('GROUP BY A.FOLIO, B.NOMBRE , D.NOMBRE , CALLE, F.NOMBRE, ');
  dm.IBQuery.SelectSQL.Add(' G.NOMBRE, G.NOMBRE_ABREV , E.CODIGO_POSTAL, E.NUM_EXTERIOR, ');
  dm.IBQuery.SelectSQL.Add(' E.NUM_INTERIOR, E.COLONIA, E.POBLACION, E.RFC_CURP ');
  dm.IBQuery.SelectSQL.Add('ORDER BY A.FOLIO, B.NOMBRE , D.NOMBRE , CALLE, F.NOMBRE , ');
  dm.IBQuery.SelectSQL.Add(' G.NOMBRE , G.NOMBRE_ABREV , E.CODIGO_POSTAL, E.NUM_EXTERIOR, ');
  dm.IBQuery.SelectSQL.Add(' E.NUM_INTERIOR, E.COLONIA, E.POBLACION, E.RFC_CURP ');
  dm.IBQuery.ParamByName('DOCTO_ID').AsInteger := DoctoCCID;
  dm.IBQuery.Open;
  TOTAL_LETRA := dm.NUMLET(dm.IBQuery.FieldByName('IMPORTE').asfloat,1,1);




  if (AnsiUpperCase(TipoArchivo) = 'PDF') then
  begin


    if VerSML = '3.3' then
    begin
        dm.ObtenerDatosFact33Pago();
    end else
        dm.ObtenerDatosFact();

   // raise exception.create('antes de gen pdf.');

    Result := dm.GeneraPDF(Folio,TOTAL_LETRA,'PA',ModalidadFact,TotalPagar,DoctoCCID);//dm.GeneraPDF('AA48','mucho dinero', 'PV', 'CFDI', 382.80, 52071);

    //Error := 'pasa_pdf_:_'+PdfPath;


    { if FileExists(PdfPath) then
         Result := dm.CodificaPDF(PdfPath);
     if not FileExists(PdfPath) then
      Result := ''; }    

   // DeleteFile(PAnsiChar(pdfpath));
  end;

  if (AnsiUpperCase(TipoArchivo) = 'XML') then
  begin
    XmlPath := dm.GetPrefer('CarpetaArchivos')+'\'+Folio+'.xml';
    dm.xmlTimbre.xml.savetofile(XmlPath);
    Result := dm.CodificaPDF(XmlPath);
    DeleteFile(PAnsiChar(XmlPath));
  end;           

 end
except on e : exception do
 begin
  Result := '1';
  Error := 'Mensaje: '+e.Message+' ->'+VerSML;
  if dm.trTrans.InTransaction then
    dm.trTrans.Rollback;
  dm.Free;
 end;
end;

end;


function TwsFactura.PAGO_POR_MAIL(StrConexion:String; DoctoCCID:Integer; EmailAlterno:String; Var Error:String ):Boolean;  stdcall;
Var Folio,Modulo :String;
begin
    sysutils.decimalseparator:='.';
    dm := TfrmDataModule.Create (nil);
	  try
    begin
     if ((not dm.Conexion(StrConexion,Error)) or (Error <> '')) then
        raise Exception.Create(Error);

     if dm.trTrans.InTransaction then
        dm.trTrans.Rollback;
     dm.trTrans.StartTransaction;

     folio := '';
     Error := '';

     dm.IBQuery.Close;
     dm.IBQuery.SelectSQL.Clear;
     dm.IBQuery.SelectSQL.Add('SELECT IIF( B.SERIE = ''@'','''',B.SERIE)||A.FOLIO FOLIO, A.SISTEMA ');
     dm.IBQuery.SelectSQL.Add('FROM USOS_FOLIOS_FISCALES A ');
     dm.IBQuery.SelectSQL.Add('INNER JOIN FOLIOS_FISCALES B ON ( A.FOLIOS_FISCALES_ID = B.FOLIOS_FISCALES_ID ) ');
     dm.IBQuery.SelectSQL.Add('WHERE A.DOCTO_ID = :DoctoCCID ');
     dm.IBQuery.ParamByName('DoctoCCID').AsInteger := DoctoCCID;
     dm.IBQuery.Open;

     folio := dm.IBQuery.FieldByName('FOLIO').AsString;

     if folio = '' then
         raise exception.Create('No existe el documento indicado.');

     Modulo := 'PA'; //dm.IBQuery.FieldByName('SISTEMA').AsString;

     Result := dm.EnviaPago(DoctoCCID,Folio,Modulo,EmailAlterno,Error);

     if Error <> '' then
            raise exception.Create(Error);

    end
	  except on e : exception do
     begin
       Error := e.Message;
       Result := False;
       dm.IBQuery.Close;
	     dm.Free;
     end;
	  end;
end;


initialization
{ Invokable classes must be registered }
   InvRegistry.RegisterInvokableClass(TwsFactura);

  SetLicenseKey('9F9E1396AE7F6332436EE0F25CAE2331F908FF2D3971253C694E193700D72101' + 
'788FFB37BE9AED96D0F0B4F0A2D24A2C89DB92B7CD42F059B2B597747AB74FCD' + 
'93E1D93FB8421C189BF362658820501B64A4DC8DBD6D59B72063C6170B975A5A' + 
'1CCB55152541D1C4669F14978334BEABF75087981A202E9C61B0F82124C5D38D' + 
'BC1BDCE243E34CC6EBC5C6A6E94248E45EC4797AB3EC71D47E481EBF9126F9C0' + 
'B6872B77AD000591301E49F09C8B7E9FFF634665854891E37A236AC866DB066A' + 
'95C03E0AC1D5CE04BD12BDEE5B2D62897B5C4F449CBEB6E331AB10D037B5DD74' + 
'11A78A5E182C04E7844C78B1E5F83E899A4802F722FE99C34CDA6214CA0A9AA7');


end.
