How to Create a Custom Report in Odoo 12

As per companies daily business activities, companies need to generate a custom report according to their business flow. That is the reason today we bring for you, how to create a custom report in Odoo 12. You need to follow many things to create a custom report in Odoo 12. But don’t worry we are going to show you step by step.

In this custom report, We will generate daily sales summary report. Select the start date and end date. Click on Get Report button, it will generate daily sales summary report. It’s represents a day-wise number of orders and total sales amount.

Prerequisites

Before continuing with this tutorial, make sure you are installed wkhtmltopdf 0.12.5 (with patched qt). If you have not installed, you need to follow this instruction to download and install it.

You can download and install our sample report module from our Github account.

1. Initialize New Database

First, you have to create a new database along with load demonstration data. Thus, we can easily generate our custom report using pre-demo data.

Furthermore, you need to install sale_management module. Once you installed navigate to Sales → Reporting. Here you see only sales menu. We add new menu Sale Summary Report. When you click the menu, wizard modal open for select your start date and end date to generate sales summary report.

Ok, so let’s move ahead and install custom_report_odoo12 module.

Install Sample Custom Report Module

2. Create a Wizard

Create a wizard model and wizard view.

Wizard TransientModel

Create a wizard model that must be the TransientModel. Also, Create two fields start date, and end date.

Another, you see get_report method defined, it will be called when you click on the get report button from the wizard.

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

from odoo import models, fields, api


class SaleSummaryReportWizard(models.TransientModel):
    _name = 'sale.summary.report.wizard'

    date_start = fields.Date(string='Start Date', required=True, default=fields.Date.today)
    date_end = fields.Date(string='End Date', required=True, default=fields.Date.today)

    @api.multi
    def get_report(self):
        data = {
            'model': self._name,
            'ids': self.ids,
            'form': {
                'date_start': self.date_start, 'date_end': self.date_end,
            },
        }

        # ref `module_name.report_id` as reference.
        return self.env.ref('custom_report_odoo12.sale_summary_report').report_action(self, data=data)

Create Wizard View

Create a wizard view to display the date_start, date_end, and button.
Also, create wizard action and wizard menu to open a wizard popup.

<record id="sale_summary_report_wizard" model="ir.ui.view" >
    <field name="name">Sale Summary Report</field>
    <field name="model">sale.summary.report.wizard</field>
    <field name="type">form</field>
    <field name="arch" type="xml">
        <form string="Sale Summary Report">
            <group>
                <group>
                    <field name="date_start"/>
                </group>
                <group>
                    <field name="date_end"/>
                </group>
            </group>
            <footer>
                <button name="get_report" string="Get Report" type="object" class="oe_highlight"/>
                <button string="Cancel" special="cancel"/>
            </footer>
        </form>
    </field>
</record>

<act_window id="action_sale_summary_report_wizard"
    name="Sale Summary Report"
    res_model="sale.summary.report.wizard"
    view_mode="form"
    target="new"/>

<menuitem action="action_sale_summary_report_wizard"
    id="menu_sale_summary_report_wizard"
    parent="sale.menu_sale_report"/>

3. Gathering Report Data

Create an abstract model object. Because, abstract model especially for the report template object. Thus, you have to add a _get_report_values method into this object.

Basically, _get_report_values method collect report data from the database and make a dictionary that you have to return.

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

from datetime import datetime, timedelta

from odoo import models, fields, api
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT


