Skip to content

Latest commit

 

History

112 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VeriFactu - Módulo para Dolibarr

Módulo de Dolibarr para la integración con el sistema VeriFactu de la Agencia Estatal de Administración Tributaria (AEAT), en cumplimiento de la Ley 11/2021 (Ley Antifraude) y el Real Decreto 1007/2023 que establece los requisitos técnicos para los sistemas de facturación en España.

Historia del Proyecto

Este proyecto tiene su origen en el código abierto verifactu desarrollado originalmente por Alberto SuperAdmin (Alberto Luque Rivas) de easysoft.es y distribuido bajo licencia GPL v3.

Desarrollo

Este módulo fue desarrollado a partir del módulo original licenciado bajo GPL v3 (GNU General Public License version 3). Sobre esta base:

  • Se reorganizó y modularizó el código para mejorar la mantenibilidad
  • Se tradujeron la documentación y los comentarios al inglés
  • Se creó una nueva librería interna (OpenAEAT\Billing)

Este fork mantiene todo el código bajo GPL v3, respetando la licencia original y los derechos de los autores originales, añadiendo la atribución correspondiente en todos los archivos.


Descripción

VeriFactu es el sistema de verificación de facturas de la AEAT que permite:

  • Envío automático de facturas a la AEAT
  • Generación de códigos QR de verificación
  • Encadenamiento criptográfico de facturas (SHA-256)
  • Consulta del estado de facturas enviadas
  • Anulación de facturas
  • Gestión de facturas rectificativas

Requisitos

  • Dolibarr 13.0 o superior
  • PHP 7.4 o superior
  • Extensión PHP SOAP habilitada
  • Extensión PHP OpenSSL habilitada
  • Extensión PHP GD habilitada (para QR)
  • Certificado digital válido (FNMT o equivalente)

Instalación

  1. Copiar la carpeta verifactu en el directorio htdocs/custom/ de Dolibarr
  2. Ir a Configuración > Módulos en Dolibarr
  3. Buscar "VeriFactu" en la lista de módulos
  4. Activar el módulo

Configuración

1. Configuración General

Ir a Configuración > Módulos > VeriFactu > Configuración

  • Entorno: Seleccionar Pruebas o Producción
  • NIF Emisor: Número de identificación fiscal de la empresa
  • Nombre/Razón Social: Nombre de la empresa

2. Certificado Digital

Ir a Configuración > Módulos > VeriFactu > Certificados

  1. Subir el certificado en formato PFX/P12
  2. Introducir la contraseña del certificado
  3. Verificar que el certificado es válido

El certificado debe ser:

  • Certificado de persona jurídica (empresa)
  • Emitido por una CA reconocida (FNMT, etc.)
  • Válido y no revocado

3. Sistema Informático

Configurar los datos del sistema de facturación:

  • NIF Desarrollador: NIF del desarrollador del software
  • Nombre del Sistema: Nombre del sistema de facturación
  • ID del Sistema: Identificador único del sistema
  • Versión: Versión del software

4. Esquemas WSDL/XSD

El módulo descarga y cachea localmente los esquemas WSDL y XSD necesarios para la comunicación SOAP con la AEAT. Esto evita dependencias de servidores externos (AEAT, W3C) y previene errores de rate-limiting al procesar muchas facturas seguidas.

  • Los esquemas se descargan automáticamente la primera vez que se envía una factura
  • En Configuración > Módulos > VeriFactu > Configuración se muestra el estado de los esquemas
  • Usar el botón Descargar/Actualizar esquemas para forzar la re-descarga si la AEAT actualiza los esquemas

Fecha de operación

Cuando la fecha en que se efectúa una operación es distinta de la fecha en que se expide la factura, la que determina el devengo del IVA es la primera. Es el caso de una factura emitida en enero por un servicio prestado en diciembre.

En Configuración → Transmitir la fecha de operación se habilita el envío de ese dato a la AEAT en el campo FechaOperacion. Al activarlo:

  • Se habilita el campo de fecha Impuestos en la factura, que es de donde se toma (Dolibarr lo controla con la constante INVOICE_POINTOFTAX_DATE).
  • La fecha solo se transmite cuando difiere de la fecha de factura. Si ambas coinciden, el registro sale igual que antes.

Opción de fecha de operación

Rellenando ese campo, la factura se expide con su fecha y el IVA se imputa al periodo de la operación:

Factura con fecha de operación

La fecha de operación no interviene en la huella ni en el código QR, así que informarla no afecta al encadenamiento.

Presentación de la ficha y de los listados

Los bloques Datos VeriFactu y Campos fiscales aparecen plegados en la ficha de la factura. Se despliegan con un clic y Dolibarr recuerda la elección.

En los listados, las columnas de detalle fiscal están disponibles en el selector de columnas, pero no se muestran de entrada: a la vista queda el estado VeriFactu. Cada usuario activa las que necesite.

El distintivo de estado junto al número de factura se controla con la constante VERIFACTU_STATUS_BADGE_ON_REF:

Valor Efecto
card Por defecto. En la ficha de la factura sí, en los listados no
always En todas partes, como hasta la versión 2.2.0
never No se muestra

Uso

Envío de Facturas

  1. Crear una factura en Dolibarr
  2. Validar la factura
  3. En la pestaña "VeriFactu" de la factura:
    • Hacer clic en "Enviar a AEAT"
    • Verificar el estado de la respuesta

Validación Masiva

La validación masiva de facturas procesa cada factura en una transacción independiente:

  • Si una factura falla, las demás continúan procesándose normalmente
  • Se detectan automáticamente conflictos de fechas con VeriFactu (orden cronológico)
  • Si hay conflictos, se muestra un diálogo de confirmación antes de ajustar las fechas
  • Las facturas se procesan ordenadas por fecha (de menor a mayor)

Validación Individual

Al validar una factura individual (PROV), el sistema:

  • Ajusta automáticamente la fecha a max(hoy, última_factura_validada) para respetar el orden cronológico de VeriFactu
  • Muestra un aviso en el diálogo de confirmación si la fecha fue ajustada, indicando la fecha original, la nueva fecha y la referencia de la última factura validada

Consulta de Facturas

  1. Ir a Facturación > VeriFactu > Consulta AEAT
  2. Seleccionar los filtros de búsqueda:
    • Período de imputación (año/mes)
    • Rango de fechas
    • Contraparte (NIF del cliente)
  3. Hacer clic en "Consultar"

Anulación de Facturas

  1. Acceder a la factura enviada
  2. En la pestaña "VeriFactu":
    • Hacer clic en "Anular en AEAT"
    • Seleccionar el tipo de anulación
    • Confirmar la operación

