Revisado en junio de 2026. Las rutas de archivo y los menús del panel de administración que se indican abajo se aplican a PrestaShop 1.7, 8 y 9 (las diferencias de la versión 1.6 se señalan en el propio texto). Las referencias a bases legales específicas de cada país, el Code de commerce francés, la UStG/GoBD alemana, el umbral polaco para el pago dividido y las demás. Eran correctas en el momento de redactar este artículo, pero la legislación cambia; trátalas como puntos de referencia y pide a un contable local que confirme el requisito vigente en tu mercado. Esto no es asesoramiento legal ni fiscal, e instalar un módulo no hace que tus facturas sean conformes por sí solo.
La mayor parte de tu tienda puedes diseñarla a tu manera. La factura, no. Es un documento legalmente vinculante, y en cuanto uno de tus clientes se la entrega a su contable, o un inspector fiscal la solicita durante una auditoría, cualquier campo que falte pasa a ser tu problema, no el suyo. Una factura alemana sin fecha de entrega, una francesa sin la indemnización por costes de cobro, una polaca de más de 15.000 PLN sin la nota de pago dividido: cada defecto puede hacer que se rechace una deducción de IVA o que se imponga una sanción. El problema es que PrestaShop genera las facturas automáticamente a partir de una plantilla PDF fija, y esa plantilla está pensada para ser genéricamente correcta, no necesariamente correcta para tu jurisdicción. Esta guía trata la parte que sí controlas: qué exige la ley en la factura impresa en los principales mercados de la UE, y cómo editar exactamente la plantilla PDF de PrestaShop para añadir esos campos sin perder el trabajo en la siguiente actualización.
Una nota rápida de alcance, porque este tema tiene vecinos cercanos. Este artículo trata del documento PDF: su diseño, sus campos y su cumplimiento normativo. No trata de cómo se numeran las facturas (eso merece su propio análisis; consulta la personalización de números de factura y pedido), ni de formatos estructurados de factura electrónica como el SDI italiano o Factur-X en Francia (cubiertos en la facturación electrónica en Europa), ni de configurar los tipos de IVA en sí (configuración de impuestos en PrestaShop). Aquí nos quedamos en el documento.
Qué hace realmente PrestaShop cuando genera una factura
Entender primero el mecanismo te evita editar el archivo equivocado más adelante. Cuando un pedido alcanza un estado que tiene activada la marca "Factura", PrestaShop crea una fila en la base de datos order_invoice y asigna el número secuencial. Qué estados generan una factura no es fijo: depende por completo de esa marca "Factura" configurada por estado en Parámetros de la tienda → Configuración de pedidos → Estados, y los valores predeterminados varían según la versión y la configuración de PrestaShop. No des por hecho que un estado concreto factura por defecto: abre tu propia lista de estados y comprueba cuáles tienen marcada la opción "Factura". El PDF en sí no se almacena: se renderiza bajo demanda cada vez que alguien hace clic en descargar, mediante una cadena de tres piezas:
- La clase PHP
classes/pdf/HTMLTemplateInvoice.php: recopila los datos del pedido, la dirección, los impuestos y los productos, y los expone a la plantilla. Aquí es donde debes ir si necesitas añadir un campo que PrestaShop todavía no pasa a la plantilla. - La plantilla Smarty
pdf/invoice.tpl: el diseño y el marcado reales del documento. Aquí cambias qué aparece y dónde. - La plantilla de estilos
pdf/invoice.style-tab.tpl: el CSS. TCPDF (la biblioteca que convierte el HTML en PDF) solo admite un subconjunto limitado de CSS, así que espera tablas y estilos en línea, no flexbox.
¿Y esto qué implica? De este diseño se derivan dos consecuencias prácticas. Primero, como el PDF se regenera a partir de datos en vivo, una factura que emitiste en marzo pasado cambiará silenciosamente si más tarde editas la plantilla o los datos del pedido; justo por eso es importante archivar una copia congelada (más abajo). Segundo, la separación entre la clase PHP y el .tpl te dice qué archivo debes tocar: si el dato ya existe en el pedido, solo editas la plantilla; si necesitas datos que PrestaShop nunca carga, también editas la clase.
Editar la plantilla sin que una actualización la sobrescriba

El error más habitual es editar directamente los archivos del núcleo: la siguiente actualización de PrestaShop, o la próxima vez que alguien restaure una instalación limpia, puede borrar sin avisar los campos que necesitas por ley. Hay dos rutas seguras, y se aplican a archivos distintos.
Los archivos de plantilla (.tpl) se sobrescriben correctamente copiándolos en tu tema activo. PrestaShop busca primero en el directorio pdf/ del tema antes de recurrir a la carpeta pdf/ del núcleo:
- Copia
pdf/invoice.tplenthemes/YOUR_THEME/pdf/invoice.tply edita la copia. - Lo mismo funciona para
invoice.style-tab.tpl,order-slip.tpl(la plantilla de abono / nota de crédito) ydelivery-slip.tpl. - No se toca nada del núcleo, así que las actualizaciones respetan tu versión; aun así, conviene revisar la copia después de un salto de versión importante, por si la plantilla del núcleo ha incorporado campos que te interese mantener.
La clase PHP usa en cambio el sistema de overrides de PrestaShop. Crea override/classes/pdf/HTMLTemplateInvoice.php extendiendo la clase del núcleo y después elimina el mapa de clases compilado para que PrestaShop lo reconstruya:
- En 1.7/8/9, el archivo de caché es
var/cache/prod/class_index.php(yvar/cache/dev/class_index.phpsi estás en modo desarrollo). En tiendas 1.6 más antiguas escache/class_index.php. - Sobrescribe
getContent()para asignar variables Smarty adicionales y luego léelas en elinvoice.tplde tu tema.
Un ejemplo mínimo hace que la ruta de plantilla sea más concreta. Si el dato ya existe en el pedido, el número de IVA del cliente en la dirección es el caso habitual, el cambio solo afecta a la plantilla. Copia el archivo del núcleo en tu tema y añade el campo donde quieras imprimirlo:
# Copy the core template into your active theme (PS 1.7/8/9)
cp pdf/invoice.tpl themes/YOUR_THEME/pdf/invoice.tpl
Después, dentro de ese invoice.tpl copiado, imprime el número de IVA del comprador cerca del bloque de dirección, protegido para que solo se muestre cuando exista:
{if $order->id_address_invoice}
{assign var=invoiceAddress value=Address::initialize($order->id_address_invoice)}
{if $invoiceAddress->vat_number}
<p>{l s='VAT number:' pdf='true'} {$invoiceAddress->vat_number}</p>
{/if}
{/if}
Para un campo que PrestaShop nunca carga (una fecha de entrega tomada de order_history, el IBAN/BIC bancario, una referencia de pedido de compra), haces la consulta en el override de HTMLTemplateInvoice::getContent(), lo asignas a Smarty y luego imprimes la variable en esta misma plantilla: mantén la recopilación de datos en PHP y el marcado en el .tpl, nunca SQL dentro de la plantilla. Regenera siempre una factura real y confirma que el campo se renderiza antes de confiar en él.
Guarda una copia de ambos archivos fuera de la tienda. Las actualizaciones del tema y las acciones agresivas de "restablecer tema" pueden eliminar el override de pdf/, y un módulo de terceros que incluya su propio override puede chocar con el tuyo; por eso conviene tratar tus plantillas personalizadas como código fuente bajo control de versiones, no como ediciones en vivo que nunca volverás a ver.
Los campos legales que cada mercado espera en el documento
A continuación tienes lo que debe aparecer en la factura impresa en los mercados donde venden muchos comerciantes de PrestaShop. Es una visión centrada en diseño y campos; la mecánica de los tipos de IVA que hay detrás está en IVA en la UE: OSS, IOSS, y si debes mostrar precios netos o brutos pertenece a otro conjunto de reglas en reglas de visualización de precios en Europa. Confírmalo siempre con un contable local; la legislación cambia.
| Mercado | Campos de factura que la plantilla predeterminada de PrestaShop suele omitir | Base legal |
|---|---|---|
| Francia (Facture) | SIREN/SIRET, ciudad de registro en el RCS, forma jurídica & capital social, tipo de penalización por demora en el pago y la indemnización fija de 40 EUR por costes de cobro para B2B | Code de commerce, Art. L441-9 |
| Alemania (Rechnung) | Fecha de entrega / prestación del servicio (distinta de la fecha de factura: el campo que más se olvida), Steuernummer o USt-IdNr, y la nota Kleinunternehmer (§19 UStG) cuando hay exención de IVA | UStG §14 / §14a |
| Italia (Fattura) | Codice Fiscale / Partita IVA de ambas partes; el B2B ya es solo electrónico mediante SDI, así que el PDF queda para B2C y para archivo | Fatturazione elettronica (SDI) |
| España (Factura) | NIF/CIF, identificador de serie de factura y línea de recargo Recargo de equivalencia para revendedores sujetos a ese régimen | RD 1619/2012 |
| Polonia (Faktura) | NIP de ambas partes en B2B y la nota "Mechanizm podzielonej płatności" (pago dividido) en facturas de más de 15.000 PLN para bienes/servicios incluidos en la lista | Ustawa o VAT |
El patrón en todos ellos es el mismo: PrestaShop imprime de forma fiable los nombres y direcciones de vendedor y comprador, las líneas de producto y el desglose del IVA. Lo que omite con frecuencia son los avisos legales específicos de cada país: la fecha de entrega alemana, la cláusula francesa de penalización, la nota polaca de pago dividido. Eso es lo que añades en la plantilla.
De dónde sale realmente cada campo que falta
Antes de empezar a programar, dos de esos avisos no necesitan tocar la plantilla en absoluto: PrestaShop ya tiene un espacio integrado para ellos:
- Texto legal estático (condiciones de pago, la cláusula francesa de penalización, una nota fija de exención de IVA) va en los campos Texto legal libre y Texto de pie de página en Pedidos → Facturas. Se renderizan en todas las facturas sin código. Si tu única carencia es un bloque constante de texto legal, quizá puedas terminar aquí.
- Campos dinámicos por factura (la fecha de entrega alemana, una referencia de pedido de compra B2B, IBAN/BIC para pedidos por transferencia bancaria) no son constantes, así que necesitan la ruta de plantilla que se explica abajo.
Para los campos dinámicos, estos son los lugares donde viven los datos para que tu override pueda recuperarlos:
- Fecha de entrega: el campo
delivery_datedel pedido, o la fecha en que el pedido entró en un estado enviado/entregado desdeorder_history. Pásala a la plantilla en tu override deHTMLTemplateInvoice.php. - Número de IVA del cliente: se almacena en la dirección (
address.vat_number), no en el cliente. PrestaShop ya expone la dirección, así que a menudo es un cambio solo de plantilla. - Datos bancarios (IBAN/BIC): viven en la configuración del módulo de pago Bank wire, no en el pedido; el enfoque más limpio es leer la configuración del módulo en tu override e imprimirla solo cuando el método de pago del pedido haya sido transferencia bancaria.
- Referencia de pedido B2B: si recoges un número de pedido de compra del cliente, sácalo del pedido y muéstralo cerca de la cabecera, donde los contables esperan verlo.
Abonos y albaranes de entrega: el mismo mecanismo, documentos separados
Los reembolsos y los envíos generan sus propios PDF, construidos y personalizados de la misma manera, pero son documentos legalmente distintos, así que no des por hecho que un cambio en la factura se traslada a ellos.
- Abonos (notas de crédito / avoirs / Gutschriften) son documentos legales por derecho propio. Necesitan su propia numeración secuencial, separada de las facturas, una referencia al número de factura original y los importes reembolsados con el IVA desglosado. PrestaShop llama internamente a este documento "order slip", así que la plantilla que personalizas es
themes/YOUR_THEME/pdf/order-slip.tpl(claseHTMLTemplateOrderSlip), aunque se imprima con el encabezado "Credit slip". - Albaranes de entrega (bons de livraison) no incluyen precios: son documentos de almacén y prueba de entrega. Se personalizan mediante
themes/YOUR_THEME/pdf/delivery-slip.tpl. Si añades la fecha de entrega alemana a las facturas, el albarán suele ser el lugar de donde procede la fecha subyacente, así que merece la pena alinear ambos.
La trampa del archivo que nadie nota hasta una auditoría
Esta es la que pasa desapercibida. Como PrestaShop regenera cada PDF desde la base de datos al descargarlo, una factura nunca queda congelada. Edita tu plantilla para añadir la fecha de entrega y todas las facturas históricas ganarán silenciosamente ese campo, incluidas las emitidas antes de que estuvieras obligado a incluirlo. Cambia el nombre de un producto o una configuración fiscal, y las facturas del trimestre pasado se volverán a renderizar de forma distinta. En el uso diario puede no tener importancia. Para cumplimiento normativo, es una exposición real: Francia exige conservar las facturas en un formato inalterable durante 10 años, y la GoBD alemana exige la misma retención con inmutabilidad.
La solución es capturar una copia congelada de cada factura en el momento en que se emite, en lugar de depender de la regeneración. En la práctica:
- Archiva en el momento en que la factura se crea y se numera por primera vez, no cada vez que se renderiza el PDF. Dispara el archivado desde la transición de estado de pedido que genera la factura (o desde un hook/servicio dedicado a la creación de facturas), para capturar el documento una sola vez, cuando se asigna su número. Engancharse al flujo de renderizado del PDF (por ejemplo,
actionPDFInvoiceRender) es el punto equivocado: se ejecuta al descargar y regenerar, por lo que puede perder facturas que nunca se vuelven a descargar y puede sobrescribir tu archivo con una salida posterior, renderizada de nuevo. Guarda ese PDF exacto de la primera renderización en disco o en almacenamiento de objetos. - Guárdalo en un lugar inmutable: el almacenamiento en la nube con una política WORM (write-once-read-many) te da tanto durabilidad como la inalterabilidad que esperan la GoBD y la legislación francesa.
- No permitas nunca que la copia archivada sea la que se vuelve a renderizar; la idea central es que no pueda cambiar después de emitirse.
Los problemas que realmente generan tickets de soporte
Cuando las facturas fallan en PrestaShop, casi siempre es por una de estas razones, y la solución rara vez está en la plantilla:
- Dirección de empresa incorrecta en la factura. Se construye a partir del nombre y la dirección de la tienda (
PS_SHOP_NAME,PS_SHOP_ADDR1y el resto), que configuras en el bloque de dirección de la tienda en Parámetros de la tienda → Contacto, no a partir de los datos generales de contacto de la tienda o del correo electrónico. Actualízala allí. - Falta el número de IVA del vendedor. No hay sorpresa: la factura predeterminada de PrestaShop no imprime ningún número de IVA/fiscal del vendedor; el bloque del vendedor se construye solo con el nombre y la dirección de la tienda (los valores
PS_SHOP_*), sin campo de IVA, y Internacional → Impuestos solo configura tipos y reglas fiscales, no un identificador del vendedor. Para que aparezca tu número de IVA, añádelo como texto constante en los campos Texto legal libre / Texto de pie de página en Pedidos → Facturas, o imprímelo desde tu override de plantilla. El número del comprador es aparte: solo se imprime si el cliente lo introdujo en su dirección. - Los caracteres especiales se deforman en el PDF (ł/ą/ę polacas, diacríticos checos, el signo del euro renderizado como cuadros). TCPDF necesita una fuente que contenga esos glifos: cambia la fuente de la factura por una familia Unicode completa (por ejemplo, DejaVu/freefont) en la configuración de PDF, en lugar de usar la predeterminada.
- La generación del PDF falla en pedidos grandes. Normalmente es el
memory_limitde PHP: las facturas con muchas líneas y una plantilla pesada pueden superarlo. Súbelo a 256M+ en el lado de PHP. - Saltos en la numeración. A menudo se deben a un pedido cancelado que ya había generado una factura. Algunos países toleran huecos; Francia no. La solución es una estrategia de numeración, no un retoque de plantilla: ese es el tema de la personalización de números de factura y pedido.
Multitienda: una plantilla, muchas identidades legales
Si gestionas varios escaparates en una instalación multitienda, cada uno necesita su propia identidad de factura: distinto nombre de empresa, distinto pie legal y, a menudo, distinto idioma. PrestaShop maneja la mayor parte de este contexto automáticamente: cambia a la tienda concreta en el selector de tiendas del panel de administración antes de editar la configuración de facturas, y el prefijo, el texto legal libre y el pie se aplicarán solo a esa tienda. El peligro está en editar en el contexto Todas las tiendas, donde cualquier cambio se propaga a todas. Los archivos de plantilla se comparten desde el tema, así que si dos tiendas necesitan diseños realmente distintos, controla la diferencia con una condición por id de tienda dentro del .tpl en lugar de mantener dos plantillas bifurcadas.
Cuándo un módulo te ahorra el trabajo de overrides
Todo lo anterior puede hacerse a mano, y para una sola tienda en un solo país puede ser la decisión correcta. La ruta de overrides se vuelve costosa cuando tienes que mantener PHP personalizado y plantillas de tema a través de actualizaciones de PrestaShop, varios idiomas y varias jurisdicciones legales a la vez; justo ahí es donde un módulo mantenido se gana su sitio, porque la carga de compatibilidad deja de estar en tu plato.
Donde esto suele doler primero es en la numeración más que en el diseño: reinicios anuales, series separadas para facturas y abonos, y formatos como FA-2029-0001 que varias jurisdicciones esperan en la práctica. Nuestro módulo mprinvoicenumber lo gestiona desde el panel de administración: reinicios anuales automáticos, numeración multiserie y formatos personalizados con año/mes y secuencias rellenadas con ceros, para que no tengas que editar el contador a mano cada enero ni arriesgarte a los huecos que Francia no perdona. ¿Cuál es el beneficio? La numeración se mantiene conforme y la configuración vive en el administrador, no en un archivo override que la siguiente actualización podría sobrescribir. El razonamiento completo sobre por qué la numeración predeterminada se queda corta está en por qué los números predeterminados no son suficientes.
El resumen honesto: el motor de facturas de PrestaShop es sólido, pero su plantilla predeterminada es deliberadamente genérica, y "genérica" no es lo mismo que "legal en tu país". Personaliza el .tpl en tu tema, sobrescribe la clase PHP solo para los campos que PrestaShop aún no carga, coloca tu texto legal constante en los espacios integrados de texto libre y, la parte que la mayoría de comerciantes omite hasta que es demasiado tarde, archiva una copia congelada de cada factura el día en que se emite. Si lo haces bien una vez, la facturación se convierte en esa parte invisible y aburrida de tu tienda que debería ser.
Preguntas frecuentes
¿Dónde edito la plantilla de factura de PrestaShop?
Copia pdf/invoice.tpl del núcleo en themes/YOUR_THEME/pdf/invoice.tpl y edita la copia: PrestaShop comprueba la carpeta pdf/ del tema antes que el núcleo, así que las actualizaciones dejan tu versión intacta. El archivo de estilos correspondiente es invoice.style-tab.tpl. Solo cuando necesitas datos que PrestaShop todavía no pasa a la plantilla debes añadir también un override/classes/pdf/HTMLTemplateInvoice.php. Nunca edites directamente el archivo del núcleo.
¿Por qué no aparece el número de IVA de mi empresa en la factura?
Porque la factura predeterminada de PrestaShop no imprime ningún número de IVA del vendedor; el bloque del vendedor se construye solo con el nombre y la dirección de la tienda (los valores PS_SHOP_*), y Internacional → Impuestos configura tipos impositivos, no un identificador del vendedor. Añade tu número de IVA como texto constante en los campos Texto legal libre o Texto de pie de página en Pedidos → Facturas, o imprímelo desde un override de plantilla. El número del comprador es independiente y solo aparece si el cliente lo introdujo en su dirección.
¿Mis cambios de plantilla sobrevivirán a una actualización de PrestaShop?
Los overrides de pdf/ a nivel de tema sobreviven a las actualizaciones del núcleo, y los overrides de clase bajo override/classes/ también; pero una actualización de tema o una acción de "restablecer tema" puede borrar la copia del tema, y un módulo de terceros que incluya su propia plantilla u override puede chocar con el tuyo. Guarda ambos archivos en control de versiones fuera de la tienda y revísalos después de un salto de versión importante por si la plantilla del núcleo ha ganado campos que te convenga incorporar.
¿Los abonos y albaranes de entrega se personalizan igual?
El mismo mecanismo, archivos distintos. El abono (nota de crédito / avoir) es internamente el "order slip", así que personalizas themes/YOUR_THEME/pdf/order-slip.tpl (clase HTMLTemplateOrderSlip); el albarán de entrega es themes/YOUR_THEME/pdf/delivery-slip.tpl. Son documentos legalmente distintos, un cambio en invoice.tpl no se traslada, , así que edita cada uno que necesites.
¿Por qué los caracteres polacos o checos se convierten en cuadros en el PDF?
TCPDF, la biblioteca que renderiza el PDF, solo muestra glifos que existen en la fuente elegida. La fuente predeterminada puede no incluir ł/ą/ę u otros diacríticos. Cambia la fuente de la factura por una familia Unicode completa (una variante de DejaVu/freefont) en la configuración de PDF, y los caracteres se renderizarán correctamente. La misma solución corrige un signo de euro que se imprime como un cuadro.
Guías relacionadas
- Personalización de números de factura y pedido: por qué los números predeterminados no son suficientes
- Facturación electrónica en Europa: qué países la exigen y cómo cumplir
- Configuración de impuestos en PrestaShop: explicación de las reglas de IVA de la UE
- IVA en la UE: OSS, IOSS y qué debe gestionar tu tienda PrestaShop
- Reglas de visualización de precios en Europa: cuándo mostrar precios netos, brutos y unitarios
Comentarios
Dejar un comentario
Comparte una pregunta, un detalle de instalación o una opinión que pueda ayudar a otro lector.