Odoo
МодульQWeb звіти — друковані форми у твоїх руках
Як Odoo рендерить PDF через QWeb: синтаксис шаблонів, директиви t-set/t-if/t-foreach, кастомізація ПН з типом причини 09 і defense-смугою.
Що це і навіщо
QWeb — це шаблонний рушій Odoo для PDF, HTML і навіть фронтенду. Треба роздрукувати інвойс, скласти ТТН, згенерувати акт виконаних робіт чи сертифікат відповідності — усе йде через QWeb. На вигляд це звичайний XML з директивами t-*. По суті — Python, обмежений до безпечної підмножини, бо рендериться у sandbox.
QWeb треба знати, бо стандартні форми Odoo для України не годяться: інвойс не схожий на видаткову накладну, delivery slip — на ТТН, sales report — на акт. Свої форми тобі доведеться писати або переробляти чужі. Або купити Oblik-ERP, де основні вже готові, — але defense-специфіка все одно лишається на тобі.
Як це працює
Чотири складники:
ir.actions.report— «дія» друку. Прив’язана до моделі, посилається на шаблон.ir.ui.viewізtype='qweb'— сам шаблон.web_layout/external_layout— обгортка з шапкою і футером компанії: логотип, адреса, контакти.wkhtmltopdfабоchromium— рендерер у PDF.
Базовий шаблон:
<template id="report_my_doc">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<h2>Документ № <span t-field="o.name"/></h2>
<p>Дата: <span t-field="o.date" t-options="{'widget': 'date'}"/></p>
<p>Партнер: <span t-field="o.partner_id"/></p>
<table class="table table-sm">
<thead>
<tr><th>Позиція</th><th>К-сть</th><th>Сума</th></tr>
</thead>
<tbody>
<tr t-foreach="o.line_ids" t-as="line">
<td t-esc="line.name"/>
<td t-esc="line.quantity"/>
<td t-esc="line.amount"
t-options="{'widget': 'monetary', 'display_currency': o.currency_id}"/>
</tr>
</tbody>
</table>
<t t-if="o.is_export">
<p><strong>Експортна операція. Ставка ПДВ — 0%.</strong></p>
</t>
<p>Підпис: ________________ <t t-esc="o.signer_name or '____________'"/></p>
</div>
</t>
</t>
</t>
</template>
Основні директиви:
t-call— вкласти інший шаблон (web.html_container,web.external_layout).t-foreach="lst" t-as="x"— цикл за списком.t-if/t-elif/t-else— умовне відображення.t-set name="varname" value="..."— оголосити змінну.t-esc— виведення з екрануванням HTML (рекомендоване).t-raw— без екранування (лише коли точно знаєш, що це безпечно).t-field— вивести поле моделі з форматуванням за типом.t-options— налаштування форматування (widget,display_currency,locale).t-att-*— динамічні атрибути HTML (t-att-class="'red' if o.overdue else 'green'").
Прив’язка до action:
<record id="action_report_my_doc" model="ir.actions.report">
<field name="name">My Custom Report</field>
<field name="model">my.model</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">my_module.report_my_doc</field>
<field name="report_file">my_module.report_my_doc</field>
<field name="binding_model_id" ref="model_my_model"/>
<field name="binding_type">report</field>
</record>
Де шукати: Settings → Technical → Reports (усі actions) і → User Interface → Views (з фільтром type=qweb).
У контексті українського обліку
Що зазвичай збираємо у QWeb для України:
- Видаткова накладна. Стандартний invoice переписуємо в український формат: номер, дата, ким відпущено, ким отримано, ким перевірено, печатка.
- ТТН. З марками авто, прізвищем водія, маршрутом і пунктом призначення.
- Акт виконаних робіт. Як видаткова, але з описом послуг.
- Касова книга. Зведення ПКО/ВКО за день із підсумками.
- Інвентаризаційна відомість. Список ТМЦ з фактичними й обліковими кількостями, ким перевірено.
- Бухгалтерська довідка. Для ручних коригувань: обґрунтування, проводка, підпис головбуха.
- ПН/РК для друку. ПН реєструється в ЄРПН, але контрагентові потрібна й друкована копія. Формат — за наказом Мінфіну № 1307.
Усі ці форми мають підписи — посади, прізвища, печатку. Шаблон це враховує: або тягне з моделі (signer_id.name, signer_id.position), або підставляє дані компанії за замовчуванням.
Як ми робимо (defense-контекст)
ТОВ «УкрПром-Тех» зібрала власний модуль kit_blanks_def:
- М-11 з defense-смугою. До стандартної М-11 додає чорну смугу зверху з написом «ОБЛІК ВТП», номер контракту А-XXXX і підпис представника замовника.
- Сертифікат відповідності виробу. Власна форма. На вході —
mrp.production(закрите МО). Виводить номер партії, серійники компонентів зіstock.lot, результати тестування (з кастомногоqc.test.result), підписи QC-офіцера й керівника виробництва. - EUC (End-User Certificate). Для експорту. На вході — окремий документ
export.declaration. Виводить дані кінцевого користувача, призначення, заборону реекспорту, посилання на дозвіл ДСЕКУ. Двома мовами — UA і EN. - Калькуляція собівартості. На основі МО та analytic_lines. Виводить прямі матеріали за BoM, прямі зарплати з таймшитів, ЗВВ за коефіцієнтом і повну виробничу собівартість.
Усі ці форми викликаються кнопками на формах відповідних моделей. Якщо defense-контекст активний (поле is_defense=True на документі), Odoo пропонує defense-варіант форми.
Типові граблі
- wkhtmltopdf не вміє CSS3. Стандартний Odoo рендерить через wkhtmltopdf 0.12.x. Він не знає flex, grid, нових селекторів. Якщо шаблон спирається на
display: grid, у PDF буде криво. Перевіряй сам PDF, а не лише HTML-прев’ю. Або переходь на рендерерchromium-pdf. - Кирилиця перетворюється на квадратики. Стандартний Helvetica кирилиці не має. Підключи шрифт через CSS і пропиши його в layout. Найнадійніші для PDF — DejaVu Sans, Roboto, Inter.
t-fieldдля Char без обробки. Порожнє поле дасть None. Кращеt-esc="o.field or ''".t-rawз користувацьким вводом. Це XSS-діра. Якщо поле редагує користувач — тількиt-esc.- Розрив сторінки в небажаному місці. Таблиця ламається на півряду. Лікується через CSS:
tr { page-break-inside: avoid }. А для примусового розриву —<div style="page-break-before: always">. - Шаблон не оновився. Після правки й
Update Appу кеші лишається стара версія. Перезавантаж модуль (-u my_module --stop-after-init) або скинь веб-кеш черезSettings → Translations → Apply(такий собі трюк). - PDF величезний, рендериться 30 секунд. Причина одна з трьох: тисячі записів в одному документі (тоді розбивай на сторінки), CSS, що тягне за собою купу reflow, або важкі картинки. Стискай PNG до 400–800 px, прибирай заглушки.
external_layoutне показав логотип. Або не заповнено company.logo, або layout перебито кастомізацією. ПеревірSettings → Companies → External Report Layout.
Дотичне
- Бланки — список форм, які треба
- Як думає Odoo — модельна основа звітів
- ПН/РК — спеціальна форма ПН
- Accounting — звіти на основі account.move
Де цей модуль зустрічається3
- ГайдЗвірка через AgedВід звіту Aged Receivables до підписаного акта звірки: як швидко знайти прострочену дебіторку по партнерові, п…
- OdooБланкиУкраїнські первинні форми як QWeb-шаблони Odoo: де брати готові, як писати свої, на що звертати увагу.
- OdooЯк думає OdooАрхітектурна основа: ORM, models, fields, views, actions, security. Без цього кастомізація — шаманство.