Generación de Envíos de Documentos Tributarios Electrónicos en Java: Clase EnvioDTE

La generación de Documentos Tributarios Electrónicos (DTE) es una parte esencial del cumplimiento fiscal en Chile. Este artículo explica cómo la clase EnvioDTE se utiliza para construir y gestionar un "sobre electrónico" (EnvioDTE), necesario para enviar documentos al Servicio de Impuestos Internos (SII).


Descripción General de la Clase EnvioDTE

La clase EnvioDTE pertenece al paquete com.egga.appdte.sii.utilidades. Se utiliza para construir documentos XML que cumplen con los estándares establecidos por el SII para los DTE. Los métodos principales de esta clase son:

  1. generaEnvio: Construye la estructura base del sobre electrónico (EnvioDTE), incluyendo la carátula con los metadatos del envío.
  2. addDTE: Agrega documentos DTE timbrados y firmados al sobre electrónico generado previamente.

Código:

Puedes adaptar el código según tus requerimientos

package com.egga.appdte.sii.utilidades;
import com.egga.appdte.models.DteModel;
import java.io.ByteArrayOutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import java.io.StringReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;

import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class EnvioDTE {

    private Document doc;

           
   public void generaEnvio(DteModel objdte,String nombredte,String pathdte,String rutusuario) throws ParserConfigurationException, FileNotFoundException, IOException, SAXException, TransformerConfigurationException, TransformerException{
       ConfigAppDTE objconfig = new ConfigAppDTE();
       	DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
	DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        this.doc = docBuilder.newDocument();
		
        
        /*
        this.doc.createComment("eeee");
        */
        Element setdte = this.doc.createElement("SetDTE");
        
        Attr attrversion = this.doc.createAttribute("ID");
	attrversion.setValue("SetDoc"); 
        setdte.setAttributeNode(attrversion);
        
        
        Element caratula = this.doc.createElement("Caratula");
        caratula.setAttribute("version", "1.0");
       
        Element rutemisor = this.doc.createElement("RutEmisor");
        rutemisor.setTextContent(objdte.getRutemisor().trim());
        
        
        Element rutenvia = this.doc.createElement("RutEnvia");
        rutenvia.setTextContent(rutusuario);
        
        
        
        
        
        Element rutreceptor = this.doc.createElement("RutReceptor");
        
        
      
       rutreceptor.setTextContent("60803000-K");
 
        caratula.appendChild(rutemisor);
        caratula.appendChild(rutenvia);
        caratula.appendChild(rutreceptor);
      /* agrego la fecha de resolucón que nos entrega el SII */  
        Element fecharesol = this.doc.createElement("FchResol");
        fecharesol.setTextContent(objdte.getFecharesol());
        caratula.appendChild(fecharesol);
        
        Element nroresol = this.doc.createElement("NroResol");
        nroresol.setTextContent(objdte.getNumresol());
        caratula.appendChild(nroresol);
        
        
           
           
        Date date = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
           
        String stringFecha = dateFormat.format(date);
        DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
        String stringHora = timeFormat.format(date);
        
        
        
        
        Element tmstfirmaenv = this.doc.createElement("TmstFirmaEnv");
        tmstfirmaenv.setTextContent(stringFecha+"T"+stringHora);
        caratula.appendChild(tmstfirmaenv);
        
        
        Element subtotdte = this.doc.createElement("SubTotDTE");
        
        Element tpodte = this.doc.createElement("TpoDTE");
        tpodte.setTextContent(objdte.getTipodte());
        subtotdte.appendChild(tpodte);
        
        Element nrodte = this.doc.createElement("NroDTE");
        nrodte.setTextContent("1");
        subtotdte.appendChild(nrodte);
        
        caratula.appendChild(subtotdte);
       
       Element enviodte = this.doc.createElement("EnvioDTE");
       enviodte.appendChild(setdte);
       setdte.appendChild(caratula);
       
       
       
       /*
       
        xmlns="http://www.sii.cl/SiiDte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://www.sii.cl/SiiDte EnvioDTE_v10.xsd"
      
        */
        Attr attr1 = this.doc.createAttribute("xmlns");
	attr1.setValue("http://www.sii.cl/SiiDte"); 
        enviodte.setAttributeNode(attr1);        
                
        
        Attr attr2 = this.doc.createAttribute("xmlns:xsi");
	attr2.setValue("http://www.w3.org/2001/XMLSchema-instance"); 
        enviodte.setAttributeNode(attr2);   
        
        
        Attr attr3 = this.doc.createAttribute("version");
	attr3.setValue("1.0"); 
        enviodte.setAttributeNode(attr3);        
                
       
        
        Attr attr4 = this.doc.createAttribute("xsi:schemaLocation");
	attr4.setValue("http://www.sii.cl/SiiDte EnvioDTE_v10.xsd"); 
        enviodte.setAttributeNode(attr4);       
        
        
        
     

         this.doc.appendChild(enviodte);
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
       
         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");   
         transformer.setOutputProperty(OutputKeys.ENCODING, "iso-8859-1");
         transformer.setOutputProperty(OutputKeys.INDENT, "yes");
          transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0"); 
              
         DOMSource source = new DOMSource(this.doc);
        
	 StreamResult result;
         /* GUARDO EL SOBRE ELECTRONICO YA INDENTADO, PPERO SIN EL DTE AUN */
         result = new StreamResult(new File(objconfig.getPathdte()+"ENV"+nombredte+".xml"));
	
   
         
         transformer.transform(source, result);
         System.out.println("Done");
      /* EN ESTA SECCIÓN ME ENCARGO DE AGREGAR EL DTE TIMBRADO Y FIRMADO FIRMADO AL SOBRE  */
        addDTE(nombredte);
}      
   
  
   private void addDTE(String nombredte) throws ParserConfigurationException, SAXException, IOException, TransformerException{
     ConfigAppDTE objconfig = new ConfigAppDTE();
      String archivo = objconfig.getPathdte()+ nombredte+".xml";

 FileInputStream archivodte = new FileInputStream(archivo);
 InputStreamReader inputdte = new InputStreamReader(archivodte,"ISO-8859-1");
 InputSource sourcedte = new InputSource(inputdte);      
        
 ByteArrayOutputStream bos=new ByteArrayOutputStream();
 StreamResult result=new StreamResult(bos);
 

	 DocumentBuilderFactory docFactory2 = DocumentBuilderFactory.newInstance();
	 DocumentBuilder docBuilder2 = docFactory2.newDocumentBuilder();
	 Document doc2 = docBuilder2.parse(sourcedte);
         Node dte = doc2.getElementsByTagName("DTE").item(0);
    
       /*   StringWriter buf = new StringWriter(); */
          Transformer xform = TransformerFactory.newInstance().newTransformer();
          
          xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        
         xform.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
         
         xform.setOutputProperty(OutputKeys.INDENT, "no");
         xform.transform(new DOMSource(dte), result);   
         byte []array=bos.toByteArray();
          
        String stringnode = new String(array,"ISO-8859-1");
   
        String filepath = objconfig.getPathdte()+"ENV"+nombredte.trim()+".xml";
	DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
	DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        System.out.print(filepath);     
        Document docENV = docBuilder.parse(filepath.trim());
        
        
        /* datos del emisor */
        Node setdte = docENV.getElementsByTagName("SetDTE").item(0);
     
      
       
    Node fragmentNode = docBuilder.parse(new InputSource(new StringReader(stringnode))).getDocumentElement();
    fragmentNode = docENV.importNode(fragmentNode, true);
    setdte.appendChild(fragmentNode);
       
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
       
         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");   
         transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
         transformer.setOutputProperty(OutputKeys.INDENT, "no");
        
         DOMSource source = new DOMSource(docENV);
        
	 StreamResult result2;
         result2 = new StreamResult(new File(objconfig.getPathdte()+"ENV"+nombredte+".xml"));
	
   
         
         transformer.transform(source, result2);
         System.out.println("Done");
   }
   
   
    

 
}
   
   
   
   



