GENERACIÓN DE UN DTE PARA EL SII

GENERAR UN DTE Y SU XML

La generación de un DTE con SIMPLE API es bastante sencillo. Utilizando C#, se mostrará como proceder para la obtención de un archivo XML válidamente emitido y su respectivo timbre en formato PDF417.

Requisitos

Para generar un DTE debe cumplir con los siguientes requisitos:

Si desea más información respecto a los primeros pasos, puede consultar nuestro artículo de instalación.

Encabezado del DTE

Parar generar un DTE, se debe realizar una instancia del objeto ubicado en el namespace ChileSystems.DTE.Engine.Documento.DTE de la API

// DOCUMENTO
var dte = new ChileSystems.DTE.Engine.Documento.DTE();
// DOCUMENTO - ENCABEZADO - CAMPO OBLIGATORIO
//Id = puede ser compuesto según tus propios requerimientos pero debe ser único         
dte.Documento.Id = "ID_CUALQUIERA_1";

// DOCUMENTO - ENCABEZADO - IDENTIFICADOR DEL DOCUMENTO - CAMPOS OBLIGATORIOS
dte.Documento.Encabezado.IdentificacionDTE.TipoDTE = ChileSystems.DTE.Engine.Enum.TipoDTE.DTEType.FacturaElectronica;
dte.Documento.Encabezado.IdentificacionDTE.FechaEmision = new DateTime(2020, 1, 8); //08 de enero de 2020
dte.Documento.Encabezado.IdentificacionDTE.Folio = 150; //La gestión del folio la debes realizar internamente

if (tipoDTE == ChileSystems.DTE.Engine.Enum.TipoDTE.DTEType.GuiaDespachoElectronica)
{
    //La guía de despacho debe indicar estos dos atributos de forma obligatoria
    dte.Documento.Encabezado.IdentificacionDTE.TipoTraslado = ChileSystems.DTE.Engine.Enum.TipoTraslado.TipoTrasladoEnum.OperacionConstituyeVenta;
    dte.Documento.Encabezado.IdentificacionDTE.TipoDespacho = ChileSystems.DTE.Engine.Enum.TipoDespacho.TipoDespachoEnum.EmisorACliente;
}
    

El objeto dte instanciado, debe contener un Id alfanumérico y los datos mínimos del encabezado que son el tipo, folio y fecha de emisión. Si el tipo es de guía de despacho electrónica, se deben agregar los dos atributos indicados.

El siguiente paso es definir los datos del emisor:

//DOCUMENTO - ENCABEZADO - EMISOR - CAMPOS OBLIGATORIOS          
dte.Documento.Encabezado.Emisor.Rut = "55555555-5";
dte.Documento.Encabezado.Emisor.DireccionOrigen = "Dirección";
dte.Documento.Encabezado.Emisor.ComunaOrigen = "Comuna";
dte.Documento.Encabezado.Emisor.ActividadEconomica = new List< int>() { 022000, 024001 };
//Para boletas electrónicas
if (tipoDTE == ChileSystems.DTE.Engine.Enum.TipoDTE.DTEType.BoletaElectronica)
{
    dte.Documento.Encabezado.IdentificacionDTE.IndicadorServicio = ChileSystems.DTE.Engine.Enum.IndicadorServicio.IndicadorServicioEnum.BoletaVentasYServicios;
    dte.Documento.Encabezado.Emisor.RazonSocialBoleta = "Razón Social";
    dte.Documento.Encabezado.Emisor.GiroBoleta = "Giro";
}
else
{
    dte.Documento.Encabezado.Emisor.RazonSocial = "Razon Social";
    dte.Documento.Encabezado.Emisor.Giro = "Giro";
}
    

Con esta información es posible identificar correctamente al emisor del DTE. Cabe señalar que los códigos de actividad económica debe contener al menos un dato, y cuatro como máximo. En el caso de que el DTE sea una boleta electrónica, la razón social y el giro se deben definir en los campos RazonSocialBoleta y GiroBoleta.

También debe indicarse los datos de quien recibe el DTE, es decir, el receptor del documento.

//DOCUMENTO - ENCABEZADO - RECEPTOR - CAMPOS OBLIGATORIOS
dte.Documento.Encabezado.Receptor.Rut = "66666666-6";
dte.Documento.Encabezado.Receptor.RazonSocial = "Razon Social de Cliente";
dte.Documento.Encabezado.Receptor.Direccion = "Dirección de cliente";
dte.Documento.Encabezado.Receptor.Comuna = "Comuna de cliente";
dte.Documento.Encabezado.Receptor.Ciudad = "Ciudad de cliente";
dte.Documento.Encabezado.Receptor.Giro = "Giro de cliente";
    

Detalles del DTE

Todos los DTE deben indicar al menos una línea de detalle, que representa un servicio o producto.

//Se instancia la lista de detalles
 dte.Documento.Detalles = new List< ChileSystems.DTE.Engine.Documento.Detalle>();

