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:
Aeroolib. Esta es la librería principal que usa report_aeroo. Para instalar aeroolib, debemos tener instalado el paquete python-setuptools y ejecutar python setup.py install dentro del directorio donde descargamos aeroolib.
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:
Genshi => python-genshi (No es necesario, ya lo instala aeroolib)
OpenOffice Python = > python-openoffice
OpenOffice.org-pyuno => ??
python-lxml => python-lxml (No es necesario, ya lo instala aeroolib)
En OpenERP:
Report Aerooreport_aeroo. En https://launchpad.net/aeroo, encontraremos versiones de report_aeroo para OpenERP 5 y 6. Luego de descargarlo, lo podemos instalar desde el cliente 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:
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'
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.
