Cómo hacer un informe a medida en Odoo 15

Nota: Si trabajas con Odoo 12 puedes mirar este otro ejemplo:https://www.flashodoo.com/blog/flashodoo-1/post/como-hacer-un-informe-a-medida-en-odoo-12-54

Para este ejemplo vamos a hacer un informe que nos muestre las ventas diarias. Partiremos de una pantalla en la que podamos seleccionar la la fecha de inicio y de final y un boton que al hacer click nos mostrará el resumen de ventas diario en un informe.

Prerequisitos

Antes de continuar tienes que tener instalado  wkhtmltopdf 0.12.5 (con los parches de qt). Si no lo tienes instalado, puedes seguir  estas instrucciones para descargar e instalarlo.

Puedes descargar e instalar el ejemplo desde : https://github.com/FoxOdoo/odoo15_informe/tree/main/flash_custom_reports

Primero tienes que instalar el módulo de Ventas (sale_management. Una vez instalado, navega a Ventas → Informes. Ahí puedes ver sólo un menú de  ventas.  Añadiremos una nueva opción de menú llamada Sale Summary Report. Cuando hagas click en el menú, se abrirá un wizard modal para despues de indicar la fecha de inicio y final poder generar el informe de ventas.

Así que continuemos e instalemos el módulo flash_custom_reports .


2. Crear un Wizard

En la carpeta wizard crearemos:

- Un fichero python con el wizard model

- Un fichero XML con el wizard view. 

En el wizard model que deberia ser TransientModelcrearemos dos campos uno para la fecha de inicio y otro para la fecha final.

El fichero wizard view tendrá tres partes: el menú, la acción y el wizard propiamente

A continuación, te muestro el contenido del wizard model llamado: wizard.py

# -*- coding: utf-8 -*-

from email.policy import default
from odoo import api, fields, models
import calendar, datetime

class SaleOrderWizard(models.TransientModel):
    _name = 'sale.order.report.wizard'
    _description = 'Sale Order Report Wizard'

    date_start = fields.Date('Fecha Inicio', default=primer_dia_mes)
    date_end = fields.Date('Fecha Fin', default=ultimo_dia_mes)
   
    def primer_dia_mes(self):
        now = datetime.datetime.now()
        year = now.year
        month = now.month

        return datetime.date(year,month,1)

    def ultimo_dia_mes(self):
        now = datetime.datetime.now()
        year = now.year
        month = now.month
        last_day = calendar.monthrange(year, month)[1] ## último día

        return datetime.date(year,month,last_day)

    def action_search_orders(self):
        form_data = self.read()[0]

        orders = self.env['sale.order'].search_read([
            ('create_date', '>=', form_data['date_start']),
            ('create_date', '<=', form_data['date_end'])
        ])

        data = {
            'form_data': form_data,
            'orders': orders
        }

        return self.env.ref('flash_custom_reports.action_report_sale_order').report_action(self, data=data)
Python

A continuación, te muestro el contenido del wizard view llamado: wizard.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <!-- Definición del Wizard -->
    <record id="sale_order_report_wizard_view_form" model="ir.ui.view">
        <field name="name">sale.order.report.wizard.view.form</field>
        <field name="model">sale.order.report.wizard</field>
        <field name="arch" type="xml">
            <form string="Informe de Ventas">
                <sheet>
                    <group>
                        <field name="date_start" />
                        <field name="date_end" />
                    </group>
                    <footer>
                        <button name="action_search_orders" type="object" string="Buscar" class="btn-primary" />
                        <button string="Cancelar" class="btn-secondary" special="cancel" />
                    </footer>
                </sheet>
            </form>
        </field>
    </record>

    <!-- Definición de la acción -->
    <record id="sale_order_report_wizard_action" model="ir.actions.act_window">
        <field name="name">Informe de Ventas</field>
        <field name="res_model">sale.order.report.wizard</field>
        <field name="view_mode">form</field>
        <field name="view_id" ref="sale_order_report_wizard_view_form" />
        <field name="target">new</field>
    </record>
   
    <!-- Definición del menú -->
    <menuitem
        id="sale_order_report_menu"
        name="Informe Ventas"
        action="sale_order_report_wizard_action"
        parent="sale.menu_sale_report"
        sequence="10" />
</odoo>

Python

3. Crear el report

A continuación, te muestro el contenido del report propiamente que es el que nos muestra los datos. Lo creamos en la carpeta report con el nombre: report.xml. Por una parte esta propiamente el informe y por otra la definición de la acción.

<?xml version="1.0" encoding="utf-8"?>
<odoo>

    <template id="sale_report_template">
        <t t-call="web.html_container">
            <t t-call="web.external_layout">
                <div class="oe_structure" />
                <div class="page">
                    <div class="text-center"><h2>Ventas</h2></div>
                    <p class="text-center"><B>Fecha Inicio:</B> <span t-esc="form_data['date_start']" t-options='{"widget": "date"}'/></p>
                    <p class="text-center"><B>Fecha Final:</B> <span t-esc="form_data['date_end']" t-options='{"widget": "date"}'/></p>
                    <table class="table o_main_table table-centered" name="contratos">
                        <thead>
                            <tr>
                                <th>Número</th>
                                <th>Cliente</th>
                                <th>Fecha</th>
                                <th class="text-right">Total</th>
                            </tr>
                        </thead>
                        <tbody>
                            <t t-foreach="orders" t-as="line">
                                <tr>
                                    <td><span t-esc="line['name']" /></td>
                                    <td><span t-esc="line['partner_id'][1]" /></td>
                                    <td><span t-esc="line['date_order']" t-options='{"widget": "date"}'/></td>
                                    <td class="text-right"><span t-esc="line['amount_total']" t-options='{"widget": "float", "precision": 2}'/></td>
                                </tr>
                            </t>
                        </tbody>
                    </table>
                </div>
            </t>
        </t>
    </template>

    <record id="action_report_sale_order" model="ir.actions.report">
        <field name="name">Ventas</field>
        <field name="model">sale.order</field>
        <field name="report_type">qweb-html</field>
        <field name="report_name">flash_custom_reports.sale_report_template</field>
        <field name="report_file">flash_custom_reports.sale_report_template</field>
        <field name="binding_model_id" ref="sale_management.model_sale_order"/>
        <field name="binding_type">report</field>
    </record>

</odoo>
Python

Una vez realizado lo anterior, reinicio Odoo e instala el módulo. A continuación, vete a Ventas → Informes. Verás un nuevo menú llamado Informe Ventas

Al hacer click en el menú se nos abre el wizard modal como en la ventana que sigue. Selecciona el rango de fechas y haz click en el boton para conseguir el Informe.


Verás el siguiente informe.

Daily Sales Summary Report - Custom report in Odoo

Tienes más información en la web oficial de Odoo QWeb Reports.