Código QR

El código QR se genera automáticamente al enviar la factura y se muestra en:

  • La vista de la factura
  • El PDF de la factura (si está configurado)
  • El ticket de TPV (si está habilitado)

Tipos de Factura Soportados

Código Descripción
F1 Factura completa
F2 Factura simplificada
F3 Factura sustitutiva de simplificadas
R1 Rectificativa (error fundado en derecho)
R2 Rectificativa (Art. 80.3)
R3 Rectificativa (Art. 80.4)
R4 Rectificativa (otras)
R5 Rectificativa en factura simplificada

Idiomas Soportados

  • Español (es_ES)
  • Catalán (ca_ES)
  • Euskera (eu_ES)
  • Gallego (gl_ES)
  • Inglés (en_US)

Declaración Responsable

El módulo incluye un sistema completo de Declaración Responsable en cumplimiento con la normativa española vigente:

  • RD 1007/2023 - Reglamento VeriFactu
  • RD 254/2025 - Modificaciones y plazos
  • Orden HAC/1177/2024 - Especificaciones técnicas
  • Art. 29.2.j) Ley 58/2003 - Ley General Tributaria

Archivo de Configuración

La configuración se encuentra en conf/declaracion_responsable.conf.php e incluye:

Sección Contenido
Datos del Productor NIF, razón social, dirección, contacto
Datos del Sistema Nombre, IdSistemaInformatico, versión
Componentes Software y hardware requeridos
Especificaciones Técnicas Tipo de firma (XAdES), algoritmo hash (SHA-256)
Integridad Hash del módulo calculado dinámicamente
Cumplimiento Declaración según Art. 29.2.j) LGT
Suscripción Fecha, lugar y firmante

Funciones Disponibles

// Obtener configuración completa con hash calculado
$declaracion = obtenerDeclaracionResponsable(true);

// Validar campos obligatorios
$errores = validarDeclaracionResponsable();

// Calcular hash SHA-256 del módulo
$hash = calcularHashModuloVerifactu();

// Exportar en formato JSON
$json = exportarDeclaracionJSON();

Visualización

La declaración responsable está disponible en:

  • Menú: VeriFactu > Declaración Responsable
  • Exportación JSON: /verifactu/views/declaration_json.php

Para más detalles, ver docs/responsible_declaration.md.

Estructura del Módulo

verifactu/
├── admin/                  # Páginas de administración
│   ├── setup.php           # Configuración general
│   ├── managecertificates.php  # Gestión de certificados
│   └── uploadcertificates.php  # Subida de certificados
├── class/                  # Clases PHP
│   ├── actions_verifactu.class.php  # Hooks y acciones
│   ├── api_verifactu.class.php      # API REST
│   └── verifactu.utils.php          # Utilidades
├── conf/                   # Configuración
│   └── declaracion_responsable.conf.php  # Declaración responsable
├── core/
│   ├── modules/            # Descriptor del módulo
│   └── triggers/           # Triggers automáticos
│       ├── interface_900_modVerifactu_BillRestrictions.class.php
│       └── interface_999_modVerifactu_VerifactuTriggers.class.php
├── docs/                   # Documentación
│   └── responsible_declaration.md  # Doc. declaración responsable
├── lib/
│   ├── newfenix/           # Librería OpenAEAT Billing
│   │   ├── src/            # Clases principales
│   │   │   ├── SchemaManager.php  # Gestión de esquemas WSDL/XSD
│   │   │   ├── SoapClient.php     # Transporte SOAP
│   │   │   ├── Config.php         # Configuración
│   │   │   ├── Manager.php        # Orquestador
│   │   │   ├── Invoice.php        # Modelo de factura
│   │   │   ├── Cancellation.php   # Modelo de anulación
│   │   │   └── Query.php          # Modelo de consulta
│   │   └── vendor/         # Dependencias (QRCode)
│   └── functions/          # Funciones del módulo
│       ├── functions.submission.php    # Envío de facturas
│       ├── functions.query.php         # Consultas AEAT
│       ├── functions.cancellation.php  # Anulación
│       ├── functions.certificates.php  # Certificados
│       ├── functions.compatibility.php # Funciones de compatibilidad
│       ├── functions.qr.php            # Generación QR
│       └── functions.response.php      # Respuestas AEAT
├── tests/                  # Tests
│   ├── MassValidateInterceptionTest.php  # Tests validación masiva
│   └── SchemaManagerTest.php             # Tests gestión de esquemas
├── views/                  # Vistas y páginas
│   ├── list.facture.php    # Lista de facturas
│   ├── query.facture.php   # Consulta AEAT
│   ├── tabVERIFACTU.facture.php  # Pestaña VeriFactu
│   ├── declaration.php     # Declaración responsable
│   ├── declaration_json.php  # Exportación JSON declaración
│   ├── faq.php             # Ayuda y FAQ
│   ├── pos.facture.php     # Ticket TPV
│   └── documentation.php   # Documentación
├── langs/                  # Archivos de idioma
├── css/                    # Estilos CSS
├── js/                     # JavaScript
└── README.md               # Este archivo

API REST

El módulo expone una API REST para integración externa. La ruta base es verifactuapi (el núcleo de Dolibarr localiza la clase VerifactuApi por el primer segmento de la URL):

GET  /api/index.php/verifactuapi/integrity      # público, como integrity.php
POST /api/index.php/verifactuapi/toProduction   # clave de API (DOLAPIKEY) de un administrador
POST /api/index.php/verifactuapi/toTest         # clave de API (DOLAPIKEY) de un administrador

Resolución de Problemas

Error SOAP 4118

Este error indica un problema con la estructura del mensaje SOAP. Verificar:

  • Formato de fecha (DD-MM-AAAA)
  • Datos del emisor y destinatario
  • Configuración del certificado

Error SOAP por rate-limiting de W3C

Si aparecen errores al crear el SoapClient al procesar muchas facturas seguidas, es porque PHP intenta descargar xmldsig-core-schema.xsd desde w3.org y este servidor aplica rate-limiting. Solución:

  • Ir a Configuración > Módulos > VeriFactu > Configuración
  • Pulsar el botón Descargar/Actualizar esquemas para cachear los WSDL/XSD localmente
  • Los esquemas se descargan automáticamente en el primer uso, pero se puede forzar desde aquí

Error de Certificado

Si el certificado no es reconocido:

  • Verificar que el certificado no ha expirado
  • Comprobar que la contraseña es correcta
  • Asegurarse de que el certificado es de persona jurídica

Certificados FNMT .p12 rechazados con OpenSSL 3

