« Back to Blogs

Generate Report from Custom Wizard in Odoo10

Odoo wizard is used to provide an interactive session to user through dynamic forms. Wizard is a model that will be created by inheriting models.TransientModel class instead of Model class. We can use it to take input from user and process it according to our business logic. Here I am going to show you how we can take input from the user in wizard and then process it to print a report.

Let's take a case in which sales manager needs to get a report for the orders placed by a salesperson in specific time period.

I am assuming here that you have basic knowledge of building an odoo module. So let’s start with creating a wizard that will take input from user. 
 
  • Create a class for the wizard:
class SalespersonWizard(models.TransientModel):
    _name = "salesperson.wizard"
    _description = "Salesperson Wizard"
   
   # Define fields according to your need
  • Now create a view for wizard in this module.
<record id="salesperson_report_view" model="ir.ui.view">
    <field name="name">Salesperson Wizard</field>
    <field name="model">salesperson.wizard</field>
    <field name="arch" type="xml">
       <form>
          <!-- Form design for your fields -->
       </form>
    </field>
</record>
  • After creating a view you need to create an action for that and later register that action with the menu to open the wizard.
<record id="action_salesperson_wizard" model="ir.actions.act_window">
    <field name="name">Generate Salesperson Report</field>
    <field name="res_model">salesperson.wizard</field>
    <field name="type">ir.actions.act_window</field>
    <field name="view_type">form</field>
    <field name="view_mode">form</field>
    <field name="view_id" ref="salesperson_report_view"/>
    <field name="target">new</field>
</record>
  • Below snippet create a new menu item “PDF Reports ? Salesperson” under “Sales?Reports” menu.
<menuitem id="sale_pdf_report" name="PDF Reports" parent="sales_team.menu_sale_report" sequence="20"/>
<menuitem id="sale_saleperson_report" name="Salesperson" action="action_salesperson_wizard" parent="sales_report.sale_pdf_report" sequence="10"/>

Now form is ready to take input from the user. So we need to process the input and print a report. To do this, first we need to create an action that process our request to print a report with our data. 

  • Add following code for calling a method in wizard class to process datas and print a report.
@api.multi
def check_report(self):
    data = {}
    data['form'] = self.read(['salesperson_id', 'date_from', 'date_to'])[0]
    return self._print_report(data)

def _print_report(self, data):
    data['form'].update(self.read(['salesperson_id', 'date_from', 'date_to'])[0])
    return self.env['report'].get_action(self, 'sales_report.report_salesperson', data=data)
  • Above method will invoke an action for printing a report. But before printing it, we need to filter data based on user input and send it to report for printing. For that we need to override the render_html() method as mentioned below:
@api.model
def render_html(self, docids, data=None):
    self.model = self.env.context.get('active_model')
    docs = self.env[self.model].browse(self.env.context.get('active_id'))
    sales_records = []
    orders = self.env['sale.order'].search([('user_id', '=', docs.salesperson_id.id)])
    if docs.date_from and docs.date_to:
       for order in orders:
         if parse(docs.date_from) <= parse(order.date_order) and parse(docs.date_to) >= parse(order.date_order):
             sales_records.append(order);
         else:
             raise UserError("Please enter duration")

    docargs = {
       'doc_ids': self.ids,
       'doc_model': self.model,
       'docs': docs,
       'time': time,
       'orders': sales_records
    }
    return self.env['report'].render('sales_report.report_salesperson', docargs)

So the coding part has been done and we have to create an xml file for printing a report with our requested data. 

  • Below is the code for creating a report. Simply modify according to your need and add it in xml file.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
   <template id="report_salesperson">
      <t t-call="report.html_container">
          <t t-foreach="docs" t-as="o">
              <t t-call="report.internal_layout">
                  <div class="page">
                      <!--  report design code goes here -->
                  </div>
              </t>
          </t>
       </t>
    </template>
</odoo>
  • Now you need to create a record entry for report under report folder.
<report 
     id="action_report_salesperson"
     model="report.sales_report.report_salesperson"
     string="Salesperson report"
     report_type="qweb-pdf"
     name="sales_report.report_salesperson"
     file="sales_report.report_salesperson" 
/>
You can create a wizard and print report from it by following this user guide. You can also go through the attached module sales_report.zip for further reference. Thank you!.
Comments
uan g
hi, great tutorial...
but i get a problem when trying this on odoo 11

the problem is ini this line

return self.env['report'].render('sales_report.report_salesperson', docargs)

because there is no modul with name report in odoo 11.
i don't know how to convert this line to odoo 11.

thanks in advance
Posted on 3/11/18 11:12 AM.
Surekha Technologies
Hello uan g,

As we know that report module is deprecated in odoo 11. So, you can use report_action() method to render any report.
i.e. self.env.ref('sales_report.report_salesperson').report_action(self,docids, data=datas)
Posted on 3/23/18 4:05 PM in reply to uan g.
contact-us Request a callback