Skip to content

Emitir CFEs

El SDK provee métodos de fábrica en UruFacturaClient para crear cada tipo de CFE:

MétodoCFE generadoCódigo DGI
CrearETicket()e-Ticket101
CrearNotaCreditoETicket()Nota de Crédito e-Ticket102
CrearNotaDebitoETicket()Nota de Débito e-Ticket103
CrearEFactura()e-Factura111
CrearNotaCreditoEFactura()Nota de Crédito e-Factura112
CrearNotaDebitoEFactura()Nota de Débito e-Factura113
CrearEFacturaExportacion()e-Factura de Exportación121
CrearNotaCreditoEFacturaExportacion()NC e-Factura de Exportación122
CrearNotaDebitoEFacturaExportacion()ND e-Factura de Exportación123
CrearERemitoDespachante()e-Remito Despachante131
CrearEResguardo()e-Resguardo151
CrearERemito()e-Remito181
CrearNotaCreditoERemito()Nota de Crédito e-Remito182

El e-Ticket es el comprobante más común para ventas al consumidor final (sin identificación del receptor).

var eticket = client.CrearETicket();
eticket.Numero = 1; // Número del comprobante
eticket.FechaEmision = DateOnly.FromDateTime(DateTime.Today); // Opcional, por defecto hoy
// Agregar líneas de detalle
eticket.Detalle.Add(new LineaDetalle
{
NroLinea = 1,
NombreItem = "Servicio de consultoría",
Cantidad = 2,
PrecioUnitario = 3500m,
IndFactIva = TipoIva.Basico, // 22%
});
eticket.Detalle.Add(new LineaDetalle
{
NroLinea = 2,
NombreItem = "Viáticos",
Cantidad = 1,
PrecioUnitario = 1000m,
IndFactIva = TipoIva.Exento, // Sin IVA
});
var respuesta = await client.EnviarCfeAsync(eticket);

La e-Factura requiere identificar al receptor (empresa o persona).

var efactura = client.CrearEFactura();
efactura.Numero = 1;
// Datos del receptor (obligatorio para e-Factura)
efactura.Receptor = new Receptor
{
Documento = "210000000013",
TipoDocumento = TipoDocumentoReceptor.Rut,
RazonSocial = "Empresa Compradora S.A.",
Direccion = "Bulevar España 2345",
Ciudad = "Montevideo",
};
efactura.Detalle.Add(new LineaDetalle
{
NroLinea = 1,
NombreItem = "Licencia de software anual",
Cantidad = 1,
PrecioUnitario = 50000m,
IndFactIva = TipoIva.Basico,
});
var respuesta = await client.EnviarCfeAsync(efactura);

Las notas de corrección deben referenciar el CFE original.

var notaCredito = client.CrearNotaCreditoETicket();
notaCredito.Numero = 1;
// Referenciar el comprobante que se está corrigiendo
notaCredito.Referencias.Add(new RefCfe
{
TipoCfe = TipoCfe.ETicket,
Serie = "A",
NroCfe = 42, // Número del CFE original
FechaCfe = new DateTime(2025, 6, 15),
Razon = "Devolución parcial de mercadería",
});
notaCredito.Detalle.Add(new LineaDetalle
{
NroLinea = 1,
NombreItem = "Devolución - Producto X",
Cantidad = 2,
PrecioUnitario = 500m,
IndFactIva = TipoIva.Basico,
});
var respuesta = await client.EnviarCfeAsync(notaCredito);

El enum TipoIva define cómo se calcula el IVA de cada línea:

ValorTasaUso común
TipoIva.Basico22%Servicios y bienes generales
TipoIva.Minimo10%Alimentos de primera necesidad
TipoIva.Exento0%Bienes y servicios exonerados
TipoIva.SuspendidoIVA suspendido por disposición legal (sin cálculo, genera MntSuspenso en el XML)

Si necesitás el XML firmado para archivarlo o procesarlo por separado:

string xmlFirmado = client.GenerarYFirmar(eticket);
// Guardar el XML
await File.WriteAllTextAsync($"eticket_{eticket.Numero:D8}.xml", xmlFirmado);

try
{
var respuesta = await client.EnviarCfeAsync(eticket);
switch (respuesta.Codigo)
{
case "00":
Console.WriteLine("✅ Aceptado");
break;
case "01":
Console.WriteLine($"⚠️ Aceptado con observaciones: {respuesta.Mensaje}");
break;
default:
Console.WriteLine($"❌ Rechazado [{respuesta.Codigo}]: {respuesta.Mensaje}");
break;
}
}
catch (DgiCommunicationException ex)
{
Console.Error.WriteLine($"Error de comunicación con DGI: {ex.Message}");
}
catch (UruFacturaException ex)
{
Console.Error.WriteLine($"Error del SDK: {ex.Message}");
}

Ver Códigos de respuesta DGI para la lista completa de códigos.