España: Normativa sancionadora sistemas informáticos

Garbi
Posts: 344
Joined: Wed Nov 02, 2005 3:28 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by Garbi »

He exportado mi certificado personal a un pfx.
He creado el convert.bat y me genera el fichero jose1234.pem y jose1234_key.pem con exito,
después uso esta linea para el envio :

Code: Select all | Expand

curl --cert jose1234.pem --key jose1234_key.pem https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP  -d 1.xml -o respuesta.html
Y me da el error : curl: (58) schannel: Failed to import cert file jose1234.pem, last error is 0x80092002

He estado buscando el error pero no se a que se debe, el certificado es el mio que esta activo.

¿Alguna sugerencia?
Saludos,
Regards,

Jose Luis Alepuz
joseluis@mancomputer.com
www.mancomputer.com
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: España: Normativa sancionadora sistemas informáticos

Post by paquitohm »

Le he hecho la pregunta a Chat GPT y ha respondido esto https://chatgpt.com/share/6705190f-a6fc ... ffa6eed188
Quiza te de una pista


Mi version de curl.exe en produccion es esta:
curl --version
curl 7.54.0 (i386-pc-win32) libcurl/7.54.0 OpenSSL/1.1.0e zlib/1.2.11 WinIDN libssh2/1.8.0 nghttp2/1.21.1
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz TLS-SRP HTTP2 HTTPS-proxy

Lo primero que yo intentaria seria usar curl.exe en un servicio sencillo. Despues usarlo con certificado. Se trata de buscar donde puede estar el problema. Un buen sitio donde probar es el web service de la agencia de comprobacion de nifs llamado "Calidad de datos identificativos" o algo asi que yo creo que habria que usar si o si con VF como paso previo al envio
Garbi
Posts: 344
Joined: Wed Nov 02, 2005 3:28 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by Garbi »

Mi version de curl.exe es:
curl 8.8.0 (Windows) libcurl/8.8.0 Schannel zlib/1.3 WinIDN
Release-Date: 2024-05-22
Protocols: dict file ftp ftps http https imap imaps ipfs ipns mqtt pop3 pop3s smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM SPNEGO SSL SSPI threadsafe Unicode UnixSockets
Y ahora siguiendo las indicaciones de Paquito he creado nif.xml para probar la validez del nif porque me ha aparecido muy interesante comprobar que pueda existir el destinatario de la factura.

Code: Select all | Expand

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:vnif="http://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV2Ent.xsd">
<soapenv:Header/>
<soapenv:Body>
<vnif:VNifV2Ent>
<vnif:Contribuyente>
<vnif:Nif>99999999R</vnif:Nif>
<vnif:Nombre>APELLIDO APELLIDO JUAN</vnif:Nombre>
</vnif:Contribuyente>
</vnif:VNifV2Ent>
</soapenv:Body>
</soapenv:Envelope>
y uso la sentencia para enviarlo :

Code: Select all | Expand

curl -d nif.xml -o rnif.xml https://www1.agenciatributaria.gob.es/wlpl/BURT-JDIT/ws/VNifV2SOAP
Como resultado aparece :

Code: Select all | Expand

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     7    0     0  100     7      0     57 --:--:-- --:--:-- --:--:--    58
Pero el fichero de respuesta : rnif.xml esta a 0 kb, vamos que esta en blanco.

¿Qué no estoy haciendo bien ?

Agradecería cualquier ayuda, me parece algo muy importante el próximo uso de VERI*FACTU, porque las indicaciones para que sea NO VERI+FACTU me parecen exageradas a parte de que también tiene que ser VERI*FACTU por si nos solicitan las facturas poder subirlas.
No sé si me he perdido algo o desconozco algo de que los usuarios del foro españoles no estén preocupados por este tema.
Saludos,
Regards,

Jose Luis Alepuz
joseluis@mancomputer.com
www.mancomputer.com
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: España: Normativa sancionadora sistemas informáticos

Post by paquitohm »

Agradecería cualquier ayuda, me parece algo muy importante el próximo uso de VERI*FACTU, porque las indicaciones para que sea NO VERI+FACTU me parecen exageradas aparte de que también tiene que ser VERI*FACTU por si nos solicitan las facturas poder subirlas.
No es eso: Es que la agencia exige que todos los programa sean SI VF, es decir, no se puede instalar un programa que no pueda funcionar en modo SI VF, aunque no se use en modo SI VF.
No sé si me he perdido algo o desconozco algo de que los usuarios del foro españoles no estén preocupados por este tema.
Yo creo que esperan agazapados a ver si alguien se lo resuelve. Lo de ponerse a colaborar no van con ellos
Ya he tenido la experiencia de SII y TBAI: Cero colaboración


Esta es mi cadena de envío para la calidad de datos identificativos:

Code: Select all | Expand

\Pw\Conta\Dat\Sii\Utilidades\Curl.Exe -k --connect-timeout 60 -m 300 -s -S -L --header "Content-Type: text/xml;charset=UTF-8" --cert "\Pw\Conta\Dat\Sii\Certificados\Certificado.Pem" --key "\Pw\Conta\Dat\Sii\Certificados\Certificado_key.Pem" --data @\Pw\Conta\Err\Nif_Envio_3754552.xml https://www1.agenciatributaria.gob.es/wlpl/BURT-JDIT/ws/VNifV2SOAP --output \Pw\Conta\Err\Nif_Respuesta_3754552.xml -v
Garbi
Posts: 344
Joined: Wed Nov 02, 2005 3:28 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by Garbi »

Yo creo que esperan agazapados a ver si alguien se lo resuelve. Lo de ponerse a colaborar no van con ellos
Paquito, por tu experiencia puedes que tengas razón, pero yo muchas veces he recibido ayuda, más o menos me han servido pero siempre han contestado. Pero tengo que decir que sin tu colaboración yo ya estaría más que perdido.

Te pongo lo que me da con la prueba de calidad de datos identificativos: Creo que el problema es mi certificado, no se si al exportarlo no lo he hecho bien. Lo volveré a exportar y generar los .pem con tu convert.bat y a ver si ya lo consigo por fin. Pero ya el jueves, que mañana en Valencia es fiesta aunque tendré todo el día en la cabeza el tema, seguro.

Code: Select all | Expand

Curl.Exe -k --connect-timeout 60 -m 300 -s -S -L --header "Content-Type: text/xml;charset=UTF-8" --cert "jose1234.pem" --key "jose1234_key.Pem" --data Nif.xml https://www1.agenciatributaria.gob.es/wlpl/BURT-JDIT/ws/VNifV2SOAP --output Nif_Respuesta_3754552.xml -v
* Host www1.agenciatributaria.gob.es:443 was resolved.
* IPv6: (none)
* IPv4: 195.77.198.17
*   Trying 195.77.198.17:443...
* Connected to www1.agenciatributaria.gob.es (195.77.198.17) port 443
* schannel: disabled automatic use of client certificate
* schannel: Failed to import cert file jose1234.pem, last error is 0x80092002
* Closing connection
curl: (58) schannel: Failed to import cert file jose1234.pem, last error is 0x80092002

Bueno he tenido tiempo de hacerlo ahora, lo he exportado desde opciones de internet el certificado y lo he convertido y hay algo que no hago bien porque me ha el mismo error al hacer el curl, falla al importar el certificado.

Un saludo.
Saludos,
Regards,

Jose Luis Alepuz
joseluis@mancomputer.com
www.mancomputer.com
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: España: Normativa sancionadora sistemas informáticos

Post by paquitohm »

Parece ser que curl.exe de windows no esta preparado para trabajar con openssl
Pillate un curl.exe desde "la fuente" que dirían en Matrix

Descárgatelo de aquí a ver que tal: https://curl.se/windows/

https://stackoverflow.com/questions/713 ... shell-work
FiveWiDi
Posts: 1207
Joined: Mon Oct 10, 2005 2:38 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by FiveWiDi »

paquitohm wrote:La gente, as usual, agazapada esperando que ofrecen otros. A mi me hubiera gustado que se hubiera abierto un debate, aun a tiempo estamos, de como vamos a abordar todo esto desde la optica xBase-fwh.
Me siento un poco aludido, en este foro soy un mirón de los que más; pero es que mis conocimientos son limitados.
Estoy "hasta arriba", espero meterme de nuevo con Verifactu a finales de mes o en noviembre.
Hoy hacía varios días que no os leía con tiempo.
Un Saludo
Carlos G.

FiveWin 24.02 + Harbour 3.2.0dev (r2403071241), BCC 7.7 Windows 10
FiveWiDi
Posts: 1207
Joined: Mon Oct 10, 2005 2:38 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by FiveWiDi »

Garbi wrote:Vamos por partes.
1.- Crear fichero xml
Tenemos nuestros datos en .dbf

Con el ejemplo que hay de un ejemplo de xml podría usar las funciones
fcreate() para crear el xml
ir añadiendo lineas con outfile()
y una vez terminado todo con fclose() cerrar el fichero.

¿Con eso obtendría un fichero valido xml?

Es por empezar por algo, y saber si estoy perdiendo el tiempo o voy por buen camino.

¿Qué pensáis?
No estoy de acuerdo.

Yo creo que el camino es con este tipo de funciones (no son definitivas):

Las clases que estan en desarrollo

Code: Select all | Expand

/* 16/07/2024

   CLASSE PER GENERAR EL XML DE VERIFACTU.
   =======================================

   Classes per a crear el fitxer XML que serà enviat a VERI*FACTU.
   
   En fase de desenvolupament 30/07/2024.
   Sembla que ja és operativa en aspectes bàsics. 13/08/2024

*/

#include "Hbxml.ch"
#include "Hbclass.ch"
#include "Fileio.ch"

CLASS TVeriFactu00

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.
    DATA oXmlTop
    DATA oXmlSoapEnvelope
        DATA oXmlRegFactuSistemaFacturacion
            DATA oXmlCabecera
                // Dades pel TAG Cabecera
                //DATA cIDVersion
                DATA oXmlObligadoEmision
                    // Dades pel TAG ObligadoEmision
                    DATA cObligadoEmision_NombreRazon
                    DATA cObligadoEmision_NIF
                DATA oXmlRemisionVoluntaria
                    // Dades pel TAG RemisionVoluntaria
                    DATA cFechaFinVeriFactu
                    DATA cIncidencia
                DATA oXmlRemisionRequerimiento
                    // Dades pel TAG RemisionRequerimiento
                    DATA cRefRequerimiento

            DATA aRegistroFactura  INIT {}  //  -- >> Fins a 1000


    // DATA d'ús intern o que no contenen la informació a tractar.
    DATA     aTree INIT {}
    DATA     lError


    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.
    //ACCESS IDVersion                   INLINE ( hb_StrToUTF8( alltrim( ::cIDVersion ) ) )
    ACCESS ObligadoEmision_NombreRazon INLINE ( hb_StrToUTF8( alltrim( ::cObligadoEmision_NombreRazon ) ) )
    ACCESS ObligadoEmision_NIF         INLINE ( hb_StrToUTF8( alltrim( ::cObligadoEmision_NIF ) ) )
    //ACCESS FechaFinVeriFactu           INLINE ( hb_StrToUTF8( alltrim( ::cFechaFinVeriFactu ) ) )
    //ACCESS Incidencia                  INLINE ( hb_StrToUTF8( alltrim( ::cIncidencia ) ) )
    ACCESS RefRequerimiento            INLINE ( hb_StrToUTF8( alltrim( ::cRefRequerimiento ) ) )


    // Métodes per gestionar la classe.

    METHOD New( aTree ) CONSTRUCTOR
    METHOD ToXML()          //  Genera estructura XML con los datos.
    METHOD GeneraXml( cFichero )      //  Vuelca el XML a fichero.

    // Añade datos de una factura para ser usados en el momento de generar XML.
    METHOD AddFactura( oFactura )   INLINE ( AADD( ::aRegistroFactura, oFactura ) )

ENDCLASS

//---------------------------------------------------------------------------//

METHOD New(  ) CLASS TVeriFactu00

   //::aTree                          := aTree

   ::lError                         := .f.

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS TVeriFactu00

    Local oXmlBody         := Nil
    Local nContador        := 0


    /*
       Comienza el Nodo principal--------------------------------------------------
    */
    //::oXmlTop         := TXmlDocument():new( '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sum="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" xmlns:sum1="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">' )

    ::oXmlTop         := TXmlDocument():new( )

    ::oXmlTop:oRoot:AddBelow( TxmlNode():New( HBXML_TYPE_COMMENT, , , "Primeres proves..." ) )
    ::oXmlTop:oRoot:AddBelow( TxmlNode():New( HBXML_TYPE_COMMENT, , , "Date: " + DToC( Date() ) + " Time: " + Time() ) )
    ::oXmlTop:oRoot:AddBelow( TxmlNode():New( HBXML_TYPE_COMMENT, , , "Last access: " + GetEnv( "USERNAME" ) ) )

    ::oXmlSoapEnvelope := TxmlNode():New( HBXML_TYPE_TAG, "soapenv:Envelope" )
    ::oXmlTop:oRoot:AddBelow( ::oXmlSoapEnvelope )
    ::oXmlSoapEnvelope:SetAttribute( "xmlns:soapenv", "http://schemas.xmlsoap.org/soap/envelope/" )
    ::oXmlSoapEnvelope:SetAttribute( "xmlns:sum", "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" )
    ::oXmlSoapEnvelope:SetAttribute( "xmlns:sum1", "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" )
    ::oXmlSoapEnvelope:SetAttribute( "xmlns:xd", "http://www.w3.org/2000/09/xmldsig#" )
    //::oXmlTop:oRoot:AddBelow( ::oXmlSoapEnvelope )


    ::oXmlSoapEnvelope:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, "soapenv:Header" ) )
    oXmlBody := TxmlNode():New( HBXML_TYPE_TAG, "soapenv:Body" )
    ::oXmlSoapEnvelope:AddBelow( oXmlBody )


    /*
       Comienza el Nodo RegFactuSistemaFacturacion--------------------------------------------------
    */  
    ::oXmlRegFactuSistemaFacturacion := TxmlNode():New( HBXML_TYPE_TAG, "sum:RegFactuSistemaFacturacion" )
    oXmlBody:AddBelow( ::oXmlRegFactuSistemaFacturacion )


    /*
       Comienza el Nodo Cabecera--------------------------------------------------
    */
    ::oXmlCabecera := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Cabecera" )
    ::oXmlRegFactuSistemaFacturacion:AddBelow( ::oXmlCabecera )

    //::oXmlCabecera:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'IDVersion', , ::cIDVersion ) )
    ::oXmlObligadoEmision := TxmlNode():New( HBXML_TYPE_TAG, "sum1:ObligadoEmision" )
    ::oXmlCabecera:AddBelow( ::oXmlObligadoEmision )
    ::oXmlObligadoEmision:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::ObligadoEmision_NombreRazon() ) )
    ::oXmlObligadoEmision:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::ObligadoEmision_NIF() ) )
    //::oXmlCabecera:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'TipoRegistroAEAT', , ::cTipoRegistroAEAT ) )
    If .Not. Empty( ::cFechaFinVeriFactu ) .or. .Not. Empty( ::cIncidencia ) 
        ::oXmlRemisionVoluntaria := TxmlNode():New( HBXML_TYPE_TAG, 'RemisionVoluntaria' )
        ::oXmlCabecera:AddBelow( ::oXmlRemisionVoluntaria )
        If .Not. Empty( ::cFechaFinVeriFactu )
            ::oXmlRemisionVoluntaria:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'FechaFinVeriFactu', , ::cFechaFinVeriFactu ) )
        EndIf
        If .Not. Empty( ::cIncidencia )
            ::oXmlRemisionVoluntaria:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'Incidencia', , ::cIncidencia ) )
        EndIf
    EndIf
    If .Not. Empty( ::cRefRequerimiento )
        ::oXmlRemisionRequerimiento := TxmlNode():New( HBXML_TYPE_TAG, 'RemisionRequerimiento' )
        ::oXmlCabecera:AddBelow( ::oXmlRemisionRequerimiento )
        ::oXmlRemisionRequerimiento:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'RefRequerimiento', , ::RefRequerimiento() ) )
    EndIf

    /*
       Comienza el Nodo RegistroFactura--------------------------------------------------
    */
    For nContador := 1 To Len( ::aRegistroFactura )
        ::oXmlRegFactuSistemaFacturacion:AddBelow( ::aRegistroFactura[nContador]:ToXML() )
    End