Si al subir un .p12 de la FNMT (habitual en autónomos y personas físicas) el módulo responde que la contraseña no es correcta aunque sí lo sea, lo más probable es que el problema no sea la contraseña sino el cifrado del contenedor PKCS#12.

La FNMT ha protegido históricamente estos ficheros con algoritmos legacy (RC2-40-CBC y PBE-SHA1-3DES). OpenSSL 3 —el que traen Debian 12 y la imagen oficial dolibarr/dolibarr— desactiva estos algoritmos salvo que se active el legacy provider, por lo que openssl_pkcs12_read() falla con error:0308010C: digital envelope routines::unsupported.

Desde la versión 2.0.0 el módulo:

  • Reintenta automáticamente la extracción con openssl pkcs12 -legacy, de modo que en la mayoría de servidores el certificado se acepta sin tocar nada.
  • Distingue en el mensaje de error entre contraseña incorrecta y algoritmo de cifrado legacy no soportado, en lugar de culpar siempre a la contraseña.

Hosting compartido: exec() y proc_open() desactivados

En muchos alojamientos compartidos (Loading.es, Hostinger y similares) tanto exec() como proc_open() están en disable_functions, por lo que el módulo no puede invocar el binario openssl del sistema.

Desde la versión 2.0.0 esto ya no impide usar certificados: la extracción intenta primero las funciones OpenSSL propias de PHP (openssl_pkcs12_read()), que no necesitan lanzar ningún proceso, y solo recurre al binario externo cuando hace falta. En la práctica:

Certificado Hosting normal Hosting compartido sin proc_open
Cifrado moderno funciona funciona
Cifrado legacy (FNMT antiguo) funciona (vía -legacy) no es posible

El único caso que no tiene solución desde el módulo es un certificado con cifrado legacy en un servidor sin acceso al binario openssl ni a openssl.cnf: ahí hay que reexportar el certificado con un algoritmo moderno (opción B más abajo) desde otra máquina.

Si el certificado legacy sigue fallando

Si el binario openssl del servidor no tiene el proveedor legacy disponible, hay dos soluciones:

Opción A — activar el legacy provider en el servidor. Editar /etc/ssl/openssl.cnf y dejar la sección de proveedores así:

[provider_sect]
default = default_sect
legacy = legacy_sect

[default_sect]
activate = 1

[legacy_sect]
activate = 1

Opción B — reexportar el certificado con un algoritmo moderno, en una máquina donde sí se pueda abrir:

openssl pkcs12 -legacy -in certificado_fnmt.p12 -nodes -out temporal.pem -password pass:TU_CLAVE
openssl pkcs12 -export -in temporal.pem -out certificado_moderno.p12 -password pass:TU_CLAVE
rm temporal.pem

Después subir certificado_moderno.p12 desde la pestaña Certificados.

Pantalla en Blanco

Si aparece una pantalla en blanco al ver facturas:

  • Revisar los logs de PHP en busca de errores
  • Verificar que todas las extensiones PHP están instaladas

Facturas con Retención IRPF

El módulo calcula correctamente el ImporteTotal para VeriFactu excluyendo la retención IRPF:

  • ImporteTotal = Base Imponible + IVA + Recargo de Equivalencia (sin deducir IRPF)
  • El código QR refleja este importe correcto
  • Las consultas a AEAT comparan con el importe correcto

Información del Módulo

  • Versión: 2.2.3
  • Autor: Germán Luis Aracil Boned
  • Email: garacilb@gmail.com
  • Licencia: GPL-3.0-or-later
  • Dedicado a: Mi compañero y amigo Ildefonso González Rodríguez

Agradecimientos

