Отчеты пишутся в формате HTML/QWeb, как и все обычные представления в Odoo. Вы можете использовать стандартный QWeb. Сам рендеринг PDF выполняется системной утилитой wkhtmltopdf.
Если вы хотите создать отчет для определенной модели, вам нужно будет определить Отчет и Шаблон отчета, которые он будет использовать. Если вы хотите, вы также можете указать конкретный Формат бумаги для этого отчета. Наконец, если вам нужен доступ к чему то большему чем ваша модель, вы можете определить класс Кастомные отчеты, который даст вам доступ к большему количеству моделей и записей в шаблоне.
Отчет
Каждый отчет должен быть объявлен с помощью действия.
Для простоты определения отчета доступен сокращенный элемент <report>
, а не настраивать действие и его окружение вручную. Этот <report>
может принимать следующие атрибуты:
id
- Сгенерированный записью external id
name
(обязательный параметр)- полезен только в качестве запоминающегося описания, чтобы можно было найти в списке аналогичных объектов
model
(обязательный параметр)- модель к которой относится отчет
report_type
(обязательный параметр)- укажите
qweb-pdf
для создания PDF файлов печатных форм, илиqweb-html
для HTML report_name
- имя отчета (которое будет присвоено выданному PDF файлу)
groups
Many2many
поле со ссылкой на группы которым разрешено использовать отчетattachment_use
- Если установлено значение True, отчет будет сохранен как прикрепление к записи с использованием имени, сгенерированного выражением
attachment
; Вы можете это использовать , если вам нужно, чтобы ваш отчет генерировался только один раз (по юридическим причинам, например) attachment
- Выражение python, которое определяет имя отчета; Запись доступна как переменная
object
paperformat
- Внешний идентификатор формата бумаги, который вы хотите использовать (по умолчанию используется формат бумаги компании, если он не указан явно)
Пример:
<report
id="account_invoices"
model="account.invoice"
string="Invoices"
report_type="qweb-pdf"
name="account.report_invoice"
file="account.report_invoice"
attachment_use="True"
attachment="(object.state in ('open','paid')) and
('INV'+(object.number or '').replace('/','')+'.pdf')"
/>
Шаблон отчета
Минимальный жизнеспособный шаблон
Минимальный шаблон будет выглядеть так:
<template id="report_invoice">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<h2>Report title</h2>
<p>This object's name is <span t-field="o.name"/></p>
</div>
</t>
</t>
</t>
</template>
Вызов external_layout
добавит стандартные заголовок и нижний колонтитул в ваш отчет. Тело PDF будет содержимым внутри <div class="page">
. id
шаблона должен быть именем, указанным при объявлении отчета; Например account.report_invoice
для вышеупомянутого отчета. Поскольку это шаблон QWeb, вы можете получить доступ ко всем полям объекта docs
принятого внутри шаблона.
В отчетах доступны переменные, в основном:
docs
- записи для текущего отчета
doc_ids
- список id для записей
docs
doc_model
- модель для записей
docs
time
- ссылка на
time
из стандартной библиотеки Python user
- запись
res.user
для пользователя, печатающего отчет res_company
- запись компании текущего
user
Если вы хотите получить доступ к другим записям/моделям в шаблоне, вам понадобится кастомный отчет..
Переводимые шаблоны
Если вы хотите перевести отчеты (например, на язык партнера), вам необходимо определить два шаблона:
- Основной шаблон отчета
- Переводимый документ
Затем вы можете вызвать переводимый документ из вашего основного шаблона с атрибутом t-lang
, для назначено код языка (например, fr
или en_US
) или назначено поле записи кде этот код содержится. Вам также нужно будет повторно просмотреть связанные записи с надлежащим контекстом, если вы используете поля, которые можно переводить (например, названия стран, состояния продаж и т.д.),
Предупреждение
Если в вашем шаблоне отчета не используются переводимые поля записей, повторный просмотр записи на другом языке не необходим и повлияет на производительность.
Например, рассмотрим отчет Sale Order из модуля «Продажи»:
<!-- Main template -->
<template id="report_saleorder">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/>
</t>
</t>
</template>
<!-- Translatable template -->
<template id="report_saleorder_document">
<!-- Re-browse of the record with the partner lang -->
<t t-set="doc" t-value="doc.with_context({'lang':doc.partner_id.lang})" />
<t t-call="web.external_layout">
<div class="page">
<div class="oe_structure"/>
<div class="row">
<div class="col-xs-6">
<strong t-if="doc.partner_shipping_id == doc.partner_invoice_id">Invoice and shipping address:</strong>
<strong t-if="doc.partner_shipping_id != doc.partner_invoice_id">Invoice address:</strong>
<div t-field="doc.partner_invoice_id" t-options="{"no_marker": True}"/>
<...>
<div class="oe_structure"/>
</div>
</t>
</template>
Основной шаблон вызывает переводимый шаблон с doc.partner_id.lang
в качестве параметра t-lang
, поэтому он будет отображаться на языке партнера. Таким образом, каждый Sale Order будет напечатан на языке соответствующего покупателя. Если вы хотите перевести только тело документа, но сохранить верхний и нижний колонтитулы на языке по умолчанию, вы можете вызвать внешний макет отчета следующим образом:
<t t-call="web.external_layout" t-lang="en_US">
Совет
Обратите внимание, что это работает только при вызове внешних шаблонов, вы не сможете перевести часть документа, установив атрибут t-lang
на узле xml отличный от t-call
. Если вы хотите перевести часть шаблона, вы можете создать внешний шаблон с этим неполным шаблоном и вызвать его из основного с атрибутом t-lang
.
Штрих-коды
Штрих-коды - это изображения, возвращаемые контроллером и легко встраиваемые в отчеты благодаря синтаксису QWeb (см Атрибуты:
<img t-att-src="'/report/barcode/QR/%s' % 'My text in qr code'"/>
Дополнительные параметры могут быть переданы как строка запроса
<img t-att-src="'/report/barcode/?
type=%s&value=%s&width=%s&height=%s'%('QR', 'text', 200, 200)"/>
Полезные заметки
- Классы Bootstrap и FontAwesome можно использовать в шаблоне отчета.
- Локальный CSS можно поместить непосредственно в шаблон
Глобальный CSS можно вставить в основной макет отчета, унаследовав его шаблон и вставить свой CSS
<template id="report_saleorder_style" inherit_id="report.style"> <xpath expr="."> <t> .example-css-class { background-color: red; } </t> </xpath> </template>
- Если кажется, что в вашем отчете PDF отсутствуют стили, проверьте эти инструкции.
Формат бумаги
Форматы бумаги - это записи модели report.paperformat
и могут содержать следующие атрибуты:
name
(обязательный параметр)- полезен только в качестве запоминающегося описания, чтобы можно было найти в списке аналогичных объектов
description
- небольшое описание вашего формата
format
- либо предопределенный формат (от A0 до A9, от B0 до B10, Legal, Letter, Tabloid, …) или
custom
; A4 по умолчанию. Вы не можете использовать нестандартный формат, если вы определяете размеры страницы. dpi
- значение DPI на выходе; 90 по умолчанию
margin_top
,margin_bottom
,margin_left
,margin_right
- размеры полей в мм
page_height
,page_width
- размер страницы в мм
orientation
- Landscape или Portrait
header_line
- булево значение для отображения строки заголовка
header_spacing
- Отступ от заголовка в мм
Пример:
<record id="paperformat_frenchcheck" model="report.paperformat">
<field name="name">French Bank Check</field>
<field name="default" eval="True"/>
<field name="format">custom</field>
<field name="page_height">80</field>
<field name="page_width">175</field>
<field name="orientation">Portrait</field>
<field name="margin_top">3</field>
<field name="margin_bottom">3</field>
<field name="margin_left">3</field>
<field name="margin_right">3</field>
<field name="header_line" eval="False"/>
<field name="header_spacing">3</field>
<field name="dpi">80</field>
</record>
Кастомные отчеты
The report model has a default get_html
function that looks for a model
named report.module.report_name
. If it exists, it will use it to
call the QWeb engine; otherwise a generic function will be used. If you wish
to customize your reports by including more things in the template (like
records of others models, for example), you can define this model, overwrite
the function get_report_values
and pass objects in the docargs
dictionary:
from odoo import api, models
class ParticularReport(models.AbstractModel):
_name = 'report.module.report_name'
@api.model
def get_report_values(self, docids, data=None):
report_obj = self.env['ir.actions.report']
report = report_obj._get_report_from_name('module.report_name')
docargs = {
'doc_ids': docids,
'doc_model': report.model,
'docs': self,
}
return docargs
Кастомные шрифты
Если вы хотите задейтсвовать кастомные шрифты, вам нужно добавить свой собственный шрифт и связанный с ним less/CSS в бандле ассетов web.reports_assets_common
. Добавление кастомных шрифтов в бандл web.assets_common
или web.assets_backend
не сделает ваш шрифт доступным в отчетах QWeb.
Пример:
<template id="report_assets_common_custom_fonts" name="Custom QWeb fonts" inherit_id="web.report_assets_common">
<xpath expr="." position="inside">
<link href="/your_module/static/src/less/fonts.less" rel="stylesheet" type="text/less"/>
</xpath>
</template>
Вам нужно будет определить ваш @font-face
в этом less файле, даже если вы использовали его в другом бандле ассетов (кроме web.reports_assets_common
).
Пример:
@font-face {
font-family: 'MonixBold';
src: local('MonixBold'), local('MonixBold'), url(/your_module/static/src/fonts/MonixBold-Regular.otf) format('opentype');
}
.h1-title-big {
font-family: MonixBold;
font-size: 60px;
color: #3399cc;
}
После того, как вы добавили less в свой бандл ассетов, вы можете использовать классы - в этом примере h1-title-big
- в своем кастомном отчете QWeb.
Отчеты - это веб-страницы
Отчеты динамически генерируются модулем отчета и могут быть доступны напрямую через URL:
Например, вы можете получить доступ к отчету Sale Order в режиме html, перейдя в http://<server-address>/report/html/sale.report_saleorder/38
Или вы можете получить доступ к PDF-версии по адресу http://<server-address>/report/pdf/sale.report_saleorder/38