Flujo Principal

1. Preparación del Documento XML

El método generaEnvio crea un documento XML utilizando la API DOM de Java. Esto incluye:

  • Construcción del nodo SetDTE: Nodo raíz del sobre electrónico.
  • Creación de la Caratula: Contiene información clave como:
    • RUT del emisor (RutEmisor).
    • RUT del usuario que envía (RutEnvia).
    • Fecha y hora del envío (TmstFirmaEnv).
    • Resolución del emisor (FchResol, NroResol).
    • Subtotal de DTE enviados (SubTotDTE).
2. Transformación y Escritura

El XML es transformado y almacenado como archivo utilizando la clase Transformer. Esto asegura que el formato final cumpla con los estándares de codificación y estructura exigidos por el SII.

3. Adición de DTE

El método addDTE carga un DTE previamente firmado, lo inserta en el nodo SetDTE, y reescribe el sobre electrónico. Esto implica:

  • Leer el archivo XML del DTE con DocumentBuilder.
  • Importar y agregar el nodo DTE al XML principal.

Características Clave del Código

1. Uso de API DOM para Manejo de XML

El código aprovecha DocumentBuilder, Transformer, y otros elementos de la API DOM para:

  • Crear nodos.
  • Agregar atributos y contenido.
  • Escribir el documento XML resultante.

2. Manejo de Formatos de Fecha y Hora

El código utiliza SimpleDateFormat para generar las marcas de tiempo (TmstFirmaEnv), garantizando que cumplen con el formato ISO exigido.

3. Codificación y Estandarización

Todos los documentos se generan con codificación ISO-8859-1, estándar para documentos XML del SII. Además, el uso de xsi:schemaLocation asegura la validez del esquema.

4. Módulos Extensibles

El diseño de la clase permite integrarse con módulos adicionales, como:

  • ConfigAppDTE: Para manejar rutas y configuraciones específicas.
  • Modelos (DteModel): Contienen los datos básicos del DTE.

Ejemplo de Uso

DteModel objdte = new DteModel();
objdte.setRutemisor("12345678-9"); objdte.setFecharesol("2023-01-01"); objdte.setNumresol("80"); objdte.setTipodte("33"); EnvioDTE envioDTE = new EnvioDTE(); envioDTE.generaEnvio(objdte, "Factura123", "/path/to/dtes/", "98765432-1");

Conclusión

La clase EnvioDTE proporciona un enfoque robusto y eficiente para gestionar el envío de DTE en cumplimiento con las normativas chilenas. Al combinar estructuras claras de XML, manejo de codificaciones y diseño modular, permite un fácil mantenimiento y adaptabilidad en proyectos de factura electrónica. Este diseño facilita su integración en sistemas existentes y garantiza la generación de documentos confiables y válidos para el SII.

Comentarios

Entradas populares de este blog

Configurando Servlets y JSP en Jetty

Firma de un Documento XML con Certificado Digital en Java para Uso Tributario en Chile

RESOLUCION SET BASICO DE FACTURA ELECTRÓNICA SII