//Se crea un nuevo detalle
var detalle = new ChileSystems.DTE.Engine.Documento.Detalle();
detalle.NumeroLinea = 1;
detalle.Nombre = "YOGURT 2+2=5";
detalle.Cantidad = 12;
detalle.Precio = 170;
detalle.Descuento = 50;
/*Monto del item*/
detalle.MontoItem = 2040 - 50; //(Cantidad * Precio) - Descuento
//Se agrega el detalle al DTE
dte.Documento.Detalles.Add(detalle);


detalle = new ChileSystems.DTE.Engine.Documento.Detalle();
detalle.NumeroLinea = 2;
detalle.IndicadorExento = ChileSystems.DTE.Engine.Enum.IndicadorFacturacionExencion.IndicadorFacturacionExencionEnum.NoAfectoOExento;
detalle.Nombre = "SERVICIO DESARROLLO DE ETL";
detalle.Cantidad = 20;
detalle.Precio = 1050;
detalle.MontoItem = 21000;
dte.Documento.Detalles.Add(detalle);

En el ejemplo, el detalle N° 2 corresponde a un item exento de IVA.

Impuestos Específicos

En el caso de que el item tuviese impuesto específico, como I.L.A. de bebidas, cervezas, harina, entre otros, se debe indicar en el detalle de esta forma:

//Se instancia el objeto respectivo
detalle.CodigoImpuestoAdicional = new List< ChileSystems.DTE.Engine.Enum.TipoImpuesto.TipoImpuestoEnum>();
//Se agrega el valor correspondiente
detalle.CodigoImpuestoAdicional.Add(valor);
                        

Si por ejemplo, el detalle tuviese un impuesto a los vinos con código 25 (y tasa del 20.5%) sería:

detalle.CodigoImpuestoAdicional.Add(ChileSystems.DTE.Engine.Enum.TipoImpuesto.TipoImpuestoEnum.Vinos);
                        

Descuentos o Recargos de un DTE

Los descuentos pueden existir a nivel de detalle o a nivel global. En el caso de estar en el detalle, sólo se debe restar del monto total y ese valor, corresponderá al monto neto del producto (salvo se indique lo contrario en el DTE), por lo tanto el valor total ya tendrá el descuento aplicado.

En cambio, si desea aplicar un descuento a nivel global, se debe realizar de la siguiente manera:

    
dte.Documento.DescuentosRecargos = new List< ChileSystems.DTE.Engine.Documento.DescuentosRecargos>();
dte.Documento.DescuentosRecargos.Add(new ChileSystems.DTE.Engine.Documento.DescuentosRecargos()
{
Numero = 1,
Descripcion = "DESCUENTO DE BUENA ONDA",
TipoMovimiento = ChileSystems.DTE.Engine.Enum.TipoMovimiento.TipoMovimientoEnum.Descuento,
TipoValor = ChileSystems.DTE.Engine.Enum.ExpresionDinero.ExpresionDineroEnum.Porcentaje,
Valor = 10
});
                        

De la misma forma se pueden agregar recargos al DTE. Se permite un máximo de 20 descuentos o recargos globales. También el valor se puede expresar en pesos.

Cálculo de Totales del DTE

El cálculo de los totales es responsabilidad de cada desarrollador, sin embargo en el proyecto de ejemplo, hay un método en la clase Handler.cs que también los calcula. Corresponde a:

    
dte.Documento.Encabezado.Totales.TasaIVA = Convert.ToDouble(19);

//Cálculo de la suma del neto de detalles que no son exentos.
var neto = dte.Documento.Detalles
.Where(x => x.IndicadorExento == ChileSystems.DTE.Engine.Enum.IndicadorFacturacionExencion.IndicadorFacturacionExencionEnum.NotSet)
.Sum(x => x.MontoItem);

//Cálculo de la suma del exento de detalles que sí son exentos.
var exento = dte.Documento.Detalles
.Where(x => x.IndicadorExento == ChileSystems.DTE.Engine.Enum.IndicadorFacturacionExencion.IndicadorFacturacionExencionEnum.NoAfectoOExento)
.Sum(x => x.MontoItem);

//Cálculo de la suma de los descuentos por detalle
var descuentos = dte.Documento.DescuentosRecargos?
.Where(x => x.TipoMovimiento == ChileSystems.DTE.Engine.Enum.TipoMovimiento.TipoMovimientoEnum.Descuento
&& x.TipoValor == ChileSystems.DTE.Engine.Enum.ExpresionDinero.ExpresionDineroEnum.Porcentaje)
.Sum(x => x.Valor);

if (descuentos.HasValue && descuentos.Value > 0)
{
    var montoDescuentoAfecto = (int)Math.Round(neto * (descuentos.Value / 100), 0, MidpointRounding.AwayFromZero);
    neto -= montoDescuentoAfecto;
}
var iva = (int)Math.Round(neto * 0.19, 0);

Si existen descuentos globales, se deben restar para volver a calcular el neto. Si los detalles tuviesen impuesto adicional, como el vino, se debe agregar lo siguiente:


//Se utiliza el método First() pues se asume que solo hay un impuesto en el detalle (que es lo más común), sin embargo, si este tiene más de un impuesto, el tratamiento debe ser diferente
adicional = (int)Math.Round(
    dte.Documento.Detalles
    .Where(x=>x.CodigoImpuestoAdicional.First() == ChileSystems.DTE.Engine.Enum.TipoImpuesto.TipoImpuestoEnum.Vinos)
    .Sum(x => x.MontoItem) * 0.205, 0);

if (adicional != 0)
{
    dte.Documento.Encabezado.Totales.ImpuestosRetenciones = new List< ChileSystems.DTE.Engine.Documento.ImpuestosRetenciones>();
    dte.Documento.Encabezado.Totales.ImpuestosRetenciones.Add(new ChileSystems.DTE.Engine.Documento.ImpuestosRetenciones()
    {
        MontoImpuesto = adicional,
        TasaImpuesto = 20.5,
        TipoImpuesto = ChileSystems.DTE.Engine.Enum.TipoImpuesto.TipoImpuestoEnum.Vinos
    });
} 

Esta porción de código solo ejemplifica un tipo de impuesto. Es responsabilidad de cada desarrollador la implementación según sus necesidades y modelos.

Finalmente se agregan los totales previamente calculados:

dte.Documento.Encabezado.Totales.MontoNeto = neto;
dte.Documento.Encabezado.Totales.MontoExento = exento;
dte.Documento.Encabezado.Totales.IVA = iva;
dte.Documento.Encabezado.Totales.MontoTotal = neto + exento + iva - adicional;

Referencias

Las referencias a otros documentos son comunes de encontrar, por ejemplo, una factura puede referenciar guías de despacho, ordenes de compra, cotizaciones, entre otros. Así también una nota de crédito que anula una factura, generará una referencia a esta.

dte.Documento.Referencias = new List< ChileSystems.DTE.Engine.Documento.Referencia>();
dte.Documento.Referencias.Add(new ChileSystems.DTE.Engine.Documento.Referencia()
{
    Numero = 1,
    CodigoReferencia = ChileSystems.DTE.Engine.Enum.TipoReferencia.TipoReferenciaEnum.CorrigeMontos, //Si es que aplica
    FechaDocumentoReferencia = DateTime.Now, 
    //Folio de Referencia = Debe ir el folio de la factura o documento que estás refenciando. Es un dato string
    FolioReferencia = "39",                    
    RazonReferencia = "ORDEN DE COMPRA N° 397841A del " + dte.Documento.Encabezado.IdentificacionDTE.FechaEmisionString,
    TipoDocumento = ChileSystems.DTE.Engine.Enum.TipoDTE.TipoReferencia.OrdenCompra
});

Las referencias solo deben aplicarse cuando amerite, no es obligatorio que todos los DTE lleven una, salvo en el caso de que se encuentre en etapa de certificación, pues todos los documentos de los sets deben tener una referencia a su caso de prueba:

dte.Documento.Referencias.Add(new ChileSystems.DTE.Engine.Documento.Referencia()
{
    CodigoReferencia = ChileSystems.DTE.Engine.Enum.TipoReferencia.TipoReferenciaEnum.NotSet,
    FechaDocumentoReferencia = DateTime.Now,
    FolioReferencia = "30", //Acá va el folio del documento que está referenciando, pues cada caso del set de pruebas debe tener asignado uno
    Numero = 1,
    RazonReferencia = "CASO 785178-1",
    TipoDocumento = ChileSystems.DTE.Engine.Enum.TipoDTE.TipoReferencia.SetPruebas
});

Timbrar el DTE

El timbraje de un DTE se debe realizar indicando la ruta del archivo CAF y un API Key que se te entrega al momento de la descarga.

dte.Documento.Timbrar("out\\caf\\", "API-KEY", out string messageOut);

Si existe algún error en el timbraje, se indicará a través de la variable de salida messageOut, caso contrario, este vendrá vacío.

Firmar el DTE

Para la firma electrónica del documento, se debe conocer el nombre del certificado digital, indicar un API Key y la ruta donde se generará el XML.

dte.Firmar("NOMBRE_CERTIFICADO", "API-KEY", out messageOut, "out\\temp\\");

Si existe algún error en el firmado, se indicará a través de la variable de salida messageOut, caso contrario, este vendrá vacío.

El método retorna un string con la ruta del archivo generado.

Descarga el ejemplo y genera tus DTE

El código presentado se encuentra disponible en Github. La clase handler es la que contiene todos los métodos necesarios para la operación de la API.

También se encuentra disponible en Youtube, esta explicación en video Certificacion set de pruebas SII Chile con Simple API .NET C#.