Return ( Self )
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//
METHOD GeneraXML( cFichero )  CLASS TVeriFactu00

Local hDC := 0
    
   /*
   Generar fisicamente el fichero----------------------------------------------
   */

   //oBlock         := ErrorBlock( {| oError | ApoloBreak( oError ) } )
   BEGIN SEQUENCE

      ferase( cFichero )

      hDC       := fCreate( cFichero )

      if hDC < 0
          hDC := 0
      endif

      ::oXmlTop:Write( hDC, HBXML_STYLE_INDENT + HBXML_STYLE_THREESPACES )

      fClose( hDC )

      hDC := 0

      AADD( ::aTree,  "Fichero generado " + cFichero + " satisfactoriamente."  )

   RECOVER   //   USING oError

      ::lError    := .t.

      AADD( ::aTree,  "Error el generar el fichero " + cFichero )

   END SEQUENCE

   //ErrorBlock( oBlock )

   // GoWeb( AllTrim( cFichero ) )

Return ( Self )

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS RegistroFactura

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    //DATA oXmlRegistroFactura
        // Dades pel TAG oXmlRegistroFactura
        //DATA oXmlRegistroAlta
            // Dades pel TAG RegistroAlta
            DATA cIDVersion
            //DATA oXmlIDFactura
                // Dades pel TAG IDFactura
                DATA cIDEmisorFactura
                DATA cNumSerieFactura
                DATA cFechaExpedicionFactura
            DATA cNombreRazonEmisor
            DATA cSubsanacion
            DATA cRechazoPrevio
            //DATA cTipoRegistroSIF
            DATA cTipoFactura
            DATA cTipoRectificativa
            //DATA oXmlFacturasRectificadas
                // Dades pel TAG FacturasRectificadas
                DATA aIDFacturaRectificada  INIT {}     //  -- >> Fins a 1000
            //DATA oXmlFacturasSustituidas
                // Dades pel TAG FacturasSustituidas
                DATA aIDFacturaSustituida  INIT    {} //  -- >> Fins a 1000
            //DATA oXmlImporteRectificacion
                // Dades pel TAG ImporteRectificacion
                DATA cBaseRectificada
                DATA cCuotaRectificada
                DATA cCuotaRecargoRectificado
            DATA cFechaOperacion
            DATA cDescripcionOperacion
            DATA cFacturaSimplificadaArt7273
            DATA cFacturaSinIdentifDestinatarioArt61d
            DATA cMacrodato
            DATA cEmitidaPorTercerosODestinatario
            //DATA oXmlTercero
                // Dades pel TAG Tercero
                DATA cTercero_NombreRazon
                DATA cTercero_NIF
                //DATA oXmlTercero_IDOtro
                    // Dades pel TAG IDOtro
                    DATA cTercero_IDOtro_CodigoPais
                    DATA cTercero_IDOtro_IDType
                    DATA cTercero_IDOtro_ID
            //DATA oXmlDestinatarios
                // Dades pel TAG Destinatarios
                DATA aIDDestinatario  INIT  {}  //    -- >> Fins a 1000
            DATA cCupon
            //DATA oXmlDesglose
                // Dades pel TAG Desglose
                DATA aDetalleDesglose  INIT {}  //    -- >> Fins a 12
            DATA cCuotaTotal
            DATA cImporteTotal
            //DATA oXmlEncadenamiento
                // Dades pel TAG Encadenamiento
                DATA cPrimerRegistro
                //DATA oXmlIRegistroAnterior
                    // Dades pel TAG IDRegistroAnterior
                    DATA cIDEmisorFacturaRegistroAnterior
                    DATA cNumSerieFacturaRegistroAnterior
                    DATA cFechaExpedicionFacturaRegistroAnterior
                    DATA cHuellaRegistroAnterior
            //DATA oXmlSistemaInformatico
                // Dades pel TAG SistemaInformatico
                DATA cSistemaInformatico_NombreRazon
                DATA cSistemaInformatico_NIF
                //DATA oXmlSistemaInformatico_IDOtro
                    // Dades pel TAG IDOtro
                    DATA cSistemaInformatico_IDOtro_CodigoPais
                    DATA cSistemaInformatico_IDOtro_IDType
                    DATA cSistemaInformatico_IDOtro_ID
                DATA cNombreSistemaInformatico
                DATA cIdSistemaInformatico
                DATA cVersion
                DATA cNumeroInstalacion
                DATA cTipoUsoPosibleSoloVerifactu
                DATA cTipoUsoPosibleMultiOT
                DATA cIndicadorMultiplesOT
                //DATA cNumeroOTAlta
            DATA cFechaHoraHusoGenRegistro

            //DATA cFechaGenRegistro
            //DATA cHoraGenRegistro
            //DATA cHusoHorarioGenRegistro

            DATA cNumRegistroAcuerdoFacturacion
            DATA cIdAcuerdoSistemaInformatico
        //DATA oXmlDatosControl
            // Dades pel TAG DatosControl
            DATA cTipoHuella
            DATA cHuella
            DATA cSignature
            

    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS IDVersion                                  INLINE ( hb_StrToUTF8( alltrim( ::cIDVersion ) ) )
    ACCESS IDEmisorFactura                            INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFactura ) ) )
    ACCESS NumSerieFactura                            INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFactura ) ) )
    ACCESS FechaExpedicionFactura                     INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFactura ) ) )
    ACCESS NombreRazonEmisor                          INLINE ( hb_StrToUTF8( alltrim( ::cNombreRazonEmisor ) ) )
    ACCESS Subsanacion                                INLINE ( hb_StrToUTF8( alltrim( ::cSubsanacion ) ) )
    ACCESS RechazoPrevio                              INLINE ( hb_StrToUTF8( alltrim( ::cRechazoPrevio ) ) )
    //ACCESS TipoRegistroSIF                            INLINE ( hb_StrToUTF8( alltrim( ::cTipoRegistroSIF ) ) )
    ACCESS TipoFactura                                INLINE ( hb_StrToUTF8( alltrim( ::cTipoFactura ) ) )
    ACCESS TipoRectificativa                          INLINE ( hb_StrToUTF8( alltrim( ::cTipoRectificativa ) ) )
    ACCESS BaseRectificada                            INLINE ( hb_StrToUTF8( alltrim( ::cBaseRectificada ) ) )
    ACCESS CuotaRectificada                           INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRectificada ) ) )
    ACCESS CuotaRecargoRectificado                    INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRecargoRectificado ) ) )
    ACCESS FechaOperacion                             INLINE ( hb_StrToUTF8( alltrim( ::cFechaOperacion ) ) )
    ACCESS DescripcionOperacion                       INLINE ( hb_StrToUTF8( alltrim( ::cDescripcionOperacion ) ) )
    ACCESS FacturaSimplificadaArt7273                 INLINE ( hb_StrToUTF8( alltrim( ::cFacturaSimplificadaArt7273 ) ) )
    ACCESS FacturaSinIdentifDestinatarioArt61d        INLINE ( hb_StrToUTF8( alltrim( ::cFacturaSinIdentifDestinatarioArt61d ) ) )
    ACCESS Macrodato                                  INLINE ( hb_StrToUTF8( alltrim( ::cMacrodato ) ) )
    ACCESS EmitidaPorTercerosODestinatario            INLINE ( hb_StrToUTF8( alltrim( ::cEmitidaPorTercerosODestinatario ) ) )
    ACCESS Tercero_NombreRazon                        INLINE ( hb_StrToUTF8( alltrim( ::cTercero_NombreRazon ) ) )
    ACCESS Tercero_NIF                                INLINE ( hb_StrToUTF8( alltrim( ::cTercero_NIF ) ) )
    ACCESS Tercero_IDOtro_CodigoPais                  INLINE ( hb_StrToUTF8( alltrim( ::cTercero_IDOtro_CodigoPais ) ) )
    ACCESS Tercero_IDOtro_IDType                      INLINE ( hb_StrToUTF8( alltrim( ::cTercero_IDOtro_IDType ) ) )
    ACCESS Tercero_IDOtro_ID                          INLINE ( hb_StrToUTF8( alltrim( ::cTercero_IDOtro_ID ) ) )
    ACCESS Cupon                                      INLINE ( hb_StrToUTF8( alltrim( ::cCupon ) ) )
    ACCESS CuotaTotal                                 INLINE ( hb_StrToUTF8( alltrim( ::cCuotaTotal ) ) )
    ACCESS ImporteTotal                               INLINE ( hb_StrToUTF8( alltrim( ::cImporteTotal ) ) )
    ACCESS PrimerRegistro                             INLINE ( hb_StrToUTF8( alltrim( ::cPrimerRegistro ) ) )
    ACCESS IDEmisorFacturaRegistroAnterior            INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFacturaRegistroAnterior ) ) )
    ACCESS NumSerieFacturaRegistroAnterior            INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFacturaRegistroAnterior ) ) )
    ACCESS FechaExpedicionFacturaRegistroAnterior     INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFacturaRegistroAnterior ) ) )
    ACCESS HuellaRegistroAnterior                     INLINE ( alltrim( ::cHuellaRegistroAnterior ) )
    ACCESS SistemaInformatico_NombreRazon             INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_NombreRazon ) ) )
    ACCESS SistemaInformatico_NIF                     INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_NIF ) ) )
    ACCESS SistemaInformatico_IDOtro_CodigoPais       INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_IDOtro_CodigoPais ) ) )
    ACCESS SistemaInformatico_IDOtro_IDType           INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_IDOtro_IDType ) ) )
    ACCESS SistemaInformatico_IDOtro_ID               INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_IDOtro_ID ) ) )
    ACCESS NombreSistemaInformatico                   INLINE ( hb_StrToUTF8( alltrim( ::cNombreSistemaInformatico ) ) )
    ACCESS IdSistemaInformatico                       INLINE ( hb_StrToUTF8( alltrim( ::cIdSistemaInformatico ) ) )
    ACCESS Version                                    INLINE ( hb_StrToUTF8( alltrim( ::cVersion ) ) )
    ACCESS NumeroInstalacion                          INLINE ( hb_StrToUTF8( alltrim( ::cNumeroInstalacion ) ) )
    ACCESS TipoUsoPosibleSoloVerifactu                INLINE ( hb_StrToUTF8( alltrim( ::cTipoUsoPosibleSoloVerifactu ) ) )
    ACCESS TipoUsoPosibleMultiOT                      INLINE ( hb_StrToUTF8( alltrim( ::cTipoUsoPosibleMultiOT ) ) )
    ACCESS IndicadorMultiplesOT                       INLINE ( hb_StrToUTF8( alltrim( ::cIndicadorMultiplesOT ) ) )
    //ACCESS NumeroOTAlta                               INLINE ( hb_StrToUTF8( alltrim( ::cNumeroOTAlta ) ) )
    ACCESS FechaHoraHusoGenRegistro                   INLINE ( hb_StrToUTF8( alltrim( ::cFechaHoraHusoGenRegistro ) ) )

    //ACCESS HoraGenRegistro                            INLINE ( hb_StrToUTF8( alltrim( ::cHoraGenRegistro ) ) )
    //ACCESS HusoHorarioGenRegistro                     INLINE ( hb_StrToUTF8( alltrim( ::cHusoHorarioGenRegistro ) ) )
    
    ACCESS NumRegistroAcuerdoFacturacion              INLINE ( hb_StrToUTF8( alltrim( ::cNumRegistroAcuerdoFacturacion ) ) )
    ACCESS IdAcuerdoSistemaInformatico                INLINE ( hb_StrToUTF8( alltrim( ::cIdAcuerdoSistemaInformatico ) ) )
    ACCESS TipoHuella                                 INLINE ( hb_StrToUTF8( alltrim( ::cTipoHuella ) ) )
    ACCESS Huella                                     INLINE ( alltrim( ::cHuella ) )
    ACCESS Signature                                  INLINE ( hb_StrToUTF8( alltrim( ::cSignature ) ) )
    

    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.


    // Guardan grupos de DATA repetititvos.
    METHOD AddFacturaRectificada( oFacturaRectificada ) INLINE ( AADD( ::aIDFacturaRectificada, oFacturaRectificada ) )
    METHOD AddFacturaSustituida( oFacturaSustituida )   INLINE ( AADD( ::aIDFacturaSustituida, oFacturaSustituida ) )
    METHOD AddIDDestinatario( oIDDestinatario )         INLINE ( AADD( ::aIDDestinatario, oIDDestinatario ) )
    METHOD AddaDetalleDesglose( oDetalleDesglose )      INLINE ( AADD( ::aDetalleDesglose, oDetalleDesglose ) )

ENDCLASS

//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS RegistroFactura

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS RegistroFactura