Este módulo mejora gracias a quien se toma el trabajo de reproducir un fallo, leer la normativa y contarlo con detalle. Nominalmente, y por lo que aportó cada uno:

  • @hisie (Diego Cebrián) — revisión de conformidad con el RD 1007/2023 y la Orden HAC/1177/2024 (issue #30), con referencia al articulado punto por punto. De ahí salieron la identidad del sistema informático declarada y transmitida, el hash de integridad que dejaba ficheros fuera, la exclusión de las proformas y el tipo rectificativo que se mostraba distinto del que se enviaba. Y en la 2.1.0, su análisis de la condición de carrera en el encadenamiento y del envío no garantizado en la validación: al ir a resolverlo apareció además que la cadena no se construía en absoluto sobre PostgreSQL, así que ese hallazgo se le debe también a él.
  • @braito4 — ocho propuestas de corrección normativa (PR #34 a #41): respuestas parciales de la AEAT, semántica de RechazoPrevio, validación del registro contra el esquema, control de flujo del servicio, validez del certificado e identidad fiscal, aislamiento entre entidades MultiCompany y la columna de fecha de creación. Cada una venía con su test.
  • @hippo16214 — los certificados .p12 de la FNMT rechazados por OpenSSL 3 (issue #33), con el comando exacto para generar un contenedor legacy reproducible, que hoy se ejecuta en cada pasada de la suite de regresión; y el TypeError del generador de QR que rompía la vista de factura en PHP 8 (issue #32), diagnosticado hasta la línea.
  • @jose73wrc (José Antonio) — el error fatal del informe de pagos (issue #31), con la traza y la causa raíz ya identificadas; y el aviso de que la corrección de los certificados no servía en alojamientos compartidos donde proc_open está desactivado, que es lo que llevó a leer el .p12 con las funciones nativas de PHP antes que con el binario.

Registro de Cambios

v2.2.3 (2026-09-24)

Atiende la issue #51, propuesta por @xabitrigo, y las observaciones sobre la interfaz que planteó en el mismo hilo.

Fecha de operación

La fecha en que se efectúa la operación es la que determina el devengo del IVA, mientras que la fecha de expedición es la que ordena la numeración de las facturas (Art. 10.1.d del RD 1007/2023, Art. 6.1.f del RD 1619/2012). Hasta ahora el módulo solo transmitía la de expedición.

SuministroInformacion.xsd declara FechaOperacion como opcional, de tipo sf:fecha —el mismo formato dd-mm-aaaa de FechaExpedicionFactura— y la sitúa justo antes de DescripcionOperacion, que es donde se inserta. No interviene en la huella, que se calcula sobre IDEmisorFactura, NumSerieFactura, FechaExpedicionFactura, TipoFactura, CuotaTotal, ImporteTotal, la huella anterior y FechaHoraHusoGenRegistro; se ha comprobado generando el registro con y sin ella.

Se toma de date_pointoftax, el campo «Impuestos» que Dolibarr muestra en la factura, y solo se transmite cuando difiere de la fecha de expedición.

Hay una opción nueva en la configuración del módulo, Transmitir la fecha de operación, desactivada por defecto porque cambia lo que se remite a la AEAT. Al activarla se habilita también INVOICE_POINTOFTAX_DATE, la constante de Dolibarr que muestra ese campo en la factura y que de otro modo hay que fijar a mano.

La ficha de factura ya no queda sepultada

Los separadores de los bloques fiscales se declaraban desplegados, de modo que ocupaban 730 px de los 1870 de la página y las líneas de factura quedaban fuera de la vista. Dolibarr admite separadores plegados —la clave 2 del array de opciones, que showSeparator() interpreta—, así que pasan a declararse así. La página baja a 1209 px y quien los despliegue mantiene su preferencia, porque el propio núcleo la guarda en una cookie.

Los listados vuelven a caber en la pantalla

El módulo añadía 16 columnas a los listados de facturas, casi todas vacías, que dejaban la tabla en 8153 px de ancho. Con la visibilidad en negativo —patrón del propio Dolibarr— la columna sigue disponible en el selector de columnas pero no aparece marcada: el listado baja a 2190 px y 15 columnas, con el estado VeriFactu a la vista.

El distintivo de estado que se pegaba a cada número de factura lo gobierna ahora VERIFACTU_STATUS_BADGE_ON_REF: card por defecto (en la ficha sí, en los listados no), always para el comportamiento anterior y never para retirarlo.

Una instalación que actualice recibe estos mismos ajustes: addExtraField() no reescribe un campo que ya existe, así que alignExtraFieldDisplay() los aplica sobre los campos ya creados, respetando los que el administrador haya cambiado por su cuenta.

Verificación

Sobre una instalación real de Dolibarr 19.0.3 con PostgreSQL 16, con el módulo activado y facturas de prueba:

Comprobación Antes Después
Alto de la ficha de factura 1870 px 1209 px
Ancho del listado de facturas 8153 px 2190 px
Columnas por fila en el listado 30 15
FechaOperacion en el registro no existía se transmite y no altera la huella

v2.2.2 (2026-09-19)

Correcciones propias del autor del módulo, @garacil (Germán Luis Aracil Boned), detectadas al revisar el código fuente para redactar la wiki del proyecto.

La API REST permitía cambiar el entorno sin autenticación

class/api_verifactu.class.php declaraba @access public en la clase y en sus tres métodos. Restler, el framework de la API de Dolibarr, solo autentica los métodos con un nivel de acceso superior a público, así que toProduction y toTest podían invocarse sin clave de API ni permiso alguno: cualquiera que alcanzase la URL de la API podía decidir a qué entorno de la AEAT se remitían los registros de facturación de una entidad.

Ahora ambos métodos se declaran @access protected, como los de la API del núcleo de Dolibarr, de modo que exigen una clave de API válida (DOLAPIKEY), y además rechazan con HTTP 403 a cualquier usuario que no sea administrador, antes de tocar la configuración. El hash de integridad sigue siendo público, igual que integrity.php. La ruta base de la API es verifactuapi y no verifactu como indicaba este README; queda corregida en la sección «API REST».

En Dolibarr 17 la API del módulo no llega a ejecutarse: el Restler que incluye esa versión del núcleo termina con Access to undeclared static property Composer\Autoload\ClassLoader::$loader en cuanto hay registrado un autoloader de Composer, como el de lib/newfenix/vendor. Es un fallo del núcleo, corregido en versiones posteriores de Dolibarr, anterior a esta versión e independiente de ella. Donde la API sí funciona (Dolibarr 19 y posteriores), la corrección cierra el acceso sin credenciales.

Una anulación fallida borraba la huella del alta

El bloque catch de execVERIFACTUCall() vaciaba verifactu_huella y verifactu_csv_factura fuera cual fuera la operación que había fallado. Si una anulación o una subsanación terminaba con una excepción (sin conexión, error de certificado, bloqueo de la cadena ocupado…), la factura perdía en Dolibarr la huella y el CSV de un registro que la AEAT sí había aceptado: getLastInvoiceHash() dejaba de verla, la siguiente factura se encadenaba sobre un registro anterior al real y el código QR desaparecía de una factura que seguía registrada.

Ahora una excepción nunca toca la huella ni el CSV. Si la factura ya tiene un registro aceptado, conserva además su estado «Enviada» y solo se anota el error de la operación fallida en verifactu_error y verifactu_ultima_salida, de modo que la baja o la subsanación pueden repetirse. Si nunca llegó a aceptarse, se muestra el estado «Error» como hasta ahora. La decisión se toma sobre los campos guardados en la base de datos, no sobre lo que la operación fallida hubiera dejado en memoria, y está en la nueva función buildVerifactuExceptionErrorData().

Mensajes que se mostraban como claves sin traducir

El código pedía varios textos con un nombre de clave distinto del que definían los ficheros de idioma, y Dolibarr mostraba la clave en bruto: los avisos de factura no modificable y de datos obligatorios del cliente (VERIFACTU_INVOICE_CAN_NOT_BE_*), el estado «Anulada», el aviso de factura ya anulada, los tipos de anulación del diálogo de baja, los avisos de NIF de tercero no modificable, los valores fiscales aplicados desde el tercero, el título «Factura simplificada» del PDF, la etiqueta del campo «Cliente de factura simplificada» y los textos de ayuda de varios campos. Además, los textos de la validación masiva, el aviso de ajuste de fecha de la validación individual y el título de la guía de ayuda solo existían en español e inglés.

Se añaden en los cinco idiomas las claves que faltaban, como alias con el mismo texto que su clave equivalente, y las traducciones que no existían en catalán, euskera y gallego.

Verificación

Tres tests nuevos, que fallan con el código de la 2.2.1 y pasan con esta versión: tests/ApiAccessTest.php (acceso de cada método de la API, rechazo 403 antes de cambiar la configuración, ningún método público que escriba), tests/ExceptionKeepsRecordTest.php (la excepción conserva huella, CSV y estado de un registro aceptado) y tests/LanguageKeysTest.php (toda clave del módulo que pide el código existe y no está vacía en los cinco idiomas). La suite completa, 15 ficheros, pasa.

v2.2.1 (2026-09-19)

Corrección propia del autor del módulo, @garacil (Germán Luis Aracil Boned), detectada al actualizar a la 2.2.0 una instalación en producción sobre PostgreSQL.

La página principal del módulo devolvía un error 500

Desde la 2.1.0, al abrir la entrada de menú «VeriFactu» (verifactuindex.php) PHP terminaba con Call to undefined function dol_get_first_day(). El gráfico de facturas por mes se reescribió en esa versión para que funcionase también en PostgreSQL, sustituyendo MONTH() y YEAR() por dol_get_first_day() y dol_get_last_day(); pero esos dos ayudantes viven en core/lib/date.lib.php, que Dolibarr no carga en todas las páginas, y la página no lo incluía. La configuración del módulo seguía abriéndose, así que el fallo se percibía como «el módulo ha dejado de funcionar», aunque la validación, el envío a la AEAT y la pestaña VeriFactu de la factura no usan esos ayudantes y no estaban afectados.

La página carga ahora la librería junto al resto de sus dependencias, y la suite de regresión comprueba que cualquier fichero del módulo que use un ayudante de date.lib.php lo incluya antes de llamarlo.

v2.2.0 (2026-09-19)

Resuelve los dos últimos PR abiertos de @braito4, el #34 y el #39. En ambos casos se aplica el fondo del hallazgo, no la implementación propuesta, y el motivo está explicado en cada PR.

Una anulación puede abrir la cadena (PR #39)

El PR proponía impedir que un registro de anulación fuese el primero de la cadena. El esquema oficial dice lo contrario: RegistroFacturacionAnulacionType declara Encadenamiento como un choice entre PrimerRegistro y RegistroAnterior, y existe SinRegistroPrevioType precisamente para anular un registro que nunca se remitió a la AEAT.

Pero el PR apuntaba a algo real: sin registro anterior, el módulo no configuraba el encadenamiento en absoluto, así que validate() fallaba con un error genérico. Ahora la anulación se marca explícitamente como primer registro, que es lo que el esquema admite y lo que el propio módulo ya ofrecía con el tipo de anulación «sin registro previo».

Un obligado tributario no puede tener dos entidades VeriFactu (PR #34)

Dos entidades de Multicompany con VeriFactu activado son dos obligados tributarios, cada uno con su cadena. El mismo NIF en las dos significa dos cadenas para un solo obligado.

La comprobación se hace ahora al guardar la configuración, y solo con tablas del núcleo (llx_const), sin leer la estructura interna de Multicompany, que no forma parte de Dolibarr y cambia entre versiones. Falla en abierto: un error de consulta no bloquea la pantalla de configuración, porque lo que protege una cadena ya existente es el bloqueo del NIF que entró en la 2.0.0.

Nada de esto se ejecuta en el camino del envío. Ahí un false revierte la factura a borrador, de modo que un fallo transitorio de base de datos habría des-validado facturas ya emitidas.

Además, si Multicompany está compartiendo la numeración de facturas, la pantalla de configuración lo advierte: dos obligados tomarían su serie del mismo contador y VeriFactu no puede conciliarlo. Se lee de la constante de configuración del propio módulo, no de sus tablas.

No se incorpora la unicidad de la huella del certificado que proponía el mismo PR: un certificado de representante o de colaborador social puede firmar legítimamente por varios obligados tributarios, así que bloquear su reutilización entre entidades impediría un caso de uso válido.

v2.1.0 (2026-09-19)

Corrige el punto 4 de la issue #30, planteado por @hisie, y un defecto que apareció al verificarlo y que afecta a toda instalación sobre PostgreSQL.

La cadena no se construía en PostgreSQL

getLastInvoiceHash() leía el registro anterior con DATE_FORMAT(f.datef, '%d-%m-%Y'). Esa función solo existe en MySQL y Dolibarr no la traduce: convertSQLFromMysql() no la contempla, de modo que en PostgreSQL la consulta falla con function date_format(date, unknown) does not exist.

El fallo era silencioso. La función solo comprobaba si había filas, así que un error de consulta y una cadena vacía eran indistinguibles: devolvía null y cada factura se encadenaba como primer registro, incumpliendo el Art. 13 de la Orden HAC/1177/2024.

  • La fecha se formatea ahora en PHP con $db->jdate(), con el mismo formato d-m-Y que se usa al construir el envío, de modo que ambos extremos de la cadena llevan la misma cadena de fecha.
  • Un error de lectura lanza una excepción en lugar de pasar por «no hay registro anterior». Es preferible no enviar a enviar con la cadena rota.
  • El panel tenía el mismo problema con MONTH() y YEAR(): el gráfico mensual quedaba vacío en PostgreSQL. Ahora filtra por rango de fechas y agrupa en PHP, sin funciones específicas de ningún motor.

Si tu instalación usa PostgreSQL, conviene revisar los registros ya enviados: es posible que se remitieran como primer registro de cadena.

Condición de carrera en el encadenamiento

Entre leer la huella anterior y guardar la nueva hay una llamada al servicio de la AEAT que dura segundos. Dos validaciones simultáneas leían el mismo registro anterior y encadenaban ambas facturas sobre él.

La sección crítica se serializa ahora con un bloqueo de sesión de base de datos: GET_LOCK() en MySQL y un advisory lock en PostgreSQL, por entidad y entorno, con espera configurable en VERIFACTU_CHAIN_LOCK_TIMEOUT (30 segundos por defecto). El bloqueo vive en la sesión de base de datos, así que se libera solo si el proceso muere, y se libera igualmente cuando el envío lanza una excepción.

El registro existe siempre que se valida una factura

Con VERIFACTU_DIRECT_CALL_ON_VALIDATE desactivado y una factura que no venía de TakePOS, la validación terminaba sin dejar ningún rastro VeriFactu. Ese indicador decide cómo se remite el registro, no si existe: el Art. 6 del RD 1007/2023 lo exige en el momento de la expedición.

Ahora la factura queda marcada como pendiente, con Incidencia = 'S', y la cola de reintentos la recoge, igual que ocurre cuando falla la conexión.

La identidad declarada ya no se recorta en silencio

getDeclaredSystemIdentity() aplicaba los límites del esquema con substr() sin avisar, de modo que una declaración responsable con valores demasiado largos volvía a transmitir algo distinto de lo declarado, que es justo lo que corrigió la 2.0.0. El recorte se registra ahora en el log como error, y se hace con mb_substr() para contar caracteres, como hace el esquema, sin partir por la mitad un carácter multibyte.

Sobre la parametrización de la declaración responsable

La segunda parte pendiente de la issue #30 —configurar los datos del productor desde la pantalla de administración— no se implementa, y no por descuido: en multiempresa, lo que identifica al obligado tributario ante la AEAT (VERIFACTU_HOLDER_NIF y VERIFACTU_HOLDER_COMPANY_NAME) ya es configuración por entidad, porque Dolibarr carga llx_const con WHERE entity IN (0, n). Lo que quedaría por parametrizar son los datos del productor del software, que es quien suscribe la declaración responsable; quien redistribuya el módulo bajo su nombre edita conf/declaracion_responsable.conf.php, que existe para eso.

Verificación

Comprobación Resultado
Consulta de la cadena, antigua y nueva, contra PostgreSQL 16 real la antigua falla, la nueva devuelve el registro
convertSQLFromMysql() de Dolibarr 19.0.3 sobre la consulta antigua deja DATE_FORMAT sin traducir
Exclusión mutua del advisory lock con dos sesiones concurrentes la segunda espera hasta que la primera libera
Suite de regresión completa 10 ficheros, 100%

v2.0.0 (2026-09-19)

Numeración de versión

El número de versión que declaraba el módulo llevaba desde diciembre de 2025 congelado en 1.0.3: los paquetes publicados como 1.0.4 y 1.1 seguían instalándose y mostrándose en Dolibarr como 1.0.3, porque las etiquetas se movieron pero modVerifactu.class.php no. Esto importa más allá de lo cosmético, porque ese mismo valor es el que se transmite a la AEAT en el campo Version del bloque SistemaInformatico (Art. 15.2.c de la Orden HAC/1177/2024).

Esta versión se numera 2.0.0. Además de dejar atrás sin ambigüedad la etiqueta 1.1 ya publicada —para que quien la tenga instalada no vea un retroceso al actualizar—, el salto de versión mayor corresponde a lo que cambia de comportamiento: registros que antes se transmitían ahora se rechazan localmente por incumplir los límites del esquema, las consultas dejan de abarcar las entidades con las que se comparten facturas, un envío parcialmente correcto con líneas rechazadas deja de darse por enviado y el NIF del obligado tributario queda fijado en cuanto existe la primera huella. El número está unificado en los tres sitios donde aparecía descoordinado: la clase del módulo, la declaración responsable y este README.

Correcciones

  • Fatal error en el informe de pagos (issue #31, reportada por @jose73wrc): beforePDFCreation() daba Call to undefined method pdf_paiement_fourn::fetch_optionals() al generar el informe de pagos de facturas de cliente o de proveedor. Ese hook no lo disparan solo los modelos PDF de factura: los modelos de informe (pdf_paiement, pdf_paiement_fourn) también lo lanzan, y lo que pasan como $object no es una factura. En Dolibarr 22.x pasan el propio modelo PDF, que extiende CommonDocGenerator y no tiene fetch_optionals(); en Dolibarr 17.x pasan una variable $object que nunca se asigna en write_file(), es decir null. En ambos casos la llamada sin comprobación era un error fatal. Añadido un guard que sale limpiamente cuando el objeto no es un objeto de negocio. De paso, se deja de acceder al extrafield cuando no existe, lo que además eliminaba un warning de PHP 8.

  • TypeError en el QR con PHP 8 (issue #32, reportada por @hippo16214): QRGenerator::renderQrCode() declaraba int $outputType, pero las constantes QRCode::OUTPUT_IMAGE_PNG y QRCode::OUTPUT_MARKUP_SVG de chillerlan/php-qrcode son strings. Con declare(strict_types=1), PHP 8 rechazaba toda llamada y rompía la pestaña VeriFactu y la vista de factura (el QR del PDF no se veía afectado porque usa TCPDF::write2DBarcode()). Corregido el tipo del parámetro a string.

  • Certificados en hosting compartido (feedback del PR #42): en alojamientos donde exec() y proc_open() están ambos en disable_functions el módulo no podía leer el certificado en absoluto, y por tanto no podía comunicarse con la AEAT. La extracción usa ahora primero las funciones OpenSSL propias de PHP (openssl_pkcs12_read()), que no lanzan ningún proceso, y solo recurre al binario externo cuando hace falta (contenedores legacy). Se ha eliminado también el requisito duro de proc_open en la conversión a PEM. Los certificados con cifrado moderno funcionan ya de forma transparente en esos servidores; los legacy siguen necesitando el binario, lo que se comunica con un mensaje explícito.

  • Certificados FNMT .p12 con cifrado legacy (issue #33, reportada por @hippo16214, con la aportación de @jose73wrc sobre alojamientos compartidos): los contenedores PKCS#12 protegidos con RC2-40-CBC / PBE-SHA1-3DES —los habituales de la FNMT— fallaban bajo OpenSSL 3 y el módulo lo notificaba como "Verifique la contraseña", que es engañoso. Ahora la extracción reintenta automáticamente con openssl pkcs12 -legacy y el mensaje de error distingue entre contraseña incorrecta, algoritmo legacy no soportado y fallo genérico. Documentado en la sección de resolución de problemas.

  • Identidad del sistema declarada vs. transmitida (issue #30, puntos 1 y 6, revisión de @hisie): la declaración responsable declaraba IdSistemaInformatico = VERIFACTU-DOLIBARR-OSS y nombre VeriFactu para Dolibarr ERP/CRM, mientras que a la AEAT se enviaban DV y Dolibarr Verifactu Module. El Art. 15.2 de la Orden HAC/1177/2024 exige que coincidan. Se ha unificado tomando como válidos los valores que admite el esquema oficial: SuministroInformacion.xsd define IdSistemaInformatico como sf:TextMax2Type (máximo 2 caracteres) y NombreSistemaInformatico como sf:TextMax30Type (máximo 30), por lo que los valores largos que se declaraban serían rechazados por el webservice. getSystemConfig() lee ahora la identidad de la propia declaración responsable, de modo que ya no pueden divergir, y aplica los límites del esquema. Además el campo Version transmitía DOL_VERSION (la versión de Dolibarr) en lugar de la del módulo, que es lo que exige el Art. 15.2.c.

  • Hash de integridad incompleto (issue #30, punto 2, revisión de @hisie): la lista ficheros_verificados referenciaba interface_99_... en vez de interface_999_... y class/verifactu.class.php, que no existe. Como calcularHashModuloVerifactu() ignoraba en silencio los ficheros ausentes, el trigger principal quedaba fuera del cálculo de integridad. Corregida la lista, ampliada con los ficheros críticos de hash, envío y anulación, y ahora la función registra los ficheros no encontrados en integridad.ficheros_no_encontrados y en el log en lugar de callarlos.

  • Facturas proforma enviadas a la AEAT como F1 (issue #30, punto 3, revisión de @hisie): una proforma no es una factura expedida legalmente y no debe generar registro de facturación (Art. 6 RD 1007/2023). Nueva función isVerifactuApplicableInvoice() que las excluye tanto en el trigger de validación como en execVERIFACTUCall(), con lo que quedan fuera de todas las vías de envío (validación, pestaña VeriFactu, listado, envío masivo y reintentos). Las proformas siguen validándose con normalidad en Dolibarr.

  • Tipo rectificativo divergente (issue #30, punto 5, revisión de @hisie): billCreate() almacenaba R2 para abonos y facturas de sustitución, pero el envío transmitía R1. La pestaña VeriFactu mostraba por tanto un tipo que nunca era el enviado. Unificado a R1, que es lo que realmente se transmite.

Seguridad

  • La contraseña del certificado ya no se interpola en la línea de comandos de openssl. Las llamadas usan proc_open con argumentos en array y pasan la contraseña por variable de entorno (-password env:), lo que elimina la posibilidad de inyección de comandos a través de la contraseña y evita que quede visible en la lista de procesos del servidor.

  • prepareLocalCertificate() ya no hace die() ante un fallo de extracción (tumbaba la petición entera): lanza una excepción que el llamador convierte en el mensaje de error habitual del módulo.

Archivos Modificados

  • class/actions_verifactu.class.php - Guard en beforePDFCreation()
  • lib/newfenix/src/QRGenerator.php - Tipo del parámetro $outputType
  • lib/functions/functions.certificates.php - Reintento -legacy, clasificación de errores y llamadas seguras a OpenSSL
  • admin/managecertificates.php - Mensajes de error diferenciados
  • lib/functions/functions.configuration.php - getDeclaredSystemIdentity() y getSystemConfig()
  • lib/functions/functions.compatibility.php - Nueva función isVerifactuApplicableInvoice()
  • lib/functions/functions.submission.php - Exclusión de proformas
  • core/triggers/interface_999_modVerifactu_VerifactuTriggers.class.php - Exclusión de proformas y tipos rectificativos
  • conf/declaracion_responsable.conf.php - Identidad del sistema y lista de integridad
  • core/modules/modVerifactu.class.php - Versión del módulo
  • Todos los archivos de idioma (es_ES, en_US, ca_ES, eu_ES, gl_ES)

Correcciones normativas aportadas por la comunidad

Integradas a partir de las propuestas de @braito4, verificadas una a una contra el esquema oficial SuministroInformacion.xsd, el de respuesta RespuestaSuministro.xsd y el código de Dolibarr 19.0.3.

  • Respuestas parciales de la AEAT (PR #36): un envío ParcialmenteCorrecto puede contener líneas con EstadoRegistro = Incorrecto. El módulo aceptaba el envío completo mirando solo el estado global, de modo que una factura rechazada quedaba almacenada como enviada. Ahora isAEATResponseAccepted() exige que todas las líneas estén aceptadas, tanto en el alta como en la anulación.
  • RechazoPrevio (PR #38): el esquema distingue S (la AEAT rechazó el registro antes) de X (el registro nunca llegó a la AEAT, por ejemplo al acogerse a Veri*factu desde un sistema que no lo usaba). El módulo transmitía siempre X.
  • Validación del registro antes de enviarlo (PR #40): tipo de factura, longitudes de NombreRazonEmisor y DescripcionOperacion, número de destinatarios y de líneas de desglose, encadenamiento y formato de las huellas se comprueban contra los límites del XSD antes de llamar al servicio.
  • Control de flujo de la AEAT (PR #37): se registra el TiempoEsperaEnvio que devuelve cada respuesta y lo respeta el reintento automático de pendientes. No se aplica en la validación, donde abortar el envío revierte la factura a borrador, ni en los envíos que el usuario pide explícitamente.
  • Certificados y identidad fiscal (PR #41): se rechaza un certificado fuera de su periodo de validez X.509 con mensaje propio, los bundles PEM se escriben con permisos 0600, y el NIF del obligado tributario queda fijado en cuanto la entidad tiene su primera huella. El certificado sigue pudiendo sustituirse, que es lo que hace falta al renovarlo.
  • Aislamiento entre entidades MultiCompany (PR #34): las consultas de VeriFactu usaban getEntity('invoice'), que incluye las entidades con las que se comparten facturas. En la cadena fiscal eso encadena registros de otro obligado tributario. Ahora cada consulta se acota a la entidad activa, igual que la activación del módulo, integrity.php y la búsqueda de la vista de consulta.
  • Columna de fecha de creación (PR #35): la vista de consulta seleccionaba date_creation, que es una propiedad del objeto Facture y no una columna de llx_facture; la columna es datec.

Quedan fuera de esta versión, para tratarlas con sus autores: las comprobaciones de compartición, unicidad de NIF y huella de certificado entre entidades del PR #34, que inspeccionan la estructura interna del módulo MultiCompany y bloquean activación y validación; y el PR #39, que impide que un registro de anulación sea el primero de la cadena, algo que el esquema oficial admite explícitamente.

Compatibilidad verificada

Los cambios se han verificado sobre instalaciones reales, no solo en aislamiento:

Entorno Resultado
Dolibarr 22.0.5 + PHP 8.4 + PostgreSQL 16 22/22 comprobaciones en vivo
Dolibarr 17.0.2 + PHP 8.2 + PostgreSQL 16 20/20 comprobaciones en vivo
Dolibarr 17.0.2 + PHP 8.4 + PostgreSQL 16 20/20 comprobaciones en vivo
Dolibarr 17.0.2 + PHP 7.4 (mínimo declarado) 20/20 comprobaciones en vivo
Dolibarr 19.0.3 + PHP 8.4 (fuente oficial) 69/69, constantes y hooks contrastados
Suite de regresión completa (9 ficheros) 100%

En todas ellas se activa el módulo, se dispara el hook beforePDFCreation con el objeto que realmente pasa cada una, se generan los QR y se comprueban las constantes de tipo de factura contra la clase Facture real.

Sobre Dolibarr 19.0.3 se ha contrastado además el esquema de llx_facture, el objeto que recibe beforePDFCreation (también ahí es el modelo PDF, así que el fallo de la issue #31 se daba igualmente) y que las 186 funciones del núcleo que invoca el módulo existen en esa rama.

El reintento con openssl pkcs12 -legacy está condicionado a que el binario sea OpenSSL 3 o superior: en servidores con OpenSSL 1.1.1 o LibreSSL, donde ese modificador no existe, no se añade (añadirlo convertiría una extracción correcta en un error de "opción desconocida").

Tests

  • tests/IssueFixesTest.php - 65 tests de regresión para los issues #30, #31, #32 y #33

v1.0.4 (2026-03-04)

Correcciones

  • Retención IRPF en VeriFactu: Corregido el cálculo de ImporteTotal en el código QR y en las consultas a AEAT. Las facturas con retención IRPF ahora envían correctamente ImporteTotal = Base + IVA + Recargo sin deducir el IRPF. Creada función helper getVerifactuImporteTotal() para centralizar el cálculo.

  • Validación masiva con transacciones independientes: Reescrito completamente el sistema de validación masiva de facturas. Cada factura se procesa en su propia transacción de base de datos, de modo que si una falla, las demás continúan procesándose. Se intercepta la acción estándar de Dolibarr massvalidation con procesamiento individual por factura.

  • Orden cronológico de fechas en validación masiva: Antes de validar masivamente, el sistema detecta si alguna factura tiene fecha anterior a la última factura validada en VeriFactu. Si hay conflicto, muestra un diálogo de confirmación y ajusta las fechas automáticamente. Las facturas se procesan ordenadas por fecha ascendente y la fecha mínima se va actualizando conforme se procesan.

  • Orden cronológico de fechas en validación individual: Al validar una factura individual (PROV), la fecha se ajusta a max(hoy, última_factura_validada) en vez de solo a hoy. Si la fecha se ajustó, se muestra un aviso en el diálogo de confirmación.

  • Envío masivo desde lista de facturas: Corregido el problema por el que al confirmar el envío masivo desde la lista de facturas no se transmitían los IDs seleccionados (el diálogo formconfirm no soporta arrays). Se usa ahora un campo oculto verifactu_toselect con IDs separados por comas. Las facturas ya enviadas se filtran automáticamente.

  • Archivos PEM al renovar certificado: Al subir un nuevo certificado P12/PFX, los archivos PEM antiguos no se eliminaban, provocando que el sistema siguiera usando el certificado anterior (potencialmente expirado). Añadida función deleteExistingPemFiles() que limpia los PEM antes de procesar el nuevo certificado. Añadida visualización de la fecha de expiración del certificado con indicadores de color (expirado/próximo a expirar/válido).

Nuevas Funcionalidades

  • Caché local de esquemas WSDL/XSD: Nueva clase SchemaManager que descarga los 7 archivos de esquema (1 WSDL + 5 XSD de AEAT + 1 XSD de W3C) localmente y reescribe las referencias schemaLocation para eliminar dependencias externas. Esto previene errores de rate-limiting de w3.org al procesar muchas facturas. Los esquemas se descargan automáticamente en el primer uso y pueden actualizarse desde la página de configuración.

Archivos Modificados

  • class/actions_verifactu.class.php - Validación masiva e individual con transacciones independientes y control de fechas
  • lib/functions/functions.compatibility.php - Nueva función getVerifactuImporteTotal()
  • lib/functions/functions.qr.php - Corrección importes QR con IRPF
  • lib/functions/functions.query.php - Corrección comparación importes AEAT
  • lib/functions/functions.submission.php - Integración SchemaManager
  • lib/newfenix/src/SchemaManager.php - Nueva clase gestión de esquemas
  • lib/newfenix/src/SoapClient.php - Uso de WSDL local con fallback remoto
  • lib/newfenix/src/Config.php - Propiedad localWsdlPath
  • lib/newfenix/src/Manager.php - Integración setSchemasDir()
  • admin/setup.php - Sección estado de esquemas con botón de descarga + expiración de certificado
  • admin/managecertificates.php - Limpieza de PEM al subir nuevo certificado
  • admin/uploadcertificates.php - Limpieza de PEM al subir nuevo certificado
  • lib/functions/functions.certificates.php - Nueva función deleteExistingPemFiles()
  • views/list.facture.php - Corrección transmisión IDs en envío masivo
  • Todos los archivos de idioma (es_ES, en_US, ca_ES, eu_ES, gl_ES)

Tests

  • tests/MassValidateInterceptionTest.php - 52 tests para validación masiva, transacciones, fechas
  • tests/SchemaManagerTest.php - 19 tests para gestión de esquemas

v1.0.3 (2025-12-20)

Cambios

  • Fechas obligatorias VeriFactu actualizadas: Ajustadas las fechas de transición automática a producción de 2026 a 2027 según el anuncio del Gobierno:
    • Sociedades: 1 de enero de 2027 (antes 1 de enero de 2026)
    • Autónomos: 1 de julio de 2027 (antes 1 de julio de 2026)
  • Documentación del proyecto simplificada: Simplificada la sección de historia del proyecto en el README manteniendo la atribución GPL v3 al autor original
  • Declaración responsable actualizada: Configurados los datos del productor con la información de 7Kas Servicios de Internet SL (CIF B98515273, Benicasim, Castellón)

Archivos Actualizados

  • lib/functions/functions.configuration.php - Lógica de cambio de entorno
  • admin/setup.php - Fechas de visualización de estado
  • conf/declaracion_responsable.conf.php - Datos del productor 7Kas Servicios de Internet SL
  • Todos los archivos de idioma (es_ES, en_US, ca_ES, eu_ES, gl_ES)

v1.0.2 (2025-12-12)

Nuevas Funcionalidades

  • Declaración Responsable configurable: Añadido archivo de configuración conf/declaracion_responsable.conf.php que cumple con la normativa española (RD 1007/2023, Orden HAC/1177/2024):
    • Datos del productor (NIF, dirección, contacto)
    • Datos del sistema informático (IdSistemaInformatico, versión)
    • Especificaciones técnicas (firma XAdES, hash SHA-256)
    • Hash de integridad del módulo calculado dinámicamente
    • Declaración de cumplimiento con referencias legales
  • Exportación JSON: Nuevo endpoint /views/declaration_json.php para exportar la declaración responsable en formato JSON
  • Documentación: Añadido docs/responsible_declaration.md con guía de configuración completa

Mejoras

  • Actualizada la página de Declaración Responsable para usar los datos del archivo de configuración
  • Validación automática de campos obligatorios con mensajes de aviso
  • Visualización del hash de integridad del módulo en la declaración

v1.0.1 (2025-12-06)

Correcciones

  • Gestión de errores en validación masiva de facturas: Corregido el problema por el que facturas con errores de VeriFactu cancelaban todo el proceso de validación por lotes. Ahora, cuando una factura falla al enviar a VeriFactu:
    • La factura permanece como borrador con referencia PROV en lugar de ser validada y luego revertida
    • Las demás facturas del lote continúan procesándose normalmente
    • Mejorada la gestión de conexiones PostgreSQL para evitar errores "connection already closed"
    • Los mensajes de error se muestran correctamente al usuario

About

Verifactu para Dolibarr

Resources

Stars

20 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages