Núcleo de facturación electrónica DIAN y SUNAT
El motor fiscal de un ERP contable: construye, firma y envía los documentos electrónicos de miles de empresas ante las autoridades tributarias de Colombia y Perú.
2
autoridades tributarias
15
tipos de evento de título valor
11
estrategias de error
0
contratos rotos al modernizar
La facturación electrónica no admite “casi bien”. Un atributo fuera de lugar en el XML, una firma mal construida o un identificador mal calculado y la autoridad tributaria rechaza el documento: la empresa no puede facturar, y no facturar es no vender. A eso se suma que el catálogo no para de crecer —documento soporte, documentos equivalentes POS, notas crédito y débito, exportación, sector transporte, sector salud, AIU, retenciones— y que cada país tiene su propio esquema y su propia forma de firmar.
Construí y mantengo el núcleo que resuelve el ciclo completo: armado del XML bajo el estándar UBL 2.1, cálculo de los identificadores únicos de cada documento, firma digital XAdES con certificado, envío a la autoridad, comparación de la respuesta contra lo enviado, generación del PDF con su código QR, envío del correo con los adjuntos y reproceso automático de lo que quedó a medias. Cubre facturación electrónica, nómina electrónica y los eventos de factura como título valor.
El diálogo con la autoridad tributaria es SOAP, un protocolo de otra época que no se puede cambiar de forma unilateral: del otro lado hay una entidad estatal. La tentación era dejar ese núcleo congelado en el framework antiguo para siempre. En vez de eso lo reescribí sobre .NET moderno usando CoreWCF, que permite seguir hablando SOAP exactamente igual mientras el resto del código gana inyección de dependencias, acceso a datos moderno y pruebas. El contrato hacia afuera no cambió ni un carácter; hacia adentro cambió todo. Los errores de la autoridad, por su parte, no se resuelven con una cadena de condicionales que nadie se atreve a tocar: cada tipo de error es una estrategia independiente que una factoría selecciona.
Miles de empresas facturando a diario contra dos autoridades tributarias, con reprocesos automáticos que resuelven las caídas del servicio estatal sin intervención humana, y un núcleo que hoy corre sobre .NET moderno sin que ningún consumidor tuviera que migrar.
Cómo se ve por dentro
Ejemplos ilustrativos de los patrones aplicados, con la razón de cada decisión.
Cada error de la autoridad es una clase, no un caso más del switch
public interface IEstrategiaErrorDian
{
bool Aplica(string codigo);
Task<ResultadoReproceso> ResolverAsync(DocumentoElectronico doc, CancellationToken ct);
}
public sealed class FabricaEstrategiasError
{
private readonly IEnumerable<IEstrategiaErrorDian> _estrategias;
public IEstrategiaErrorDian Resolver(string codigo) =>
_estrategias.FirstOrDefault(e => e.Aplica(codigo))
?? throw new ErrorDianNoReconocidoException(codigo);
}La autoridad devuelve decenas de códigos de rechazo distintos, y aparecen nuevos cada resolución. Con estrategias registradas, soportar uno nuevo es añadir una clase: el orquestador no se toca y no hay riesgo de romper el manejo de los demás.
Ejemplo ilustrativo del patrón aplicado; no es código de ningún producto.SOAP heredado sobre .NET moderno
builder.Services.AddServiceModelServices();
app.UseServiceModel(serviceBuilder =>
{
serviceBuilder.AddService<ServicioFacturacionElectronica>();
serviceBuilder.AddServiceEndpoint<ServicioFacturacionElectronica, IFacturacionElectronica>(
new BasicHttpBinding(BasicHttpSecurityMode.Transport),
"/FacturacionElectronica.svc");
});CoreWCF expone el mismo contrato SOAP de siempre desde .NET moderno. Para la autoridad tributaria nada cambió; del lado de acá el servicio ya recibe sus dependencias por inyección y es comprobable con pruebas.
Ejemplo ilustrativo del patrón aplicado; no es código de ningún producto.Stack del proyecto
¿Necesitas algo parecido?
Cuéntame tu caso y te digo con franqueza si es viable y cuánto toma.
Hablemos