Openerp - Introduccion Técnica

60
Introducción Técnica Junio - 2014

Transcript of Openerp - Introduccion Técnica

Page 1: Openerp - Introduccion Técnica

Introducción TécnicaJunio - 2014

Page 2: Openerp - Introduccion Técnica

Contenido

• Estructura de módulos

• ORM

• Tipos de campos

• Métodos estándares

• Vistas

• Herencia

• Reportes

• Ejercicios

Page 3: Openerp - Introduccion Técnica

Estructura de módulos

Page 4: Openerp - Introduccion Técnica

En OpenERP todos los módulos se encuentran en la carpeta C:\Archivos de Programa\OpenERP 7 (o numero de versión)\Server\server\openerp\addons .

Para crear nuevos módulos se debe ir dentro de la carpeta “addons” y crear una nueva carpeta con el nombre del nuevo modulo. Dicho nombre no puede contener mayúsculas ni espacios, por lo que si es un nombre de varias palabras debe estar escrito de la siguiente manera: modulo_nombre

La estructura de un modulo completo es la siguiente:

addons/modulo_nombre/ # La carpeta del modulo

demo/ # Datos pre cargados a la BD para el demo y la unidad de testeoi18n/ # Archivos de traducciónreport/ # Definición de reportessecurity/ # Declaración de grupos y derechos de accesowizard/ # Definición de los wizardsworkflow/ # Definición de los flujos de trabajo__init__.py # Paquete Python de inicialización (requerido)__openerp__.py # Declaración del modulo (requerido)modulo_nombre.py # Clases Python, objetos del modulomodulo_nombre_view.xml # La vista del modulo con los forms, trees, menus

Page 5: Openerp - Introduccion Técnica

El archivo __init__.py es aquel que se encarga de inicializar el modulo. Para este caso el contenido de este archivo seria:

# -*- encoding: utf-8 -*-

import modulo_nombre

Es muy importante prestar atención al código de arriba ya que ese código es lo que hace que los archivos Python se lean correctamente y OpenERP no de errores al leerlos.

Page 6: Openerp - Introduccion Técnica

El archivo __openerp__.py es aquel que contiene un único diccionario conteniendo el nombre del modulo, su descripción, sus dependencias, sus vistas, demos y datos. Para nuestro caso este archivo se vería de la siguiente manera:

# -*- encoding: utf-8 -*-

{

'name' : Nombre del Modulo',

'version' : '1.0',

'author' : 'OpenERP',

'description' : Descripcion del Modulo',

'category': ‘Categoria del Modulo',

'website': 'http://www.openerp.com',

'depends' : ['base'], # lista de dependencias, sin estas no se inicia el modulo

'data' : [ # vistas y datos del modulo

'security/groups.xml', # siempre carguen los grupos primero!

'security/ir.model.access.csv', # cargar los derechos de acceso despues de los grupos

'workflow/workflow.xml',

'wizard/wizard.xml',

'report/report.xml',

‘modulo_nombre_view.xml’

],

'demo': ['demo/demo.xml'], # Datos del demo (para testeo de la unidad)

"active": False,

"installable": True,

"certificate" : "",

}

Page 7: Openerp - Introduccion Técnica

El archivo modulo_nombre.py define los objetos que componen un modulo en la vista y en la base de datos, estos objetos tienen atributos predeterminados los cuales son usados e interpretados por Open ERP.

Atributos predeterminados:

• _columns: Este atributo es requerido, en el se definen los campos que se crean en la tabla de la base de datos y las vistas

• _constraints: Permite establecer restricciones a un campo de un objeto

• _sql_constraints: Permite establecer restricciones SQL a un campo de un objeto

• _defaults: Establece valores predeterminados para un campo

• _inherit: Establece la herencia entre los objetos

• _name: Este atributo es requerido y pone nombre al objeto creado

• _order: Este atributo es usado como resultado de una búsqueda y lectura de métodos

• _rec_name: Nombre del campo que se usa para recursos de búsqueda

Page 8: Openerp - Introduccion Técnica

El archivo modulo_nombre_view.xml contiene la vista del modulo. En OpenERP se dividen en tres principales; las tree, las form y las graphic. Las vistas describen como es mostrado cada objeto y como y donde es dibujado cada campo de nuestro objeto.

La definición de la vista contiene tres tipos de tag:

- <record> un tags con el atributo model=”ir.ui.view”, que contiene la definicion de la vista - <record> un tags con el atributo model=”ir.actions.act_window”, que contiene el tipo de acción perteneciente a esa vista - <menuitem> un tags que crea la entrada en el menu y el vinculo de la acción.

La estructura de básica de una vista consta del siguiente formato:

<?xml version="1.0"?>

<openerp><data>

[view definitions] </data>

</openerp>

Page 9: Openerp - Introduccion Técnica

ORM

Page 10: Openerp - Introduccion Técnica

ORM (Object Relational Mapping)

Para todos aquellos que no conozcan el significado de las siglas ORM (Object RelationalMapping), diremos que es una técnica de programación para convertir datos entre el lenguaje de programación orientado a objetos utilizado y el sistema de base de datos relacional utilizado en el desarrollo de nuestra aplicación.