Local oXmlRegistroFactura
Local oXmlRegistroAlta
Local oXmlIDFactura
Local oXmlFacturasRectificadas
Local oXmlFacturasSustituidas
Local oXmlImporteRectificacion
Local oXmlTercero
Local oXmlIDOtro
Local oXmlDestinatarios
Local oXmlDesglose
Local oXmlEncadenamiento
Local oXmlRegistroAnterior
//Local oXmlIDEmisorFacturaRegistroAnterior
Local oXmlSistemaInformatico
Local oXmlSistemaInformatico_IDOtro
//Local oXmlDatosControl
Local nContador           := 0

    oXmlRegistroFactura := TxmlNode():New( HBXML_TYPE_TAG, "sum:RegistroFactura" )

    oXmlRegistroAlta := TxmlNode():New( HBXML_TYPE_TAG, "sum:RegistroAlta" )
    oXmlRegistroFactura:AddBelow( oXmlRegistroAlta )

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDVersion', , ::IDVersion() ) )

    // IDFactura
    oXmlIDFactura := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDFactura" )
    oXmlRegistroAlta:AddBelow( oXmlIDFactura )
    oXmlIDFactura:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFactura() ) )
    oXmlIDFactura:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFactura() ) )
    oXmlIDFactura:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFactura() ) )

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazonEmisor', , ::NombreRazonEmisor() ) )
    
    If .Not. Empty( ::cSubsanacion )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Subsanacion', , ::Subsanacion() ) )
    EndIf
    If .Not. Empty( ::cRechazoPrevio )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:RechazoPrevio', , ::RechazoPrevio() ) )
    EndIf
    
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoFactura', , ::TipoFactura() ) )
    If .Not. Empty( ::cTipoRectificativa )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoRectificativa', , ::TipoRectificativa() ) )
    EndIf

    // IDFacturaRectificada
    If .Not. Empty( ::aIDFacturaRectificada )
        oXmlFacturasRectificadas := TxmlNode():New( HBXML_TYPE_TAG, "sum1:FacturasRectificadas" )
        oXmlRegistroAlta:AddBelow( oXmlFacturasRectificadas )
        For nContador := 1 To Len( ::aIDFacturaRectificada )
            oXmlFacturasRectificadas:AddBelow( ::aIDFacturaRectificada[nContador]:ToXML() )
        End
    EndIf

    // IDFacturaSustituida
    If .Not. Empty( ::aIDFacturaSustituida )
        oXmlFacturasSustituidas := TxmlNode():New( HBXML_TYPE_TAG, "sum1:FacturasSustituidas" )
        oXmlRegistroAlta:AddBelow( oXmlFacturasSustituidas )
        For nContador := 1 To Len( ::aIDFacturaSustituida )
            oXmlFacturasSustituidas:AddBelow( ::aIDFacturaSustituida[nContador]:ToXML() )
        End
    EndIf

    // ImporteRectificacion
    If .Not. Empty( ::cBaseRectificada )
        oXmlImporteRectificacion := TxmlNode():New( HBXML_TYPE_TAG, "sum1:ImporteRectificacion" )
        oXmlRegistroAlta:AddBelow( oXmlImporteRectificacion )
        oXmlImporteRectificacion:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:BaseRectificada', , ::BaseRectificada() ) )
        oXmlImporteRectificacion:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRectificada', , ::CuotaRectificada() ) )
        If .not. Empty( ::cCuotaRecargoRectificado )
            oXmlImporteRectificacion:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRecargoRectificado', , ::CuotaRecargoRectificado() ) )
        EndIf
    EndIf
    
    If .not. Empty( ::cFechaOperacion )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaOperacion', , ::FechaOperacion() ) )
    EndIf

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:DescripcionOperacion', , ::DescripcionOperacion() ) )

    If .not. Empty( ::cFacturaSimplificadaArt7273 )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FacturaSimplificadaArt7273', , ::FacturaSimplificadaArt7273() ) )
    EndIf

    If .not. Empty( ::cFacturaSinIdentifDestinatarioArt61d )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FacturaSinIdentifDestinatarioArt61d', , ::FacturaSinIdentifDestinatarioArt61d() ) )
    EndIf

    If .not. Empty( ::cMacrodato )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Macrodato', , ::Macrodato() ) )
    EndIf

    // EmitidaPorTercerosODestinatario
    If .not. Empty( ::cEmitidaPorTercerosODestinatario )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:EmitidaPorTercerosODestinatario', , ::EmitidaPorTercerosODestinatario() ) )
        oXmlTercero := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Tercero" )
        oXmlRegistroAlta:AddBelow( oXmlTercero )
        oXmlTercero:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::Tercero_NombreRazon() ) )
        If .Not. Empty( ::cTercero_NIF )
            oXmlTercero:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::Tercero_NIF() ) )
        EndIf

        If .Not. Empty( ::cTercero_IDOtro_IDType )
            oXmlIDOtro := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDOtro" )
            oXmlTercero:AddBelow( oXmlIDOtro )
            If .Not. Empty( ::cTercero_IDOtro_CodigoPais )
                oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CodigoPais', , ::Tercero_IDOtro_CodigoPais() ) )
            EndIf
            oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDType', , ::Tercero_IDOtro_IDType() ) )
            oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ID', , ::Tercero_IDOtro_ID() ) )
        EndIf
    EndIf
    
    // IDDestinatario
    If .Not. Empty( ::aIDDestinatario )
        oXmlDestinatarios := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Destinatarios" )
        oXmlRegistroAlta:AddBelow( oXmlDestinatarios )
        For nContador := 1 To Len( ::aIDDestinatario )
            oXmlDestinatarios:AddBelow( ::aIDDestinatario[nContador]:ToXML() )
        End
    EndIf

    If .not. Empty( ::cCupon )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Cupon', , ::Cupon() ) )
    EndIf
    
    // Desglose
    oXmlDesglose := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Desglose" )
    oXmlRegistroAlta:AddBelow( oXmlDesglose )
    For nContador := 1 To Len( ::aDetalleDesglose )
        oXmlDesglose:AddBelow( ::aDetalleDesglose[nContador]:ToXML() )
    End

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaTotal', , ::CuotaTotal() ) )
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ImporteTotal', , ::ImporteTotal() ) )
    
    // Encadenamiento
    oXmlEncadenamiento := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Encadenamiento" )
    oXmlRegistroAlta:AddBelow( oXmlEncadenamiento )
    If .Not. Empty( ::cPrimerRegistro )
        oXmlEncadenamiento:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:PrimerRegistro', , ::PrimerRegistro() ) )
    EndIf

    If .Not. Empty( ::cIDEmisorFacturaRegistroAnterior )
        oXmlRegistroAnterior := TxmlNode():New( HBXML_TYPE_TAG, "sum1:RegistroAnterior" )
        oXmlEncadenamiento:AddBelow( oXmlRegistroAnterior )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFacturaRegistroAnterior() ) )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFacturaRegistroAnterior() ) )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFacturaRegistroAnterior() ) )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Huella', , ::HuellaRegistroAnterior() ) )
    EndIf

    // SistemaInformatico
    oXmlSistemaInformatico := TxmlNode():New( HBXML_TYPE_TAG, "sum1:SistemaInformatico" )
    oXmlRegistroAlta:AddBelow( oXmlSistemaInformatico )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::SistemaInformatico_NombreRazon() ) )
    If .not. Empty( ::cSistemaInformatico_NIF )
        oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::SistemaInformatico_NIF() ) )
    EndIf
    If .not. Empty( ::cSistemaInformatico_IDOtro_IDType )
        oXmlSistemaInformatico_IDOtro := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDOtro" )
        oXmlSistemaInformatico:AddBelow( oXmlSistemaInformatico_IDOtro )
        If .not. Empty( ::cSistemaInformatico_IDOtro_CodigoPais )
            oXmlSistemaInformatico_IDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CodigoPais', , ::SistemaInformatico_IDOtro_CodigoPais() ) )
        EndIf
        oXmlSistemaInformatico_IDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDType', , ::SistemaInformatico_IDOtro_IDType() ) )
        oXmlSistemaInformatico_IDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ID', , ::SistemaInformatico_IDOtro_ID() ) )
    EndIf
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreSistemaInformatico', , ::NombreSistemaInformatico() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IdSistemaInformatico', , ::IdSistemaInformatico() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Version', , ::Version() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumeroInstalacion', , ::NumeroInstalacion() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoUsoPosibleSoloVerifactu', , ::TipoUsoPosibleSoloVerifactu() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoUsoPosibleMultiOT', , ::TipoUsoPosibleMultiOT() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IndicadorMultiplesOT', , ::IndicadorMultiplesOT() ) )
    
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaHoraHusoGenRegistro', , ::FechaHoraHusoGenRegistro() ) )

    If .Not. Empty( ::cNumRegistroAcuerdoFacturacion )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumRegistroAcuerdoFacturacion', , ::NumRegistroAcuerdoFacturacion() ) )
    EndIf
    If .Not. Empty( ::cIdAcuerdoSistemaInformatico )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IdAcuerdoSistemaInformatico', , ::IdAcuerdoSistemaInformatico() ) )
    EndIf
    
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoHuella', , ::TipoHuella() ) )
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Huella', , ::Huella() ) )
    If .Not. Empty( ::cSignature )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Signature', , ::Signature() ) )
    EndIf

Return oXmlRegistroFactura

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS IDFacturaRectificada

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG IDFacturaRectificada
    DATA cIDEmisorFactura
    DATA cNumSerieFactura
    DATA cFechaExpedicionFactura


    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS IDEmisorFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFactura ) ) )
    ACCESS NumSerieFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFactura ) ) )
    ACCESS FechaExpedicionFactura          INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFactura ) ) )


    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS IDFacturaRectificada

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS IDFacturaRectificada

Local oXmlIDFacturaRectificada

    oXmlIDFacturaRectificada := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDFacturaRectificada" )

    oXmlIDFacturaRectificada:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFactura() ) )
    oXmlIDFacturaRectificada:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFactura() ) )
    oXmlIDFacturaRectificada:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFactura() ) )

Return oXmlIDFacturaRectificada

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS IDFacturaSustituida

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG IDFacturaSustituida
    DATA cIDEmisorFactura
    DATA cNumSerieFactura
    DATA cFechaExpedicionFactura


    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.
    ACCESS IDEmisorFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFactura ) ) )
    ACCESS NumSerieFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFactura ) ) )
    ACCESS FechaExpedicionFactura          INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFactura ) ) )


    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS IDFacturaSustituida

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS IDFacturaSustituida

Local oXmlIDFacturaSustituida

    oXmlIDFacturaSustituida := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDFacturaSustituida" )

    oXmlIDFacturaSustituida:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFactura() ) )
    oXmlIDFacturaSustituida:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFactura() ) )
    oXmlIDFacturaSustituida:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFactura() ) )


Return oXmlIDFacturaSustituida

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS IDDestinatario

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG IDDestinatario  -- >> Fins a 1000
    DATA cNombreRazon
    DATA cNIF
    DATA oXmlIDOtro
        // Dades pel TAG IDOtro
        DATA cCodigoPais
        DATA cIDType
        DATA cID

    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS NombreRazon                      INLINE ( hb_StrToUTF8( alltrim( ::cNombreRazon ) ) )
    ACCESS NIF                              INLINE ( hb_StrToUTF8( alltrim( ::cNIF ) ) )
    ACCESS CodigoPais                       INLINE ( hb_StrToUTF8( alltrim( ::cCodigoPais ) ) )
    ACCESS IDType                           INLINE ( hb_StrToUTF8( alltrim( ::cIDType ) ) )
    ACCESS ID                               INLINE ( hb_StrToUTF8( alltrim( ::cID ) ) )


    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS IDDestinatario

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS IDDestinatario

Local oXmlIDDestinatario
Local oXmlIDOtro

    oXmlIDDestinatario := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDDestinatario" )

    oXmlIDDestinatario:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::NombreRazon() ) )
    If .Not. Empty( ::cNIF )
        oXmlIDDestinatario:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::NIF() ) )
    EndIf

    If .Not. Empty( ::cIDType )
        oXmlIDOtro := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDOtro" )
        oXmlIDDestinatario:AddBelow( oXmlIDOtro )
        If .Not. Empty( ::cCodigoPais )
            oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CodigoPais', , ::CodigoPais() ) )
        EndIf
        oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDType', , ::IDType() ) )
        oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ID', , ::ID() ) )
    EndIf

Return oXmlIDDestinatario

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS DetalleDesglose

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG DetalleDesglose  -- >> Fins a 12
    DATA cClaveRegimen
    DATA cCalificacionOperacion
    DATA cOperacionExenta
    DATA cTipoImpositivo
    DATA cBaseImponibleOimporteNoSujeto
    DATA cBaseImponibleACoste
    DATA cCuotaRepercutida
    DATA cTipoRecargoEquivalencia
    DATA cCuotaRecargoEquivalencia
    
    
    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS ClaveRegimen                          INLINE ( hb_StrToUTF8( alltrim( ::cClaveRegimen ) ) )
    ACCESS CalificacionOperacion                 INLINE ( hb_StrToUTF8( alltrim( ::cCalificacionOperacion ) ) )
    ACCESS OperacionExenta                       INLINE ( hb_StrToUTF8( alltrim( ::cOperacionExenta ) ) )
    ACCESS TipoImpositivo                        INLINE ( hb_StrToUTF8( alltrim( ::cTipoImpositivo ) ) )
    ACCESS BaseImponibleOimporteNoSujeto         INLINE ( hb_StrToUTF8( alltrim( ::cBaseImponibleOimporteNoSujeto ) ) )
    ACCESS BaseImponibleACoste                   INLINE ( hb_StrToUTF8( alltrim( ::cBaseImponibleACoste ) ) )
    ACCESS CuotaRepercutida                      INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRepercutida ) ) )
    ACCESS TipoRecargoEquivalencia               INLINE ( hb_StrToUTF8( alltrim( ::cTipoRecargoEquivalencia ) ) )
    ACCESS CuotaRecargoEquivalencia              INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRecargoEquivalencia ) ) )
    

    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS DetalleDesglose

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS DetalleDesglose

Local oXmlDetalleDesglose

    oXmlDetalleDesglose := TxmlNode():New( HBXML_TYPE_TAG, "sum1:DetalleDesglose" )

    oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ClaveRegimen', , ::ClaveRegimen() ) )

    //If .Not. Empty( ::cCalificacionOperacion )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CalificacionOperacion', , ::CalificacionOperacion() ) )
    //EndIf
    If .Not. Empty( ::cOperacionExenta )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:OperacionExenta', , ::OperacionExenta() ) )
    EndIf
    If .Not. Empty( ::cTipoImpositivo )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoImpositivo', , ::TipoImpositivo() ) )
    EndIf
    oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:BaseImponibleOimporteNoSujeto', , ::BaseImponibleOimporteNoSujeto() ) )
    If .Not. Empty( ::cBaseImponibleACoste )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:BaseImponibleACoste', , ::BaseImponibleACoste() ) )
    EndIf
    If .Not. Empty( ::cCuotaRepercutida )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRepercutida', , ::CuotaRepercutida() ) )
    EndIf
    If .Not. Empty( ::cTipoRecargoEquivalencia )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoRecargoEquivalencia', , ::TipoRecargoEquivalencia() ) )
    EndIf
    If .Not. Empty( ::cCuotaRecargoEquivalencia )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRecargoEquivalencia', , ::CuotaRecargoEquivalencia() ) )
    EndIf

