Ver Mensaje Individual
  #824  
Antiguo 11-07-2023
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 112
Reputación: 8
seccion_31 Va por buen camino
buenas tardes !

tras varias consultas con la AEAT, he llegado a la conclusión que hoy no hay mucha mas información disponible.

Tras leer el PDF informativo, parece que el envio al sistema verifactu sera opcional:
https://www.agenciatributaria.es/sta...tubre_2022.pdf

Pagina 9


Sobre programacion, como no puedo quedarme quieto y no tengo los WSDL, he desarrollado una funcion capaz de convertir un TRecord a XML, usando las rttis, incluyendo anidaciones y toda clase arrays, de tal forma que facilmente se puede componer no solo la factura, sino cualquier estructura TRecord.

Actualmente los tipos que he creado han sido para el alta de facturacion y anulacion.

Este foro me ayudo mucho con el SII, y me gustaria viendo que tenemos tiempo, aportar lo que pueda, y que os animeis a colgar codigo, en mi caso para devolver lo aprendido.

Pero como no quiero crear mas confusion voy a postear unas porciones de ejemplo: para que os hagais una idea.
(Ha costado un par de minutos desarrollar la anulacion de facturas).


type (parcial)

Código:
  TRegistroFacturacion=record

        PeriodoLiquidacion:TPeriodoliquidacion;

        IDFactura:TIDFactura;

        tipoFactura:string;
        FechaOperacion:string;
        DescripcionOperacion:String;

        Desglose:array of TDesglose;

        ImporteTotal:string;

        Contraparte:TContraparte;

        EncadenamientoFacturaAnterior:TEncadenamiento;
        SistemaInformatico:TSistemaInformatico;
  end;

  TDatosControl=record
        huella:string;
        TipoHash:string;
        FechaGenRegistro:string;
        HoraGenRegistro:string;
        HUsoHorarioGenRegistro:string;
        Incidencia:string;
  end;

  TRegistroAltaFacturas=record
        empty:boolean;              //<- interpretado por la funcion xmlRecord (no genera XML), permite incluir o no el nodo.  (es opcional, y se puede añadir en cualquier nodo)

        RegistroFacturacion: TRegistroFacturacion;
        DatosControl: TDatosControl;
  end;

  TSistemaFacturacionAltaFact=record
        Cabecera:TCabecera;
        RegistroAltaFacturas:array[1..1000] of  TRegistroAltaFacturas;     // <- diseñado fijo pero podria ser un array dinamico, como desglose. (cada elemento incluye empty para determinar si hay factura)
  end;

codigo: (parcial)

Código:
var
  j:integer;
begin
      // vaciar array de facturas
      for j:=1 to 1000 do
          veriFactu.RegistroAltaFacturas[j].empty:=true;        // <-propiedad opcional "empty" no genera XML pero permite decidir si se genera el nodo, o no.

      // empezar a cargar datos:
      veriFactu.Cabecera.IDVersion:='0.1';
      veriFactu.Cabecera.ObligadoEmision.NombreRazon:='EMPRESA PRUEBAS';
      veriFactu.Cabecera.ObligadoEmision.NIF:='00000006Y';

      // cargar facturas
      veriFactu.RegistroAltaFacturas[1].empty:=false;
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.PeriodoLiquidacion.ejercicio:='2022';
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.PeriodoLiquidacion.periodo:='3T';

      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.IDFactura.IdEmisorFactura.NIF:='00000006Y';
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.IDFactura.NumSerieFacturaEmisor:='84.2.1.2566';
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.IDFactura.FechaExpedicionFacturaEmisor:='31/07/2022';

      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.tipoFactura:='F2';
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.FechaOperacion:='31/07/2022';
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.DescripcionOperacion:='VENTA MINORISTA';

      // un desglose
      setLength(veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.Desglose,1);
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.Desglose[0].claveRegimen:='01';
      veriFactu.RegistroAltaFacturas[1].RegistroFacturacion.Desglose[0].calificacionOperacion:='S1';

....

etc.... llenando el record.... y finalmente:

      // crear archivo XML desde el record  (aqui se hace la magia)
     // parametros:  tipo de dato, el record "master" del alta,  un pointer a la variable de ese record, el archivo xml a crear, y el callback para calcular huellas y lo que haga falta. (opcional)
      recordToXML('uVeriExp.TSistemaFacturacionAltaFact', @veriFactu, 'c:\pruebas\v1.xml', calcularHuellas );
callback, (opcional) para calcular huellas, es llamado cada vez que se analiza un nodo o value en el record.
Es decir cuando se va construyendo el XML desde el record, se va llamando a este callback y se intercepta el nodo registrofacturacion para calcular la huella.

Código:
// CALLBACK de nodos y valores

parametros del callback:  xmlFile en construccion, xmlArray: indice si se esta dentro de un array dentro del record, xmlNodo y xmlLabel identificador del nodo y etiqueta de valor, xmlValue, valor de la etiqueta, que puede ser alterado en el callback, y xmlLabelFin, etiqueta marcador de fin de valor.  </

Segun en que momento se este procesado el record, el callback recibe unos u otros valores. xmlArray en nuestro ejemplo tendria sentido, dentro de la zona desglose o registrodefacturacion, fuera marcara -1.


procedure calcularHuellas(xmlFile:TStringList; xmlarray:integer; xmlNodo, xmlLabel:string; var xmlValue:string; xmlLabelFin:string);
var
    j:integer;
    numeroAnterior:string;
begin
     //
    // calcular huella
    //
      if (uppercase(xmlNodo)='<CABECERA>') then
      begin
          _huella:='';
          _huella256:='';
      end;

      if (uppercase(xmlNodo)='<REGISTROFACTURACION>') then    // empezamos a guardar el registro
      begin
          _huella:=xmlNodo;
          exit;
      end;

      if (uppercase(xmlNodo)='</REGISTROFACTURACION>') then // finalizamos y calculamos
      begin
          _huella:=_huella+xmlNodo;
          _huella256:=THashSHA2.GetHashString(_huella, SHA256);
          veriFactu.RegistroAltaFacturas[xmlArray+1].DatosControl.huella:=_huella256;

          _huella:='';
          exit;
      end;

      if _huella<>'' then                       // vamos guardando la huella por cada nodo y valor
        _huella:=_huella+xmlLabel+xmlValue+xmlLabelFin;


      if uppercase(xmlLabel)='<HUELLA>' then    // colocamos la huella
      begin
              xmlValue:=_huella256;
              _huella256:='';
              exit;
      end;

        /////// HUELLA FACTURA ANTERIOR //////////////
       if uppercase(xmlLabel)='<HUELLAFACTURAANTERIOR>' then
       begin
            numeroAnterior:=veriFactu.RegistroAltaFacturas[xmlArray+1].RegistroFacturacion.EncadenamientoFacturaAnterior.NumSerieFacturaAnterior;
            for j:=1 to 1000 do
            begin
                if (veriFactu.RegistroAltaFacturas[j].RegistroFacturacion.IDFactura.NumSerieFacturaEmisor=numeroAnterior)and
                   (not veriFactu.RegistroAltaFacturas[j].empty) then
                begin
                     xmlValue:=veriFactu.RegistroAltaFacturas[j].DatosControl.huella;
                     exit;
                end;
            end;
            xmlValue:='';
       end;
       // si no estuviera en este bloque habria que buscarla ¿en una base de datos?

end;
Responder Con Cita