← ClaudeAtlas

odoo-reportslisted

Authoring or customizing Odoo 17/18/19 QWeb reports — the printable PDF/HTML documents (invoices, sale orders, pickings, custom certificates). Use when creating an ir.actions.report, writing or inheriting a QWeb report template, adding a report.<module>.<name> parser to feed extra data, fixing paperformat / margins / page breaks, translating a report per partner language, or debugging "my changes don't show / wrong template / values undefined in the PDF". Don't guess the template id or whether a parser exists — find the existing report with the `odoo-introspect` skill first, then inherit. NOT for the dynamic financial-statement grids under Accounting → Reporting (P&L, balance sheet, tax reports) — those are the `account.report` engine: use `odoo-statutory-reports`.
tuanle96/odoo-ai-skills · ★ 4 · Data & Documents · score 62
Install: claude install-skill tuanle96/odoo-ai-skills
# Odoo QWeb reports (PDF / HTML) An Odoo report is **three layers**, and most bugs come from touching the wrong one: | Layer | What it is | Lives in | |-------|-----------|----------| | **Action** | `ir.actions.report` — `model`, `report_name`→template, `report_type`, `paperformat_id`, Print-menu binding | data XML | | **Template** | QWeb: `web.html_container` → `web.external_layout` → your `<div class="page">` | data XML (loaded via `__manifest__['data']`) | | **Data** | *optional* `models.AbstractModel` named `report.<module>.<report_name>` with `_get_report_values()` | Python | PDFs are rendered from the HTML by **wkhtmltopdf** (0.12.6, qt-patched). Version floor: Odoo 17/18, through Odoo 19 (current LTS). Use `t-out` for output (v17+ — `t-esc` superseded, `t-raw` removed). **The rule: there is almost always an existing report — find its action, template, and parser, then *inherit*. Don't rebuild and don't guess ids.** ## Discover before you customize (introspect-first) Use the `odoo-introspect` skill: - `metadata.py` enumerates `ir.actions.report` records with their QWeb template + paperformat; `entrypoints.py` (reads the resolved `get_view`) surfaces the reports bound to a model (the **Print** menu). Get `report_name` → the template external id → whether a `report.<module>.<name>` AbstractModel parser already exists. Never hand-guess the template id. - **Two-template trap:** real reports split into a *main* template (loops `docs`, sets `lang`) and a `*_document` *