Return oXmlDetalleDesglose
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//
 
Como las utilizo:

Code: Select all | Expand


........
    oXmlVerifactu := TVeriFactu00():New()

    oXmlVerifactu:cObligadoEmision_NombreRazon := cGetNomampa( AMPAARRA )
    oXmlVerifactu:cObligadoEmision_NIF         := cGetNifBD( AMPAARRA )
    // oXmlVerifactu:cFechaFinVeriFactu           :=  No l'utilitzo  01/08/2024
    // oXmlVerifactu:cIncidencia                  := "T0"
    // oXmlVerifactu:cRefRequerimiento            := Aquí no.


    While oTdbfFacAlb:Locate( , , lRestFacAlb) .and. .Not. oTdbfFacAlb:CheckEofBof( ):Eof

        lRestFacAlb := .T.
        
        If oTdbfFacAlb:Deleted(); Loop; EndIf
        
        oTdbfFacAlb:Load()

        msgnowait( AMPAarra, GetTrad( "Factura:" ) + Str( oTdbfFacAlb:NumeFact, 10, 0) + "-" + AllTrim(oTdbfFacAlb:RAOSOC), GetTrad( "Generant XML per a Verifactu de les Factures emeses...") )

        Traza( 1, GetTrad( "Factura:" ) + Str( oTdbfFacAlb:NumeFact, 10, 0) + "-" + + DToc( oTdbfFacAlb:DataFact) + "-" + AllTrim(oTdbfFacAlb:RAOSOC) )

        oXMLRegistroFactura := RegistroFactura():New()

        lSetXMLRegistroFactura( AMPAARRA, ;
                                oXMLRegistroFactura, ;
                                oTdbfFacAlb, ;
                                oTDbfFactur, ;
                                oTDbfFacAlbDummy, ;
                                lPrimerTractament, ;
                                @nRecnoAnterior, ;
                                @cIdFacturAnterior, ;
                                cNumSerieFacturaRegistroAnteriorDummy, ;
                                cFechaExpedicionFacturaRegistroAnteriorDummy, ;
                                cHuellaRegistroAnteriorDummy ;
                               )
..........
 
La función:
FUNCTION lSetXMLRegistroFactura( AMPAARRA, ;
                                 oXMLRegistroFactura, ;
                                 oTdbfFacAlb, ;
                                 oTDbfFactur, ;
                                 oTDbfFacAlbDummy, ;
                                 lPrimerTractament, ;
                                 nRecnoAnterior, ;
                                 cIdFacturAnterior, ;
                                 cNumSerieFacturaRegistroAnteriorDummy, ;
                                 cFechaExpedicionFacturaRegistroAnteriorDummy, ;
                                 cHuellaRegistroAnteriorDummy ;
                               )

// Seteja els valors de un objecte oXMLRegistroFactura.

Local lRespuesta          := .T.
Local oXmlIDDestinatario  := Nil
Local oXmlDetalleDesglose := Nil

        oXMLRegistroFactura:cIDVersion                   := "1.0"

        oXMLRegistroFactura:cIDEmisorFactura                            := cGetNifBD( AMPAARRA )
        oXMLRegistroFactura:cNumSerieFactura                            := Str( Year( oTdbfFacAlb:DataFact), 4, 0) + "-000-" + Right( Str( 1000000 + oTdbfFacAlb:NumeFact, 10, 0), 6)
        oXMLRegistroFactura:cFechaExpedicionFactura                     := hb_dtoc( oTdbfFacAlb:DataFact, "dd-mm-yyyy" )     //  DToc( oTdbfFacAlb:DataFact )
        oXMLRegistroFactura:cNombreRazonEmisor                          := cGetNomampa( AMPAARRA )
        //oXMLRegistroFactura:cTipoRegistroSIF                            := "S0"
        oXMLRegistroFactura:cTipoFactura                                := "F1"
        //oXMLRegistroFactura:cTipoRectificativa                          :=
        //oXMLRegistroFactura:cBaseRectificada                            :=
        //oXMLRegistroFactura:cCuotaRectificada                           :=
        //oXMLRegistroFactura:cCuotaRecargoRectificado                    :=
        //oXMLRegistroFactura:cFechaOperacion                             := hb_dtoc( oTdbfFacAlb:DataFact, "dd-mm-yyyy" )  //  DToc( oTdbfFacAlb:DataFact )   No cal al ser igual que la data d'expedició
        oXMLRegistroFactura:cDescripcionOperacion                       := "Prestación de servicios."
        oXMLRegistroFactura:cFacturaSimplificadaArt7273                 := "N"
        oXMLRegistroFactura:cFacturaSinIdentifDestinatarioArt61d        := "N"
        oXMLRegistroFactura:cMacrodato                                  := "N"
        //oXMLRegistroFactura:cEmitidaPorTercerosODestinatario            :=   No cal
        //oXMLRegistroFactura:cTercero_NombreRazon                        :=
        //oXMLRegistroFactura:cTercero_NIF                                :=
        //oXMLRegistroFactura:cTercero_IDOtro_CodigoPais                  :=
        //oXMLRegistroFactura:cTercero_IDOtro_IDType                      :=
        //oXMLRegistroFactura:cTercero_IDOtro_ID                          :=
       
        oXmlIDDestinatario := IDDestinatario():New()
        oXMLRegistroFactura:AddIDDestinatario( oXmlIDDestinatario )
        oXmlIDDestinatario:cNombreRazon                                      := oTdbfFacAlb:RAOSOC
        oXmlIDDestinatario:cNIF                                              := oTdbfFacAlb:NIF
        //oXmlIDDestinatario:cCodigoPais                                       :=
        //oXmlIDDestinatario:cIDType                                           :=
        //oXmlIDDestinatario:cID                                               :=

        oXMLRegistroFactura:cCupon                                      := "N"

        //Traza( 1, "oTdbfFacAlb:IdFactur=", oTdbfFacAlb:IdFactur )

        nGotoFacturIdFactur( AMPAarra, oTDbfFactur, AllTrim( oTdbfFacAlb:IdFactur ) + "-4", .T., .T., 1 )
        // IVA deduible
            oXmlDetalleDesglose := DetalleDesglose():New()
            oXMLRegistroFactura:AddaDetalleDesglose( oXmlDetalleDesglose )
            oXmlDetalleDesglose:cClaveRegimen                                   := "01"
            oXmlDetalleDesglose:cCalificacionOperacion                          := "S1"
            // oXmlDetalleDesglose:cOperacionExenta                                :=
            oXmlDetalleDesglose:cTipoImpositivo                                 := Alltrim( TransForm( oTDbfFactur:PERCENTA, "999.99" ) )
            oXmlDetalleDesglose:cBaseImponibleOimporteNoSujeto                  := Alltrim( TransForm( oTDbfFactur:BASECALC, "999999999999.99" ) )
            //oXmlDetalleDesglose:cBaseImponibleACoste                             :=
            oXmlDetalleDesglose:cCuotaRepercutida                                := Alltrim( TransForm( oTDbfFactur:IMPORT__, "999999999999.99" ) )
            //oXmlDetalleDesglose:cTipoRecargoEquivalencia                         :=
            //oXmlDetalleDesglose:cCuotaRecargoEquivalencia                        :=

        oXMLRegistroFactura:cCuotaTotal                                 := Alltrim( TransForm( oTDbfFactur:IMPORT__, "999999999999.99" ) )

        oXMLRegistroFactura:cImporteTotal                               := Alltrim( TransForm( oTDbfFacAlb:IMPOTOTA, "999999999999.99" ) )

        //nGotoFaAl( AMPAarra, oTDbfFacAlbDummy, oTDbfFacAlb:NumeFact, .T., .T., 1, Nil, Nil )

        /* Com que es poden tractar vàries factures per generar el XML, fins que no s'envia amb certesa
           els registres de oTDbfFacAlb no s'enregistren les Huella; per tant ha de ser en aquest bucle
           que es vagi 'traspassant' el valor de HuellaAnterior d'un registre al següent.
        */
        If lPrimerTractament
            // Es cerca a oTdbfFacAlb el registre que serà l'Anterior al tractat ara.
            If cGetLastIdFactur( AMPAARRA, oTdbfFacAlbDummy ) = ""
                oXMLRegistroFactura:cPrimerRegistro                         := "S"
                oXMLRegistroFactura:cHuellaRegistroAnterior                 := ""
                //Traza( 1 , "cIdFacturAnterior= cGetLastIdFactur() no trovat",)
              Else
                nRecnoAnterior    := oTdbfFacAlbDummy:Recno()
                cIdFacturAnterior := oTdbfFacAlbDummy:IdFactur
                //Traza( 1 , "cIdFacturAnterior=", cIdFacturAnterior)
                oXMLRegistroFactura:cIDEmisorFacturaRegistroAnterior        := cGetNifBD( AMPAARRA )
                oXMLRegistroFactura:cNumSerieFacturaRegistroAnterior        := Str( Year( oTdbfFacAlbDummy:DataFact), 4, 0) + "-000-" + Right( Str( 1000000 + oTdbfFacAlbDummy:NumeFact, 10, 0), 6)
                oXMLRegistroFactura:cFechaExpedicionFacturaRegistroAnterior := hb_dtoc( oTdbfFacAlbDummy:DataFact, "dd-mm-yyyy" )
                oXMLRegistroFactura:cHuellaRegistroAnterior                 := oTdbfFacAlbDummy:HuellaVF
            EndIf

          Else
            // oXMLRegistroFactura:cPrimerRegistro  està buit.
            oXMLRegistroFactura:cIDEmisorFacturaRegistroAnterior        := cGetNifBD( AMPAARRA )
            oXMLRegistroFactura:cNumSerieFacturaRegistroAnterior        := cNumSerieFacturaRegistroAnteriorDummy
            oXMLRegistroFactura:cFechaExpedicionFacturaRegistroAnterior := cFechaExpedicionFacturaRegistroAnteriorDummy
            oXMLRegistroFactura:cHuellaRegistroAnterior                 := cHuellaRegistroAnteriorDummy
        EndIf

        //Traza( 1, "a-nRecnoAnterior=", nRecnoAnterior )

        oXMLRegistroFactura:cSistemaInformatico_NombreRazon             := cVerifactuSINombreRazon( AMPAARRA )
        oXMLRegistroFactura:cSistemaInformatico_NIF                     := cVeriFactuSINif( AMPAARRA )
        //oXMLRegistroFactura:cSistemaInformatico_IDOtro_CodigoPais       :=
        //oXMLRegistroFactura:cSistemaInformatico_IDOtro_IDType           :=
        //oXMLRegistroFactura:cSistemaInformatico_IDOtro_ID               :=
        oXMLRegistroFactura:cNombreSistemaInformatico                   := cVeriFactuSINombreSistemaInformatico( AMPAARRA )
        oXMLRegistroFactura:cIdSistemaInformatico                       := cVeriFactuSIIdSistemaInformatico( AMPAARRA )
        oXMLRegistroFactura:cVersion                                    := cVeriFactuSIVersion( AMPAARRA )
        oXMLRegistroFactura:cNumeroInstalacion                          := cVeriFactuSINumeroInstalacion( AMPAARRA )
        oXMLRegistroFactura:cTipoUsoPosibleSoloVerifactu                := cVeriFactuSIPosibleSoloVerifactu( AMPAARRA )
        oXMLRegistroFactura:cTipoUsoPosibleMultiOT                      := cVeriFactuSITipoUsoPosibleMultiOT( AMPAARRA )
        oXMLRegistroFactura:cIndicadorMultiplesOT                       := cVeriFactuSIIndicadorMultiplesOT( AMPAARRA )

        //oXMLRegistroFactura:cNumeroOTAlta                               := "1"

        oXMLRegistroFactura:cFechaHoraHusoGenRegistro                   := FechaHoraHuso( oTdbfFacAlb:DataAlta, oTdbfFacAlb:HoraAlta )
       
        //oXMLRegistroFactura:cHoraGenRegistro                            := oTdbfFacAlb:HoraAlta
        //oXMLRegistroFactura:cHusoHorarioGenRegistro                     := "02"
       
       
       
        //oXMLRegistroFactura:cNumRegistroAcuerdoFacturacion              := De moment no.
        //oXMLRegistroFactura:cIdAcuerdoSistemaInformatico                := De moment no.

        oXMLRegistroFactura:cTipoHuella                                := "01"
        oXMLRegistroFactura:cHuella                                    := hb_VerifactuHuella( cGetNifBD( AMPAARRA ), ;
                                                                                              Str( Year( oTdbfFacAlb:DataFact), 4, 0) + "-000-" + Right( Str( 1000000 + oTdbfFacAlb:NumeFact, 10, 0), 6), ;
                                                                                              oTdbfFacAlb:DataFact, ;
                                                                                              "F1", ;
                                                                                              oTDbfFactur:IMPORT__, ;
                                                                                              oTDbfFacAlb:IMPOTOTA, ;
                                                                                              oXMLRegistroFactura:cHuellaRegistroAnterior, ;
                                                                                              FechaHoraHuso( oTdbfFacAlb:DataAlta, oTdbfFacAlb:HoraAlta ) ;
                                                                                            )

        //oXMLRegistroFactura:cSignature                                 := No cal aquí

Return lRespuesta[/code]
Un Saludo
Carlos G.

FiveWin 24.02 + Harbour 3.2.0dev (r2403071241), BCC 7.7 Windows 10
FiveWiDi
Posts: 1207
Joined: Mon Oct 10, 2005 2:38 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by FiveWiDi »

VictorCasajuana wrote:
paquitohm wrote:Yo creo que ahí simplemente hay que procesar el dato t que devuelve la petición, si te pone 10 minutos (por ejemplo) pues hasta 10 minutos no puedes enviar la siguiente factura. Que puede pasar? que tengas más de una factura por enviar. Solución? pues preparar el proceso de generación de xml para poder incluir n facturas, y cada vez que se genera un envío, mirar en el dbf de facturas las que no se han enviado y meterlas todas. Habrá que guardar el dato t que se recibe en algun fichero por si se sale y entra del programa tener constancia del último envío y del tiempo a esperar para el próximo.
Yo así lo veo también.
Si se les cae el sistema no seran 10 minutos... por tanto debemos hacer algo que no nos ate y nos permita seguir facturando.
Un Saludo
Carlos G.

FiveWin 24.02 + Harbour 3.2.0dev (r2403071241), BCC 7.7 Windows 10
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: España: Normativa sancionadora sistemas informáticos

Post by paquitohm »

Carlos,

