Informes PDF con QWeb en Odoo: del formulario al documento que cierra ventas
QWeb es HTML que se convierte en PDF. Te enseñamos a montar un informe, recorrer registros con t-foreach y por qué t-field te ahorra mil dolores de cabeza.
Forma parte de nuestra guía completa: Desarrollo de módulos en Odoo.
Hay una parte de Odoo que el cliente final ve más que ninguna otra y que, paradójicamente, suele ser la peor cuidada: los informes en PDF. La factura, el presupuesto, la ficha de producto, la orden de trabajo. Son el documento que sale de tu empresa con tu logo y llega al cliente. Y, sin embargo, demasiadas veces es un PDF descuadrado, con la fecha en formato americano y un total que no cuadra con la pantalla.
La buena noticia: en Odoo los informes son QWeb, que en el fondo es HTML con superpoderes. Si sabes maquetar una tabla, sabes hacer un informe. Vamos a verlo.
Dos piezas: la acción y la plantilla
Un informe son siempre dos cosas. Primero, una acción de informe (ir.actions.report) que le dice a Odoo "sobre este modelo, ofrece este PDF y añádelo al menú Imprimir":
<record id="action_report_property" model="ir.actions.report">
<field name="name">Ficha de propiedad</field>
<field name="model">estate.property</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">estate.report_property</field>
<field name="binding_model_id" ref="model_estate_property"/>
<field name="binding_type">report</field>
</record>
Ese binding_model_id es el detalle que mucha gente olvida: es lo que hace que el botón "Imprimir" aparezca en el formulario. Sin él, el informe existe pero no hay forma de lanzarlo desde la interfaz, y empiezan los "no me sale por ningún lado".
La plantilla: HTML que recorre tus datos
La segunda pieza es la plantilla QWeb. Aquí es donde se ve que QWeb es HTML con directivas t-. Te apoyas en los layouts estándar de Odoo (web.html_container, web.external_layout) para heredar la cabecera con el logo y el pie de página de la empresa gratis:
<template id="report_property">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.external_layout">
<div class="page">
<h2 t-field="doc.name"/>
<p>Precio esperado: <span t-field="doc.expected_price"/></p>
<table class="table table-sm">
<thead>
<tr><th>Cliente</th><th>Oferta</th></tr>
</thead>
<tbody>
<tr t-foreach="doc.offer_ids" t-as="offer">
<td t-field="offer.partner_id"/>
<td t-field="offer.price"/>
</tr>
</tbody>
</table>
</div>
</t>
</t>
</t>
</template>
Ese docs es la colección de registros que mandaste a imprimir; el t-foreach los recorre uno a uno (y aquí también funciona con el One2many de las ofertas, justo como vimos en relaciones entre modelos). Como ves, las clases table table-sm son Bootstrap: Odoo lo trae de serie, así que no maquetas desde cero.
t-field vs t-esc: el detalle que separa un PDF profesional de uno cutre
Aquí está el matiz que más impacto tiene en la calidad del documento, y casi nadie lo explica bien. Tienes dos formas de pintar un valor:
t-esc(ot-out) imprime el dato en crudo. Un float sale como250000.0. Una fecha, en formato técnico.t-fieldimprime el dato formateado según su tipo y la configuración de la empresa: el precio sale como250.000,00 €, la fecha en el formato del idioma, el Many2one como el nombre del registro.
Regla simple: para mostrar campos de un registro, usa siempre t-field. Reserva t-esc/t-out para valores calculados al vuelo que no son un campo. El día que entiendes esto, tus PDF dejan de parecer un volcado de base de datos y empiezan a parecer documentos de empresa.
Hereda los informes estándar, no los copies
¿Necesitas añadir tu campo a la factura estándar de Odoo? La tentación es duplicar la plantilla de factura entera y editarla. Mal. Igual que con las vistas, se hereda con xpath —el mismo principio que explicamos en herencia en Odoo—:
<template id="report_invoice_zone" inherit_id="account.report_invoice_document">
<xpath expr="//div[@id='informations']" position="inside">
<p>Zona de reparto: <span t-field="o.delivery_zone"/></p>
</xpath>
</template>
Así tu añadido sobrevive a las actualizaciones, en lugar de quedarte con una factura congelada que pierde cada mejora que Odoo publique.
El gotcha del motor de renderizado
Un aviso que ahorra horas: el PDF lo genera wkhtmltopdf, que no es un navegador moderno. Hay CSS que en pantalla se ve perfecto y en el PDF se rompe (flexbox caprichoso, márgenes que se ignoran, saltos de página inesperados). La cura es maquetar sobre las clases de Bootstrap que Odoo ya usa y probar siempre el PDF real, no solo la previsualización HTML. Lo que ves en el navegador no es lo que imprime el motor.
Por qué esto no es un detalle menor
Un presupuesto bien maquetado transmite seriedad antes de que el cliente lea una sola cifra; uno descuadrado siembra dudas. El informe es marketing silencioso. Por eso, cuando montamos un Odoo, los documentos que salen al exterior reciben el mismo cuidado que la lógica de negocio.
¿Tus PDF de Odoo dan una imagen que no te representa, o necesitas un informe a medida que hoy no existe? En una sesión de diagnóstico los revisamos, o míralo dentro de nuestro desarrollo a medida. Para el resto del recorrido, tienes la anatomía de un módulo y las acciones automatizadas.
Comentarios (0)
Sé el primero en comentar.
Inicia sesión para dejar un comentario.
AccederLos comentarios se revisan antes de publicarse.
Artículos relacionados
Acciones automatizadas en Odoo: deja que el ERP haga el trabajo aburrido
Acciones de servidor, reglas de automatización y tareas planificadas: las tres piezas para que Odoo reaccione, avise y ejecute solo, sin que nadie se acuerde.
Herencia en Odoo: la función que decide si tu código sobrevive a las actualizaciones
Extensión clásica, delegación y herencia de vistas. Las tres formas de modificar Odoo sin tocar el core —y por qué heredar en vez de copiar te ahorra cada migración.
Relaciones entre modelos en Odoo: Many2one, One2many y Many2many sin liarte
Las tres relaciones que conectan tus datos, qué guardan de verdad en la base de datos y los comandos para escribirlas sin romper nada.