Implementar VeriFactu en PrestaShop no debería significar reconstruir la factura a partir del carrito ni introducir XML, certificado o reglas fiscales dentro del módulo ecommerce. Una integración VeriFactu para PrestaShop robusta debe aprovechar OrderInvoice para facturas y OrderSlip para abonos, además de los hooks nativos de PDF. El conector 0.5.0 de Puente VeriFactu utiliza esas capacidades como fuentes comerciales, aplica validación y reconciliación al céntimo, y delega MappingProfile, clasificación y transporte a un motor central. La automatización es opt-in y la compatibilidad se evalúa por capacidades, con una matriz ejecutada sobre 1.7.8.11, 8.1.7 y 8.2.7. Esta arquitectura reduce drift entre tiendas, mantiene secretos fuera del ecommerce y permite actualizar el módulo sin perder recordId, idempotencia o estado de operaciones previas.
1. Empieza por el modelo documental que PrestaShop ya mantiene
OrderInvoice contiene una representación de factura que ya incorpora totales y desgloses propios de PrestaShop. El conector utiliza `getProductTaxesBreakdown()`, `getShippingTaxesBreakdown()` y `getWrappingTaxesBreakdown()` junto con los totales del documento. Recalcular el IVA desde líneas del carrito introduciría diferencias con descuentos, portes o redondeos que la propia plataforma ya resolvió. Reutilizar la factura nativa reduce la cantidad de lógica paralela y facilita comparar lo que ve el cliente con lo que llega a preflight.
El flujo automático actual exige una sola OrderInvoice fiscal por pedido. Un pedido con múltiples facturas no se resuelve escogiendo la primera ni sumándolas: se bloquea hasta que exista una estrategia explícita. Esa decisión refleja una regla general útil para integraciones: cuando el sistema de origen expresa una ambigüedad documental, el adaptador debe exponerla y no inventar una respuesta para mantener la automatización. El diagnóstico de una tienda incluye precisamente estos casos antes de activar hooks automáticos.
2. Los impuestos se agrupan y reconcilian al céntimo antes de emitir
Una factura puede mezclar 21 %, 10 %, 4 %, portes, wrapping y descuentos. El extractor agrupa el desglose por tipo y compara base, cuota y totales contra OrderInvoice. Las pruebas adicionales de fixtures cubren esos tres tipos de IVA, redondeos tolerables y desajustes que deben bloquearse. Este gate evita que una diferencia material quede escondida por una transformación y solo aparezca después de haber creado el registro fiscal.
La ecotasa o cualquier concepto que necesite clasificación adicional tampoco se fuerza dentro de un tipo genérico: requiere mapping explícito. Cuando la tienda opera en varias monedas, la vista comercial se conserva y la conversión fiscal se resuelve en servidor, no dentro de PrestaShop. El principio es siempre el mismo: la tienda declara hechos que puede demostrar y el motor fiscal decide cómo mapearlos; si no puede reconciliar, preflight falla sin efectos fiscales.
3. Un OrderSlip es una operación rectificativa con identidad independiente
Cuando PrestaShop crea un abono, `actionOrderSlipAdd` representa un evento nativo de OrderSlip. El conector lo convierte en un payload neutral con identidad, número y fecha del abono, destinatario, moneda, referencia a factura original y totales negativos. La tabla `pvf_order_slip_sync` mantiene una fila por tienda y OrderSlip, permitiendo varios abonos del mismo pedido sin sobrescribir estado. Antes de procesar el abono, la factura principal debe tener recordId.
La clasificación fiscal no se deduce del nombre «abono». Un perfil rectificativo server-side decide R1–R5, tipo de rectificación y resto de reglas. Para determinar el IVA histórico, el módulo obtiene el TaxCalculator de cada OrderDetail original y compara la cuota observada con ese tipo. No divide importe por base para adivinar el porcentaje. De esta forma un cambio posterior de configuración de impuestos no altera silenciosamente cómo se interpreta una devolución asociada a una venta anterior.
4. Factura y abono comparten la misma regla: recordId existente nunca se reemite
La factura ordinaria utiliza una clave estable basada en tienda, pedido y número de factura; el OrderSlip utiliza una identidad distinta basada en tienda, abono y número rectificativo. Si una operación nueva sufre un fallo recuperable antes de recibir recordId, el siguiente intento conserva exactamente la misma idempotencia. Si ya existe recordId, tanto un error retryable como uno no retryable conservan esa identidad y pasan a reconciliación o revisión, nunca a una nueva emisión.
Esta semántica se ejecuta en Connector Contract Suite v2 para factura y rectificativa dentro de las instalaciones reales de la matriz. Un error recuperable puede dejar `retry_pending`, mientras uno definitivo deja estado bloqueado, pero ambos preservan lo que ya se sabe de la operación. Esto reduce el riesgo de que un timeout, una caída de red o una actualización del módulo se conviertan en duplicados fiscales. La interfaz local muestra el problema sin cambiar el significado del estado del servidor.
5. PrestaShop renderiza la presentación; el servidor es quien la autoriza
La documentación de PrestaShop ofrece hooks PDF dinámicos como `displayPDFInvoice` y `displayPDFOrderSlip`. El módulo 0.5.0 registra estos puntos y consume `presentation_json` persistido después de issue o reconcile. Ese bloque contiene los metadatos necesarios para URL, QR y literal asociados a una operación. PrestaShop no vuelve a construir NIF, URL de consulta ni textos regulatorios desde campos locales, lo que evita una segunda fuente de verdad de presentación.
El comportamiento es fail-closed. Si existe recordId pero la presentación no está disponible o no supera validación, el módulo no inventa un QR para que el PDF parezca completo. Factura y OrderSlip conservan presentación separada porque son operaciones distintas. Además, volver a generar un PDF no desencadena emisión. Esa separación entre lifecycle fiscal y rendering documental hace posible actualizar plantillas sin modificar el contrato de identidad o transporte.
6. Capability-first permite evolucionar sin prometer versiones que no se han probado
La matriz de distribución cubre tres combinaciones: PrestaShop 1.7.8.11/PHP 7.4, 8.1.7/PHP 8.1 y 8.2.7/PHP 8.1. En cada una se instala y activa el ZIP real, se crean factura y OrderSlip y se ejecutan escenarios de contrato. El código no utiliza esos números para decidir lógica fiscal; una clase de compatibilidad detecta hooks y capacidades disponibles. La matriz es evidencia, no una lista codificada de condicionales.
Eso permite evaluar versiones fuera de la matriz sin afirmar automáticamente que están soportadas. Para una operación concreta deben existir capacidades mínimas, como hooks PDF y objetos nativos compatibles. Si falta `displayPDFOrderSlip`, por ejemplo, el diagnóstico puede reconocer la tienda y quizá validar otros datos, pero la emisión rectificativa no se habilita. Con PrestaShop 9 o futuras versiones, el mismo criterio exige una validación específica antes de publicar compatibilidad comercial.
7. Los hooks automáticos existen, pero ambos switches empiezan en OFF
Para facturas se utiliza un evento posterior al cambio de estado; para abonos, `actionOrderSlipAdd`. Sin embargo, instalar el módulo no significa procesar esos eventos fiscalmente. La configuración mantiene switches independientes para Automatic invoices y Automatic corrective credit slips, ambos desactivados por defecto. Cuando el switch de factura está activo, el flujo exige una única OrderInvoice y reutiliza preflight e idempotencia del modo manual. Los abonos aplican su propio perfil y requisitos.
La activación gradual permite comprobar primero una factura manual, después una factura automática y finalmente, si el negocio usa devoluciones, un OrderSlip. Este orden facilita asociar errores a configuración, datos o timing del hook. También impide que un update comience a enviar facturas sin decisión del comercio. El upgrade probado 0.4.0→0.5.0 verifica específicamente que los switches sigan en OFF, incluso mientras incorpora nuevos hooks de presentación PDF.
8. Un upgrade fiscal debe preservar historia local, no solo instalar archivos
El smoke de upgrade mantiene una factura principal y una rectificativa ya sincronizadas, despliega versiones sucesivas y exige que recordId, idempotencia y estado sobrevivan. En 0.5.0 añade `presentation_json` y registra `displayPDFInvoice` y `displayPDFOrderSlip`. Esta prueba demuestra que ampliar presentación no obliga a recrear operaciones. También comprueba que una actualización no habilite automatización accidentalmente.
En una tienda real hay más variables: overrides, módulos de checkout, multitienda, personalizaciones PDF, módulos de impuestos y cambios de tema. El procedimiento recomendado replica el principio del CI con un staging: inventario, backup, upgrade, revisión de hooks, factura existente, factura nueva, OrderSlip y PDF. Solo cuando esas evidencias son coherentes se considera listo el módulo. El rollback de aplicación no debe borrar ni reinterpretar registros fiscales existentes.
9. Certificado y clasificación fiscal permanecen fuera de PrestaShop
El token que permite al módulo hablar con Puente se cifra localmente usando una clave derivada de `_COOKIE_KEY_`, pero el certificado AEAT y su clave privada nunca se entregan a la tienda. Tampoco se guardan en las tablas de sincronización. Esta frontera limita el impacto de un compromiso del ecommerce y permite rotar o gestionar credenciales fiscales en el runtime especializado. Los logs y tarjetas de estado utilizan información operativa, no secretos.
El módulo tampoco conoce las decisiones fiscales sensibles que varían por organización. `invoiceType`, R1–R5, modalidad S/I, taxCode, regimeKey, operationClass, emisor y criterios de conversión pertenecen a MappingProfile y configuración server-side. Una instalación PrestaShop puede actualizarse o clonarse sin copiar una política fiscal completa dentro del código. Esto convierte el módulo en adaptador y reduce el riesgo de que dos tiendas ejecuten versiones divergentes de las mismas reglas.
10. Go-live empieza después de la validación técnica, no con la instalación
Una tienda puede tener el módulo instalado, endpoint configurado, facturas de TEST aceptadas y PDF correcto sin que AEAT producción esté habilitada. Separar readiness de producción permite terminar trabajo reversible mientras se revisa normativa, certificado, identidad fiscal y autorización. También permite probar upgrades y hooks sin afectar al canal fiscal productivo. El pago o entitlement comercial no cambia esa frontera.
Antes de go-live se vuelve a comprobar la versión concreta, capacidades, MappingProfile, token, certificado, automatización seleccionada, manejo de abonos, recuperación ante fallos, soporte y rollback. Si la tienda ha cambiado módulos desde el diagnóstico, se repite el smoke relevante. La meta no es solo lograr una respuesta aceptada, sino dejar un flujo reproducible donde factura, rectificativa, PDF y estado puedan explicarse y reconciliarse sin duplicar operaciones.
CONCLUSIONES
Qué debes recordar
- Usa OrderInvoice como fuente documental y bloquea pedidos con múltiples facturas hasta definir una política explícita.
- Trata cada OrderSlip como operación independiente y decide R1–R5 mediante un MappingProfile rectificativo server-side.
- Reconciliar impuestos al céntimo antes de preflight evita fiscalizar discrepancias ocultas en descuentos, portes o redondeos.
- Consume presentación server-authored mediante hooks PDF y no reconstruyas QR, NIF o URL AEAT dentro de PrestaShop.
- Mantén automatización OFF hasta probar manualmente, y valida upgrades preservando recordId, idempotencia, estado y switches.
FUENTES Y TRAZABILIDAD
Fuentes utilizadas
Agencia Estatal de Administración Tributaria
RECURSOS EXTERNOS
Lecturas y recursos relacionados
Referencia de `displayPDFInvoice`, `displayPDFOrderSlip` y extensión de plantillas PDF.
SIGUIENTE PASO
Software VeriFactu
Software VeriFactu adaptable para conectar WooCommerce, PrestaShop, ERP, CRM, Excel, software propio y sistemas locales sin sustituir el sistema de origen.