Actualmente, las bases de datos relacionales solo pueden guardar datos primitivos, por lo que no podemos guardar objetos que vayamos creando en nuestra aplicación, sino que lo que hacemos es convertir los datos del objeto en datos primitivos que si podremos almacenar en las tablas correspondientes de nuestras bases de datos. Si luego necesitamos ese objeto en alguna parte de nuestra aplicación, debemos de recuperar los datos primitivos de la base de datos y volver a construir el objeto.

El mapeo objeto-relacional lo que nos ayudará será precisamente a eso, a olvidarnos completamente de como convertir los objetos en datos primitivos para almacenarlos y viceversa.

Page 11: Openerp - Introduccion Técnica

Para ver el efecto que tiene el ORM en nuestro código al momento de declarar un nuevo objeto en OpenERP, debajo se encuentra la declaración de los objetos de nuestro modulo “modulo_nombre” en el archivo “modulo_nombre.py”.

# -*- encoding: utf-8 -*-

from osv import osv, fields

class objeto_modulo_nombre(osv.osv):

_name = objeto.modulo.nombre'

_columns = {

'name': fields.char('Title', size=64, required=True, translate=True),

'state': fields.selection([('draft','Draft'),

('confirmed','Confirmed')],'State',required=True,readonly=True),

'description': fields.text('Description', readonly=True,

states={'draft': [('readonly', False)]} )

}

_defaults = {

'active': True,

'state': 'draft',

}

def _check_name(self,cr,uid,ids):

for idea in self.browse(cr, uid, ids):

if 'spam' in idea.name: return False

return True

_sql_constraints = [('name_uniq','unique(name)', 'Ideas must be unique!')]

_constraints = [(_check_name, 'Please avoid spam in ideas !', ['name'])]

objeto_modulo_nombre()

Page 12: Openerp - Introduccion Técnica

Tipos de campos

Page 13: Openerp - Introduccion Técnica

Los objetos en Open ERP contienen campos los cuales permiten introducir datos en la base de datos, estos campos van definidos en el atributo _columns. Hay tres tipos de campos, los básicos, los relacionales y los funcionales. Los básicos solos sirven para introducir datos básicos, los relacionales (many2one, one2many, many2many) permiten establecer relaciones entre los objetos y los funcionales no se guardan en la base de datos y son calculados al vuelo como funciones Python.

Campos simples principales:

