Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Envío de registros y sus respuestas (https://www.clubdelphi.com/foros/forumdisplay.php?f=66)
-   -   Demo con código Verifactu.dll para (delphi 7) (https://www.clubdelphi.com/foros/showthread.php?t=97004)

seccion_31 11-11-2024 12:15:40

Demo con código Verifactu.dll para (delphi 7)
 
He actualizado la demo para enviar y procesar registros

Enviar registros desde Excel
Prmite obtener el codigo QR
Validar la respuesta
Validar el QR

https://github.com/seccion31/verifactu-delphi-demo

Saludos !

Neftali [Germán.Estévez] 11-11-2024 13:37:53

Gracias por en código.
He "fijado" el hilo al inicio del foro.
Actualizo el mensaje#2 con la recopilación de códigos y subo también el ejemplo al FTP del club (v2).

muli 11-11-2024 17:06:12

Gracias a DEMO DE ENVIOS
 
Gran aporte realizado por Seccion_31, y gran idea de Germán de crear un tema especifico para estos aportes, justamente había estado estudiando el anterior aporte de Seccion_31 durante el fin de semana, y ahora me encuentro con estas mejoras, vamos a seguir estudiando, es más ameno leer tu codigo fuente que los manuales de la agencia tributaria, he leido también por ahí el tema de los tiempos de envios, o sea, en un bar que hay momentos que se generan tickets cada dos por tres y desde varios puestos, me pregunto se podrían seleccionar todos las ventas en un tiempo, digamos una hora, y enviarlos todos juntos, tal y como se puede hacer en la propuesta de Seccion_31, es una idea, se van generando las huellas de todos los registros y una vez cada hora por ejemplo, se hace una búsqueda de todas las ventas y venga hacia la agencia tributaria, el problema lo tenemos en los códigos QR, que no tenemos las respuestas.

Saludos. Y Gracias a todos por vuestros aportes.

newtron 11-11-2024 17:23:10

Cita:

Empezado por muli (Mensaje 559593)
Gran aporte realizado por Seccion_31, y gran idea de Germán de crear un tema especifico para estos aportes, justamente había estado estudiando el anterior aporte de Seccion_31 durante el fin de semana, y ahora me encuentro con estas mejoras, vamos a seguir estudiando, es más ameno leer tu codigo fuente que los manuales de la agencia tributaria, he leido también por ahí el tema de los tiempos de envios, o sea, en un bar que hay momentos que se generan tickets cada dos por tres y desde varios puestos, me pregunto se podrían seleccionar todos las ventas en un tiempo, digamos una hora, y enviarlos todos juntos, tal y como se puede hacer en la propuesta de Seccion_31, es una idea, se van generando las huellas de todos los registros y una vez cada hora por ejemplo, se hace una búsqueda de todas las ventas y venga hacia la agencia tributaria, el problema lo tenemos en los códigos QR, que no tenemos las respuestas.

Saludos. Y Gracias a todos por vuestros aportes.


Hay que hacer los envíos según se van generando los documentos si no quieres tener problemas, eso creo que ya lo tenemos claro.


saludos.

Neftali [Germán.Estévez] 12-11-2024 08:15:35

Cita:

Empezado por muli (Mensaje 559593)
Gran aporte realizado por Seccion_31,




Al igual, que una pregunta nueva requiere un hilo nuevo, lo normal es que si vamos a hacer referencia a un hilo ya creado, continuemos con ese hilo.
Junto este con el original de [Seccion_31] sobre su aporte.

jalvar28 14-11-2024 14:08:14

Error en la demo
 
1 Archivos Adjunto(s)
Cita:

Empezado por seccion_31 (Mensaje 559557)
He actualizado la demo para enviar y procesar registros

Enviar registros desde Excel
Prmite obtener el codigo QR
Validar la respuesta
Validar el QR

https://github.com/seccion31/verifactu-delphi-demo

Saludos !

Buenos días.

Estoy probando el programa en windows pero me da siempre un error. Al importar el excel de ejemplo y cuando hago cualquier acción me dice 'Field Total not found'.

Me pasa con cualquier excel que importe.

Adjunto imagen.

mqm 18-11-2024 11:45:47

Has encontrado la solución?. Llevo dos días con el mismo problema.

Neftali [Germán.Estévez] 18-11-2024 13:36:41

Cita:

Empezado por mqm (Mensaje 559831)
Has encontrado la solución?. Llevo dos días con el mismo problema.

Escríbele un privado a [seccion_31] explicándole el problema. Tal vez no ha visto el mensaje.

gohermo 19-11-2024 10:52:57

Error
 
Buenos días compañeros!!! Saben si ya han solucionado el problema del programa demo? A mí me da el mismo error que al compañero.

Saludos,

mqm 19-11-2024 17:19:12

Después de 4 días peleándome con el, lo he solucionado instalando la version 10.1 berlin. Ahí no da problema ninguno.
Pero ahora me he dado cuenta de que si eliminas el fichero ...\Win32\Debug\facturas.xml, con delphi 11, ya tampoco te da error.

ramherfer 27-11-2024 23:17:22

Si es borrar el fichero facturas.xml que viene con la demo y el problema creo recordar queda resuelto compañero.

ramherfer 29-11-2024 08:19:07

Buenos días. Estoy probando el ejecutable y si la empesa que envía es un NIF (de un autónomo) por ejemplo se produce un error y la AEAT no admite los registros. Si es un CIF de empresa los registros son admitidos obteniendo la respuesta y siendo correcto el cotejamiento y obtención del QR.
Alguien sabria decirme por que ocurre esto.
Por otro lado no veo ningún ejemplo para la comunicación de facturas sustitutivas/rectificativas ¿puede el sistema hacer el envío de este tipo de facturas?
Estoy estudiando el código para tratar de entenderlo y aplicarlo a mi aplicación.
Otra duda que me surge es si la WSDL URL del endpoint es de pruebas, ya que he realizado algún envío con éxito y no me gustaría que no fuera de pruebas y como tienen poco sentido levantar las orejas de la AEAT.

bmfranky 29-11-2024 09:09:50

Cita:

Empezado por ramherfer (Mensaje 560267)
Buenos días. Estoy probando el ejecutable y si la empesa que envía es un NIF (de un autónomo) por ejemplo se produce un error y la AEAT no admite los registros. Si es un CIF de empresa los registros son admitidos obteniendo la respuesta y siendo correcto el cotejamiento y obtención del QR.
Alguien sabria decirme por que ocurre esto.
Por otro lado no veo ningún ejemplo para la comunicación de facturas sustitutivas/rectificativas ¿puede el sistema hacer el envío de este tipo de facturas?
Estoy estudiando el código para tratar de entenderlo y aplicarlo a mi aplicación.
Otra duda que me surge es si la WSDL URL del endpoint es de pruebas, ya que he realizado algún envío con éxito y no me gustaría que no fuera de pruebas y como tienen poco sentido levantar las orejas de la AEAT.

Hola, buenos dias, de momento , los unicos endpoint disponibles , son los de pruebas, y ni siquiera estan disponibles todos, pueto que ahun faltan los endpoint de requerimiento.
En segundo lugar para poder saber que le falla, necesitamos saber, los datos que envia y la respuesta completa del servidor de la aeat, para poder orientarle al respecto.

ramherfer 29-11-2024 09:34:26

Cita:

Empezado por ramherfer (Mensaje 560267)
Buenos días. Estoy probando el ejecutable y si la empesa que envía es un NIF (de un autónomo) por ejemplo se produce un error y la AEAT no admite los registros. Si es un CIF de empresa los registros son admitidos obteniendo la respuesta y siendo correcto el cotejamiento y obtención del QR.
Alguien sabria decirme por que ocurre esto.
AEAT.

Me autorespondo a parte de mis preguntas pidiendo disculpas. Era una tontería y que al hacer la pregunta me di cuenta ¡joroba!. Al poner el nombre y apellidos en el Obligado Tributario (OT) en lugar de apellidos y nombre puse nombre y apellidos. Nada más cambiarlo me acepto las facturas.

seccion_31 05-12-2024 14:41:20

siento ver este hilo

como con la anterior publicacion nadie hizo mucho caso no he vuelto a aparecer por el foro hasta hoy.

voy a ver lo que comentais

saludos !

seccion_31 05-12-2024 14:53:19

simplemente hay que borrar este XML:

Facturas.xml

que esta en win32\debug

el programa lo creara correctamente con el campo 'total' que le falta.

saludos

Pero ahora da otro error de respuesta de la AEAT que no se si es por culpa de mis datos de ejemplo.

seccion_31 05-12-2024 15:03:50

Eliminando el win32\debug\facturas.xml

y colocando los datos de emision, etc... en la ultima pestaña funciona perfecto para lo que se propone en la demo.

(ya he eliminado el archivo de github)

desde hace 1 semana estoy portando el ejemplo para mi implementación real y ha sido sencillo adaptarlo.

Saludos !

ramherfer 05-12-2024 23:13:02

Pues mi opinión personal, es simplemente que esta demo es oro.
Yo estoy dudando si adaptar la aplicación o dejarla. Mi pensamiento es que es una responsabilidad enorme para un desarrollador y que ante cualquier fallo, problema, llamese como uno quiera puede costar la torta un pan. Es una gran duda que tengo.
Tambien tengo muy claro, que si intento adaptar mi maldita aplicación por supuesto que la basaré en esta gran demo.
La verdad, no se si me atreveré o no.
Personalmente seccion_31 te doy las gracias por este gran aporte, tanto si doy el paso, como si no lo doy. No se si seré capaz de integrarlo con mi aplicación.

seccion_31 06-12-2024 08:21:46

gracias por tus palabras ramherfer !

me alegra saber que es de utilidad.

voy a comentar algo propio: (que cada caso de implementacion es distinto)

A mi el tema del verifactu me pilla un poco de refilon, ya he implementado una version muy limitada del mismo, funcional.

Facturas F1 F2 - R4 R5 positivo - negativo (x diferencias) y listo. NO tengo usuarios que vayan a exigir mucho mas.

Lo que me causa mucha inquietud, es que no haya un portal donde verificar que la informacion que estas enviando coincide con la que tienes en tu gestion (como tiene el SII). La verificacion atraves del codigo QR me parece muy endeble. NO dice nada.

Tampoco entiendo ese interes en hacer la factura y enviarla en "directo", pienso que puedes entrar a facturar, hacerte tus 15 o 20 facturas (1 hora de trabajo) (tipo cliente que tengo), acceder al programa y enviarlas todas o enviar 1 a 1 en manual, sin mas. (otro tema pueden ser los tickets).

Asi mismo, seguimos esperando ese programa de la AEAT para quienes "facturen poco", quizas permita una importacion de registros de alguna manera.

Para finalizar, me gustaria desarrollar un componente no visual que mediante eventos solicite los datos genere el XML, aislandolo de la parte que todos tenemos diferente que es la base de datos, que es un poco lo que plantea la demo. Pero para cubrir mas casos necesitaria ayuda. En realidad TODOS aqui estamos repitiendo una y otra vez el mismo trabajo.


Saludos !

ramherfer 06-12-2024 08:47:16

Cita:

Empezado por seccion_31 (Mensaje 560509)
gracias por tus palabras ramherfer !

me alegra saber que es de utilidad.

voy a comentar algo propio: (que cada caso de implementacion es distinto)

A mi el tema del verifactu me pilla un poco de refilon, ya he implementado una version muy limitada del mismo, funcional.

Facturas F1 F2 - R4 R5 positivo - negativo (x diferencias) y listo. NO tengo usuarios que vayan a exigir mucho mas.

Lo que me causa mucha inquietud, es que no haya un portal donde verificar que la informacion que estas enviando coincide con la que tienes en tu gestion (como tiene el SII). La verificacion atraves del codigo QR me parece muy endeble. NO dice nada.

Tampoco entiendo ese interes en hacer la factura y enviarla en "directo", pienso que puedes entrar a facturar, hacerte tus 15 o 20 facturas (1 hora de trabajo) (tipo cliente que tengo), acceder al programa y enviarlas todas o enviar 1 a 1 en manual, sin mas. (otro tema pueden ser los tickets).

Asi mismo, seguimos esperando ese programa de la AEAT para quienes "facturen poco", quizas permita una importacion de registros de alguna manera.

Para finalizar, me gustaria desarrollar un componente no visual que mediante eventos solicite los datos genere el XML, aislandolo de la parte que todos tenemos diferente que es la base de datos, que es un poco lo que plantea la demo. Pero para cubrir mas casos necesitaria ayuda. En realidad TODOS aqui estamos repitiendo una y otra vez el mismo trabajo.


Saludos !

Y tanto que es de utilidad, yo si lo implemento será basandome en tu codigo de principio a fin.

Yo llevo mucho tiempo con el tema de verifactu, pero en su día consideré que si era todo borradores para que empezar y cambiar una y otra vez lo hecho (gran error) ahora me pilla con muy poca posibilidad de que pueda cumplir los tiempos.

Referente a tu inquietud, cuando se den cuenta de lo endeble que es la comprobación ya se encargaran de darle una vuelta de tuerca y complicarnos más la vida.

El interés de enviar una factura o grupo de facturas directamente nada más confeccionarlas, entiendo que es no dejar espacios de tiempo para hacer una ñapa y engañarlos. Pero ya te digo que de una u otra forma siempre hay alguien que encuentra el modo. Pero bueno si hay que enviarlas se envian y uno descansa de responsabilidades.
Yo mi tipo de cliente me ocurre lo mismo que a ti, son talleres de automoción, imprentas y algún recambista de automoción. Suelen hacer muy pocas facturas al día y alguno hace la facturación del mes y con el tipo de facturas que has indicado, poco mas. Y ese interés que tienen en todo es que muchas empresas de desarrollo como la mia, si no desaparecen será un milagro divino, despues de 35 años de trabajo honrrado, entregando a los clientes una herramienta sencilla y al mismo tiempo potente, sin ningún ánimo de que con ella se engañe a hacienda, todo lo contrario.

Sobre el esperado tema, ya te anticipo que esa aplicación de la AEAT lo que no llevará será ninguna importación ya que considero que va contra el principio VERIFACTU.

Ese componente que comentas, eso sería la leche. Yo por ejemplo estoy utilizando Delphi 7 y me las voy a ver y desear para poder codificar en el todos los procesos, teniendo que acudir a codigo externo en Delphi 10 para que pueda hacer todo lo que va a hacer y con ese componente me facilitaría migraciones posteriores a Delphi 10 de toda mi aplicación, cosa que tiempo material ahora no tengo.

Ya construí una dll que permitia generar el maldito codigo de encadenamiento en sha256 y pienso lo mismo que tu, miles de programadores haciendo el mismo trabajo y para el mismo fin, en lugar de entre todos facilitarnos la solución con componentes y dll's e implementarla luego en nuestras aplicaciones. Somo todos tan listos que acabamos siendo burros de carga. En fin, entiendo que cada uno mire por su propio beneficio y su aplicación, pero esto hubiese sido sencillo, sencillo de hacer, pero si una comunidad como esta no ha sido capaz de organizarlo así, es que no somos tan inteligentes.
Si decides empezar y yo te puedo ayudar, nos organizamos y nos ponemos manos a la obra. mis conocimientos en este tipo de procesos es muy limitado (mi gran problema) pero seguro que en algo te podría ayudar ante la problemática.

Gracias de nuevo por tu aporte, no me cansaré de dartelas y estoy convencido que muchos igual que yo, pero al ser humano parece ser que le cuesta mucho agradecer y hacerlo público.

Un saludo,

CarlosMz 10-12-2024 12:01:53

Interesante el proyecto, muchas gracias por este aporte seccion_31

La parte que falta sería el tema de qué hacer con cada respuesta de la AEAT como códigos de error...

seccion_31 11-12-2024 10:03:21

procesar los codigos de error,

bueno, eso esta mas o menos en el codigo, en la funcion que procesa el envio.

anuncio que tengo previsto hacer otra demo (quizas la ultima), espero poder llegar al final, porque creo que ese codigo lo voy a usar. (sino tendre que tirar un monton de codigo)

se podra enviar facturas desde delphi 7, mediante un componente no visual, le das los datos de la factura, y recibes la respuesta.

soportara facturas, tickets, alta, rectificacion por diferencia, anulacion, exportacion...

En principio podras hacer una factura con D7 y enviarla a la AET sin mas.

Saludos

CarlosMz 11-12-2024 10:24:32

Buenas noticias, no sería más sencillo encapsularlo en una clase ?

Una pregunta ¿por qué usas capicom ? no es más sencillo cargar desde un fichero el certificado:

Código Delphi [-]
procedure TMain.HTTPRIO1HTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp;
  Client: THTTPClient);
var
   CertStream: TMemoryStream;
begin
     CertStream := TMemoryStream.Create;
     CertStream.LoadFromFile('file.pfx');
     HTTPReqResp.ClientCertificate.Stream := CertStream;
     HTTPReqResp.ClientCertificate.Password := 'password';

end;

seccion_31 11-12-2024 10:51:39

¿Sinceramente?

porque no tengo mucha idea, y se hacerlo asi. XD

ahora mismo esta echo asi.

¿que ventajas tiene un metodo sobre otro?

CarlosMz 11-12-2024 11:02:38

xD, pues como ventajas, a simple vista, que no hay necesidad de instalar el certificado,
se puede cargar directamente desde un fichero o stream, y simplifica el código reduciendo dependencias

seccion_31 11-12-2024 11:37:11

uummmm...

voy a ver que hago finalmente, de momento publico este componente asi y luego se puede incoporar.

gracias por el extracto de codigo.

El que se pueda enviar una factura desde D7 para mi no es sencillo. la unidad de la AEAT no compila, y el httprio tampoco funciona.

Interaccionar con una DLL en berlin tampoco he podido porque el httprio da un error de proteccion al enviar.

He descartado el DDE

Al final he usado mensajes definidos por el usuario para comunicar con una aplicacion (D10) que se queda residente y va recibiendo las facturas, ordenes de envio y comunica el resultado.
Los datos se transmiten en dos direcciones atraves de funciones "filemapping".

Funcionar, funciona, y enviar una factura es muy simple. En caso de fallo solo haria falta cambiar la aplicacion residente o servidor, que incopora un sistema de log que te va diciendo lo que hace.

seccion_31 11-12-2024 12:58:56

mas o menos quedara asi:

Código:

procedure TForm1.Button2Click(Sender: TObject);
var
  factura, anterior:TRegistroFactura;
  resultado:TResultadoEnvio;
  j:integer;
begin
    // datos generales
    verifactu1.Emisor.NombreRazonEmisor:='Industrias Pepe';
    verifactu1.Emisor.nifEmisor:='Emisor nif';
    verifactu1.SistemaInformatico.razonSocial:='Software prueba sl';
    verifactu1.SistemaInformatico.nif:='informatico nif';
    verifactu1.SistemaInformatico.nombre:='software aeat';
    verifactu1.SistemaInformatico.ID:='1000';
    verifactu1.SistemaInformatico.Version:='11';
    verifactu1.SistemaInformatico.NumeroInstalacion:='01';
    verifactu1.certificado:='mi certificado';

    // cargar factura
    if verifactu1.inicio then
    begin
          factura.numSerieFactura:='F0001';
          factura.fechaFactura:='01/10/2024';
          factura.estado:='A';
          factura.DescripcionOperacion:='VENTA MERCADERIAS';
          factura.cliente:='CLIENTE';
          factura.clienteNIF:='NIF-CLIENTE';
          factura.nivas:=1;
          factura.iva[0].iva:=21;
          factura.iva[0].baseImp:=100;
          factura.iva[0].impIVA:=120;
          factura.cuotatotal:=120;
          factura.total:=1120;

          // sin anterior
          anterior.numSerieFactura:='';


    end;
    if verifactu1.envio(resultado) then
    begin
        for j:=0 to resultado.nfacturas do
        begin
              if not resultado.facturas[j].error then
                  showmessage(resultado.facturas[j].numserieFactura+' '+resultado.facturas[j].csv)
              else
                  showmessage(resultado.facturas[j].numserieFactura+' '+inttostr(resultado.facturas[j].errorCodigo) );
        end;
    end
    else
        showmessage('Error En El Envio');
end;


seccion_31 11-12-2024 13:03:42

voy a intentar hacer que admita un nombre de certificado o nombre de fichero.pfx en el certificado para tener las dos opciones.

CarlosMz 11-12-2024 13:14:38

Tiene buena pinta, creo que ¿habría que agregarle un control de flujo según los errores recibidos por parte de la AEAT?

seccion_31 14-12-2024 09:10:27

buenos dias !

el servidor de mensajes en B10 funciona
el componente en D7 funciona
la demo que envía una excel D7 funciona


Hay un componente en D7 que crea una sesion en el servidor B10
El componente D7 recoge los datos de la facturas y las envia al servidor B10
El componente D7 da orden de envio al servidor B10
El servidor B10 devuelve el resultado del envio al componente D7

Este es un trozo de código del ejemplo de la anterior demo programada en B10, AHORA reprogramada con el nuevo componente para D7

Código en D7 que hace uso del componente:

Código:

// carga los datos de la rejilla en TVerifactu enviandolos a nuestro servidor
function TForm1.stringGrid_to_VerFactuD7( fila:integer ):TRegistroFactura;
var
  actual, anterior:TRegistroFactura;
  n:integer;
begin
      // asignar datos de 1 factura a un record
      actual.alta_baja          :=copy(StringGridFacturas.Cells[ 0, fila ],1,1);  // A o B
      actual.numSerieFactura    :=StringGridFacturas.Cells[ 1, fila ];
      actual.fechafactura        :=StringGridFacturas.Cells[ 2, fila ];
      actual.descripcionOperacion:=StringGridFacturas.Cells[ 3, fila ];
      actual.cliente            :=StringGridFacturas.Cells[ 4, fila ];
      actual.clienteNIF          :=StringGridFacturas.Cells[ 5, fila ];
      actual.clientetipoNIF      :=StringGridFacturas.Cells[ 6, fila ];
      actual.clienteCodPais      :=StringGridFacturas.Cells[ 7, fila ];

      // cargar 2 ivas
      actual.nivas:=0;
      if StringGridFacturas.Cells[10, fila]<>'' then  // añadir iva 1
      begin
            actual.iva[0].iva    :=value( StringGridFacturas.Cells[10, fila] );
            actual.iva[0].req    :=value( StringGridFacturas.Cells[11, fila] );
            actual.iva[0].baseImp :=value( StringGridFacturas.Cells[12, fila] );
            actual.iva[0].impIVA  :=actual.iva[0].baseImp*actual.iva[0].iva / 100;
            actual.iva[0].impREQ  :=actual.iva[0].baseImp*actual.iva[0].req / 100;
            inc(actual.nivas);
      end;
      if StringGridFacturas.Cells[13, fila]<>'' then  // añadir iva 1
      begin
            actual.iva[1].iva    :=value( StringGridFacturas.Cells[13, fila] );
            actual.iva[1].req    :=value( StringGridFacturas.Cells[14, fila] );
            actual.iva[1].baseImp :=value( StringGridFacturas.Cells[15, fila] );
            actual.iva[1].impIVA  :=actual.iva[0].baseImp*actual.iva[0].iva / 100;
            actual.iva[1].impREQ  :=actual.iva[0].baseImp*actual.iva[0].req / 100;
            inc(actual.nivas);
      end;

      // totales
      actual.cuotatotal    :=value( StringGridFacturas.Cells[ 8, fila ] );
      actual.total        :=value( StringGridFacturas.Cells[ 9, fila ] );

      //
      // localizar la factura anterior:  (en nuestra base de datos XML)
      //
      anterior.numSerieFactura  :='';
      anterior.fechaFactura    :='';
      anterior.huella          :='';

      if FacturasEnviadas.locate('emisor;numSerieFactura',VarArrayOf([ VeriFactuD7.Emisor.nifEmisor, actual.numSerieFactura ]),[] ) then
      begin
          FacturasEnviadas.prior;
          if not FacturasEnviadas.bof then
          begin
                anterior.numSerieFactura  :=FacturasEnviadas.FieldByName('numSerieFactura').text;
                anterior.fechaFactura    :=FacturasEnviadas.FieldByName('fechaExpedicioFactura').text;
                anterior.huella          :=FacturasEnviadas.FieldByName('huella').text;
          end;
      end;
      //
      // enviarlo al servidor
      //
      n:=VeriFactuD7.addFactura( actual, anterior );
      //
      //
      if n<=0 then
      begin
            showmessage('Error Añadiendo Factura '+factura+' Al Servidor');
            abort;
      end;
      result:=actual;
end;

//
// enviar los datos cargados en la rejilla
//
procedure TForm1.enviarClick(Sender: TObject);
var
  resultado        : TResultadoEnvio;    // Respuesta tras el envio
  factura          : TFacturas;          // records con los datos de 1 factura la actual y anterior
  actual            : TRegistroFactura;  // para almacenar en la BD
  fila              : integer;            // fila de la rejilla

  alta_baja        : string;            // estado de la fila, 'A' ó 'B'
begin
      screen.Cursor:=crHourglass;

      if sender=enviar  then VerifactuD7.Simular:=false;
      if sender=soloXML then VerifactuD7.Simular:=true;

      // url EndPoint
      VerifactuD7.urlEndPoint:=editURL.text;

      // Datos de sistema Informatico:
      VerifactuD7.SistemaInformatico.razonSocial      :=editRazonSocial.Text;
      VerifactuD7.SistemaInformatico.nif              :=editNIF.Text;
      VerifactuD7.SistemaInformatico.nombre          :=editNombre.Text;
      VerifactuD7.SistemaInformatico.ID              :=editID.text;
      VerifactuD7.SistemaInformatico.Version          :=editVersion.text;
      VerifactuD7.SistemaInformatico.NumeroInstalacion:=editInstalacion.text;

      // Certificado:
      VerifactuD7.Certificado                        :=comboCertificados.text;

      // Emisor
      VerifactuD7.Emisor.NombreRazonEmisor            :=editEmisor.Text;
      VerifactuD7.Emisor.nifEmisor                    :=editNIFEmisor.Text;

      // Otros datos
      VeriFactuD7.pathXML_Envio                      :=xmlEnvio;      // siempre guardaremos una copia de la ultima transmision
      VeriFactuD7.pathXML_Respuesta                  :=xmlRespuesta;  // siempre guardaremos una copia del ultimo resultado

      // Iniciamos Sesion !!
      if not VeriFactuD7.inicio then
      begin
            showmessage('Error Iniciando Sesion');
            exit;
      end;

      // recorrer las facturas de la rejilla
      for fila:=1 to StringGridFacturas.RowCount do
      begin
          alta_baja:=StringGridFacturas.Cells[ 0, fila ];          // estado de la factura (ALTA, BAJA)

          if alta_baja<>'' then
          begin                                                    // SI ALTA ó BAJA:
                actual:=stringGrid_to_VerFactuD7( fila );          // <---- envia al servidor la factura de la fila correspondiente
                archivoFactura(actual);
          end;
      end;

      // resultados:
      PageControlVerifactu.TabIndex:=1;                              // nos preparamos para ver el resultado del envio en su tabulador
      memoXML.lines.clear;

      if VeriFactuD7.envio(resultado) then                          // enviarlo !!
        procesarEnvio(resultado)                                    // procesar el resultado (mostrar en pantalla, y guardarlo en xmlFacturas)
      else
        memoRes.lines.add('El Envio No Ha Podido Ser Realizado');

      // Finalmente:
      FacturasEnviadas.SaveToFile(xmlFacturas);                    // Guardamos el archivo propio de facturas  ( para encadenamiento )

      // cerrar sesion:
      VeriFactuD7.final;                                            // Liberamos la sesion

      screen.Cursor:=crDefault;
end;

[/quote]




Hay varios temas preliminares

Faltan mejorar y afinar algunos temas

¿hay alguien interesado en usarlo?

Para publicarlo, necesito alguien que entienda BIEN la composicion de los mensajes de la AEAT segun cada tipo de factura para componerlo con la informacion basica de una factura y se encargue de ello.
El resto de la logica de envio y recepcion como digo ya funciona.

Seria tomar la funcion que hace la carga del objeto de la AEAT e indicarle los datos segun la factura suministrada.

Ahi dejo este mensaje, a ver si alguien se anima.

ramherfer 16-12-2024 09:16:49

Yo estoy interesado, aunque tampoco tengo mucha idea en este tipo de procesos.
Toda mi aplicación está programada en D7. Y tengo un problemón de narices. Ya que tiempo material para recodificar todo es imposible.
Ya comenté que en lo que pueda ayudar y echar un cable, intento hacer lo que medigas.
Tambien me gustaría tener más claro la metodología de uso del componente para no tener fallos a la hora de su uso y que todo vaya como la seda.
Sigo sin entender porque no se trabajó en los foros orientado en este sentido. Muchos tendríamos la solución con un poquito de aporte de todos.

CarlosMz 16-12-2024 19:16:14

Yo podría echar una mano para convertir el código a delphi 12, intentando minimizar dependencias y encapsulando todo el código en una clase para evitar el uso de componentes no "nativos"

Cita:

Empezado por seccion_31 (Mensaje 560739)
buenos dias !

el servidor de mensajes en B10 funciona
el componente en D7 funciona
la demo que envía una excel D7 funciona


Hay un componente en D7 que crea una sesion en el servidor B10
El componente D7 recoge los datos de la facturas y las envia al servidor B10
El componente D7 da orden de envio al servidor B10
El servidor B10 devuelve el resultado del envio al componente D7

Este es un trozo de código del ejemplo de la anterior demo programada en B10, AHORA reprogramada con el nuevo componente para D7

Código en D7 que hace uso del componente:

Código:

// carga los datos de la rejilla en TVerifactu enviandolos a nuestro servidor
function TForm1.stringGrid_to_VerFactuD7( fila:integer ):TRegistroFactura;
var
  actual, anterior:TRegistroFactura;
  n:integer;
begin
      // asignar datos de 1 factura a un record
      actual.alta_baja          :=copy(StringGridFacturas.Cells[ 0, fila ],1,1);  // A o B
      actual.numSerieFactura    :=StringGridFacturas.Cells[ 1, fila ];
      actual.fechafactura        :=StringGridFacturas.Cells[ 2, fila ];
      actual.descripcionOperacion:=StringGridFacturas.Cells[ 3, fila ];
      actual.cliente            :=StringGridFacturas.Cells[ 4, fila ];
      actual.clienteNIF          :=StringGridFacturas.Cells[ 5, fila ];
      actual.clientetipoNIF      :=StringGridFacturas.Cells[ 6, fila ];
      actual.clienteCodPais      :=StringGridFacturas.Cells[ 7, fila ];

      // cargar 2 ivas
      actual.nivas:=0;
      if StringGridFacturas.Cells[10, fila]<>'' then  // añadir iva 1
      begin
            actual.iva[0].iva    :=value( StringGridFacturas.Cells[10, fila] );
            actual.iva[0].req    :=value( StringGridFacturas.Cells[11, fila] );
            actual.iva[0].baseImp :=value( StringGridFacturas.Cells[12, fila] );
            actual.iva[0].impIVA  :=actual.iva[0].baseImp*actual.iva[0].iva / 100;
            actual.iva[0].impREQ  :=actual.iva[0].baseImp*actual.iva[0].req / 100;
            inc(actual.nivas);
      end;
      if StringGridFacturas.Cells[13, fila]<>'' then  // añadir iva 1
      begin
            actual.iva[1].iva    :=value( StringGridFacturas.Cells[13, fila] );
            actual.iva[1].req    :=value( StringGridFacturas.Cells[14, fila] );
            actual.iva[1].baseImp :=value( StringGridFacturas.Cells[15, fila] );
            actual.iva[1].impIVA  :=actual.iva[0].baseImp*actual.iva[0].iva / 100;
            actual.iva[1].impREQ  :=actual.iva[0].baseImp*actual.iva[0].req / 100;
            inc(actual.nivas);
      end;

      // totales
      actual.cuotatotal    :=value( StringGridFacturas.Cells[ 8, fila ] );
      actual.total        :=value( StringGridFacturas.Cells[ 9, fila ] );

      //
      // localizar la factura anterior:  (en nuestra base de datos XML)
      //
      anterior.numSerieFactura  :='';
      anterior.fechaFactura    :='';
      anterior.huella          :='';

      if FacturasEnviadas.locate('emisor;numSerieFactura',VarArrayOf([ VeriFactuD7.Emisor.nifEmisor, actual.numSerieFactura ]),[] ) then
      begin
          FacturasEnviadas.prior;
          if not FacturasEnviadas.bof then
          begin
                anterior.numSerieFactura  :=FacturasEnviadas.FieldByName('numSerieFactura').text;
                anterior.fechaFactura    :=FacturasEnviadas.FieldByName('fechaExpedicioFactura').text;
                anterior.huella          :=FacturasEnviadas.FieldByName('huella').text;
          end;
      end;
      //
      // enviarlo al servidor
      //
      n:=VeriFactuD7.addFactura( actual, anterior );
      //
      //
      if n<=0 then
      begin
            showmessage('Error Añadiendo Factura '+factura+' Al Servidor');
            abort;
      end;
      result:=actual;
end;

//
// enviar los datos cargados en la rejilla
//
procedure TForm1.enviarClick(Sender: TObject);
var
  resultado        : TResultadoEnvio;    // Respuesta tras el envio
  factura          : TFacturas;          // records con los datos de 1 factura la actual y anterior
  actual            : TRegistroFactura;  // para almacenar en la BD
  fila              : integer;            // fila de la rejilla

  alta_baja        : string;            // estado de la fila, 'A' ó 'B'
begin
      screen.Cursor:=crHourglass;

      if sender=enviar  then VerifactuD7.Simular:=false;
      if sender=soloXML then VerifactuD7.Simular:=true;

      // url EndPoint
      VerifactuD7.urlEndPoint:=editURL.text;

      // Datos de sistema Informatico:
      VerifactuD7.SistemaInformatico.razonSocial      :=editRazonSocial.Text;
      VerifactuD7.SistemaInformatico.nif              :=editNIF.Text;
      VerifactuD7.SistemaInformatico.nombre          :=editNombre.Text;
      VerifactuD7.SistemaInformatico.ID              :=editID.text;
      VerifactuD7.SistemaInformatico.Version          :=editVersion.text;
      VerifactuD7.SistemaInformatico.NumeroInstalacion:=editInstalacion.text;

      // Certificado:
      VerifactuD7.Certificado                        :=comboCertificados.text;

      // Emisor
      VerifactuD7.Emisor.NombreRazonEmisor            :=editEmisor.Text;
      VerifactuD7.Emisor.nifEmisor                    :=editNIFEmisor.Text;

      // Otros datos
      VeriFactuD7.pathXML_Envio                      :=xmlEnvio;      // siempre guardaremos una copia de la ultima transmision
      VeriFactuD7.pathXML_Respuesta                  :=xmlRespuesta;  // siempre guardaremos una copia del ultimo resultado

      // Iniciamos Sesion !!
      if not VeriFactuD7.inicio then
      begin
            showmessage('Error Iniciando Sesion');
            exit;
      end;

      // recorrer las facturas de la rejilla
      for fila:=1 to StringGridFacturas.RowCount do
      begin
          alta_baja:=StringGridFacturas.Cells[ 0, fila ];          // estado de la factura (ALTA, BAJA)

          if alta_baja<>'' then
          begin                                                    // SI ALTA ó BAJA:
                actual:=stringGrid_to_VerFactuD7( fila );          // <---- envia al servidor la factura de la fila correspondiente
                archivoFactura(actual);
          end;
      end;

      // resultados:
      PageControlVerifactu.TabIndex:=1;                              // nos preparamos para ver el resultado del envio en su tabulador
      memoXML.lines.clear;

      if VeriFactuD7.envio(resultado) then                          // enviarlo !!
        procesarEnvio(resultado)                                    // procesar el resultado (mostrar en pantalla, y guardarlo en xmlFacturas)
      else
        memoRes.lines.add('El Envio No Ha Podido Ser Realizado');

      // Finalmente:
      FacturasEnviadas.SaveToFile(xmlFacturas);                    // Guardamos el archivo propio de facturas  ( para encadenamiento )

      // cerrar sesion:
      VeriFactuD7.final;                                            // Liberamos la sesion

      screen.Cursor:=crDefault;
end;





Hay varios temas preliminares

Faltan mejorar y afinar algunos temas

¿hay alguien interesado en usarlo?

Para publicarlo, necesito alguien que entienda BIEN la composicion de los mensajes de la AEAT segun cada tipo de factura para componerlo con la informacion basica de una factura y se encargue de ello.
El resto de la logica de envio y recepcion como digo ya funciona.

Seria tomar la funcion que hace la carga del objeto de la AEAT e indicarle los datos segun la factura suministrada.

Ahi dejo este mensaje, a ver si alguien se anima.[/quote]

ramherfer 16-12-2024 20:20:19

¿De donde puedo descargar el componente D7 para intentar integrarlo y poder hacer pruebas?
¿cual sería el path para ubicar el servidor B10?
Ya tengo los datos del sistema informático emisor implementados en la ficha de empresa y me faltaría desde donde emito las ordenes de envío y recojo las respuestas, que, imagino sería desde un grid de facturas emitidas gestionando las pendientes de envío.
Soy un mar de dudas para empezar las pruebas

mqm 16-12-2024 20:26:33

Primero de nada, agradecer a "seccion_31" por la grandísima aportación que ha tenido para con este foro, al brindarnos la posibilidad de usar el código facilitado.
Yo personalmente lo he adaptado para, desde Delphi 10, hace una aplicación en segundo plano que se conecta a la base de datos MYSQL y va enviando la facturas
simplificadas y ordinarias que se van generando en una aplicación en delphi 7.
Estoy intentando desarrollarlo tanto para una application con MYSQL/MariaDB y otra con ficheros DBF de paradox.
De momento consigo enviar con tu código y capturar la respuesta de la AEAT. Ahora estoy esperando a ver como actuar ante las repuestas de la AEAT.
Si en algo puedo ayudar... aquí me tenéis.

ramherfer 16-12-2024 22:24:50

Si pudieras enviar algo de codigo de esa aplicación que funciona en segundo plano para poder ver como estableces las conexiones entre el servidor B10 y tu base de datos, estaría genial y me ayudaría posiblemente a entender un poco más. Mi aplicación tambien funciona en Delphi 7 y uso tablas paradox db y voy perdido, no, lo siguiente

mqm 17-12-2024 18:11:23

Simplemente hago uso de los componentes de Devart unidac. Los demás es adaptar el ejemplo a mis tables, es fácil no te lleva mucho tiempo adaptarlos. Simplemente en vez de la rejilla del excell a enviar, tengo dos grid con las facturas simplificadas y las ordinarias, y para "envioFacturas" me he creado una tabla donde en lugar de un excell , voy guardando todos los registros que voy enviando.
Termino de depurar un poco y te paso el proyecto por si te ayuda.
En mi caso para mis aplicaciones, es solo añadir 4 campos a las tablas y crear la tabla de envíos.

ramherfer 17-12-2024 21:13:04

Cita:

Empezado por mqm (Mensaje 560799)
Simplemente hago uso de los componentes de Devart unidac. Los demás es adaptar el ejemplo a mis tables, es fácil no te lleva mucho tiempo adaptarlos. Simplemente en vez de la rejilla del excell a enviar, tengo dos grid con las facturas simplificadas y las ordinarias, y para "envioFacturas" me he creado una tabla donde en lugar de un excell , voy guardando todos los registros que voy enviando.
Termino de depurar un poco y te paso el proyecto por si te ayuda.
En mi caso para mis aplicaciones, es solo añadir 4 campos a las tablas y crear la tabla de envíos.

Claro que me serviria de ayuda, lo cual agradecdería. Cualquier codigo que vea su planteamiento me serviría y mucho para ir entendiendo.

seccion_31 19-12-2024 21:08:52

Hola !

El componente desde Delphi 7 ya envia y devuelve la respuesta. Ya es operativo en la DEMO que importaba de una hoja de calculo, compilada con D7.

En este otro ejemplo de codigo de delphi 7 se procesa la respuesta tras un envio:

Código:

procedure TForm1.procesarEnvio(resultado:TResultadoEnvio);
var
  desError,error,estado,factura, emisor:string;

  j:integer;

  _ok,_oke,_err:integer;

begin
      memoXML.Lines.LoadFromFile(xmlEnvio);
      memoXML.Text:=FormatXMLData(memoXML.Text);

      memoRes.lines.clear;
      memoRes.lines.Add('Se ha realizado el envío');
      memoRes.Lines.Add('');
      memoRes.Lines.Add('Estado Del Envio:'+resultado.EstadoEnvio );
      memoRes.lines.Add('CSV: ' + resultado.CSV);
      memoRes.lines.Add('TimeStamp: ' + resultado.Fecha+' '+resultado.Hora);
      memoRes.Lines.Add('');


      _ok  :=0;    // nº facturas OK
      _oke  :=0;    // nº facturas OK ( aceptada con errores )
      _err  :=0;    // nº facturas con errores

      for j:=0 to resultado.nFacturas-1 do
      begin
            factura  := resultado.facturas[j].NumSerieFactura;
            emisor  := resultado.facturas[j].IDEmisorFactura;
            estado  := resultado.facturas[j].estado;
            error    := inttostr(resultado.facturas[j].errorcodigo);
            desError := resultado.facturas[j].descripcionError;


            memoRes.Lines.Add( factura + ' ' + estado + ' '+error+' '+desError );    // ver en pantalla

            if resultado.facturas[j].OK then                        // Es correcto ó aceptado con errores
            begin
                // colocar el csv y huella en la factura
                if facturasEnviadas.locate('emisor;NumSerieFactura',vararrayof([emisor, factura ]),[]) then
                begin
                    FacturasEnviadas.edit;
                    FacturasEnviadas.fieldbyName('csv').text      :=resultado.CSV;
                    FacturasEnviadas.FieldByName('huella').text  :=resultado.facturas[j].huellaFactura;
                    FacturasEnviadas.fieldbyName('situacion').text:=estado;
                    FacturasEnviadas.post;
                end;
                if resultado.facturas[j].aceptadoConErrores then inc(_oke) else inc(_ok);
            end
            else
                inc(_err);                            // Es erronea
      end;

      memoRes.Lines.Add('');
      memoRes.Lines.Add('Facturas Aceptadas: '+inttostr(_ok) );
      memoRes.Lines.Add('Facturas Aceptadas Con Errores: '+inttostr(_oke) );
      memoRes.Lines.Add('Facturas Con Errores: '+inttostr(_err) );

      // tiempo de espera:
      if resultado.tiempoDeEspera<>'' then memoRes.Lines.Add('Se Ha Establecido Un Tiempo De Espera Proximo Envio De '+resultado.tiempoDeEspera);
end;



En teoria, sube factura, tickets, rectificativas, comunitarias, y exportación. (hasta 1.000 facturas x envio) Pero lamentablemente ahora mismo no se bien como cubrir el resto de casos.

Genera el QR

Ya esta implementado el cotejo contra la AEAT con el nuevo objeto de consulta: tan simple como llamar a una funcion desde DELPHI 7 y se devuelve un array con los resultados:



Lo voy a incoporar en una aplicacion real que espero empiece a ser probada en un entorno real de facturacion al inicio de año enviandolas a pre-produccion, e imprimiendo el codigo QR real sobre la factura, como demo. Pero todo muy real.

Pero claro, me doy cuenta de la responsabilidad que adquiero una vez publicado, esto NO es una demo.

Permite hacer todo el trabajo desde Delphi 7 con el apoyo de la aplicacion servidora, y desde la version 10 en adelante, puede usarse como una unidad, sin mas con un uses.

En unas semanas una vez probado veo que hacer.

mqm 19-12-2024 21:34:39

Yo sigo implementado tu demo inicial.
Pero.. que hacer en caso de que no tengamos respuesta de la aeat?
Para mi es fácil la implementation. Son pequeña tiendas... facturo envio y en caso de equivocación mando una en negativo. Ni permito borrado ni anulación.
Pero me he encontrado con 2-3 casos en mis pruebas, que la aeat no responde nada ... y posteriormente he visto que las facturas enviadas estaban recogidas.
Con lo fácil que seria una consulta a la aeat, para saber cual es la ultima factura enviada/grabada y aceptada.

Sinceramente..... me estoy planteando dejar todo esto. Hablando claro.... esto es una puñetera mierda que no hay dios que la entienda. Si quieren controlar... les mandamos la caja del día al finalizar la jornada y listo. Tengo algunos clientes de 50 y pico de años que dicen que cierran el negocio.
Amen de las XXX empresas en la web que te ofrecen el kit, y la solución milagrosa para tu software, y muchas ponen que homologadas por hacienda. Quc homologación ni leches..... En manos de que o quienes estamos.

seccion_31 20-12-2024 08:14:24

buenos dias

yo siempre he encontrado respuesta de la aeat. es mas: lo normal es archivarla.

Creo y digo creo (porque tengo que comprobarlo) que cuando en una lista de facturas hay una erronea importa hasta ahi, ignorando el resto que va detras.

ahora el tema es mas sencillo, con la consulta que se puede obtener, puedes interrogar con el objeto de consulta y ver que facturas estan subidas, tambien podras consultarlas en un portal como se hace con el SII. Eso da mucha seguridad.

Despues de mi experiencia con el SII: los primeros dias habra millones de registros subidos, cientos de miles con posibles errores y poco a poco ira la cosa a mejor. No es para tanto, creo que hay que confiar mas en nuestras capacidades y en la sensatez. Con el SII pensaba que seria terrible y no ha sido para tanto.

Ahora bien: sigo sin entender porque con el SII para una empresa que factura 20 millones al año, por ejemplo puedas enviar tus facturas de miles de euros en 4 dias habiles y en verifactu una factura de 10 euros deba ser enviada al instante, obligando a mantener una infraestructura, programa, etc... 24/7 en perfecto funcionamiento. Para mi es incomprensible.

Saludos !


La franja horaria es GMT +2. Ahora son las 16:25:02.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi