Использование системы печати в Odoo

Оглавление

Подготовка

Для того, чтобы использовать следующий пример, вам необходимо переключить текущий разрабатываемый проект на другую ветку.

Вот ее имя - 16.0-print-form

Затем удалите текущую базу и создайте новую.

Убедитесь, что у вас не осталось вкладок со старыми сессиями

Основные данные

В этой статье я опишу как добавить свою печатную форму для какой либо модели, как на рисунке ниже

Печать

В документации, к сожалению не описано подробно как сделать печатную форму.

Общий сценарий работы системы печати:

        Report Action(На который ссылается формат бумаги)
            |
            |
    Формируется объект из выбранного рекордсета
            |
            |
    Передача объекта и указанного в экшене шаблона на рендеринг в QWeb
            |
            |
    Финальный объект рендеринга, либо HTML либо PDF

Экшен печати

Пример репорт экшена, в котором мы должны указать модель, к которой он будет прикреплен, тип финального контента после рендеринга, в этом случае я указал qweb-html, и external_id шаблона на базе которого будет происходить рендеринг. Детально описание всех параметров вы можете узнать тут. Код ниже взят отсюда

    <record id="first_model_print_form_001" model="ir.actions.report">
        <field name="name">Print Form Name 001</field>
        <field name="model">first.model</field>
        <field name="report_type">qweb-html</field>
        <field name="report_name">first_module.print_form_001_template</field>
        <field name="report_file">first_module.print_form_001_template</field>
        <field name="print_report_name">'Document №%s - %s' % (object.id, object.create_date)</field>
        <field name="binding_model_id" ref="first_module.model_first_model"></field>
    </record>

Печать

  1. Отображаемое имя экшена
  2. тип генерируемого контента
  3. Имя документа, в нем может быть использованы значения полей записи, к которой будет формироваться документ записи
  4. атрибут, который связывает экшен с моделью

Модель расширения объекта печати

Затем на основании вот этой документации мы можем создать модель которая будет создавать объекты для моего шаблона. Это может быть полезно в случаях когда нам нужно, например, добавить дополнительные объекты, или расширить существующие Вот код модели:

class ParticularReport(models.AbstractModel):
    _name = "report.first_module.print_form_001_template"
    _description = "Extend of print form"

    def _get_report_values(self, docids, data=None):
        """
        Функция для расширения данных подаваемых на печать в шаблон
        param : docids : list : список id записей модели, к которой прикреплен шаблон для печати
        param : data : {} : дополнительные которые содержат в себе метаинформацию
        return : dict : словарь данными, используемыми в шаблоне
        """
        first_model_recordset = self.env["first.model"].browse(docids)
        return {
            "doc_ids": docids,
            "docs": first_model_recordset,
            "data": data,
        }

Данная модель может быть создана для любого шаблона. Для этого достаточно правильно указать ее имя и определить метод _get_report_values. Принцип формирования имени следующий: report.полный.xml_d_шаблона или report.имя_модуля.id_шаблона. Как вы можете видеть в примере выше имя нашей модели полностью соответствует этому правилу report.first_module.print_form_001_template. Все параметры и структура объекта, который надо вернуть методом _get_report_values вы можете увидеть в примере и прочесть в контракте функции.

Использование шаблона

Вот код шаблона, который будет отрендерен. Как создавать шаблоны для QWeb движка и какие директивы вы может использовать можно ознакомиться здесь. Вот код

<template id="print_form_001_template">
    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="document">
            <div class="article" t-att-data-oe-model="document and document._name" t-att-data-oe-id="document and document.id">
                <t t-call="first_module.print_form_001_body_template" />
            </div>
        </t>
    </t>
</template>

И вот код основного шаблона, обратите внимание что нам внутри могут быть доступны значения атрибутов и методы набора записей (экземпляра класса модели) по котрой происходит формирование печатной формы


<template id="print_form_001_body_template">
    <h1 t-esc="document.name"></h1>
    <p>This is example of print form for record <span> </span><span t-esc="document.name"/></p>
    <table  class="table table-main">
        <tr>
            <th class="text-center" t-esc="document._fields['field_one'].string"></th>  
            <th class="text-center" t-esc="document._fields['field_two'].string"></th>
            <th class="text-center" t-esc="document._fields['result_field'].string"></th>
        </tr>
        <tr>
            <td class="text-center" t-esc="document.field_one" ></td>
            <td class="text-center" t-esc="document.field_two" ></td>
            <td class="text-center" t-esc="document.result_field" ></td>
        </tr>
    </table>

    <p t-esc="docs"/>

    <p t-esc="data"/>
</template>

Здесь вы можете видеть, как используются дополнительные данные, созданные в служебной промежуточной модели в шаблоне документа:

Дополнительные данные

Формат бумаги

Пример собственного формата бумаги. В данном случае я создал специальный формат, который соответствует накладной Республики Беларусь.

    <record id="paperformat_a4_belarus_tn_portrait" model="report.paperformat">
        <field name="name">ТН Вертикальная Беларусь</field>
        <field name="default" eval="True"/>
        <field name="format">custom</field>
        <field name="page_height">288</field>
        <field name="page_width">204</field>
        <field name="orientation">Portrait</field>
        <field name="margin_top">4</field>
        <field name="margin_bottom">12</field>
        <field name="margin_left">11</field>
        <field name="margin_right">2</field>
        <field name="header_line" eval="False"/>
        <field name="header_spacing">0</field>
        <field name="dpi">90</field>
        <field name="report_ids" eval="[(4, ref('first_module.first_model_print_form_001'))]"/>
    </record>

В целом это весьма синтетический пример, но на его основе вы можете полностью понять, как создавать произвольную печатную форму

Задания для самостоятельного повторения:

  1. Создайте свой шаблон для печати данных из записи
  2. Создайте альтернативный экшен, который будет запускать созданный вами шаблон.

Обсуждение

Обсудить можно здесь