Muchas gracias por tu gran aporte.
Ya se ve que te lo has currado.

Tu codigo puede ser un buen punto de partida para muchos.
A ver si se sigue sumando gente y entre todos aportamos, aunque sólo sean ideas.

El .xml es importante, sin duda, pero para mi es una de las dos piezas. La otra pieza es un sistema de envio eficaz y fiable el cual debe primero revisar que todo esté en condiciones de envio que puede incluir pruebas de conexion, validacion de nifs, aseguramiento de la ultima factura, etc..., enviar con seguridad, y recoger el envio y asignar lo aceptado, medio aceptado y rechazado.

Salu2
User avatar
VictorCasajuana
Posts: 268
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs
Contact:

Re: España: Normativa sancionadora sistemas informáticos

Post by VictorCasajuana »

FiveWiDi wrote:
Garbi wrote:Vamos por partes.
1.- Crear fichero xml
Tenemos nuestros datos en .dbf

Con el ejemplo que hay de un ejemplo de xml podría usar las funciones
fcreate() para crear el xml
ir añadiendo lineas con outfile()
y una vez terminado todo con fclose() cerrar el fichero.

¿Con eso obtendría un fichero valido xml?

Es por empezar por algo, y saber si estoy perdiendo el tiempo o voy por buen camino.

¿Qué pensáis?
No estoy de acuerdo.

Yo creo que el camino es con este tipo de funciones (no son definitivas):

Las clases que estan en desarrollo

Code: Select all | Expand

/* 16/07/2024

   CLASSE PER GENERAR EL XML DE VERIFACTU.
   =======================================

   Classes per a crear el fitxer XML que serà enviat a VERI*FACTU.
   
   En fase de desenvolupament 30/07/2024.
   Sembla que ja és operativa en aspectes bàsics. 13/08/2024

*/

#include "Hbxml.ch"
#include "Hbclass.ch"
#include "Fileio.ch"

CLASS TVeriFactu00

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.
    DATA oXmlTop
    DATA oXmlSoapEnvelope
        DATA oXmlRegFactuSistemaFacturacion
            DATA oXmlCabecera
                // Dades pel TAG Cabecera
                //DATA cIDVersion
                DATA oXmlObligadoEmision
                    // Dades pel TAG ObligadoEmision
                    DATA cObligadoEmision_NombreRazon
                    DATA cObligadoEmision_NIF
                DATA oXmlRemisionVoluntaria
                    // Dades pel TAG RemisionVoluntaria
                    DATA cFechaFinVeriFactu
                    DATA cIncidencia
                DATA oXmlRemisionRequerimiento
                    // Dades pel TAG RemisionRequerimiento
                    DATA cRefRequerimiento

            DATA aRegistroFactura  INIT {}  //  -- >> Fins a 1000


    // DATA d'ús intern o que no contenen la informació a tractar.
    DATA     aTree INIT {}
    DATA     lError


    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.
    //ACCESS IDVersion                   INLINE ( hb_StrToUTF8( alltrim( ::cIDVersion ) ) )
    ACCESS ObligadoEmision_NombreRazon INLINE ( hb_StrToUTF8( alltrim( ::cObligadoEmision_NombreRazon ) ) )
    ACCESS ObligadoEmision_NIF         INLINE ( hb_StrToUTF8( alltrim( ::cObligadoEmision_NIF ) ) )
    //ACCESS FechaFinVeriFactu           INLINE ( hb_StrToUTF8( alltrim( ::cFechaFinVeriFactu ) ) )
    //ACCESS Incidencia                  INLINE ( hb_StrToUTF8( alltrim( ::cIncidencia ) ) )
    ACCESS RefRequerimiento            INLINE ( hb_StrToUTF8( alltrim( ::cRefRequerimiento ) ) )

      if hDC < 0
          hDC := 0
      endif

      ::oXmlTop:Write( hDC, HBXML_STYLE_INDENT + HBXML_STYLE_THREESPACES )

      fClose( hDC )

      hDC := 0

      AADD( ::aTree,  "Fichero generado " + cFichero + " satisfactoriamente."  )

   RECOVER   //   USING oError

      ::lError    := .t.

      AADD( ::aTree,  "Error el generar el fichero " + cFichero )

   END SEQUENCE

   //ErrorBlock( oBlock )

   // GoWeb( AllTrim( cFichero ) )

Return ( Self )

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS RegistroFactura

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    //DATA oXmlRegistroFactura
        // Dades pel TAG oXmlRegistroFactura
        //DATA oXmlRegistroAlta
            // Dades pel TAG RegistroAlta
            DATA cIDVersion
            //DATA oXmlIDFactura
                // Dades pel TAG IDFactura
                DATA cIDEmisorFactura
                DATA cNumSerieFactura
                DATA cFechaExpedicionFactura
            DATA cNombreRazonEmisor
            DATA cSubsanacion
            DATA cRechazoPrevio
            //DATA cTipoRegistroSIF
            DATA cTipoFactura
            DATA cTipoRectificativa
            //DATA oXmlFacturasRectificadas
                // Dades pel TAG FacturasRectificadas
                DATA aIDFacturaRectificada  INIT {}     //  -- >> Fins a 1000
            //DATA oXmlFacturasSustituidas
                // Dades pel TAG FacturasSustituidas
                DATA aIDFacturaSustituida  INIT    {} //  -- >> Fins a 1000
            //DATA oXmlImporteRectificacion
                // Dades pel TAG ImporteRectificacion
                DATA cBaseRectificada
                DATA cCuotaRectificada
                DATA cCuotaRecargoRectificado
            DATA cFechaOperacion
            DATA cDescripcionOperacion
            DATA cFacturaSimplificadaArt7273
            DATA cFacturaSinIdentifDestinatarioArt61d
            DATA cMacrodato
            DATA cEmitidaPorTercerosODestinatario
            //DATA oXmlTercero
                // Dades pel TAG Tercero
                DATA cTercero_NombreRazon
                DATA cTercero_NIF
                //DATA oXmlTercero_IDOtro
                    // Dades pel TAG IDOtro
                    DATA cTercero_IDOtro_CodigoPais
                    DATA cTercero_IDOtro_IDType
                    DATA cTercero_IDOtro_ID
            //DATA oXmlDestinatarios
                // Dades pel TAG Destinatarios
                DATA aIDDestinatario  INIT  {}  //    -- >> Fins a 1000
            DATA cCupon
            //DATA oXmlDesglose
                // Dades pel TAG Desglose
                DATA aDetalleDesglose  INIT {}  //    -- >> Fins a 12
            DATA cCuotaTotal
            DATA cImporteTotal
            //DATA oXmlEncadenamiento
                // Dades pel TAG Encadenamiento
                DATA cPrimerRegistro
                //DATA oXmlIRegistroAnterior
                    // Dades pel TAG IDRegistroAnterior
                    DATA cIDEmisorFacturaRegistroAnterior
                    DATA cNumSerieFacturaRegistroAnterior
                    DATA cFechaExpedicionFacturaRegistroAnterior
                    DATA cHuellaRegistroAnterior
            //DATA oXmlSistemaInformatico
                // Dades pel TAG SistemaInformatico
                DATA cSistemaInformatico_NombreRazon
                DATA cSistemaInformatico_NIF
                //DATA oXmlSistemaInformatico_IDOtro
                    // Dades pel TAG IDOtro
                    DATA cSistemaInformatico_IDOtro_CodigoPais
                    DATA cSistemaInformatico_IDOtro_IDType
                    DATA cSistemaInformatico_IDOtro_ID
                DATA cNombreSistemaInformatico
                DATA cIdSistemaInformatico
                DATA cVersion
                DATA cNumeroInstalacion
                DATA cTipoUsoPosibleSoloVerifactu
                DATA cTipoUsoPosibleMultiOT
                DATA cIndicadorMultiplesOT
                //DATA cNumeroOTAlta
            DATA cFechaHoraHusoGenRegistro

            //DATA cFechaGenRegistro
            //DATA cHoraGenRegistro
            //DATA cHusoHorarioGenRegistro

            DATA cNumRegistroAcuerdoFacturacion
            DATA cIdAcuerdoSistemaInformatico
        //DATA oXmlDatosControl
            // Dades pel TAG DatosControl
            DATA cTipoHuella
            DATA cHuella
            DATA cSignature
            

    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS IDVersion                                  INLINE ( hb_StrToUTF8( alltrim( ::cIDVersion ) ) )
    ACCESS IDEmisorFactura                            INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFactura ) ) )
    ACCESS NumSerieFactura                            INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFactura ) ) )
    ACCESS FechaExpedicionFactura                     INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFactura ) ) )
    ACCESS NombreRazonEmisor                          INLINE ( hb_StrToUTF8( alltrim( ::cNombreRazonEmisor ) ) )
    ACCESS Subsanacion                                INLINE ( hb_StrToUTF8( alltrim( ::cSubsanacion ) ) )
    ACCESS RechazoPrevio                              INLINE ( hb_StrToUTF8( alltrim( ::cRechazoPrevio ) ) )
    //ACCESS TipoRegistroSIF                            INLINE ( hb_StrToUTF8( alltrim( ::cTipoRegistroSIF ) ) )
    ACCESS TipoFactura                                INLINE ( hb_StrToUTF8( alltrim( ::cTipoFactura ) ) )
    ACCESS TipoRectificativa                          INLINE ( hb_StrToUTF8( alltrim( ::cTipoRectificativa ) ) )
    ACCESS BaseRectificada                            INLINE ( hb_StrToUTF8( alltrim( ::cBaseRectificada ) ) )
    ACCESS CuotaRectificada                           INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRectificada ) ) )
    ACCESS CuotaRecargoRectificado                    INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRecargoRectificado ) ) )
    ACCESS FechaOperacion                             INLINE ( hb_StrToUTF8( alltrim( ::cFechaOperacion ) ) )
    ACCESS DescripcionOperacion                       INLINE ( hb_StrToUTF8( alltrim( ::cDescripcionOperacion ) ) )
    ACCESS FacturaSimplificadaArt7273                 INLINE ( hb_StrToUTF8( alltrim( ::cFacturaSimplificadaArt7273 ) ) )
    ACCESS FacturaSinIdentifDestinatarioArt61d        INLINE ( hb_StrToUTF8( alltrim( ::cFacturaSinIdentifDestinatarioArt61d ) ) )
    ACCESS Macrodato                                  INLINE ( hb_StrToUTF8( alltrim( ::cMacrodato ) ) )
    ACCESS EmitidaPorTercerosODestinatario            INLINE ( hb_StrToUTF8( alltrim( ::cEmitidaPorTercerosODestinatario ) ) )
    ACCESS Tercero_NombreRazon                        INLINE ( hb_StrToUTF8( alltrim( ::cTercero_NombreRazon ) ) )
    ACCESS Tercero_NIF                                INLINE ( hb_StrToUTF8( alltrim( ::cTercero_NIF ) ) )
    ACCESS Tercero_IDOtro_CodigoPais                  INLINE ( hb_StrToUTF8( alltrim( ::cTercero_IDOtro_CodigoPais ) ) )
    ACCESS Tercero_IDOtro_IDType                      INLINE ( hb_StrToUTF8( alltrim( ::cTercero_IDOtro_IDType ) ) )
    ACCESS Tercero_IDOtro_ID                          INLINE ( hb_StrToUTF8( alltrim( ::cTercero_IDOtro_ID ) ) )
    ACCESS Cupon                                      INLINE ( hb_StrToUTF8( alltrim( ::cCupon ) ) )
    ACCESS CuotaTotal                                 INLINE ( hb_StrToUTF8( alltrim( ::cCuotaTotal ) ) )
    ACCESS ImporteTotal                               INLINE ( hb_StrToUTF8( alltrim( ::cImporteTotal ) ) )
    ACCESS PrimerRegistro                             INLINE ( hb_StrToUTF8( alltrim( ::cPrimerRegistro ) ) )
    ACCESS IDEmisorFacturaRegistroAnterior            INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFacturaRegistroAnterior ) ) )
    ACCESS NumSerieFacturaRegistroAnterior            INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFacturaRegistroAnterior ) ) )
    ACCESS FechaExpedicionFacturaRegistroAnterior     INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFacturaRegistroAnterior ) ) )
    ACCESS HuellaRegistroAnterior                     INLINE ( alltrim( ::cHuellaRegistroAnterior ) )
    ACCESS SistemaInformatico_NombreRazon             INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_NombreRazon ) ) )
    ACCESS SistemaInformatico_NIF                     INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_NIF ) ) )
    ACCESS SistemaInformatico_IDOtro_CodigoPais       INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_IDOtro_CodigoPais ) ) )
    ACCESS SistemaInformatico_IDOtro_IDType           INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_IDOtro_IDType ) ) )
    ACCESS SistemaInformatico_IDOtro_ID               INLINE ( hb_StrToUTF8( alltrim( ::cSistemaInformatico_IDOtro_ID ) ) )
    ACCESS NombreSistemaInformatico                   INLINE ( hb_StrToUTF8( alltrim( ::cNombreSistemaInformatico ) ) )
    ACCESS IdSistemaInformatico                       INLINE ( hb_StrToUTF8( alltrim( ::cIdSistemaInformatico ) ) )
    ACCESS Version                                    INLINE ( hb_StrToUTF8( alltrim( ::cVersion ) ) )
    ACCESS NumeroInstalacion                          INLINE ( hb_StrToUTF8( alltrim( ::cNumeroInstalacion ) ) )
    ACCESS TipoUsoPosibleSoloVerifactu                INLINE ( hb_StrToUTF8( alltrim( ::cTipoUsoPosibleSoloVerifactu ) ) )
    ACCESS TipoUsoPosibleMultiOT                      INLINE ( hb_StrToUTF8( alltrim( ::cTipoUsoPosibleMultiOT ) ) )
    ACCESS IndicadorMultiplesOT                       INLINE ( hb_StrToUTF8( alltrim( ::cIndicadorMultiplesOT ) ) )
    //ACCESS NumeroOTAlta                               INLINE ( hb_StrToUTF8( alltrim( ::cNumeroOTAlta ) ) )
    ACCESS FechaHoraHusoGenRegistro                   INLINE ( hb_StrToUTF8( alltrim( ::cFechaHoraHusoGenRegistro ) ) )

    //ACCESS HoraGenRegistro                            INLINE ( hb_StrToUTF8( alltrim( ::cHoraGenRegistro ) ) )
    //ACCESS HusoHorarioGenRegistro                     INLINE ( hb_StrToUTF8( alltrim( ::cHusoHorarioGenRegistro ) ) )
    
    ACCESS NumRegistroAcuerdoFacturacion              INLINE ( hb_StrToUTF8( alltrim( ::cNumRegistroAcuerdoFacturacion ) ) )
    ACCESS IdAcuerdoSistemaInformatico                INLINE ( hb_StrToUTF8( alltrim( ::cIdAcuerdoSistemaInformatico ) ) )
    ACCESS TipoHuella                                 INLINE ( hb_StrToUTF8( alltrim( ::cTipoHuella ) ) )
    ACCESS Huella                                     INLINE ( alltrim( ::cHuella ) )
    ACCESS Signature                                  INLINE ( hb_StrToUTF8( alltrim( ::cSignature ) ) )
    

    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.


    // Guardan grupos de DATA repetititvos.
    METHOD AddFacturaRectificada( oFacturaRectificada ) INLINE ( AADD( ::aIDFacturaRectificada, oFacturaRectificada ) )
    METHOD AddFacturaSustituida( oFacturaSustituida )   INLINE ( AADD( ::aIDFacturaSustituida, oFacturaSustituida ) )
    METHOD AddIDDestinatario( oIDDestinatario )         INLINE ( AADD( ::aIDDestinatario, oIDDestinatario ) )
    METHOD AddaDetalleDesglose( oDetalleDesglose )      INLINE ( AADD( ::aDetalleDesglose, oDetalleDesglose ) )

ENDCLASS

//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS RegistroFactura

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS RegistroFactura

Local oXmlRegistroFactura
Local oXmlRegistroAlta
Local oXmlIDFactura
Local oXmlFacturasRectificadas
Local oXmlFacturasSustituidas
Local oXmlImporteRectificacion
Local oXmlTercero
Local oXmlIDOtro
Local oXmlDestinatarios
Local oXmlDesglose
Local oXmlEncadenamiento
Local oXmlRegistroAnterior
//Local oXmlIDEmisorFacturaRegistroAnterior
Local oXmlSistemaInformatico
Local oXmlSistemaInformatico_IDOtro
//Local oXmlDatosControl
Local nContador           := 0

    oXmlRegistroFactura := TxmlNode():New( HBXML_TYPE_TAG, "sum:RegistroFactura" )

    oXmlRegistroAlta := TxmlNode():New( HBXML_TYPE_TAG, "sum:RegistroAlta" )
    oXmlRegistroFactura:AddBelow( oXmlRegistroAlta )

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDVersion', , ::IDVersion() ) )

    // IDFactura
    oXmlIDFactura := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDFactura" )
    oXmlRegistroAlta:AddBelow( oXmlIDFactura )
    oXmlIDFactura:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFactura() ) )
    oXmlIDFactura:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFactura() ) )
    oXmlIDFactura:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFactura() ) )

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazonEmisor', , ::NombreRazonEmisor() ) )
    
    If .Not. Empty( ::cSubsanacion )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Subsanacion', , ::Subsanacion() ) )
    EndIf
    If .Not. Empty( ::cRechazoPrevio )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:RechazoPrevio', , ::RechazoPrevio() ) )
    EndIf
    
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoFactura', , ::TipoFactura() ) )
    If .Not. Empty( ::cTipoRectificativa )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoRectificativa', , ::TipoRectificativa() ) )
    EndIf

    // IDFacturaRectificada
    If .Not. Empty( ::aIDFacturaRectificada )
        oXmlFacturasRectificadas := TxmlNode():New( HBXML_TYPE_TAG, "sum1:FacturasRectificadas" )
        oXmlRegistroAlta:AddBelow( oXmlFacturasRectificadas )
        For nContador := 1 To Len( ::aIDFacturaRectificada )
            oXmlFacturasRectificadas:AddBelow( ::aIDFacturaRectificada[nContador]:ToXML() )
        End
    EndIf

    // IDFacturaSustituida
    If .Not. Empty( ::aIDFacturaSustituida )
        oXmlFacturasSustituidas := TxmlNode():New( HBXML_TYPE_TAG, "sum1:FacturasSustituidas" )
        oXmlRegistroAlta:AddBelow( oXmlFacturasSustituidas )
        For nContador := 1 To Len( ::aIDFacturaSustituida )
            oXmlFacturasSustituidas:AddBelow( ::aIDFacturaSustituida[nContador]:ToXML() )
        End
    EndIf

    // ImporteRectificacion
    If .Not. Empty( ::cBaseRectificada )
        oXmlImporteRectificacion := TxmlNode():New( HBXML_TYPE_TAG, "sum1:ImporteRectificacion" )
        oXmlRegistroAlta:AddBelow( oXmlImporteRectificacion )
        oXmlImporteRectificacion:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:BaseRectificada', , ::BaseRectificada() ) )
        oXmlImporteRectificacion:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRectificada', , ::CuotaRectificada() ) )
        If .not. Empty( ::cCuotaRecargoRectificado )
            oXmlImporteRectificacion:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRecargoRectificado', , ::CuotaRecargoRectificado() ) )
        EndIf
    EndIf
    
    If .not. Empty( ::cFechaOperacion )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaOperacion', , ::FechaOperacion() ) )
    EndIf

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:DescripcionOperacion', , ::DescripcionOperacion() ) )

    If .not. Empty( ::cFacturaSimplificadaArt7273 )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FacturaSimplificadaArt7273', , ::FacturaSimplificadaArt7273() ) )
    EndIf

    If .not. Empty( ::cFacturaSinIdentifDestinatarioArt61d )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FacturaSinIdentifDestinatarioArt61d', , ::FacturaSinIdentifDestinatarioArt61d() ) )
    EndIf

    If .not. Empty( ::cMacrodato )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Macrodato', , ::Macrodato() ) )
    EndIf

    // EmitidaPorTercerosODestinatario
    If .not. Empty( ::cEmitidaPorTercerosODestinatario )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:EmitidaPorTercerosODestinatario', , ::EmitidaPorTercerosODestinatario() ) )
        oXmlTercero := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Tercero" )
        oXmlRegistroAlta:AddBelow( oXmlTercero )
        oXmlTercero:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::Tercero_NombreRazon() ) )
        If .Not. Empty( ::cTercero_NIF )
            oXmlTercero:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::Tercero_NIF() ) )
        EndIf

        If .Not. Empty( ::cTercero_IDOtro_IDType )
            oXmlIDOtro := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDOtro" )
            oXmlTercero:AddBelow( oXmlIDOtro )
            If .Not. Empty( ::cTercero_IDOtro_CodigoPais )
                oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CodigoPais', , ::Tercero_IDOtro_CodigoPais() ) )
            EndIf
            oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDType', , ::Tercero_IDOtro_IDType() ) )
            oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ID', , ::Tercero_IDOtro_ID() ) )
        EndIf
    EndIf
    
    // IDDestinatario
    If .Not. Empty( ::aIDDestinatario )
        oXmlDestinatarios := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Destinatarios" )
        oXmlRegistroAlta:AddBelow( oXmlDestinatarios )
        For nContador := 1 To Len( ::aIDDestinatario )
            oXmlDestinatarios:AddBelow( ::aIDDestinatario[nContador]:ToXML() )
        End
    EndIf

    If .not. Empty( ::cCupon )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Cupon', , ::Cupon() ) )
    EndIf
    
    // Desglose
    oXmlDesglose := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Desglose" )
    oXmlRegistroAlta:AddBelow( oXmlDesglose )
    For nContador := 1 To Len( ::aDetalleDesglose )
        oXmlDesglose:AddBelow( ::aDetalleDesglose[nContador]:ToXML() )
    End

    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaTotal', , ::CuotaTotal() ) )
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ImporteTotal', , ::ImporteTotal() ) )
    
    // Encadenamiento
    oXmlEncadenamiento := TxmlNode():New( HBXML_TYPE_TAG, "sum1:Encadenamiento" )
    oXmlRegistroAlta:AddBelow( oXmlEncadenamiento )
    If .Not. Empty( ::cPrimerRegistro )
        oXmlEncadenamiento:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:PrimerRegistro', , ::PrimerRegistro() ) )
    EndIf

    If .Not. Empty( ::cIDEmisorFacturaRegistroAnterior )
        oXmlRegistroAnterior := TxmlNode():New( HBXML_TYPE_TAG, "sum1:RegistroAnterior" )
        oXmlEncadenamiento:AddBelow( oXmlRegistroAnterior )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFacturaRegistroAnterior() ) )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFacturaRegistroAnterior() ) )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFacturaRegistroAnterior() ) )
        oXmlRegistroAnterior:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Huella', , ::HuellaRegistroAnterior() ) )
    EndIf

    // SistemaInformatico
    oXmlSistemaInformatico := TxmlNode():New( HBXML_TYPE_TAG, "sum1:SistemaInformatico" )
    oXmlRegistroAlta:AddBelow( oXmlSistemaInformatico )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::SistemaInformatico_NombreRazon() ) )
    If .not. Empty( ::cSistemaInformatico_NIF )
        oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::SistemaInformatico_NIF() ) )
    EndIf
    If .not. Empty( ::cSistemaInformatico_IDOtro_IDType )
        oXmlSistemaInformatico_IDOtro := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDOtro" )
        oXmlSistemaInformatico:AddBelow( oXmlSistemaInformatico_IDOtro )
        If .not. Empty( ::cSistemaInformatico_IDOtro_CodigoPais )
            oXmlSistemaInformatico_IDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CodigoPais', , ::SistemaInformatico_IDOtro_CodigoPais() ) )
        EndIf
        oXmlSistemaInformatico_IDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDType', , ::SistemaInformatico_IDOtro_IDType() ) )
        oXmlSistemaInformatico_IDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ID', , ::SistemaInformatico_IDOtro_ID() ) )
    EndIf
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreSistemaInformatico', , ::NombreSistemaInformatico() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IdSistemaInformatico', , ::IdSistemaInformatico() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Version', , ::Version() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumeroInstalacion', , ::NumeroInstalacion() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoUsoPosibleSoloVerifactu', , ::TipoUsoPosibleSoloVerifactu() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoUsoPosibleMultiOT', , ::TipoUsoPosibleMultiOT() ) )
    oXmlSistemaInformatico:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IndicadorMultiplesOT', , ::IndicadorMultiplesOT() ) )
    
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaHoraHusoGenRegistro', , ::FechaHoraHusoGenRegistro() ) )

    If .Not. Empty( ::cNumRegistroAcuerdoFacturacion )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumRegistroAcuerdoFacturacion', , ::NumRegistroAcuerdoFacturacion() ) )
    EndIf
    If .Not. Empty( ::cIdAcuerdoSistemaInformatico )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IdAcuerdoSistemaInformatico', , ::IdAcuerdoSistemaInformatico() ) )
    EndIf
    
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoHuella', , ::TipoHuella() ) )
    oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Huella', , ::Huella() ) )
    If .Not. Empty( ::cSignature )
        oXmlRegistroAlta:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:Signature', , ::Signature() ) )
    EndIf

Return oXmlRegistroFactura

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS IDFacturaRectificada

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG IDFacturaRectificada
    DATA cIDEmisorFactura
    DATA cNumSerieFactura
    DATA cFechaExpedicionFactura


    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS IDEmisorFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFactura ) ) )
    ACCESS NumSerieFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFactura ) ) )
    ACCESS FechaExpedicionFactura          INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFactura ) ) )


    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS IDFacturaRectificada

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS IDFacturaRectificada

Local oXmlIDFacturaRectificada

    oXmlIDFacturaRectificada := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDFacturaRectificada" )

    oXmlIDFacturaRectificada:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFactura() ) )
    oXmlIDFacturaRectificada:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFactura() ) )
    oXmlIDFacturaRectificada:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFactura() ) )

Return oXmlIDFacturaRectificada

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS IDFacturaSustituida

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG IDFacturaSustituida
    DATA cIDEmisorFactura
    DATA cNumSerieFactura
    DATA cFechaExpedicionFactura


    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.
    ACCESS IDEmisorFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cIDEmisorFactura ) ) )
    ACCESS NumSerieFactura                 INLINE ( hb_StrToUTF8( alltrim( ::cNumSerieFactura ) ) )
    ACCESS FechaExpedicionFactura          INLINE ( hb_StrToUTF8( alltrim( ::cFechaExpedicionFactura ) ) )


    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS IDFacturaSustituida

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS IDFacturaSustituida

Local oXmlIDFacturaSustituida

    oXmlIDFacturaSustituida := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDFacturaSustituida" )

    oXmlIDFacturaSustituida:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDEmisorFactura', , ::IDEmisorFactura() ) )
    oXmlIDFacturaSustituida:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NumSerieFactura', , ::NumSerieFactura() ) )
    oXmlIDFacturaSustituida:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:FechaExpedicionFactura', , ::FechaExpedicionFactura() ) )


Return oXmlIDFacturaSustituida

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS IDDestinatario

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG IDDestinatario  -- >> Fins a 1000
    DATA cNombreRazon
    DATA cNIF
    DATA oXmlIDOtro
        // Dades pel TAG IDOtro
        DATA cCodigoPais
        DATA cIDType
        DATA cID

    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS NombreRazon                      INLINE ( hb_StrToUTF8( alltrim( ::cNombreRazon ) ) )
    ACCESS NIF                              INLINE ( hb_StrToUTF8( alltrim( ::cNIF ) ) )
    ACCESS CodigoPais                       INLINE ( hb_StrToUTF8( alltrim( ::cCodigoPais ) ) )
    ACCESS IDType                           INLINE ( hb_StrToUTF8( alltrim( ::cIDType ) ) )
    ACCESS ID                               INLINE ( hb_StrToUTF8( alltrim( ::cID ) ) )


    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS IDDestinatario

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS IDDestinatario

Local oXmlIDDestinatario
Local oXmlIDOtro

    oXmlIDDestinatario := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDDestinatario" )

    oXmlIDDestinatario:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NombreRazon', , ::NombreRazon() ) )
    If .Not. Empty( ::cNIF )
        oXmlIDDestinatario:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:NIF', , ::NIF() ) )
    EndIf

    If .Not. Empty( ::cIDType )
        oXmlIDOtro := TxmlNode():New( HBXML_TYPE_TAG, "sum1:IDOtro" )
        oXmlIDDestinatario:AddBelow( oXmlIDOtro )
        If .Not. Empty( ::cCodigoPais )
            oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CodigoPais', , ::CodigoPais() ) )
        EndIf
        oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:IDType', , ::IDType() ) )
        oXmlIDOtro:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ID', , ::ID() ) )
    EndIf

Return oXmlIDDestinatario

/* ***************************************************************************** */
/* ***************************************************************************** */
/* ***************************************************************************** */

