Search code examples
pythonodooodoo-8

Odoo8 - generate report from Python by given user and data range


I need to generate timesheets report for a given user in a given data range. And I also need to sum the timesheets hours by date so each row in the report has unique date.

I have simple report ready as well as wizard for picking particular user and dates.

But I'm having trouble with actually generating report in Python and passing data to the report. When I click the print button on my wizard I get this error:

ProgrammingError: relation "hr_timesheet_karty_wizard" does not exist
LINE 1: INSERT INTO "hr_timesheet_karty_wizard" ("id", "date_from", ...

What I'm doing wrong? I'm not really sure what to do with records. Should I put them in 'doc_ids' or 'docs'? How to sum the records by dates?

I'm using Odoo 8.

Here is my python code:

# __init__.py

# -*- coding: utf-8 -*-
from . import wizard
# wizard/__init__.py

# -*- coding: utf-8 -*-
from . import wizard_karty
# wizard/wizard_karty.py

from openerp import api, models, fields
from datetime import datetime

class hr_timesheet_karty_wizard(models.AbstractModel):
    _name = 'hr.timesheet.karty.wizard'

    employee_id = fields.Many2one(comodel_name="hr.employee", required=True)
    date_from = fields.Date(default=fields.Datetime.now, required=True)
    date_to = fields.Date(default=fields.Datetime.now, required=True)

    @api.multi
    def print_report(self, data=None):

        records = self.env['hr.analytic.timesheet'].search([('employee_id', '=', self.employee_id),('date_from', '>=', self.date_from),('date_to', '<=', self.date_to)])   
        # sum records hours if date is the same (group by date)

        report_obj = self.env['report']
        report = report_obj._get_report_from_name('hr_timesheet_karty.template_hr_timesheet_karty')
        docargs = {
            'doc_ids': self._ids,
            'doc_model': report.model,
            'docs': records,
        }
        return report_obj.render('hr_timesheet_karty.template_hr_timesheet_karty', docargs)

Here is my wizard:

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

    <record id="view_hr_timesheet_karty_wizard" model="ir.ui.view">
        <field name="name">hr.timesheet.karty.wizard.form</field>
        <field name="model">hr.timesheet.karty.wizard</field>
        <field name="arch" type="xml">
        <form string="Leaves by Department">
            <group>
                <field name="employee_id"/>
                <field name="date_from"/>
                <field name="date_to"/>
            </group>
            <footer>
                <button name="print_report" string="Print" type="object" class="oe_highlight"/> or
                <button string="Cancel" special="cancel" class="oe_link"/>
            </footer>
        </form>
        </field>
    </record>

    <record id="action_hr_timesheet_karty_wizard" model="ir.actions.act_window">
        <field name="name">Time sheet report</field>
        <field name="res_model">hr.timesheet.karty.wizard</field>
        <field name="view_type">form</field>
        <field name="view_mode">form</field>
        <field name="view_id" ref="view_hr_timesheet_karty_wizard"/>
        <field name="target">new</field>
    </record>

    <menuitem id="menu_hr_timesheet_karty_wizard"
        name="Time sheet report"
        parent="hr.menu_hr_reporting_timesheet"
        action="action_hr_timesheet_karty_wizard"
        sequence="1"
        icon="STOCK_PRINT"/>

  </data>
</openerp>

And here is my report:

<?xml version="1.0" encoding="utf-8"?>
<openerp>
  <data>
    <report
        id="action_hr_timesheet_karty"
        string="Time sheet report"
        model="hr.analytic.timesheet"
        report_type="qweb-pdf"
        name="hr_timesheet_karty.template_report_hr_timesheet_karty"
    />

    <template id="template_hr_timesheet_karty">
        <t t-call="report.html_container">
            <t t-call="report.external_layout">
                <div class="page">

                    <table class="table table-condensed">
                        <thead>
                            <tr>
                                <th>User</th>
                                <th>Date</th>
                                <th>Time</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr t-foreach="docs" t-as="o">
                                <td><span t-field="o.user_id.name"/></td>
                                <td><span t-field="o.date"/></td>
                                <td class="text-right"><span t-field="o.unit_amount"/> h</td>
                            </tr>
                        </tbody>
                    </table>

                </div>

            </t>
        </t>
    </template>

  </data>
</openerp>

Please help


Solution

  • Abstract Model super-class for creating an abstract class meant to be inherited by regular models (Models or TransientModels) but not meant to be usable on its own or persisted.

    • _auto = False # don't create any database backend for AbstractModels
    • _register = False # not visible in ORM registry, meant to be python-inherited only

    TransientModel is used for temporary data, stored in the database but automatically vacuumed every so often.

    You need to use TransientModel instead of AbstractModel.

    class hr_timesheet_karty_wizard(models.TransientModel):
        _name = 'hr.timesheet.karty.wizard'
    

    The print_report method looks like the render_html method of qweb report parser.

    • Change print_report to :

      @api.multi
      def print_report(self):
          self.ensure_one()
          datas = {'wizard_id': self.id}
          return self.env['report'].get_action(self, 'hr_timesheet_karty.template_hr_timesheet_karty', data=datas)
      
    • Add a report parser:

      class HrTimesheetKartyReport(models.AbstractModel):
          _name = 'report.hr_timesheet_karty.template_hr_timesheet_karty'
      
          @api.multi
          def render_html(self, data=None):
              hr_analytic_timesheet = self.env['hr.analytic.timesheet']
              if data and 'wizard_id' in data:
                  wizard = self.env['hr.timesheet.karty.wizard'].browse(data['wizard_id'])
                  records = hr_analytic_timesheet.search([('employee_id', '=', wizard.employee_id.id),
                                                          ('date_from', '>=', wizard.date_from),
                                                          ('date_to', '<=', wizard.date_to)])
              else:
                  records = hr_analytic_timesheet.browse(self._ids)
              # sum records hours if date is the same (group by date)
      
              report_obj = self.env['report']
              report = report_obj._get_report_from_name('hr_timesheet_karty.template_hr_timesheet_karty')
              docargs = {
                  'doc_ids': self._ids,
                  'doc_model': report.model,
                  'docs': records,
              }
              return report_obj.render('hr_timesheet_karty.template_hr_timesheet_karty', docargs)
      
    • Change report action name and template id to hr_timesheet_karty.template_hr_timesheet_karty.

      <report
          id="action_hr_timesheet_karty"
          string="Time sheet report"
          model="hr.analytic.timesheet"
          report_type="qweb-pdf"
          name="hr_timesheet_karty.template_hr_timesheet_karty"
      />
      
      <template id="template_hr_timesheet_karty">