- Boleano (True, False): fields.boolean(‘Nombre' [, Parametors Opcionales]),

- Integer: fields.integer('Nombre' [, Parametors Opcionales]),

- Float: fields.float('Nombre' [, Parametors Opcionales]),

- Char: fields.char(‘Nombre', size=n [, Parametors Opcionales]),

- Date: fields.date(‘Nombre' [, Parametors Opcionales]),

- Selection: fields.selection((('n',‘No confirmado'), ('c','Confirmado')),‘Nombre' [, Parametors Opcionales]),

Existen otros campos como ‘Text’, ‘Datetime’ y ‘Binary’ también.

Page 14: Openerp - Introduccion Técnica

Campos relacionales principales:

- Many2one: Asocia este objeto con un objeto padre en una relación muchos a uno, por ejemplo, de muchas marcas de autos existe una que pertenece a un vehículo en particular.

fields.many2one(‘nombre.otro.objeto', ‘Nombre', parametro opcional)

- One2many: Este campo expresa una relación uno a muchos entre dos objetos, este campo es obsoleto utilizando una relación many2one. Se utiliza en tablas.

fields.one2one('nombre.otro.objeto', ‘Nombre') fields.one2many('nombre.otro.objeto', ‘id del campo relacional', ‘Nombre',

parametro opcional)

- Many2many: Es una relación bilateral entre dos objetos.

fields.many2many( ‘nombre.otro.objeto', ‘objetorelacional', ‘id.objeto.actual', ‘id.otro.objeto', ‘Nombre')

Page 15: Openerp - Introduccion Técnica

Campos funcionales principales:

- Function: fields.function(fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type="float,

fnct_search=None, obj=None, method=False, store=False, multi=False,...)

- type es el tipo de campo devuelto por la función. Puede ser cualquiera excepto function. - method indica si el campo se calcula mediante un método (de un objeto) o una función global. - store y multi son mecanismos de optimización, para guardar los valores de los campos funcionales en la base de datos (store=True) aunque se seguirán calculando mediante una función Python o para calcular varios campos funcionales a la vez con el atributo multi. - fnct es la función o método que calculará el valor del campo. Es un parámetro obligatorio. Debe haberse declarado antes de declarar el campo funcional.

Si method es verdadero (True), la signatura del método debe ser:

def fnct(self, cr, uid, ids, nombre_campo, arg, context)

en otro caso (si se trata de una función global), su signatura debe ser:

def fnct(cr, tabla, ids, nombre_campo, arg, context)

De cualquier manera, debe devolver un diccionario de valores de la forma {id'_1_': valor'_1_',id'_2_': valor'_2_',...}.

Los valores del diccionario devuelto deben ser del tipo indicado en el parámetro type de la declaración del campo.

Page 16: Openerp - Introduccion Técnica

- fnct_inv es la función o método que permitirá escribir valores en ese campo. Si method es verdadero (True), la signatura del método debe ser:

def fnct(self, cr, uid, ids, nombre_campo, valor_campo, arg, context)

en otro caso (si se trata de una función global), su signatura debe ser:

def fnct(cr, table, ids, nombre_campo, valor_campo, arg, context)

- fnct_search permite definir el comportamiento de las búsquedas en ese campo. Si method es verdadero (True), la signatura del método debe ser:

def fnct(self, cr, uid, obj, name, args)

en otro caso (si se trata de una función global), su signatura debe ser:

def fnct(cr, uid, obj, name, args)

También existen otros dos campos llamados ‘related’ y ‘property’. Por referencias acerca de estos se puede ir a la dirección web:

https://doc.openerp.com/6.0/developer/2_5_Objects_Fields_Methods/field_type

Page 17: Openerp - Introduccion Técnica

Métodos estándares

Page 18: Openerp - Introduccion Técnica

OpenERP tiene definido una cantidad considerable de métodos que son muy útiles al momento de desarrollar nuevos módulos. Estos métodos tienen definido de que manera se le tienen que pasar los datos y de que forma devuelven los mismos. Para acceder a la información especifica de cada método perteneciente a OpenERP se recomienda acceder a https://doc.openerp.com/6.0/developer/2_5_Objects_Fields_Methods/methods/ en donde podrán encontrar todos o casi todos los métodos y la información detallada de cada uno.

Métodos principales:

- Método crear: create (cr, uid, values, context=None)

Crea un nuevo registro con los valores especificados. Parámetros específicos:

• values: Diccionario con los valores de los campos para el nuevo registro.

Devuelve el id del registro creado. Puede generar los siguientes errores:

•AccessError: Si el usuario no tiene permisos de escritura en el objeto solicitado, o si el usuario intentaignorar las reglas de acceso para crear el objeto solicitado.

•ValidateError: Si el usuario intenta introducir un valor inválido para un campo que no está en laselección.

•UserError: Si se crease un bucle en una estructura de objetos jerárquica como resultado de la operación (como establecer un objeto como su propio padre).

Page 19: Openerp - Introduccion Técnica

- Método buscar: search(cr, uid, args, offset=0, limit=None, order=None, context=None, count=False)

Busca registros basándose en el dominio de búsqueda. Parámetros específicos:

• offset: Número de registros a omitir. Opcional. Por defecto 0.• limit: Número máximo de registros a devolver. Opcional. Por defecto None.• order: Columnas para establecer el criterio de ordenación. Opcional. Por defecto self._order=id.• count: Devuelve sólo el número de registros que coinciden con el criterio de búsqueda.• args: Lista de tuplas que especifican el dominio de búsqueda. Cada tupla de la lista del dominio debúsqueda necesita 3 elementos en la forma ('field_name', 'operator', value), donde:• field_name: Debe ser un nombre válido del campo de un modelo de un objeto, posiblementesiguiendo las relaciones many2one, usando la notación de punto. Por ejemplo partner_id.country esun valor válido.• operator: Debe ser una cadena con un operador de comparación válido de esta lista: =, !=, >, >=, <,<=, like, ilike, in, not in, child_of, parent_left, parent_right. El significado de muchos de estos operadores es obvio. El operador child_of buscará registros que son hijos o descendientes de un registro dado, de acuerdo al significado de dicho modelo.

• value: Debe ser un valor válido con que comparar los valores del campo field_name, dependiendo de su tipo.El criterio del dominio puede ser una combinación que use 3 operadores lógicos que pueden añadirse entre tuplas:

•'&': Y lógico. Por defecto.•'|': O lógico.•'!': No lógico o negación.

Page 20: Openerp - Introduccion Técnica

Para mostrar todos los registros, se debe pasar una lista vacía.

Devuelve una lista de ids (lista de números enteros) de los registros que coinciden con el criterio.

Posibles errores:

• AccessError: Si el usuario no tiene permisos de lectura en el objeto solicitado.

- Método browse: browse (cr, uid, ids, context=None)

Obtiene registros como objetos permitiendo utilizar la notación de puntos para explorar los campos y las relaciones.

Devuelve un objeto (si ids es un entero) o lista de objetos (si ids es una lista de enteros) solicitados.Es un método muy potente, pues permite consultar con facilidad campos relacionados de forma encadenada a partir de un objeto.

- Método leer: read (cr, uid, ids, fields=None, context=None)

Obtiene una lista de los valores de los campos fields de los registros ids. Tiene los siguientes parámetros:

• fields: Lista de campos.

Esto me devuelve un diccionario con el nombre y valor de los campos solicitados algo como:

{'list_price': 5500.00, 'default_code': 'CLHTC1'}

Page 21: Openerp - Introduccion Técnica

- Método modificar: write(cr, uid, ids, values, context=None)

Actualiza los registros con los ids dados con los valores de los campos dados. Parámetros específicos:

• values: Diccionario con los valores de los campos a modificar. El tipo de los valores de campo que se pasan para los campos relacionales es específico.

Devuelve True.

Posibles errores:

• AccessError: Si el usuario no tiene permisos de escritura en el objeto solicitado, o si intenta soslayar las reglas de escritura del objeto solicitado.

• ValidateError: Si el usuario intenta entrar un valor inválido en un campo que no está en la selección.

• UserError: Si se crease un bucle en una estructura de objetos jerárquica como resultado de la operación (como es establecer un objeto como su propio padre).

Page 22: Openerp - Introduccion Técnica

- Método copiar: copy (cr, uid, id, defaults=None, context=None)

Duplica el registro con el id propuesto actualizándolo con los valores por defecto. Parámetros:

• defaults: Diccionario de valores de campo para cambiar antes de guardar el objeto duplicado.Devuelve True.

- Método eliminar: unlink(cr, uid, ids, context=None)

Borra los registros con los ids dados. Devuelve True. Posibles errores:

• AccessError: Si el usuario no tiene permisos de escritura en el objeto solicitado, o si intenta soslayar las reglas de borrado del objeto solicitado.

• UserError: Si el registro es una propiedad por defecto para otros registros.

Page 23: Openerp - Introduccion Técnica

- Método desplegar nombre: name_get(cr, user, ids, context=None)

Devuelve el valor a mostrar (el texto que ve el usuario) para los registros con los ids dados.

Devuelve una lista con tuplas (id, texto_a_mostrar) para los registros con los ids dados.

- Método buscar nombre: name_search(cr, user, name='', args=None, operator='ilike', context=None, limit=100)

Busca registros que tengan un nombre como el dado en ‘name’ y cumplan la comparación del operador ‘operator’.

Parametros:

• args (lista) – dominio de búsqueda opcional (como en el método search())

• operator (cadena) – operador de comparación para la búsqueda como ‘ilike’ o ‘=‘

• limit (entero) – numero máximo opcional de registro a devolver

Devuelve una lista con tuplas (id, texto_a_mostrar) con los ids de los registros devuelvos y sus respectivos nombres.

Page 24: Openerp - Introduccion Técnica

Vistas

Page 25: Openerp - Introduccion Técnica

Las vistas en OpenERP se dividen en seis tipos; las tree, las form, las graphic, las kanban, las Grantt y las search view. Dentro de las vistas también se definen los menus y las acciones o ‘actions’.

Elementos de diseño dentro de las vistas:

Existen varios elementos de diseño que nos permiten personalizar las vistas form y tree de los objetos creados.

• Notebook: Permite distribuir los campos de la vista en diferentes tabs que van definidos por paginas, ejemplo:

<notebook colspan="4">....</notebook>

• Page: Define una nueva página para el notebook, ejemplo:

<page string="Order Line"> ... </page>:

El atributo string define el nombre de la pagina

• Separator: Agrega una línea de separación en el formato, ejemplo:

<separator string="Links" colspan="4"/>

El atributo string define la etiqueta del separador y el atributo colspan define su tamaño

Page 26: Openerp - Introduccion Técnica

• Group: Permite crear grupos de varias columnas, ejemplo:

<group col="3" colspan="2"><field name="invoiced" select="2"/><button colspan="1" name="make_invoice" states="confirmed"

string="Make Invoice“ type="object"/></group>

Parámetros para crear grupos:

• colspan: numero de columnas para usar• rowspan: numero de filas para expandir o no el grupo• col: numero de columnas proporcionas (a su hijo)• string: (opcional) Si se establece, un marco será dibujado alrededor del grupo con una etiqueta de texto conteniendo el valor de ‘string’.

Page 27: Openerp - Introduccion Técnica

Atributos para los campos (field) dentro de la vista

• select=”1”: Esta marca proporciona un criterio de búsqueda para la vista árbol, este criterio es un campo del objeto. Cuando su valor es 1 significa que es un criterio.

• colspan=”4”:El numero de columnas por las que se puede extender un campo

• readonly=”1”: Establece un widget como solo lectura

• invisible=”True”: Oculta el campo y su etiqueta

• password=”True”: Reemplaza la entrada de un campo con un símbolo “•”

• string=”“: Cambia la etiqueta de un campo. También es usado como parámetro de búsqueda por la vista árbol.

• domain: puede restringir un dominio

Ejemplo: domain=”[(‘partner_id’,’=’,partner_id)]”

• widget: puede cambiar un widget.

Ejemplo: widget=”one2many_list”

• También puede ser: one2one_list, one2many_list, many2one_list, many2many, url, email, image, float_time, reference

Page 28: Openerp - Introduccion Técnica

Vistas Form

Distribuyen los campos en una forma o ventana siguiendo ciertos criterios y personalizaciones. Los campos son distribuidos usando las siguientes reglas:

• Cada campo es precedido por una etiqueta con su nombre• Los capos son puestos de izquierda a derecha, de acuerdo al orden con que son declarados en el archivo xml• El formato siempre esta divido en cuatro espacios ocupados por dos campos con sus respectivas etiquetas, sin embargo un campo puede usar varias columnas como es el caso de deun campo de relación one2many. También se puede realizar la operación inversa, tomar varias columnas y dividirlas en varias columnas.

Vistas Arbol o Tree:

Las vistas árbol son usadas como modo de listado la cual nos perímete realizar búsquedas en la pantalla. Esta vista es simple y solo tiene algunas opciones de diseño.

Page 29: Openerp - Introduccion Técnica

Diseño de vista con un Form declarado:

<?xml version="1.0"?>

<openerp><data>

<record id="vista_pelicula_form" model="ir.ui.view"> <field name="name">motion.pelicula.form</field> <field name="model">motion.pelicula</field> <field name="type">form</field> <field name="arch" type="xml">

<form string="Peliculas"> <group col="2" colspan="2">

<separator string="Informacion Secundaria" colspan="2"/> <field name="fecha"/> <field name="costo"/> <field name="numero"/> <field name="costo_a"/>

</group> <notebook colspan="4">

<page string="Notas"> <field colspan="4" nolabel="1" name="notas"/>

</page> </notebook>

</form> </field>

</record></data>

</openerp>

Page 30: Openerp - Introduccion Técnica

Diseño de vista con un Tree declarado:

<?xml version="1.0"?>

<openerp><data>

<record id="vista_peliculas_arbol" model="ir.ui.view"><field name="name">motion.pelicula.tree</field><field name="model">motion.pelicula</field><field name="type">tree</field><field name="arch" type="xml">

<tree string="Peliculas"><field name="nombre"/><field name="codigo"/><field name="nombre_d"/>

</tree></field>

</record></data>

</openerp>

Page 31: Openerp - Introduccion Técnica

Diseño de vista con un Form declarado y un Tree adentro usando widgets:

<?xml version="1.0"?>

<openerp><data>

<record id="vista_peliculas_arbol" model="ir.ui.view"><field name="name">motion.pelicula.tree</field><field name="model">motion.pelicula</field><field name="type">tree</field><field name="arch" type="xml">

<field name=‘ids’ widget=‘one2many_list’><tree>

<field name="nombre"/><field name="codigo"/><field name="nombre_d"/>

</tree></field>

</field></record>

</data></openerp>

Page 32: Openerp - Introduccion Técnica

Acciones:

Las acciones determinan el comportamiento del sistema en respuesta a las acciones de usuario, las tipos de acciones son:

• Window: Abren una nueva ventana • Report: Imprimen un reporte • Custom Report: Personaliza los reportes • Wizard: Iniciar un Wizard• Execute: Ejecutar un método del lado del servidor • Group: Reúne algunas acciones en un grupo

A continuación se construye una nueva acción para la vista form y tree del objeto motion.pelicula que creara la entrada para el formulario.

Page 33: Openerp - Introduccion Técnica

Acciones Form:

<?xml version="1.0"?><openerp>

<data><record id="abrir_vista_nueva_pelicula" model="ir.actions.act_window">

<field name="name">Nueva pelicula</field><field name="res_model">motion.pelicula</field><field name="view_type">form</field><field name="view_mode">form,tree</field>

</record></data>

</openerp>

Acciones Tree:

<?xml version="1.0"?><openerp>

<data><record id="abrir_vista_peliculas_arbol" model="ir.actions.act_window"><field name="name">Todas las peliculas</field>

<field name="res_model">motion.pelicula</field><field name="view_type">tree</field><field name="view_mode">tree,form</field><field name="view_id" ref="vista_peliculas_arbol"/><field name="domain">[]</field>

</record></data>

</openerp>

Page 34: Openerp - Introduccion Técnica

Menus:

Los menús en Open ERP poseen las siguientes características:

• Id: Todos los menús necesitan un id para poder ser identificados por Open ERP dentro de la tabla de item’s

• Name: Especifica la posición jerárquica y el nombre del menú o entrada

• Action: Identifica la acción asociada al menú (este campo no es obligatorio)

• Icon: Especifica el icono que será utilizado por el menú

Los iconos disponibles son : STOCK_ABOUT, STOCK_ADD, STOCK_APPLY, STOCK_BOLD, STOCK_CANCEL, STOCK_CDROM, STOCK_CLEAR, STOCK_CLOSE, STOCK_COLOR_PICKER, STOCK_CONNECT….

• Groups: Especifica los grupos que pueden ver el menú

Page 35: Openerp - Introduccion Técnica

Sintaxis menú principal:

<?xml version="1.0"?><openerp>

<data><menuitem icon="STOCK_MEDIA_PLAY"id="menu_raiz_motion"name="Motion Peliculas"/>

</data></openerp>

Sintaxis sub-menus :

<?xml version="1.0"?><openerp>

<data><menuitem id="menu_motion_reporte“ name="Reportes“ parent="motion.menu_raiz_motion"/>

<menuitem id="menu_motion_peli“ name="Peliculas“ parent=“motion.menú_raíz_motion”/></data>

</openerp>

Page 36: Openerp - Introduccion Técnica

Herencia

Page 37: Openerp - Introduccion Técnica

Herencia de objetos

En OpenERP existen tres tipos de herencia, herencia por prototipo, por extensión y por delegación (herencia múltiple), todas son completamente diferentes y constituyen una gran herramienta para el desarrollo de los módulos en OpenERP.

En la herencia por prototipo y por extensión se debe agregar el siguiente atributo:

_inherit='object.name'

Donde “object.name” es el objeto del cual se hereda.

Herencia por extensión

Al igual que en programación orientada a objetos en las nuevas clases creadas heredan los atributos y los métodos de la superclase padre, sin embargo la diferencia radica en que el objeto afectado es el padre y no el hijo, ejemplo:

Page 38: Openerp - Introduccion Técnica

Ejemplo herencia por extensión:

class res_partner(osv.osv):_name = 'res.partner'_inherit="res.partner"_columns = {

'codEmpresaCliente': fields.integer('Codigo Empresa Cliente',size=4),'nit': fields.char('NIT',size=10),'ciudades_cod_dane_ciudad': fields.integer('Codigo de Ciudades',size=3), 'tel1': fields.char('Telefono 1',size=16),'tel2': fields.char('Telefono 2',size=16),'cel': fields.char('Celular',size=16),'email': fields.char('Email',size=100),'fax': fields.char('FAX',size=100),'direccion': fields.char('Direccion',size=200),'autoretenedor': fields.boolean('Autoretenedor'),'granContribuyente': fields.boolean('Gran Contribuyente'),'diponibilidad': fields.boolean('Disponibilidad'),'es_empleado': fields.boolean('Es Empleado'),

}res_partner()

Es importante apreciar que el campo “_name” tiene el mismo valor que el campo “_inherit”, sin embargo el nombre general de la clase puede ser dife-rente o igual a la clase original sin afectar el resultado de la operación (heren-cia). Con la herencia establecida se especifica que los nuevos campos del atributo “_columns” creados en la nueva clase podrán ser vistos en las vistas form y tree de la clase original (superclase), En el ejemplo todos los campos serán agregados a la superclase, cabe resaltar que para que los campos sean visibles en la vista se debe heredar la vista de la superclase en el archivo <modulo_view>. xml y agregar estos campos.

Page 39: Openerp - Introduccion Técnica

Herencia por prototipo En este tipo de herencia la diferencia radica en que la nueva clase “copia” todos los atributos y métodos de su padre (superclase), ejemplo:

class other_material(osv.osv): _name = 'other.material' _inherit = 'network.material' _columns = {

'manuf_warranty': fields.boolean('Manufacturer warranty?'), }_defaults = {

'manuf_warranty': lambda *a: False, }

other_material()

En este ejemplo el campo “_inherit ” y ”_name ” son diferentes debido a que la tabla (el objeto nuevo) es el que está operando y no su padre, por lo tanto sus atributos y métodos no serán reconocidos en las vistas de la superclase.

Page 40: Openerp - Introduccion Técnica

Herencia por delegación La herencia por delegación es parecida a la herencia múltiple de c++, en este caso el objeto heredad de múltiples tablas, la técnica cosiste en agregar una columna a la tabla al objeto heredado. Estas columnas guardaran una clave foranea (id de otra tabla). Ejemplo:

class tiny_object(osv.osv) _name = 'tiny.object' _table = 'tiny_object' _inherits = {

'tiny.object_a': 'object_a_id', 'tiny.object_b': 'object_b_id', ... , 'tiny.object_n': 'object_n_id'

}(...)

Los valores “object_a_id”, “object_b_id”, “object_n_id” son de tipo string y determina el titulo de las columnas las cuales son las claves foráneas de “tiny.object_a”,… “tiny.object_n” que son guardadas. El objeto “tiny.object” hereda todos las columnas y métodos de los n objectos “tiny.object_a”,… “tiny.object_n”.

Page 41: Openerp - Introduccion Técnica

Herencia de vistas

Cuando se crean objetos heredades a veces es necesario modificar la vista del objeto por lo tanto es necesario heredar también la vista de la superclase, así se puede agregar, quitar o modificar los campos que se deseen.

Es posible anexar o editar el contenido de un tag. Los tags tienen algunos atributos que permiten especificar la posición en la cual se desean hacer modificaciones, en el siguiente ejemplo se agrega una página a la vista “res.partner.form” en el modulo base.

Se pueden utilizar los siguientes valores para indicar la posición:

• inside (default): Este valor indica que se anexara un tag dentro. • after: Se agrega un contenido después del tag• before: Se agregara un contenido después del tag• replace: Se remplazara el contenido de un tag

Page 42: Openerp - Introduccion Técnica

Ejemplo herencia de vistas:

<record model="ir.ui.view" id="view_partner_form"> <field name="name">res.partner.form.inherit</field> <field name="model">res.partner</field> <field name="inherit_id" ref="base.view_partner_form"/> <field name="type">form</field> <field name="arch" type="xml">

<notebook position="inside"> <page string="Relations">

<field name="relation_ids" colspan="4" nolabel="1"/> </page>

</notebook> </field>

</record>

En algunos casos un mismo campo (id) es usado en el mismo <record> por lo que al momento de llamarlo de la manera que se especifica arriba OpenERP dará un error debido a que no sabe a cual de todos esos campos iguales tiene que efectuar el cambio. Para estos casos existe el uso del <xpath> al cual se le debe poner la dirección exacta del campo y de esta forma OpenERP sabrá cual de todos estos campos va a ser el que será modificado.

Para ello debemos ir a la vista original (padre) y ubicarnos en el <record> que estamos heredando. Luego, debemos seguir el camino de tags hasta llegar al campo que deseamos modificar. Ejemplo:

Page 43: Openerp - Introduccion Técnica

Ejemplo herencia de vistas usando xpath:

<record model="ir.ui.view" id="view_partner_form"> <field name="name">res.partner.form.inherit</field> <field name="model">res.partner</field> <field name="inherit_id" ref="base.view_partner_form"/> <field name="type">form</field> <field name="arch" type="xml">

<xpath expr="/form/sheet/notebook/page/field[@name='line_cr_ids']/tree/field[@name='amount_original']"position="after">

<field name="relation_ids" colspan="4" nolabel="1"/> </xpath>

</field> </record>

Page 44: Openerp - Introduccion Técnica

Ejercicios

Page 45: Openerp - Introduccion Técnica

Crear nuevo modulo

• Dentro de la carpeta OpenERP7\Server\server\openerp\addons\ cada subcarpeta es un modulo.

• Dentro de cada modulo por lo menos existen los siguientes archivos▫ __init__.py, __openerp__.py, modulo.py y modulo_view.xml

• __init__.py: Aqui se importan todos los archivos y directorios que contienen codigo python, éste archivo hace que OPENERP reconozca al directorio o capeta modulo como un módulo.

• __openerp__.py: Contiene un diccionario en Python para agregar las descripciones del módulo, como autor, versión, etc.

• modulo.py: Aquí escribiremos el código Python que permitirá agregar o modificar las funcionalidades de OPENERP, este archivo será importado en __init__.py, como veremos mas abajo.

• modulo_view.xml: Aquí vamos agregar los codigos XML que permitirá la vista del Módulo en OPENERP, en nombre debe de terminar en _view.xml por convencion.

Page 46: Openerp - Introduccion Técnica

Modificación de Pantallas

• Proceso▫ Crear un nuevo modulo

Crear un directorio y los 4 primeros archivos▫ Heredar elementos a modificar

Seleccionar que elementos queremos modificar, tomar el modulo y modificarlos

En el modulo.py Se puede o no utilizar el mismo nombre de la clase a heredar Utilizar _inherit

En el modulo.xml Definir de quien queremos heredar

▫ <field name='inherit_id' ref='base.view_partner_form'/>

Agregar el campo<field name="website" position="after"> <!-- after: despues del campo sitio web -->

<field name="rut"/> <!-- llamamos al campo rut con el atributo name de field -->

</field>

▫ Agregar nuevos objetos.▫ Ej: Uy_localizacion

Page 47: Openerp - Introduccion Técnica

Agregar validaciones en los

campos• Las validaciones se agregan como funciones dentro de la

clase que estamos trabajando.• Es decir en el modulo.py agregamos una funcion. Por

ejemplo en este caso que el rut tenga mas de 5 digitos

• Luego agregamos la sentencia para que realice el chequeo

• _constraints=[(funcion,”valor en falso”,[campo])]

def _check_rut(self,cr,uid,ids,context=None):for registro in self.browse(cr,uid,ids,context=context):

rut=registro.rutif len(registro.rut) >= 5:

return Trueelse:

return False

_constraints = [(_check_rut,"El valor ingresado en RUT debe tener mas de 5 digitos",['rut'] )]

Page 48: Openerp - Introduccion Técnica

Hacer visible o no un campo

• La definición de si un campo es visible o no se realiza en la vista, es decir en el modulo.xml

• Para ello luego del objeto colocamos la función de validación

• En nuestro caso solo vamos a hacer visible el campo rut si el partner es una empresa

<field name="rut" attrs="{'invisible': [('is_company','=', False)]}"/>

Page 49: Openerp - Introduccion Técnica

Cargar un campo cuando se

modifica otro• OpenERP permite la ejecución de eventos luego de que se actualiza

cualquier campo. Esto se hace mediante el evento Onchange que se define en la vista.

<field name="account_analytic_id" on_change="dist_prod_ori_change(product_id,account_analytic_id)"/>

• En este caso si cambia el campo account_analytic_id entonces invoco la funcion dist_prod_ori_change.

• Esta funcion tiene que estar dentro del objeto (es decir en el codigopyton

def dist_prod_ori_change(self,cr,uid,ids,product,proyecto):

#el objetivo de esta funcion es buscar en la factura el monto del producto, proyecto que estamos colocando

v={}

if proyecto:

v['price_subtotal']=2000

return {'value':v}

• En este caso coloca 2000 en el campo price_subtotal que es un cambo del mismo objeto

Page 50: Openerp - Introduccion Técnica

Ejercicio 11. Para comenzar tener instalado el módulo de proyectos y de RRHH (para que aparezca los

departamentos esto se ve en RRHH/configuración/departamentos )

2. Crear un objeto "x_oficinas_q" solo con un campo

a. x_oficinas_q tipo Char 20

b. Crear una opción de menú dentro de configuración/configuración para este nuevo objeto

3. En la pantalla de proyectos habría que agregar los siguientes campos

a. x_area del tipo many2one al objeto "hr.department"

b. x_cod_proy del tipo char de 11 posiciones

c. x_oficina del tipo many2one que mire el objeto x_oficinas_q

4. Habría que dejar la pantalla tipo la siguiente (en amarillo los nuevos campos)

Page 51: Openerp - Introduccion Técnica

Ejercicio 1

Page 52: Openerp - Introduccion Técnica

Ejercicio 2

1. Tiene que estar instalado el modulo de invoice y payment

2. Cuando vas a hacer una factura de cliente hay un campo de fecha que podes poner cualquier fecha.

3. El objetivo es que la fecha sea de este mes. Es decir que salga un mensaje de error cuando le ponen una fecha de un mes diferente al actual.

4. Yo lo haría utilizando el método on_change en la vista. Es decir agregando en la vista (el xml) que cuando salga del campo ejecute una validación.

Page 53: Openerp - Introduccion Técnica

5. Por ejemplo en este caso un campo verifica que exista el proyecto. – El raise es el que ejecuta el mensaje para desplegar en la pantalla

a. En la vista

<field name="product_id" on_change="dist_prod_ori_change(product_id,parent.id)"/>

b. En la clase

def dist_prod_ori_change(self,cr,uid,ids,producto,factura):

#controlo que el producto este entre los productos de la factura

v={}

if producto:

cr.execute('select count(*) as cantidad from account_invoice_line where invoice_id=%s and product_id=%s', (factura,producto))

valor=0

for r in cr.fetchall():

valor = r[0]

if valor==0:

raise osv.except_osv(('Warning!'), ('Elija otro producto, el elegido no esta en la factura')

return {'value':v}

Page 54: Openerp - Introduccion Técnica

Ejercicio 3

1. Tiene que estar instalado el modulo de facturación y pagos

2. Agregar una solapa más que sea distribución

Page 55: Openerp - Introduccion Técnica

4. En esa solapa agregar un campo que dependa de la factura (un campo one2many) (https://doc.openerp.com/6.0/developer/2_5_Objects_Fields_Methods/field_type/)

5. Y la tabla asociada llámala account_invoice_distribucion y que tenga los siguientes campos

'sequence': fields.integer('Sequence', help="Gives the sequence of this line when displaying the invoice."),

'invoice_id': fields.many2one('account.invoice', 'Invoice Reference', ondelete='cascade', select=True),

'product_id': fields.many2one('product.product', 'Producto Actual', ondelete='set null', select=True),

'price_subtotal': fields.float('Importe total', digits_compute= dp.get_precision('Product Unit of Measure'), required=True),

'account_analytic_id': fields.many2one('account.analytic.account', 'Proyecto Actual'),

'account_analytic_id_destino': fields.many2one('account.analytic.account', 'Proyecto Destino'),

'product_id_destino': fields.many2one('product.product', 'Producto Destino', ondelete='set null', select=True),

'cantidad_distr': fields.float('Importe a distribuir', digits_compute= dp.get_precision('Product Unit of Measure'), required=True),

'por_distr': fields.float('Porcentage a distribuir (%)', digits_compute= dp.get_precision('Discount')),

'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True),

'partner_id': fields.related('invoice_id','partner_id',type='many2one',relation='res.partner',string='Partner',store=True)

Page 56: Openerp - Introduccion Técnica

6. Agrega en la vista distribución

7. Luego agrega los siguientes controles cuando agrego una línea

a. El producto actual 'product’ tiene que estar en las líneas de esta factura.

i. Yo lo haría con un evento on_change

ii. Ten en cuenta que en la vista cuando estas llamando al evento podes pasar también referencias al padre. En este caso parent.id seria el id de factura.

b. El proyecto y producto actual ('account_analytic_id') también tiene que estar en las líneas de la factura.

Page 57: Openerp - Introduccion Técnica

Ejercicio 41. Crear asientos analíticos por cada línea que estás haciendo.

2. Esto implica en el momento de grabar la línea de distribución que se grabe también la línea de contabilidad analítica. Esto es la tabla account.analytic.line

3. Es importante ver que cuando se graba una transacción se ejecuta uno de los siguientes eventos

a. create si se esta grabando un registro nuevo, o en nuestro caso una línea de distribución nueva

b. write si se esta actualizando un registro.

4. Para hace esto yo crearía un evento create y un evento write dentro de la clase account_invoice_distribucion

5. En este evento sacaría los datos y grabaria el account.analytic.line

Page 58: Openerp - Introduccion Técnica

6. Hay que grabar 2 líneas

a. Una que resta la cantidad en el proyecto origen

b. Uno que suma la cantidad en el proyecto destino.

Este es un ejemplo de como grabar

account_analytic_line = self.pool.get('account.analytic.line')data = {

'move_id': v_move_id,'product_uom_id': 1,'product_id': vals['product_id'],'general_account_id': v_general_account_id,'journal_id':v_journal_id,'code': '','ref': 'distribucion','currency_id': v_currency_id,'amount_currency': -1*vals['cantidad_distr'],'amount': -1*v_amount_currency,'name': 'prueba','account_id': vals['account_analytic_id']

}if data['move_id']:

account_analytic_line.create(cr, uid, data, context)

Page 59: Openerp - Introduccion Técnica

• Donde v_move_id es el id del asiento contable. Esta en la tabla de invoice en el campo move_id

• product_id es el producto origen en el primer asiento y en producto destino en el segundo

• general_account_id es la cuenta contable. Esta en la tabla account_move_line filtrando por el move_id y el producto y el proyecto. Recordad que proyecto y cuenta analítica es lo mismo.

• journal_id es el campo journal_id de la factura

• ref: hay que cambiarlo para que guarde la línea el id de la línea de distribución. Esto lo vamos a usar en el write para saber que tenemos que modificar.

• Currency_id es la moneda de la factura

• Amount_currency_ es el valor que viene en la línea de distribución.

• Amount es el valor pero en moneda contable. Dentro de la clase res.currency hay una función (se llama compute) que hace el calculo para el cambio de valor a la moneda

• Account_id es el proyecto origen.

Page 60: Openerp - Introduccion Técnica

Ejercicio 51. . En contabilidad/diarios hay que crear un diario que se llame resguardo. Código RESG, tipo efectivo, moneda (NO COLOCAR MONEDA), cuenta de débito predeterminada (elegir cualquiera)

2. Haz una factura para un cliente y contabilízala

3. Luego ve a pagos del cliente y agrega un pago para el cliente. Al elegir el cliente en facturas van a aparecer todas las facturas que no están pagas, con el id de apunte contable y los montos en moneda nacional

4. Ahora bien el cambio radica en

a. Si el método de pago es resguardo el valor que se presente sea el valor el 10% de la factura (Este porcentaje va a cambiar pero eso lo hacemos después)

b. Si el método de pago es diferente a resguardo entonces es el 90% de la factura.

El modulo a extender es account_voucher. Se recomienda prestar atención a los métodos onchange_amount y onchange_partner_id.