Reportes con report_aeroo

Fuente: Wiki de Alistek(creadores de report_aeroo).

El propósito de esta página es describir como instalar y crear reportes con el módulo report_aeroo.

En nuestra experiencia probando distintas alternativas para crear reportes en OpenERP, encontramos en report_aeroo la opción mas sencilla y rápida.

Si bien la wiki de Alistek describe detalladamente como instalar y utilizar el modulo report_aeroo, es interesante mostrar lo sencillo que es crear reportes con este módulo.

Instalación

Los pasos de la instalación están pensados para llevarse a cabo en un servidor GNU/Linux. En particular, la distribución Ubuntu 10.4.

Para instalar en Windows, ver: Instalación en Windows.

Antes de poder instalar report_aeroo, debemos instalar sus dependencias. Como describe la wiki, necesitamos instalar lo siguiente:

Desde la fuente:

La instalación de aeroolib se encarga de instalar python-genshi y python-lxml por lo que no es necesario que instalemos estos desde los repositorios.

Desde los repositorios:

En OpenERP:

Posibles problemas

En la instalación de Ubuntu 10.04 64 bits, al llamar a la acción que genera el reporte recibíamos el siguiente error:

   1 File "/usr/lib/python2.6/zipfile.py", line 716, in _GetContents
   2      self._RealGetContents()
   3    File "/usr/lib/python2.6/zipfile.py", line 728, in _RealGetContents
   4      raise BadZipfile, "File is not a zip file"

En esta pagina de launchpad explican los siguiente: "This is because self.template is base64 encoded. When I put a base64.decodestring() in OOSerializer.init(), it started to work."

Y agregan un patch:

modified file 'aeroolib/aeroolib/plugins/opendocument.py'

   1  class OOSerializer:
   2 
   3      def __init__(self, oo_template, oo_styles=None):
   4 -        self.template = oo_template
   5 +        import base64
   6 +        self.template = StringIO(base64.decodestring(oo_template.getvalue()))

En mi instalación, el archivo opendocument.py, se encuentra en:

/usr/local/lib/python2.6/dist-packages/aeroolib-1.0.0-py2.6.egg/aeroolib/plugins/opendocument.py

Creación de un reporte

Para crear el reporte, necesitamos de 3 archivos: un template, un parser y un archivo xml.

Para demostrar la creación de un reporte, vamos a usar el modulo "ejemplo_reportes". Este contiene las siguientes clases:

   1 class ejemplo_reportes_habitante(osv.osv):
   2     _name = 'ejemplo_reportes.habitante'
   3     _columns = {
   4         'name': fields.char('Nombre', size=20, required=True),
   5         'apellido': fields.char('Apellido', size=20, required=True),
   6         'edad': fields.integer('Edad'),
   7         'ciudad_id': fields.many2one('ejemplo_reportes.ciudad', 'Ciudad'),
   8     }
   9 
  10 class ejemplo_reportes_ciudad(osv.osv):
  11     _name = 'ejemplo_reportes.ciudad'
  12     _columns = {
  13         'name': fields.char('Nombre', size=20, required=True),
  14         'habitante_ids': fields.one2many('ejemplo_reportes.habitante', 'ciudad_id', 'Habitantes'),
  15         'pais_id': fields.many2one('ejemplo_reportes.pais', 'Pais'),
  16         'codigo_postal': fields.integer('Codigo Postal'),
  17     }
  18 
  19 class ejemplo_reportes_pais(osv.osv):
  20     _name = 'ejemplo_reportes.pais'
  21     _columns = {
  22         'name': fields.char('Nombre', size=20, required=True),
  23         'ciudad_ids': fields.one2many('ejemplo_reportes.ciudad', 'pais_id', 'Ciudades'),
  24     }

En este ejemplo sencillo, un país tiene varias ciudades y una ciudad varios habitantes.

Parser