CLASS DetalleDesglose

    // Declaració de les DATA a on s'assignaran els valors a capturar.
    // Totes les DATA es gestionaran en modus caràcter o objectes XML.

    // Dades pel TAG DetalleDesglose  -- >> Fins a 12
    DATA cClaveRegimen
    DATA cCalificacionOperacion
    DATA cOperacionExenta
    DATA cTipoImpositivo
    DATA cBaseImponibleOimporteNoSujeto
    DATA cBaseImponibleACoste
    DATA cCuotaRepercutida
    DATA cTipoRecargoEquivalencia
    DATA cCuotaRecargoEquivalencia
    
    
    // ACCESS a les DATA per tal de ser usades.
    // De momento se aplica la conversión a UTF8, excepto a las huellas.   
    ACCESS ClaveRegimen                          INLINE ( hb_StrToUTF8( alltrim( ::cClaveRegimen ) ) )
    ACCESS CalificacionOperacion                 INLINE ( hb_StrToUTF8( alltrim( ::cCalificacionOperacion ) ) )
    ACCESS OperacionExenta                       INLINE ( hb_StrToUTF8( alltrim( ::cOperacionExenta ) ) )
    ACCESS TipoImpositivo                        INLINE ( hb_StrToUTF8( alltrim( ::cTipoImpositivo ) ) )
    ACCESS BaseImponibleOimporteNoSujeto         INLINE ( hb_StrToUTF8( alltrim( ::cBaseImponibleOimporteNoSujeto ) ) )
    ACCESS BaseImponibleACoste                   INLINE ( hb_StrToUTF8( alltrim( ::cBaseImponibleACoste ) ) )
    ACCESS CuotaRepercutida                      INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRepercutida ) ) )
    ACCESS TipoRecargoEquivalencia               INLINE ( hb_StrToUTF8( alltrim( ::cTipoRecargoEquivalencia ) ) )
    ACCESS CuotaRecargoEquivalencia              INLINE ( hb_StrToUTF8( alltrim( ::cCuotaRecargoEquivalencia ) ) )
    

    // Métodes per gestionar la classe.

    METHOD New() CONSTRUCTOR
    METHOD ToXML()      //  Genera estructura XML con los datos.

ENDCLASS
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//

METHOD New( ) CLASS DetalleDesglose

Return ( self )

//---------------------------------------------------------------------------//

METHOD ToXML() CLASS DetalleDesglose

Local oXmlDetalleDesglose

    oXmlDetalleDesglose := TxmlNode():New( HBXML_TYPE_TAG, "sum1:DetalleDesglose" )

    oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:ClaveRegimen', , ::ClaveRegimen() ) )

    //If .Not. Empty( ::cCalificacionOperacion )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CalificacionOperacion', , ::CalificacionOperacion() ) )
    //EndIf
    If .Not. Empty( ::cOperacionExenta )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:OperacionExenta', , ::OperacionExenta() ) )
    EndIf
    If .Not. Empty( ::cTipoImpositivo )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoImpositivo', , ::TipoImpositivo() ) )
    EndIf
    oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:BaseImponibleOimporteNoSujeto', , ::BaseImponibleOimporteNoSujeto() ) )
    If .Not. Empty( ::cBaseImponibleACoste )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:BaseImponibleACoste', , ::BaseImponibleACoste() ) )
    EndIf
    If .Not. Empty( ::cCuotaRepercutida )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRepercutida', , ::CuotaRepercutida() ) )
    EndIf
    If .Not. Empty( ::cTipoRecargoEquivalencia )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:TipoRecargoEquivalencia', , ::TipoRecargoEquivalencia() ) )
    EndIf
    If .Not. Empty( ::cCuotaRecargoEquivalencia )
        oXmlDetalleDesglose:AddBelow( TxmlNode():New( HBXML_TYPE_TAG, 'sum1:CuotaRecargoEquivalencia', , ::CuotaRecargoEquivalencia() ) )
    EndIf

Return oXmlDetalleDesglose
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//
 
Como las utilizo:

Code: Select all | Expand


........
    oXmlVerifactu := TVeriFactu00():New()

    oXmlVerifactu:cObligadoEmision_NombreRazon := cGetNomampa( AMPAARRA )
    oXmlVerifactu:cObligadoEmision_NIF         := cGetNifBD( AMPAARRA )
    // oXmlVerifactu:cFechaFinVeriFactu           :=  No l'utilitzo  01/08/2024
    // oXmlVerifactu:cIncidencia                  := "T0"
    // oXmlVerifactu:cRefRequerimiento            := Aquí no.


    While oTdbfFacAlb:Locate( , , lRestFacAlb) .and. .Not. oTdbfFacAlb:CheckEofBof( ):Eof

        lRestFacAlb := .T.
        
        If oTdbfFacAlb:Deleted(); Loop; EndIf
        
        oTdbfFacAlb:Load()

        msgnowait( AMPAarra, GetTrad( "Factura:" ) + Str( oTdbfFacAlb:NumeFact, 10, 0) + "-" + AllTrim(oTdbfFacAlb:RAOSOC), GetTrad( "Generant XML per a Verifactu de les Factures emeses...") )

        Traza( 1, GetTrad( "Factura:" ) + Str( oTdbfFacAlb:NumeFact, 10, 0) + "-" + + DToc( oTdbfFacAlb:DataFact) + "-" + AllTrim(oTdbfFacAlb:RAOSOC) )

        oXMLRegistroFactura := RegistroFactura():New()

        lSetXMLRegistroFactura( AMPAARRA, ;
                                oXMLRegistroFactura, ;
                                oTdbfFacAlb, ;
                                oTDbfFactur, ;
                                oTDbfFacAlbDummy, ;
                                lPrimerTractament, ;
                                @nRecnoAnterior, ;
                                @cIdFacturAnterior, ;
                                cNumSerieFacturaRegistroAnteriorDummy, ;
                                cFechaExpedicionFacturaRegistroAnteriorDummy, ;
                                cHuellaRegistroAnteriorDummy ;
                               )
..........
 
La función:
FUNCTION lSetXMLRegistroFactura( AMPAARRA, ;
                                 oXMLRegistroFactura, ;
                                 oTdbfFacAlb, ;
                                 oTDbfFactur, ;
                                 oTDbfFacAlbDummy, ;
                                 lPrimerTractament, ;
                                 nRecnoAnterior, ;
                                 cIdFacturAnterior, ;
                                 cNumSerieFacturaRegistroAnteriorDummy, ;
                                 cFechaExpedicionFacturaRegistroAnteriorDummy, ;
                                 cHuellaRegistroAnteriorDummy ;
                               )

// Seteja els valors de un objecte oXMLRegistroFactura.

Local lRespuesta          := .T.
Local oXmlIDDestinatario  := Nil
Local oXmlDetalleDesglose := Nil

        oXMLRegistroFactura:cIDVersion                   := "1.0"

        oXMLRegistroFactura:cIDEmisorFactura                            := cGetNifBD( AMPAARRA )
        oXMLRegistroFactura:cNumSerieFactura                            := Str( Year( oTdbfFacAlb:DataFact), 4, 0) + "-000-" + Right( Str( 1000000 + oTdbfFacAlb:NumeFact, 10, 0), 6)
        oXMLRegistroFactura:cFechaExpedicionFactura                     := hb_dtoc( oTdbfFacAlb:DataFact, "dd-mm-yyyy" )     //  DToc( oTdbfFacAlb:DataFact )
        oXMLRegistroFactura:cNombreRazonEmisor                          := cGetNomampa( AMPAARRA )
        //oXMLRegistroFactura:cTipoRegistroSIF                            := "S0"
        oXMLRegistroFactura:cTipoFactura                                := "F1"
        //oXMLRegistroFactura:cTipoRectificativa                          :=
        //oXMLRegistroFactura:cBaseRectificada                            :=
        //oXMLRegistroFactura:cCuotaRectificada                           :=
        //oXMLRegistroFactura:cCuotaRecargoRectificado                    :=
        //oXMLRegistroFactura:cFechaOperacion                             := hb_dtoc( oTdbfFacAlb:DataFact, "dd-mm-yyyy" )  //  DToc( oTdbfFacAlb:DataFact )   No cal al ser igual que la data d'expedició
        oXMLRegistroFactura:cDescripcionOperacion                       := "Prestación de servicios."
        oXMLRegistroFactura:cFacturaSimplificadaArt7273                 := "N"
        oXMLRegistroFactura:cFacturaSinIdentifDestinatarioArt61d        := "N"
        oXMLRegistroFactura:cMacrodato                                  := "N"
        //oXMLRegistroFactura:cEmitidaPorTercerosODestinatario            :=   No cal
        //oXMLRegistroFactura:cTercero_NombreRazon                        :=
        //oXMLRegistroFactura:cTercero_NIF                                :=
        //oXMLRegistroFactura:cTercero_IDOtro_CodigoPais                  :=
        //oXMLRegistroFactura:cTercero_IDOtro_IDType                      :=
        //oXMLRegistroFactura:cTercero_IDOtro_ID                          :=
       
        oXmlIDDestinatario := IDDestinatario():New()
        oXMLRegistroFactura:AddIDDestinatario( oXmlIDDestinatario )
        oXmlIDDestinatario:cNombreRazon                                      := oTdbfFacAlb:RAOSOC
        oXmlIDDestinatario:cNIF                                              := oTdbfFacAlb:NIF
        //oXmlIDDestinatario:cCodigoPais                                       :=
        //oXmlIDDestinatario:cIDType                                           :=
        //oXmlIDDestinatario:cID                                               :=

        oXMLRegistroFactura:cCupon                                      := "N"

        //Traza( 1, "oTdbfFacAlb:IdFactur=", oTdbfFacAlb:IdFactur )

        nGotoFacturIdFactur( AMPAarra, oTDbfFactur, AllTrim( oTdbfFacAlb:IdFactur ) + "-4", .T., .T., 1 )
        // IVA deduible
            oXmlDetalleDesglose := DetalleDesglose():New()
            oXMLRegistroFactura:AddaDetalleDesglose( oXmlDetalleDesglose )
            oXmlDetalleDesglose:cClaveRegimen                                   := "01"
            oXmlDetalleDesglose:cCalificacionOperacion                          := "S1"
            // oXmlDetalleDesglose:cOperacionExenta                                :=
            oXmlDetalleDesglose:cTipoImpositivo                                 := Alltrim( TransForm( oTDbfFactur:PERCENTA, "999.99" ) )
            oXmlDetalleDesglose:cBaseImponibleOimporteNoSujeto                  := Alltrim( TransForm( oTDbfFactur:BASECALC, "999999999999.99" ) )
            //oXmlDetalleDesglose:cBaseImponibleACoste                             :=
            oXmlDetalleDesglose:cCuotaRepercutida                                := Alltrim( TransForm( oTDbfFactur:IMPORT__, "999999999999.99" ) )
            //oXmlDetalleDesglose:cTipoRecargoEquivalencia                         :=
            //oXmlDetalleDesglose:cCuotaRecargoEquivalencia                        :=

        oXMLRegistroFactura:cCuotaTotal                                 := Alltrim( TransForm( oTDbfFactur:IMPORT__, "999999999999.99" ) )

        oXMLRegistroFactura:cImporteTotal                               := Alltrim( TransForm( oTDbfFacAlb:IMPOTOTA, "999999999999.99" ) )

        //nGotoFaAl( AMPAarra, oTDbfFacAlbDummy, oTDbfFacAlb:NumeFact, .T., .T., 1, Nil, Nil )

        /* Com que es poden tractar vàries factures per generar el XML, fins que no s'envia amb certesa
           els registres de oTDbfFacAlb no s'enregistren les Huella; per tant ha de ser en aquest bucle
           que es vagi 'traspassant' el valor de HuellaAnterior d'un registre al següent.
        */
        If lPrimerTractament
            // Es cerca a oTdbfFacAlb el registre que serà l'Anterior al tractat ara.
            If cGetLastIdFactur( AMPAARRA, oTdbfFacAlbDummy ) = ""
                oXMLRegistroFactura:cPrimerRegistro                         := "S"
                oXMLRegistroFactura:cHuellaRegistroAnterior                 := ""
                //Traza( 1 , "cIdFacturAnterior= cGetLastIdFactur() no trovat",)
              Else
                nRecnoAnterior    := oTdbfFacAlbDummy:Recno()
                cIdFacturAnterior := oTdbfFacAlbDummy:IdFactur
                //Traza( 1 , "cIdFacturAnterior=", cIdFacturAnterior)
                oXMLRegistroFactura:cIDEmisorFacturaRegistroAnterior        := cGetNifBD( AMPAARRA )
                oXMLRegistroFactura:cNumSerieFacturaRegistroAnterior        := Str( Year( oTdbfFacAlbDummy:DataFact), 4, 0) + "-000-" + Right( Str( 1000000 + oTdbfFacAlbDummy:NumeFact, 10, 0), 6)
                oXMLRegistroFactura:cFechaExpedicionFacturaRegistroAnterior := hb_dtoc( oTdbfFacAlbDummy:DataFact, "dd-mm-yyyy" )
                oXMLRegistroFactura:cHuellaRegistroAnterior                 := oTdbfFacAlbDummy:HuellaVF
            EndIf

          Else
            // oXMLRegistroFactura:cPrimerRegistro  està buit.
            oXMLRegistroFactura:cIDEmisorFacturaRegistroAnterior        := cGetNifBD( AMPAARRA )
            oXMLRegistroFactura:cNumSerieFacturaRegistroAnterior        := cNumSerieFacturaRegistroAnteriorDummy
            oXMLRegistroFactura:cFechaExpedicionFacturaRegistroAnterior := cFechaExpedicionFacturaRegistroAnteriorDummy
            oXMLRegistroFactura:cHuellaRegistroAnterior                 := cHuellaRegistroAnteriorDummy
        EndIf

        //Traza( 1, "a-nRecnoAnterior=", nRecnoAnterior )

        oXMLRegistroFactura:cSistemaInformatico_NombreRazon             := cVerifactuSINombreRazon( AMPAARRA )
        oXMLRegistroFactura:cSistemaInformatico_NIF                     := cVeriFactuSINif( AMPAARRA )
        //oXMLRegistroFactura:cSistemaInformatico_IDOtro_CodigoPais       :=
        //oXMLRegistroFactura:cSistemaInformatico_IDOtro_IDType           :=
        //oXMLRegistroFactura:cSistemaInformatico_IDOtro_ID               :=
        oXMLRegistroFactura:cNombreSistemaInformatico                   := cVeriFactuSINombreSistemaInformatico( AMPAARRA )
        oXMLRegistroFactura:cIdSistemaInformatico                       := cVeriFactuSIIdSistemaInformatico( AMPAARRA )
        oXMLRegistroFactura:cVersion                                    := cVeriFactuSIVersion( AMPAARRA )
        oXMLRegistroFactura:cNumeroInstalacion                          := cVeriFactuSINumeroInstalacion( AMPAARRA )
        oXMLRegistroFactura:cTipoUsoPosibleSoloVerifactu                := cVeriFactuSIPosibleSoloVerifactu( AMPAARRA )
        oXMLRegistroFactura:cTipoUsoPosibleMultiOT                      := cVeriFactuSITipoUsoPosibleMultiOT( AMPAARRA )
        oXMLRegistroFactura:cIndicadorMultiplesOT                       := cVeriFactuSIIndicadorMultiplesOT( AMPAARRA )

        //oXMLRegistroFactura:cNumeroOTAlta                               := "1"

        oXMLRegistroFactura:cFechaHoraHusoGenRegistro                   := FechaHoraHuso( oTdbfFacAlb:DataAlta, oTdbfFacAlb:HoraAlta )
       
        //oXMLRegistroFactura:cHoraGenRegistro                            := oTdbfFacAlb:HoraAlta
        //oXMLRegistroFactura:cHusoHorarioGenRegistro                     := "02"
       
       
       
        //oXMLRegistroFactura:cNumRegistroAcuerdoFacturacion              := De moment no.
        //oXMLRegistroFactura:cIdAcuerdoSistemaInformatico                := De moment no.

        oXMLRegistroFactura:cTipoHuella                                := "01"
        oXMLRegistroFactura:cHuella                                    := hb_VerifactuHuella( cGetNifBD( AMPAARRA ), ;
                                                                                              Str( Year( oTdbfFacAlb:DataFact), 4, 0) + "-000-" + Right( Str( 1000000 + oTdbfFacAlb:NumeFact, 10, 0), 6), ;
                                                                                              oTdbfFacAlb:DataFact, ;
                                                                                              "F1", ;
                                                                                              oTDbfFactur:IMPORT__, ;
                                                                                              oTDbfFacAlb:IMPOTOTA, ;
                                                                                              oXMLRegistroFactura:cHuellaRegistroAnterior, ;
                                                                                              FechaHoraHuso( oTdbfFacAlb:DataAlta, oTdbfFacAlb:HoraAlta ) ;
                                                                                            )

        //oXMLRegistroFactura:cSignature                                 := No cal aquí

