Académique Documents
Professionnel Documents
Culture Documents
--------------------------------------
sudo su
wget -O - https://nightly.odoo.com/odoo.key | apt-key add -
echo "deb http://nightly.odoo.com/8.0/nightly/deb/ ./" >>
/etc/apt/sources.list
apt-get update
apt-get install odoo
apt-get install -f
sudo su postgres
createuser -d -S -R odoo
psql -c "ALTER USER odoo WITH PASSWORD 'odoo';"
* Instalar el mdulo Web Tools para incluir editor para archivos XML
* Ingresar a la opcin del men **Help > Install New Software**
* En el cuadro de dialogo diligenciar **Work with:** con el valor
http://download.eclipse.org/webtools/repository/indigo y presionar la tecla
**enter**
* Seleccionar en la lista que aparece seleccione para instalar **Eclipse XML
Editors and Tools**, se ha probado con la versin 3.3.2, pero cualquier versin
reciente debe funcionar.
* Continue con el proceso de instalacin del plugin
Ya con esto esta listo Odoo y eclipse para continuar con el resto de las lecciones,
El objetivo es ir creando nuestro mdulo del taller en eclipse a medida que vamos
avanzando de leccin, cada leccin tiene un archivo **README** que contiene la
teoria de la leccin y una carpeta **src** donde puede esta el cdigo de ejemplo
para leccin, este cdigo lo puede copiar y pegar en su proyecto de eclipse a
medida que avanza en las lecciones.
## Ejercicio Propuesto
mi_modulo
__init__.py
mi_modulo.py
mi_modulo_view.xml
__openerp__.py
import mi_modulo
- **`__openerp__.py`**: Define los metadatos del modulo Odoo. En la documentaciOn
de referencia de Odoo puede encontrar [mayor informaciOn de como definir un mOdulo]
(https://www.odoo.com/documentation/8.0/reference/module.html)
{
"name" : "mi_modulo",
"version" : "1.0",
"author" : "xx",
"category" : "xx",
"description" : "xx",
"depends" : ['base',],
"data" : ['mi_modulo_view.xml','mi_modulo_datos.xml',],
"demo" : ['mi_modulo_demo.xml',],
"installable" : True,
}
class mi_modulo_mi_tabla(models.Model):
_name = "mi_modulo.mi_tabla"
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="mi_tabla_form">
<field name="model">mi_modulo.mi_tabla</field>
<field name="arch" type="xml">
<form>
<group>
<field name="name"/>
<field name="description"/>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="mi_tabla_tree">
<field name="model">mi_modulo.mi_tabla</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="description"/>
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="mi_tabla_action">
<field name="name">Tabla</field>
<field name="res_model">mi_modulo.mi_tabla</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_root" name="Mi MOdulo"/>
<menuitem id="menu_mi_modulo" name="Mi MOdulo" parent="menu_root"/>
<menuitem id="menu_mi_modulo_mi_tabla" parent="menu_mi_modulo" name="Mi
Tabla" action="mi_tabla_action"/>
</data>
</openerp>
mi-carpeta-de-modulos
nombre_modulo
__init__.py
models
__init__.py
nombre_modulo.py
__openerp__.py
views
nombre_modulo.xml
otro_modulo
__init__.py
models.py
__openerp__.py
views.xml
mi_modulo
__init__.py
__openerp__.py
mi_modulo.py
mi_modulo_view.xml
Como se ve en el secciOn anterior un archivo XML se puede usar para cargar datos al
Odoo en el momento de instalar o actualizar un mOdulo, por cada registro que se
desea cargar en la base de datos se debe utilizar las etiquetas **record** y
**field**.
<?xml version="1.0"?>
<openerp>
<data>
<record model="res.users" id="mi_usuario">
<field name="name">Usuario creado</field>
<field name="login">username</field>
</record>
<record model="mi_modulo.mi_tabla" id="dato_1">
<field name="name">dato 1</field>
<field name="description">Esto es un dato que se carga al instalar el
mOdulo</field>
<field name="usuario_id" ref="mi_usuario"/>
</record>
</data>
</openerp>
1. Para instalar el mOdulo este debe estar disponible en la carpeta addons del
servidor Odoo, se pueden utilizar varias carpetas addons en una instalaciOn de
Odoo, las carpetas se definen en el archivo de configuraciOn */etc/odoo/openerp-
server.conf* en el parametro *addons_path*, ejemplo:
[options]
db_host = False
db_port = False
db_user = openerp
db_password = False
addons_path = /usr/lib/python2.7/dist-packages/openerp/addons,/opt/mi-
carpeta-de-modulos
Actualizar un mOdulo
--------------------
Si hay cambios en archivos XML estos no se van a aplicar con solo reiniciar el
servidor.
- Cuando los **cambios son solo en archivos XML** se puede hacer la actualizaciOn a
traves de la interfaz web de administraciOn del Odoo. Para esto debe:
Ejercicio propuesto
-------------------
1. Examine como se adicionan y editan registros a travs del menu *Mi MOdulo > Mi
Tabla*
Esta leccin explica la forma bsica de construir Modelos Odoo y definir sus
campos.
[TOC]
Cada Modelo contiene campos y mtodos. Para crear un modelo solo es necesario crear
una clase python que herede de **models.Model**, models.Model es la clase base que
se encarga de servir como [ORM - Object Relational Mapping]
(http://es.wikipedia.org/wiki/Mapeo_objeto-relacional) y gestiona el acceso y
almacenamiento de datos en PostgreSQL.
```python
class mi_modulo_mi_objeto_de_negocio(osv.osv):
_name = 'mi_modulo.mi_objeto_de_negocio'
_description = 'descripcin del objeto de negocio'
nombre_campo_1 = fields.tipo_dato(parametros),
nombre_campo_2 = fields.tipo_dato(parametros),
```
Ejemplo:
```python
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
_description = 'Contiene la informacin de libros'
Definicin de campos
--------------------
Los campos que hace parte del Modelo se definen como atributos de la clase python y
son instancias del mdulo python **fields.Field**. Al crear un campo en el Modelo
puede definir los siguientes atributos bsicos:
* **string:** Etiqueta/label que se despliega en la interfaz de usuario
* **help:** Ayuda que se despliega en la interfaz como un tooltip
* **readonly:** Indica que el campo es de solo lectura, por defecto *False*
* **required:** Indica que el campo es obligatorio, por defecto *False*
* **index:** Crea un [indice en la base de datos](http://es.wikipedia.org/wiki/
%C3%8Dndice_%28base_de_datos%29), por defecto *False*
Puede consultar [mayor informacin acerca de los campos que se pueden crear en
Odoo](https://www.odoo.com/documentation/8.0/reference/orm.html#fields) en la
documentacin de referencia del sitio de Odoo.
Odoo permite crear diferentes tipos de campos en un Modelo, los bsicos son:
- fields.Char(string=None, otros_parametros)
- fields.Boolean(string=None, otros_parametros)
- fields.Integer(string=None, otros_parametros)
- fields.Float(string=None, digits=None, otros_parametros)
- fields.Text(string=None, otros_parametros)
- fields.Selection(selection=None, string=None, otros_parametros)
- fields.Html(string=None, otros_parametros)
- fields.Date(string=None, otros_parametros)
- fields.Datetime(string=None, otros_parametros)
Ejemplo:
```python
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
_description = 'Contiene la informacin de libros'
### Tip
1. Luego se requiere crear una entrada de men (menu item) que permita acceder al
Modelo, para esto debe
Ejercicio propuesto
-------------------
1. Revisar la metadata que almacena Odoo para los Modelos y Campos de los mdulos
instalados.
1. Explore la base de datos PostgreSQL utilizando el programa *pgadmin3*, busque y
revise la tabla *biblioteca_libro*, hacer una captura de pantalla para tenerlo como
referencia y poder comparar la tabla luego de realizar los cambios de los
siguientes ejercicios de esta leccin.
1. Adicionar nuevos estados al campo de tipo seleccin *state*: solicitado, proceso
de compra, adquirido.
1. Adicionar los campos:
1. Adicionar un texto de ayuda para cada uno de los campos que no lo tenga y
verifique en la interfaz que se despliega.
1. Crear un nuevo Modelo llamado **biblioteca.prestamo** y adicione los campos:
[TOC]
- form: formulario
- tree: listado/rbol
- search: bsqueda
Cada tipo de vista permite una presentacin diferente de los datos almacenados.
Para el despliegue de las vistas se utiliza comunmente un enlace desde el men de
opciones de la interfaz web, estos mens son creados en conjunto con las vistas en
el XML y cargadas posteriormente a la base de datos. En la leccin anterior creamos
un men item directamente en la base de datos, pero para poder replicar este item
en otras instalaciones de Odoo, es necesario que exista la definicin del men en
el cdigo de un mdulo.
Los formularios permiten creacin y/o edicin de registros, cada formulario puede
ser definido utilizando los siguientes elementos bsicos:
Los Actions indican a Odoo como debe responder frente a una accin del usuario,
existen varios tipos de actions, el ms utilizado es el Window Action, el cual
define que modelo se va a desplegar, que vistas van a estar disponibles y la
configuracin general de las mismas. Para generar un action utilizamos el `record`
para el model `ir.actions.act_window` a continuacin se listan los atributos ms
relevantes para configurar el action:
La estructura de mens se define al igual que las vistas usando un documento XML.
Para este caso vamos a usar el tag `menuitem`.
Ejercicios propuestos
---------------------
[TOC]
Los Modelos en Odoo permiten configuraciones adicionales que agregan reglas que
permiten manejar la consistencia de los datos basado en las necesidades de la
aplicacin.
Cada campo puede ser definido como requerido, de solo lectura o asignarsele un
valor por defecto, un campo del Modelo puede asignarsele uno o varios de estos
atributos. A continuacin un ejemplo:
```python
import random
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
def _precio_aleatorio(self):
return random.random()
```
- Atributo **`default`** se usa para indicar el valor por defecto que va a tener el
campo cuando se cree un registro nuevo. Se puede indicar el valor a tomarse o una
funcin que retornara el valor por defecto a utilizarse. En este diccionario se
adiciona como llave el nombre del campo y como valor lo que deseamos sea el valor
por defecto o una funcin que hace el clculo del mismo. Se pueden utilizar
funciones lambda o mtodos de la clase. Debe recordar que los mtodos de la clase
deben estar previamente definidos para poder utilizarlos. [Ms informacin acerca
de valores por defecto]
(https://www.odoo.com/documentation/8.0/howtos/backend.html#default-values)
Si se desea que los Modelos tengan restricciones que sean verificadas antes de
almacenar los registros, estas se deben definir como mtodos de la clase donde se
utiliza el decorador @api.constrains.
```python
from openerp.exceptions import ValidationError
import datetime
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
@api.one
@api.constrains('fecha_publicacion','fecha_compra')
def _check_fechas(self):
present = datetime.now()
if self.fecha_compra and self.fecha_compra > present:
raise ValidationError("Fecha de compra incorrecta")
if self.fecha_publicacion and self.fecha_publicacion > present:
raise ValidationError("Fecha de publicacin incorrecta")
```
_sql_constraints = [
('unique_isbn','unique(isbn)','El ISBN debe ser nico'),
]
* Nombre de la restriccin
* Restriccin SQL a aplicar
* El mensaje de error a ser desplegado en caso de que se viole la restriccin
Si la base de datos ya tiene datos que violan la restriccin, esta no va a crearse,
ni aplicarse. Cuando esto pase, va a aparecer un error en el log del servidor como
el siguiente:
Para aplicar la restriccin SQL ud debe corregir los datos primero, para este caso
eliminando los ISBN duplicados y actualizar nuevamente el mdulo.
Ejercicios propuestos
---------------------
[TOC]
Dominios
--------
Los dominios en Odoo son utilizados para filtrar los registros a los que se tiene
acceso en las vistas o en consultas dentro del cdigo del Modelo.
SELECT * FROM biblioteca_libre WHERE paginas > 100 AND nombre_autor ILIKE
'%cervantes%'
en Odoo el dominio se estructurara
[('paginas','>',100),('nombre_autor','ilike','%cervantes%')]`
SELECT * FROM biblioteca_libro WHERE paginas > 100 AND nombre_autor ILIKE
'%cervantes%' OR nombre_autor ILIKE '%marquez%'
El dominio sera:
[('paginas','>',100),'|',('nombre_autor','ilike','%cervantes%'),
('nombre_autor','ilike','%marquez%')]
Bsquedas
---------
Las bsquedas (search) son un tipo de vista que se asocia a un Modelo con el objeto
de permitir realizar bsquedas por campos especificos, adicionar filtros
predeterminados y agrupaciones sobre los registros que se despliegan en las vistas
tipo listado. A continuacin un ejemplo de una vista search.
- **Bsquedas por campos**: Para permitir la bsqueda por campos especificos del
modelo solo se debe agregar una etiqueta `field` e indicar el nombre del campo por
el cual que se pemite realizar la bsqueda. En el momento de escribir en el cuadro
de bsqueda que aparece en la parte superior derecha, se va a desplegar un listado
de los campos sobre los cuales se va a aplicar la bsqueda. Estas bsquedas son
abiertas, ud define el valor por el cual buscar.
Ejercicios propuestos
---------------------
[TOC]
Muchas veces es necesario que algunos campos del formulario se actualicen basados
en las selecciones o datos que se ingresan en otros campos del formulario, para
esto se utiliza el decorador `@api.onchange` en cualquier mtodo python que se
implemente en el Modelo. Ejemplo:
```python
from openerp import models, fields, api
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
@api.onchange('precio')
def onchange_precio(self):
if self.precio and self.precio > 1000:
self.descripcion = 'Ta muy caro el libro'
```
```python
from openerp import models, fields, api
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
@api.onchange('isbn')
def onchange_warning_isbn(self):
if self.isbn and len(self.isbn) < 10:
self.descripcion = 'Verifique el ISBN cumpla con la norma'
return {
'warning': {
'title': "ISBN",
'message': "El largo del ISBN debe ser mayor o igual a 10
caracteres",
}
}
```
```python
from openerp import models, fields, api
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
@api.one
@api.constrains('paginas')
@api.onchange('paginas')
def _check_paginas(self):
if self.paginas < 0 or self.paginas > 5000:
raise ValidationError("Un libro debe tener entre 0 y 5000 pginas")
```
- https://www.odoo.com/documentation/8.0/reference/orm.html#onchange-updating-ui-
on-the-fly
- https://www.odoo.com/documentation/8.0/howtos/backend.html#onchange
Ejercicios propuestos
---------------------
[TOC]
Las aplicaciones comunes requieren que los datos esten relacionados, veremos a
continuacin como manejar las relaciones entre Modelos, a travs de nuevos tipos de
campos one2many, many2one y many2many.
Relaciones Many2one
-------------------
Utilizando un campo de tipo Many2one creamos una relacin directa entre el Modelo
actual (donde se define el campo) y algn otro Modelo, este campo crea la llave
foranea entre las tablas de dos Modelos. Su estructura bsica es la siguiente:
- **Nombre del Modelo**: Nombre del Modelo con el cual crear la [relacin de llave
fornea](http://www.postgresql.org/docs/9.4/static/tutorial-fk.html), ej.
`biblioteca.libro`, `res.partner`, `res.users`
- **Etiqueta**: Etiqueta a desplegarse en la vista web para este campo
- **ondelete**: Indica a la base de datos como manejar la relacin cuando el
registro del modelo relacionado sea eliminado. Los valores disponibles son: `set
null`, `restrict`, `cascade`; por defecto se usa `set null`
- **domain**: Criterio que limita el listado de registros a ser listados para ser
relacionados con el Modelo actual. ej. Ver solo los libros catalogados y no los que
estan en compra. :white_up_pointing_index: Ud puede agregar el dominio como un
*string* `domain="[('state', '=', 'catalogado')]"` o como una *lista de tuplas*
`domain=[('state', '=', 'catalogado')]`, cuando se adiciona como string el dominio
se evalua en el lado del cliente y puede usar nombres de campos despues del
operador, pero cuando es una lista de tuplas se evalua en el lado del servidor y no
permite el manejo de campos, solo de valores.
Ejemplo:
```python
from openerp import models, fields, api
class biblioteca_prestamo(models.Model):
_name = 'biblioteca.prestamo'
_description = 'Registro de prestamo'
Relaciones One2many
-------------------
Un campo One2many permite que el Modelo actual (donde se define el campo) pueda
acceder a todos los registros relacionados, este campo requiere que el Modelo
relacionado tenga creado un campo tipo Many2one que haga referencia al Modelo
actual. Su estructura es la siguiente:
- **Nombre del Modelo Relacionado**: Nombre del Modelo que contiene el campo
Many2one que apunta a este Modelo. Ej. `biblioteca.prestamo`
- **Nombre del campo que contine la relacin**: Nombre del campo Many2one que
existe en el Modelo relacionado. Ej. `libro_id`
Ejemplo:
```python
from openerp import models, fields, api
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
_description = 'Libro de la biblioteca'
<field name="prestamo_ids">
<tree>
<field name="fecha"/>
<field name="fecha_devolucion"/>
</tree>
</field>
Relaciones many2many
--------------------
La relacin many2many consiste en que un Modelo A puede tener relacin con uno o
varios registros del Modelo B y a su vez el Modelo B se puede relacionar con varios
registros del Modelo A, a diferencia de one2many donde la cardinalidad es de muchos
a uno. Para esto se requiere de una tabla intermedia que almacena la relacin entre
los Modelos, esta tabla es generada automticamente y no se puede acceder como un
Modelo independiente. Su estructura es la siguiente:
- **Nombre del Modelo Relacionado**: Nombre del Modelo que contiene el campo
Many2one que apunta a este Modelo. Ej. `biblioteca.prestamo`
- **domain**: Criterio que limita el listado de registros a ser listados para ser
relacionados con el Modelo actual.
Ejemplo:
```python
from openerp import models, fields, api
class biblioteca_libro(models.Model):
_name = 'biblioteca.libro'
_description = 'Libro de la biblioteca'
class biblioteca_genero(models.Model):
_name = 'biblioteca.genero'
_description = 'Genero literario'
```
Ejercicios propuestos
---------------------
1. Crear un prestamo y ver como el campo libro solo muestra los libros en estado
*catalogado*.
1. Adicione generos a un registro del Modelo libro.
1. En la vista tipo formulario del Modelo *prestamo* adicionar el atributo
`widget="selection"` en el campo `libro_id`. Nota la diferencia?
1. En la vista tipo formulario del Modelo *libro* adicionar el atributo
`widget="many2many_tags"` en el campo `genero_ids`. Nota la diferencia? Adicione
nuevos generos a varios registros del Modelo libro.
1. En la vista tipo formulario del Modelo *libro* adicionar en el listado de
prestamos el campo `duracion_dias`.
1. Crear un Modelo **biblioteca.editorial** con el campo `name`
1. Crear una relacin many2one de *libro* a *editorial* y el inverso one2many de
*libro* a *editorial*, desplegarlos en las vista formulario.
1. Crear un Modelo **biblioteca.autor** con el campo `name`
1. Crear una relacin many2many de *libro* a *autor* y el inverso de *autor* a
*libro*, desplegarlos en las vista formulario.
1. Verifique a travs de pgadmin3 la estructura de las tablas y los *constraints*
creados.
[TOC]
Campos Related
--------------
En algunos casos es necesario tener disponible el valor de un campo de un Modelo
relacionado, como si fuera un campo del Modelo actual, por ejemplo si tenemos los
Modelos Persona -> Ciudad -> Pais, podemos adicionar un campo en Persona que nos
diga directamente cual es el Pais, basado en la seleccin de la Ciudad. Para esto
definimos un proxy a travs de un campo con el atributo `related`.
```python
from openerp import models, fields, api
class pais(models.Model):
_name = 'mi_modulo.pais'
_description = 'Pais'
name = fields.Char('Nombre')
class ciudad(models.Model):
_name = 'mi_modulo.ciudad'
_description = 'Ciudad'
name = fields.Char('Nombre')
pais_id = fields.Many2one('mi_modulo.pais','Pas')
class persona(models.Model):
_name = 'mi_modulo.persona'
_description = 'Persona'
```
Muchas veces los campos tienen valores que deben calcularse de automticamente,
para esto se utiliza el atributo: `compute` y el nombre del mtodo del Modelo que
har el clculo del valor. Por ejemplo:
```python
from openerp import models, fields, api
import datetime.timedelta
class biblioteca_prestamo(models.Model):
_name = 'biblioteca.prestamo'
_description = 'Informacion de prestamo de libros'
fecha = fields.Datetime(
'Fecha del Prestamo',
help="Fecha en la que se presta el libro",
)
duracion_dias = fields.Integer(
'Duracin del Prestamo(das)',
help="Nmero das por los cuales se presta el libro",
)
fecha_devolucion = fields.Datetime(
'Fecha Devolucin',
compute='_compute_fecha_devolucion',
help="Fecha de devolucin del libro",
)
@api.one
def _compute_fecha_devolucion(self):
"""Calcula la fecha de devolucin basado en la fecha inicial y la duracin
en das del prestamo"""
fecha = fields.Datetime.from_string(self.fecha)
self.fecha_devolucion = fecha + timedelta(days=10)
```
Con el cdigo anterior el clculo se va a realizar cuando se guarde el registro en
la base de datos y en la interfaz el campo se va a mostrar como de solo lectura. Si
se desea que se pueda tambin definir manualmente la fecha de devolucin, se debe
usar el atributo `inverse` y el nombre del mtodo del Modelo que har el clculo
inverso. Para nuestro ejemplo el mtodo inverson debera calcular la duracin en
das a partir de la fecha del prestamo y la fecha de devolucin.
```python
from openerp import models, fields, api
import datetime.timedelta
class biblioteca_prestamo(models.Model):
_name = 'biblioteca.prestamo'
[...]
fecha_devolucion = fields.Datetime(
'Fecha Devolucin',
compute='_compute_fecha_devolucion',
inverse='_compute_inv_fecha_devolucion',
help="Fecha de devolucin del libro",
)
[...]
@api.one
def _compute_inv_fecha_devolucion(self):
"""Calcula la fecha duracin en das del prestamo basado en la fecha de
devolucin"""
if self.fecha and self.fecha_devolucion:
fecha = fields.Datetime.from_string(self.fecha)
fecha_devolucion = fields.Datetime.from_string(self.fecha_devolucion)
delta = fecha_devolucion - fecha
self.duracion_dias = delta.days
```
Decorador: depends
------------------
@api.depends('fecha', duracion_dias')
Decorador: multi
----------------
Decorador: one
--------------
Decorador: model
----------------
Atributo: states
----------------
Manejo de rboles
------------------
- related
- depends
- multi
- states
- parent
Related
-------
**Estructura de definicin**
'nombre_campo_related': fields.related (
'id_busqueda',
'campo_busqueda',
type = "tipo_campo",
relation = "objeto_negocio_a_relacionar",
string = "Texto del campo",
store = False
)
**Ejemplo de aplicacin**:
'titulo': fields.related(
'libro_id','titulo',
type="char",
string="Titulo",
store=False,
readonly=True
),
En este ejemplo se crea el campo titulo de tipo related el cual devuelve el titulo
del libro segn el valor del campo libro_id.
Domain
------
El atributo domain es un atributo aplicado a los campos para definir una
restriccin de dominio en un campo relacional, su valor por defecto es vacio.
**Estructura de definicin**
* **campo**: nombre del campo del objeto de negocio, este campo ser utilizado para
la restriccin.
* **operador_comparacion**: operador para comparar el campo con el valor
establecido.
* **valor**: valor asignado para evaluar la restriccin de dominio.
**Ejemplo de aplicacin**:
Function
--------
Un campo funcional es un campo cuyo valor se calcula mediante una funcin, en lugar
de ser almacenado en la base de datos.
**Estructura de definicin**
'nombre_campo_function' : fields.function(
_nombre_metodo,
type='tipo_campo',
obj= "objeto_de_negocio.function",
method= True,
string= "Texto del campo"
)
**Ejemplo de aplicacin**:
Ejercicios propuestos
---------------------
[[
title: Leccin 09: Navegar Registros
author: STRT Grupo I+D+I
]]
[TOC]
Aadir un botn a la vista formulario
--------------------------------------
Mtodo Search
-------------
El dominio de bsqueda puede ser una combinacin que use 3 operadores lgicos que
pueden aadirse entre tuplas:
Ejemplo:
libros_pool = self.pool.get('biblioteca.libro')
libros_ids = libros_pool.search(cr, uid,[('state','=','compra')],
context=context)
En este ejemplo el mtodo search realiza una bsqueda por todos los registros del
objeto *biblioteca.libro* y cuando un registro coincida con el criterio de bsqueda
'state','=','compra', el id del registro se almacenar en libros_ids.
Mtodo Read
-----------
Obtiene una lista de los valores de los campos fields de los registros ids,
devuelve un diccionario con el nombre y valor de los campos solicitados. Tiene los
siguientes parmetros:
libros_pool = self.pool.get('biblioteca.libro')
libros_ids = libros_pool.search(cr, uid,[('state','=','compra')],
context=context)
libros_records = libros_pool.read(cr, uid, libros_ids, ['titulo','autor'])
En este ejemplo del mtodo read obtiene una lista de los valores de los campos
*'titulo', 'autor'* de los registros que coincidan con los ids almacenados en
libros_ids, esta lista se almacena en libros_records como un diccionario con nombre
y valor de los campos indicados.
def obtener_promedio_prestamo_metodo_read(self,cr,uid,ids,context=None):
prestamo_ids = self.read(cr, uid, ids, ['prestamo_ids'], context=context)
prestamo_pool = self.pool.get('biblioteca.libro_prestamo')
prestamo_records = prestamo_pool.read(cr, uid, prestamo_ids[0]
['prestamo_ids'], ['fecha_prestamo', 'fecha_regreso'], context=context)
tiempo_total = 0
for record in prestamo_records:
tiempo_dias = (datetime.strptime(record['fecha_regreso'],'%Y-%m-%d') -
datetime.strptime(record['fecha_prestamo'],'%Y-%m-%d')).days
tiempo_total = tiempo_total + tiempo_dias
raise osv.except_osv('Promedio de tiempo de prstamo','{0}
das'.format(tiempo_total))
return True
Mtodo Browse
-------------
Ejemplo:
libros_pool = self.pool.get('biblioteca.libro')
libros_ids = libros_pool.search(cr, uid,[('state','=','compra')],
context=context)
libros_records = libros_pool.browse(cr, uid, libros_ids, context=context)
En este ejemplo el mtodo browse obtiene los registros que correspondan a los ids
almacenados en libros_ids, estos registros se almacenan en libros_records.
def obtener_promedio_prestamo_metodo_browse(self,cr,uid,ids,context=None):
prestamo_ids = self.read(cr, uid, ids, ['prestamo_ids'], context=context)
prestamo_pool = self.pool.get('biblioteca.libro_prestamo')
prestamo_records = prestamo_pool.browse(cr, uid, prestamo_ids[0]
['prestamo_ids'], context=context)
tiempo_total = 0
for record in prestamo_records:
tiempo_dias = (datetime.strptime(record['fecha_regreso'],'%Y-%m-%d') -
datetime.strptime(record['fecha_prestamo'],'%Y-%m-%d')).days
tiempo_total = tiempo_total + tiempo_dias
raise osv.except_osv('Promedio de tiempo de prstamo','{0}
das'.format(tiempo_total))
return True
Ejercicios propuestos
---------------------
1. Adicionar una restriccin al prstamo por libros. Solo debe existir un prstamo
activo por cada libro.
[[
title: Leccin 10: Extensin de Mdulos Base
author: STRT Grupo I+D+I
]]
[TOC]
Extender Objetos
----------------
Los objetos de negocio pueden heredar de un mdulo base, esta herencia se puede
utilizar para modificar, extender, utilizar mtodos.
**Estructura de definicin**
_inherit = 'nombre_objeto_base_a_heredar'
Existen dos formas de extender un objeto. Ambas formas generan una nueva clase, que
tiene campos y funciones heredadas, as como campos y mtodos adicionales.
* **Forma 1**: Las instancias de estas clases son visibles por las vistas (views or
trees) que operan con la clase padre. Este tipo de herencia se denomina herencia de
clase (class inheritance), es de utilidad para sobreescribir mtodos de la clase
padre.
Ejemplo:
class nombre_clase(osv.osv):
_name = 'nombre_objeto_base'
_inherit = 'nombre_objeto_base'
_columns = {
'campo_1: fields.tipo_campo('text_campo'),
}
nombre_clase()
* **Forma 2**: Las instancias de estas clases no son visibles por las vistas (views
or trees) que operan con la clase padre. Las instancias de estas clases contienen
todos las propiedades y mtodos de la instancia padre junto con las propiedades y
mtodos definidos en la nueva entidad. Este tipo de herencia se denomina herencia
por prototipos (inheritance by prototyping). La nueva subclase contiene una copia
de las propiedades de la clase padre.
Ejemplo:
class nombre_clase(osv.osv):
_name = 'nombre_objeto_negocio'
_inherit = 'nombre_objeto_base'
_columns = {
'campo_1: fields.tipo_campo('text_campo'),
}
nombre_clase()
**Ejemplo de aplicacin**:
class res_users(osv.osv):
_inherit = "res.users"
_columns = {
'prestamo_id' : fields.one2many('biblioteca.libro_prestamo',
'user_id', 'Prstamos'),
}
res_users()
Con este ejemplo relacionamos el objeto de negocio res.users con los prstamos de
los libros. Se extieden el objeto res.users y se le adiciona el campo prestamo_id.
Extender Vistas
---------------
Tambin podemos heredar vistas, al igual que se puede heredar objetos. Parmetros:
**Estructura de definicin**
**Ejemplo de aplicacin**:
Ejercicios propuestos
---------------------
[TOC]
Widgets
-------
Los widgets son utilizados de manera automtica de acuerdo al tipo de dato del
campo a mostrar, pero estos widgets pueden ser manualmente seleccionados si es
necesario. Existen diferentes widgets que pueden seleccionarse:
Las vistas tipo kanban permiten manejar informacin importante (campos principales)
en imgenes o tarjetas, es util para poder identificar los registros de una forma
ms rpida y as agilizar la consulta sobre los datos.
Las vistas tipo gantt permiten mostrar el tiempo planificado o transcurrido para el
desarrollo de tareas o actividades, es una vista dinmica, se puede hacer click en
cualquier parte del grfico, arrastrar y soltar el objeto en otra ubicacin.
Esta vista permite desplegar los datos disponibles en una grafica. Cada vista
grfica puede ser definida utilizando los siguientes elementos bsicos:
Botones
-------
- confirm
- states
- magic
@api.one
def button_fecha_compra_hoy(self):
self.fecha_compra = fields.Date.today()
self.state = 'adquirido'
Ejercicios propuestos
---------------------
[[
title: LecciOn 12: Wizards
author: STRT Grupo I+D+I
]]
[TOC]
Wizards
-------
"data" : [
'wizard/radicar_prestamo_view.xml',
'biblioteca_view.xml',
]
class biblioteca_wizard_radicar_prestamo(osv.osv_memory):
_name = "biblioteca.wizard.radicar_prestamo"
_description = "Permite radicar un prestamo"
_columns={
'libro_id':
fields.many2one('biblioteca.libro_prestamo','Codigo prstamo',
required=False,
readonly=True,
),
'fecha_prestamo': fields.date('Fecha de Prstamo'),
'duracion_prestamo': fields.integer('das prstamo',
required= True,
),
'user_id': fields.many2one('res.users', 'Usuario
solicitante',
required= True,
help= 'Usuario que solicita el prstamo'
),
}
_defaults = {
'libro_id': lambda self, cr, uid, context :
context['libro_id'] if context and 'libro_id' in context else None,
}
def action_radicar(self, cr, uid, ids, context=None):
context['prestamo_actual'] = True
form_id = ids and ids[0] or False
form = self.browse(cr, uid, form_id, context=context)
prestamo_pool = self.pool.get('biblioteca.libro_prestamo')
vals = {
'libro_id': form.libro_id.id,
'state': 'prestado',
'fecha_prestamo': form.fecha_prestamo,
'duracion_prestamo': form.duracion_prestamo,
'user_id': form.user_id.id
}
id = prestamo_pool.create(cr, uid, vals, context=context)
return self.redirect_to_prestamo_view(cr, uid, id,
context=context)
<?xml version="1.0"?>
<openerp>
<data>
<!-- View Form Wizard -->
<record id="view_biblioteca_wizard_radicar_prestamo"
model="ir.ui.view">
<field name="name">Radicar Prestamo</field>
<field
name="model">biblioteca.wizard.radicar_prestamo</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Radicar Prestamo" version="7.0">
<group colspan="2">
<field name="libro_id" readonly="1"/>
<field name="user_id"/>
<field name="fecha_prestamo"/>
<field name="duracion_prestamo"/>
</group>
<footer>
<button name="action_radicar"
string="Radicar solicitud" type="object" class="oe_highlight" />
</footer>
</form>
</field>
</record>
Ejercicios propuestos
---------------------
[[
title: LecciOn 13: Campos y Atributos Avanzados
author: STRT Grupo I+D+I
]]
[TOC]
Que es Workflow?
-----------------
Los Workflow nos permiten gestionar las actividades relacionadas a los objetos de
negocio, se representan como grafos dirigidos donde los nodos son las actividades y
los conectores son las transiciones. La actividades son las tareas a realizar y las
transiciones indica como el workflow cambia de una actividad a otra con el fin de
gestionar los ciclos de vida de los objetos.
CreaciOn de Workflow
--------------------
Ejercicios propuestos
---------------------