En el parser, podemos declarar variables y métodos para luego accederlos desde el template. Como se puede ver, el diccionario "localcontext" contiene un metodo y una lista. En el template podemos ver como accedemos a estos elementos.

   1 """
   2 Clase parser para el reporte report_informe.
   3 """
   4 from report import report_sxw
   5 from report.report_sxw import rml_parse
   6 import random
   7 
   8 class Parser(report_sxw.rml_parse):
   9     def __init__(self, cr, uid, name, context):
  10         super(Parser, self).__init__(cr, uid, name, context)
  11 
  12         #Obtenemos el id del pais para el cual se esta imprimiendo el reporte.
  13         self.pais_id = context['active_id']
  14 
  15         #Este diccionario contiene los elementos(metodos o variables) que podemos acceder desde el template.
  16         self.localcontext.update({
  17         'calcular_habitantes': self.calcular_habitantes,
  18         'otros_paises': self.get_otros_paises(),
  19         })
  20 
  21     def calcular_habitantes(self, pais_id):
  22         """
  23         Calcula la cantidad de habitantes para un pais.
  24         Recibe como parametro el id del ejemplo_reportes.pais para el cual vamos a
  25         calcular la cantidad de habitantes.
  26         """
  27         ciudad_ids = self.pool.get('ejemplo_reportes.ciudad').search(self.cr, self.uid, [('pais_id', '=', pais_id)])
  28         return self.pool.get('ejemplo_reportes.habitante').search(self.cr, self.uid, [('ciudad_id', 'in', ciudad_ids)], count=True)
  29 
  30     def get_otros_paises(self):
  31         """
  32         Devuelve una lista de browse_record con todos los paises, menos el pais
  33         para el cual se esta imprimiendo el reporte.
  34         """
  35         pais_ids = self.pool.get('ejemplo_reportes.pais').search(self.cr, self.uid, [('id', '!=', self.pais_id)])
  36         return self.pool.get('ejemplo_reportes.pais').browse(self.cr, self.uid, pais_ids)

Template

El template lo definimos en un archivo odt. Para verlo bien, bajalo acá. Podemos ver como crear un template en la sección "Templating" de la wiki de Alistek

Informe
<o.name>
Cantidad de habitantes: <calcular_habitantes(o.id)>
Ciudades:
Nombre
Codigo Postal
<for each="c in o.ciudad_ids">

<c.name>
<c.codigo_postal>
</for>


Demas paises:
<for each="p in otros_paises">
<p.name>
</for>

XML

En el archivo xml, debemos indicar el registro que define la accion usada para lanzar el reporte. Alli debemos indicar, entre otras cosas, cual es el parser y cual el template del informe.

   1 <?xml version="1.0"?>
   2 <openerp>
   3 <data>
   4     <!-- Definicion del reporte -->
   5     <record id="ejemplo_reportes_report_pais_id" model="ir.actions.report.xml">
   6         <field name="name">Reporte para un pais</field>
   7         <field name="type">ir.actions.report.xml</field>
   8         <field name="model">ejemplo_reportes.pais</field>
   9         <field name="report_name">report_informe</field>
  10         <field name="report_type">aeroo</field>
  11         <field name="in_format">oo-odt</field>
  12         <field name="parser_loc">ejemplo_reportes/report/parser_informe.py</field>
  13         <field name="report_rml">ejemplo_reportes/report/template_informe.odt</field>
  14         <field name="parser_state">loc</field>
  15         <field name="tml_source">file</field>
  16     </record>
  17 
  18     <!-- Este registro, agrega el boton imprimir al formulario de ejemplo_reportes.pais -->
  19     <ir_set>
  20         <field eval="'action'" name="key"/>
  21         <field eval="'client_print_multi'" name="key2"/>
  22         <field eval="['ejemplo_reportes.pais']" name="models"/>
  23         <field name="name">report_informe</field>
  24         <field eval="'ir.actions.report.xml,'+str(ejemplo_reportes_report_pais_id)" name="value"/><!-- Aca tenemos que poner el id de la accion que definimos arriba-->
  25         <field eval="True" name="isobject"/>
  26         <field eval="True" name="replace"/>
  27     </ir_set>
  28 </data>
  29 </openerp>

Notas

Desde el menú Administracion > Personalizacion > Aeroo Reports > Reports, podemos ver y editar los reportes que creamos.

Desde la ultima versión de report_aeroo, podemos usar frames dentro de los templates. Estos son muy útiles cuando necesitamos tener control sobre la posición de algun elemento. Por ejemplo cuando es necesario imprimir facturas pre-impresas.

A este tutorial le falta mas teoria. Estaria bueno tener una descripcion de que indica cada campo del archivo xml.

Mas Información

El módulo report_aeroo_sample trae un template y un parser de ejemplo. En el template se pueden ver varios ejemplos de la sintaxis que debemos usar para crear los reportes.

EzequielFernandez/Report_aeroo (last edited 2011-10-03 16:38:57 by EzequielFernandez)