Sistema de facturación para pequeñas empresas eslovenas
Una herramienta de facturación PHP autoalojada construida para pequeñas empresas eslovenas — códigos UPN QR, cumplimiento de DDV/VAT, motores duales de PDF y envío por correo electrónico. Probada en libros contables reales y despliegues con clientes.
Resumen
Construí este sistema de facturación para pequeñas empresas eslovenas — del tipo que emite unas decenas de facturas al año, necesita mantenerse al día con las reglas eslovenas de DDV/VAT y quiere una herramienta autoalojada que no llame a casa ni te encierre en una suscripción SaaS.
Está en producción desde 2024, cubriendo ciclos reales de facturación. El alcance es deliberadamente estrecho: crea una factura, genera un PDF conforme con un código UPN QR que el banco del cliente pueda escanear y envíalo por correo. Todo es configurable a través de una interfaz web sin sobrecarga de framework — PHP 8 puro, almacenamiento JSON plano y un REST API que también me permite emitir facturas desde la CLI o desde otras herramientas.
La parte más difícil no fue la UI — fue lograr el código UPN QR exactamente correcto. El estándar exige un payload específico de 19 campos en codificación ISO-8859-2, un código de propósito GDSV, una referencia de pago SI00 derivada del número de factura y una suma de verificación de 3 dígitos que cuenta las longitudes de todos los campos más los caracteres de nueva línea entre ellos. Cada aplicación bancaria eslovena valida esto estrictamente. También implementé el microservicio UPN-QR adyacente como un generador de QR independiente en Node.js/Express que sigue el mismo estándar — útil para otras integraciones.
Arquitectura
Leyendo el diagrama: Las facturas entran vía la UI del navegador o el REST API (autenticado por API key). La clase InvoiceGenerator maneja el modelo completo de datos — fechas, notas de exención de DDV, descuentos por línea y generación del payload UPN QR. Los PDFs se renderizan con TCPDF (primario) con fallback automático a mPDF; el código QR se incrusta directamente. Las facturas completadas se almacenan como archivos JSON planos en un directorio fuera del web root, y el envío de correo va a través de PHPMailer 6 soportando tres métodos de envío. Todo se despliega vía GitHub → cPanel SSH.
Mockup de factura
Mockup estilizado del PDF generado — cabecera de tres columnas, tabla de líneas con descuentos por línea, nota a pie sobre la exención de DDV, código UPN QR (escaneado por cualquier aplicación bancaria eslovena) y referencia de pago SI00 derivada del número de factura.
Pequeño no significa fácil de hacer bien. La facturación eslovena tiene requisitos legales reales, y cada PDF que se envía es un documento legal.
Seis cosas entregadas,
tres difíciles resueltas.
Contribuciones clave
- Diseñé e implementé el sistema completo de facturación desde cero — interfaz web, REST API, pipeline de PDF, envío de correo y capa de datos.
- Implementé el estándar esloveno UPN QR: payload de 19 campos en ISO-8859-2, referencia de pago SI00, código de propósito GDSV y suma de verificación de 3 dígitos.
- Construí un pipeline de PDF con motor dual (TCPDF + mPDF) con fallback automático y una plantilla separada flex-free para mPDF para compatibilidad.
- Conecté el cumplimiento de DDV/VAT para dos regímenes: exención doméstica para pequeñas empresas (94. člen ZDDV-1) e inversión del sujeto pasivo UE (artículo 44 de la Directiva 2006/112/ES).
- Entregué envío de correo configurable — php_mail, sendmail y SMTP completo vía PHPMailer 6 — con mensajes plantillados en Markdown y archivo PDF adjunto.
- Configuré CI/CD desde GitHub a cPanel VPS vía SSH deploy keys; los archivos de datos viven fuera del web root y se respaldan de forma asíncrona a un repositorio privado adyacente.
Desafíos resueltos
- El estándar esloveno UPN QR es estricto: 19 campos separados por saltos de línea, importes en céntimos rellenados con ceros a 11 dígitos, contenido en ISO-8859-2 y una suma de verificación de 3 dígitos que cuenta todos los caracteres de nueva línea. Un byte mal y cada aplicación bancaria lo rechaza.
- TCPDF y mPDF se comportan de forma distinta con HTML flexbox — mPDF simplemente lo ignora. Mantener dos variantes de plantilla sin duplicar la lógica de negocio requirió una separación limpia entre el renderizado de datos y el layout.
- El hosting compartido cPanel impone restricciones estrictas: sin workers en segundo plano, sin Redis, sin temp del sistema con permisos de escritura por defecto. El respaldo asíncrono usa proc_open con bypass_shell tanto en Windows (dev) como en Linux (prod).
Qué hay bajo el capó.
¿Listo para arreglar, construir
o escalar?
30 minutos, conmigo personalmente. Leo tu sistema como un archivo de logs y te digo qué haría primero. Sin presentaciones, sin embudo de ventas.
— Davor Majc, fundador, Numen