class ReportSaleSummaryReportView(models.AbstractModel):
    """
        Abstract Model specially for report template.
        _name = Use prefix `report.` along with `module_name.report_name`
    """
    _name = 'report.custom_report_odoo12.sale_summary_report_view'

    @api.model
    def _get_report_values(self, docids, data=None):
        date_start = data['form']['date_start']
        date_end = data['form']['date_end']

        SO = self.env['sale.order']
        start_date = datetime.strptime(date_start, DATE_FORMAT)
        end_date = datetime.strptime(date_end, DATE_FORMAT)
        delta = timedelta(days=1)

        docs = []
        while start_date <= end_date:
            date = start_date
            start_date += delta

            print(date, start_date)
            orders = SO.search([
                ('confirmation_date', '>=', date.strftime(DATETIME_FORMAT)),
                ('confirmation_date', '<', start_date.strftime(DATETIME_FORMAT)),
                ('state', 'in', ['sale', 'done'])
            ])

            total_orders = len(orders)
            amount_total = sum(order.amount_total for order in orders)

            docs.append({
                'date': date.strftime("%Y-%m-%d"),
                'total_orders': total_orders,
                'amount_total': amount_total,
                'company': self.env.user.company_id
            })

        return {
            'doc_ids': data['ids'],
            'doc_model': data['model'],
            'date_start': date_start,
            'date_end': date_end,
            'docs': docs,
        }

4. Create a Paper Format

Create a new paper format record according to you need.

<record id="paperformat_sale_summary_report" model="report.paperformat">
    <field name="name">Sale Summary</field>
    <field name="default" eval="False"/>
    <field name="format">A4</field>
    <field name="page_width">0</field>
    <field name="page_width">0</field>
    <field name="orientation">Portrait</field>
    <field name="margin_top">30</field>
    <field name="margin_bottom">28</field>
    <field name="margin_right">7</field>
    <field name="margin_left">7</field>
    <field name="header_line" eval="False"/>
    <field name="header_spacing">15</field>
    <field name="dpi">90</field>
</record>

5. Make QWeb Report Template

Finally, create a report template. _get_report_values method returned dictionary will render to this template and generate PDF report.

<report id="sale_summary_report"
    model="sale.summary.report.wizard"
    string="Sale Summary Report"
    report_type="qweb-pdf"
    name="custom_report_odoo12.sale_summary_report_view"
    paperformat="custom_report_odoo12.paperformat_sale_summary_report"
    menu="False"/>

<template id="sale_summary_report_view">
    <t t-call="web.html_container">
        <div class="header" style="border-bottom: 1px solid black;">
            <h3 class="text-center">Sales Summary Report 
                <span style="font-size: 14px;"><strong>From</strong>: <t t-esc="date_start"/> <strong>To</strong>: <t t-esc="date_end"/></span>
            </h3>
        </div>
        <div class="article mt0 o_report_layout_standard">
            <table class="table table-condensed table-bordered">
                <thead>
                    <th style="width: 65%">Date</th>
                    <th class="text-center" style="width: 15%">Total Orders</th>
                    <th class="text-center" style="width: 20%">Total Amount</th>
                </thead>
                <tbody>
                    <t t-foreach="docs" t-as="doc">
                        <tr>
                            <td><span t-esc="doc['date']"/></td>
                            <td class="text-center"><span t-esc="doc['total_orders']"/></td>
                            <td class="text-center">
                                <span t-esc="doc['amount_total']" t-options='{"widget": "monetary", "display_currency": doc["company"].currency_id}'/>
                            </td>
                        </tr>
                    </t>
                </tbody>
            </table>
        </div>
        <div class="footer o_standard_footer" style="border-top: 1px solid black;">
            <div class="row text-center">
                <div class="col col-12 text-center">
                    <ul class="list-inline">
                        <li class="list-inline-item">Page:</li>
                        <li class="list-inline-item">
                            <span class="page"/>
                        </li>
                        <li class="list-inline-item">/</li>
                        <li class="list-inline-item">
                            <span class="topage"/>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </t>
</template>

Once you completed above, restart Odoo and install the module. Now, go to Sales → Reporting. You see a new menu Sale Summary Report.

Wizard Menu - Create custom report in Odoo

When you click on it open wizard modal as per below. Select the date range and click to Get Report button.

Wizard view - Select Date Range

You see the following sample report.

Daily Sales Summary Report - Custom report in Odoo

You can download above sample report module from Github. Moreover, you can refer here official Odoo QWeb Reports documentation.

We hope you have found this article helpful. Let us know your questions or feedback if any through the comment section in below. You can subscribe our newsletter and get notified when we publish new articles. Moreover, you can explore here other Odoo related articles.

Icon credit: Dream Icon


Join the Discussion.