Return lRespuesta[/code]
Yo también lo estoy montando así, pero voy un paso más allá, en vez de asignar los datos en INLINE o ACCESS lo hago mediante una clase que comprueba si el dato es correcto. Esto es un currazo del trece pero monto la clase a partir del XSD que tiene todas las especificaciones, de este modo me aseguro que el xml creado va a ser válido .

esto sería la clase que gestiona el tipo simple de ticket bai ClaveTupoFacturaType:

Code: Select all | Expand

// CLASS: TClaveTipoFacturaType 
#include 'hbclass.ch'
#include "TicketBai.inc"
            
CREATE CLASS TTB_ClaveTipoFacturaType  FROM TTB_Common
            
    EXPORTED:
        METHOD New( oTicketBai, lRequired, cTag, oFather ) CONSTRUCTOR
        METHOD Get()
        METHOD Set( uData ) 
        METHOD Check( uData )
        METHOD BuildXml( oFather )
        METHOD HasData()
        DATA __cTag AS STRING INIT ''
        DATA oFather AS OBJECT INIT Nil
            
    PROTECTED:
        DATA __ClaveTipoFacturaType AS STRING INIT ""
        DATA __oTicketBai AS OBJECT INIT NIL
        DATA __lRequired AS LOGICAL INIT .F.
        DATA __lDataSet AS LOGICAL INIT .F.

        METHOD Convert( uData )
            
ENDCLASS
            
METHOD New( oTicketBai, lRequired, cTag, oFather ) CLASS TTB_ClaveTipoFacturaType 

    hb_default( @lRequired, .F. )
    hb_default( @cTag, 'ClaveTipoFacturaType' )

    ::__oTicketBai := oTicketBai
    ::__lRequired := lRequired
    ::__cTag := cTag
    ::oFather := oFather
            
Return ( Self )
            
METHOD Set( uData ) CLASS TTB_ClaveTipoFacturaType 

    uData := ::Convert( uData )

    If ::Check( uData )
            
        ::__ClaveTipoFacturaType := uData
        ::__lDataSet := .T.

    Endif
            
Return ( Self )  

METHOD HasData() CLASS TTB_ClaveTipoFacturaType 
Return( ::__lDataSet )


METHOD Convert( uData ) CLASS TTB_ClaveTipoFacturaType 

    switch ValType( uData )

        case 'C'

            uData := Alltrim( uData )  // TODO: Revisar si hay que mantener espacios o no

        exit

    endswitch

Return( uData )

METHOD Get() CLASS TTB_ClaveTipoFacturaType 
Return ( ::__ClaveTipoFacturaType )

METHOD Check( uData ) CLASS TTB_ClaveTipoFacturaType 

    hb_default( @uData, ::__ClaveTipoFacturaType )

    If .Not. HB_ISSTRING( uData )

        ::__oTicketBai:__oReturn:Success := .F.
        ::__oTicketBai:__oReturn:Log := 'El dato ' + uData:Str() + ' Codigo no es del tipo string para ' + ::Tags()
        Return ( .F. )
            
    Endif

    If ::__lRequired .And. Len(Alltrim(( uData ))) == 0
            
        ::__oTicketBai:__oReturn:Success := .F.
        ::__oTicketBai:__oReturn:Log := 'El dato ' + uData:Str() + ' Codigo es requerido para ' + ::Tags()
        Return ( .F. )
    
    Endif

    If hb_AScan( { 'R1','R2','R3','R4','R5' } , uData ) == 0

        ::__oTicketBai:__oReturn:Success := .F.
        ::__oTicketBai:__oReturn:Log := 'El dato ' + uData:Str() + ' no se encuentra en la lista de datos permitidos de ClaveTipoFactura para ' + ::Tags()
        Return ( .F. )

    Endif

Return ( .T. )

METHOD BuildXml( oFather) CLASS TTB_ClaveTipoFacturaType 
    
    If ::HasData()
    
        oFather:NewChild( ::__cTag, hb_ValToStr( ::__ClaveTipoFacturaType ) )

    Endif

Return  ( Self )
 
Lo que tengo es un grupo de clases simples y "complex", las complex utilizan las simples, esta sería una clase complex:

Code: Select all | Expand

// Clase creada el 05/30/24 15:07:56    
#include 'hbclass.ch'
#include "TicketBai.inc"
    
CREATE CLASS TTB_FacturaRectificativaType 
    
    EXPORTED:
        METHOD New( oTicketBai, lRequired, cTag, oFather ) CONSTRUCTOR 
        METHOD BuildXml( oFather )
        METHOD Check()
        METHOD HasData()


        DATA Codigo AS OBJECT INIT Nil
        DATA Tipo AS OBJECT INIT Nil
        DATA ImporteRectificacionSustitutiva AS OBJECT INIT Nil
        DATA __cTag AS STRING INIT 'FacturaRectificativa'
        DATA oFather AS OBJECT INIT Nil

    PROTECTED:
        METHOD Init()   

        DATA __lRequired AS LOGICAL INIT .F.
        DATA __oTicketBai AS OBJECT INIT Nil

            

ENDCLASS
    
METHOD New( oTicketBai, lRequired, cTag, oFather ) CLASS TTB_FacturaRectificativaType

    hb_default( @lRequired, .F. )
    hb_default( @cTag, ::__cTag )
    

    ::__oTicketBai := oTicketBai
    ::__cTag := cTag
    ::oFather := oFather
    ::__lRequired := lRequired
    ::Init()
    
Return ( Self )
    
METHOD Init() CLASS TTB_FacturaRectificativaType

    ::Codigo := TTB_ClaveTipoFacturaType():New( ::__oTicketBai, REQUIRED, "Codigo",Self )
    ::Tipo := TTB_ClaveTipoRectificativaType():New( ::__oTicketBai, REQUIRED, "Tipo",Self )
    ::ImporteRectificacionSustitutiva := TTB_ImporteRectificacionSustitutivaType():New( ::__oTicketBai, OPTIONAL, "ImporteRectificacionSustitutiva",Self )

Return ( Self )
    
METHOD BuildXml( oFather ) CLASS TTB_FacturaRectificativaType
    
    Local oChild as Object := Nil
    Local cXml as String := ""

    If ::Codigo:HasData() .Or.;
       ::Tipo:HasData() .Or.;
       ::ImporteRectificacionSustitutiva:HasData()

        oChild := oFather:NewChild( ::__cTag,"")

        ::Codigo:BuildXml( oChild )
        ::Tipo:BuildXml( oChild )
        ::ImporteRectificacionSustitutiva:BuildXml( oChild )

    Endif
    
Return ( Self )

METHOD Check() CLASS TTB_FacturaRectificativaType


    ::Codigo:Check()
    ::Tipo:Check()
    ::ImporteRectificacionSustitutiva:Check()

Return ( Self )

METHOD HasData() CLASS TTB_FacturaRectificativaType

    Local lHasData as Logical := .F.

    lHasData := Iif( ::Codigo:HasData(), .T., lHasData)
    lHasData := Iif( ::Tipo:HasData(), .T., lHasData)
    lHasData := Iif( ::ImporteRectificacionSustitutiva:HasData(), .T., lHasData)

Return ( lHasData )


 
todas las clases tienen un método BuildXml() que devuelve el tag en sí, y para crear el XML simplemente ejecuto el método BuildXml de la clase superior, esta desencadena el BuildXml de cada dato que contiene, y así con todos las clases en cascada. Esto me genera un XML 100% chequeado con las validaciones del XSD inicial.

Puede parecer una locura de estructura de clases, pero me da mucha robustez en el proceso de creación, y cuando hay que revisar/modificar algo, está todo muy aislado, así lo hago también con la factura electrónica.

Yo continúo trasteando con el wsdl para poder montar esta estructura de clases automáticamente. Si lo llego a descifrar, pondré aquí las claves por si alguien quiere hacerlo también.

Salud!
--------
¿ Y porque no ?
¿ And why not ?
User avatar
VictorCasajuana
Posts: 268
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs
Contact:

Re: España: Normativa sancionadora sistemas informáticos

Post by VictorCasajuana »

Garbi wrote:
Yo creo que esperan agazapados a ver si alguien se lo resuelve. Lo de ponerse a colaborar no van con ellos
Paquito, por tu experiencia puedes que tengas razón, pero yo muchas veces he recibido ayuda, más o menos me han servido pero siempre han contestado. Pero tengo que decir que sin tu colaboración yo ya estaría más que perdido.

Te pongo lo que me da con la prueba de calidad de datos identificativos: Creo que el problema es mi certificado, no se si al exportarlo no lo he hecho bien. Lo volveré a exportar y generar los .pem con tu convert.bat y a ver si ya lo consigo por fin. Pero ya el jueves, que mañana en Valencia es fiesta aunque tendré todo el día en la cabeza el tema, seguro.

Code: Select all | Expand

Curl.Exe -k --connect-timeout 60 -m 300 -s -S -L --header "Content-Type: text/xml;charset=UTF-8" --cert "jose1234.pem" --key "jose1234_key.Pem" --data Nif.xml https://www1.agenciatributaria.gob.es/wlpl/BURT-JDIT/ws/VNifV2SOAP --output Nif_Respuesta_3754552.xml -v
* Host www1.agenciatributaria.gob.es:443 was resolved.
* IPv6: (none)
* IPv4: 195.77.198.17
*   Trying 195.77.198.17:443...
* Connected to www1.agenciatributaria.gob.es (195.77.198.17) port 443
* schannel: disabled automatic use of client certificate
* schannel: Failed to import cert file jose1234.pem, last error is 0x80092002
* Closing connection
curl: (58) schannel: Failed to import cert file jose1234.pem, last error is 0x80092002

Bueno he tenido tiempo de hacerlo ahora, lo he exportado desde opciones de internet el certificado y lo he convertido y hay algo que no hago bien porque me ha el mismo error al hacer el curl, falla al importar el certificado.

Un saludo.
Hombre!, también de "la terreta", estamos cerca. A ver si quedamos un día y tomamos un café o hacemos un "esmorzaret" :D
--------
¿ Y porque no ?
¿ And why not ?
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: España: Normativa sancionadora sistemas informáticos

Post by paquitohm »

Yo continúo trasteando con el wsdl para poder montar esta estructura de clases automáticamente. Si lo llego a descifrar, pondré aquí las claves por si alguien quiere hacerlo también.
No sé si habrás visto que Xmlspy puede generar toda la jerarquia de clases para un esquema en Java, C# y C++
Es una pasada.

El más cercano a lo "nuestro" evidentemente es C++, pero ya me imagino que habría que hacer un montonazo de wrappers y al final las gallinas que entran por las que salen
User avatar
VictorCasajuana
Posts: 268
Joined: Wed Mar 28, 2018 4:38 pm
Location: Vinaròs
Contact:

Re: España: Normativa sancionadora sistemas informáticos

Post by VictorCasajuana »

paquitohm wrote:
Yo continúo trasteando con el wsdl para poder montar esta estructura de clases automáticamente. Si lo llego a descifrar, pondré aquí las claves por si alguien quiere hacerlo también.
No sé si habrás visto que Xmlspy puede generar toda la jerarquia de clases para un esquema en Java, C# y C++
Es una pasada.

El más cercano a lo "nuestro" evidentemente es C++, pero ya me imagino que habría que hacer un montonazo de wrappers y al final las gallinas que entran por las que salen
si, ese software es un mundo, no obstante cuando le cargo el wsdl de VeriFactu, me marca error sobre etiquetas que no existen, y eso modificando antes las url que no enlazan a ninguna parte. Por lo que considero que el wsdl está incompleto ( ya ponen que es todo versiones 0. en modo borrado ) por lo que de momento, solo estoy "jugando" y haciendo pruebas, nada de montar algo ya que van a modificar cosas, seguro.
--------
¿ Y porque no ?
¿ And why not ?
Garbi
Posts: 344
Joined: Wed Nov 02, 2005 3:28 pm

Re: España: Normativa sancionadora sistemas informáticos

Post by Garbi »

Hola Paquito,
Con la curl que me has indicado que si que he podido enviar y recibir una respuesta, que por supuesto me da error como respuesta porque es un ejemplo sin datos validos.
Muchísimas gracias por tu aporte.

Tengo una consulta que me ha preguntado el jefe para todos:
Si montamos el sistema Veri*Factu lo que es la programación de los programas actuales que tenemos de facturación ( en total son 4) por que nuestro trabajo principal es otro, no hay que controlar que no se puedan modificar facturas, registro de las modificaciones de facturas,etc ¿Correcto?

Voy a seguir revisando los aportes de Victor y Carlos para poder montar .xml y espero que se una más gente.
Pero hay algo que no tengo claro, si debe ser 9 meses desde su aprobación, si no esta todavía reglamentado todo como indica Victor, entonces que pasa con la entrada en vigor del 1 de julio de 2025
Saludos,
Regards,

Jose Luis Alepuz
joseluis@mancomputer.com
www.mancomputer.com
Post Reply