TING! DESARROLLO DE MÓDULOS FORMACIÓN TÉCNICA MADRID 19-23 JULIO 2010



Documentos relacionados
DSI módulo de vacaciones para OpenERP 4.2.0

MANUAL DE AYUDA HERRAMIENTA DE APROVISIONAMIENTO

TING! CICLOS DE NEGOCIO FORMACIÓN TÉCNICA MADRID JULIO 2010

Person IP CRM Manual MOBILE

PHPMYADMIN Y MYSQL. Para gestionar la base de datos MySQL, lo haremos desde la aplicación PhpMyAdmin.

GESTIÓN DOCUMENTAL PARA EL SISTEMA DE CALIDAD

MANUAL DE USUARIO APLICACIÓN SYSACTIVOS

Programa diseñado y creado por Art-Tronic Promotora Audiovisual, S.L.

Manual de instalación Actualizador masivo de Stocks y Precios

MANUAL DE LA APLICACIÓN HELP DESK

Notas para la instalación de un lector de tarjetas inteligentes.

MANUAL DE USUARIO FACTURACIÓN ELECTRÓNICA

MANUAL DE AYUDA TAREA PROGRAMADA COPIAS DE SEGURIDAD

Sincronización del Servidor.

Ministerio de Educación. Base de datos en la Enseñanza. Open Office. Módulo 5: Report Builder

Toda base de datos relacional se basa en dos objetos

CREACIÓN Y CONFIGURACIÓN DE WIKIS

MANUAL DE USUARIO DE LA APLICACIÓN DE ACREDITACION DE ACTIVIDADES DE FORMACION CONTINUADA. Perfil Entidad Proveedora

Manual hosting acens

SERVICIOS PARA EL DISEÑO E IMPLEMENTACIÓN DEL PROGRAMA INTEGRAL DE TRANSFORMACIÓN DIGITAL DE LA PROVINCIA DE LUGO: TRANSFORM@TIC

Creación y administración de grupos de dominio

Definiciones. Tema 21_Módulos Menú 1

CREACIÓN Y GENERACIÓN DE REMESAS DE ADEUDOS SEPA

Introducción a la programación orientada a objetos

Plataforma e-ducativa Aragonesa. Manual de Administración. Bitácora

Instalación de FileZilla FTP Server

Manual de uso de la plataforma para monitores. CENTRO DE APOYO TECNOLÓGICO A EMPRENDEDORES -bilib

Sitios remotos. Configurar un Sitio Remoto

GVisualPDA Módulo de Almacén

REDES DE ÁREA LOCAL. APLICACIONES Y SERVICIOS EN WINDOWS

- A continuación, se nos abrirá la siguiente ventana pidiendo contraseña, que el cliente haya especificado al instalar Wingest 7

Acronis License Server. Guía del usuario

UNIDAD DIDÁCTICA Nº 7 USO DE LOS RECURSOS EN MOODLE

MARFIL CONTABILIDAD ACTUALIZACIÓN FEBRERO 2011

WINDOWS : TERMINAL SERVER

MANUAL DE AYUDA MODULO TALLAS Y COLORES

MANUAL COPIAS DE SEGURIDAD

NOTAS TÉCNICAS SOBRE EL SIT: Definición y Configuración de Usuarios

Proceso de cifrado. La fortaleza de los algoritmos es que son públicos, es decir, se conocen todas las transformaciones que se aplican al documento

01 Índice. GESTOR DE CONTENIDOS Manual de uso 01 ÍNDICE OBJETO DEL DOCUMENTO ESTRUCTURA GRÁFICA DEL SISTEMA... 3

Accede a su DISCO Virtual del mismo modo como lo Hace a su disco duro, a través de:

Manual Ingreso Notas y Acta Electrónica

Patrones para persistencia (I) Ingeniería del Software II

Para entornos con más de un equipo conectados en red es necesario que el programa de firewall conceda paso a los servicios de Microsoft SQL Server.

- Bases de Datos - - Diseño Físico - Luis D. García

Comisión Nacional de Bancos y Seguros

Manual de NetBeans y XAMPP

Guía Notas Parciales. Intermedio

MultiBase Cosmos. Notas a la versión 4.4, release 1. BASE 100, S.A.

Instalar protocolo, cliente o servicio nuevo. Seleccionar ubicación de red. Práctica - Compartir y conectar una carpeta

SISTEMA DE REGISTRO DE TRANSACCIONES BURSATILES BAGSA MANUAL DE USUARIO

Conceptos Generales en Joomla

MANUAL APLICACIÓN. SOFTWARE GESTIÓN DE CLÍNICAS DENTALES

Seven ERP Guía De Referencia - Imágenes

GUIA COMPLEMENTARIA PARA EL USUARIO DE AUTOAUDIT. Versión N 02 Fecha: 2011-Febrero Apartado: Archivos Anexos ARCHIVOS ANEXOS

MANUAL DE AYUDA HERRAMIENTA DE APROVISIONAMIENTO

Manual CMS Mobincube

FICHEROS Y BASES DE DATOS (E44) 3º INGENIERÍA EN INFORMÁTICA. Tema 9. Reglas de Integridad

Propuesta de Portal de la Red de Laboratorios Virtuales y Remotos de CEA

PS.Vending Almacén Pocket PC

CIF-KM. GUÍA DE LOS PRIMEROS PASOS

A- CREAR COPIA FÍSICA Y HEREDAR REGISTRO DE CONFIGURACIÓN

ÍTEMS DEL MENÚ CREACIÓN Y GESTIÓN (Última revisión: lunes, 9 de marzo de 2009)

Introducción a la Firma Electrónica en MIDAS

TEMA 4: EMPEZANDO A NAVEGAR ESCUELA UNIVERSITARIA DE INFORMÁTICA. Raúl Martín Martín

AGREGAR COMPONENTES ADICIONALES DE WINDOWS

Redes de área local: Aplicaciones y servicios WINDOWS

MANUAL DE USUARIO DE EGROUPWARE MANUAL DE USUARIO EGROUPWARE

Eurowin 8.0 SQL. Manual del módulo TALLAS Y COLORES

ESCUELA SUPERIOR DE INFORMATICA Prácticas de Estadística UNA SESIÓN EN SPSS

AGREGAR UN EQUIPO A UNA RED Y COMPARTIR ARCHIVOS CON WINDOWS 7

Curso de Python Inicial

Manual de operación Tausend Monitor

Tutorial: Primeros Pasos con Subversion

APLICACIONES INFORMÁTICAS de BASE de DATOS

MANUAL DE LA APLICACIÓN DE ENVÍO DE SMS

Objetivos de la práctica: - Practicar uso de ficheros: abrir, cerrar y tratamiento de información contenida en el fichero.

Listados y Etiquetas personalizados de PrefGest WhitePaper Julio 2008

Programa de Educación a Distancia MOODLE EDUC. (Modular Object Oriented Distance Learning Enviroment)

CIMA. MANUAL DE USUARIO

GUÍA Nro. 1 TECNOLOGÍA DE INTERNET. TIII PIII

Administración de la producción. Sesión 10: Gestor de Base de Datos (Access)

Servidor FTP LEECH FTP INDICE PRESENTACIÓN ACERCA DE CTRLWEB MAILING WORD AYUDA : Acceso a Panel de Control. 1.-Panel de control privado.

Herramientas CONTENIDOS. MiAulario

Mi propuesta consiste en crear un portal Web que contemple las siguientes funcionalidades:

Microsoft Access 2010 (Completo)

UNIDAD DIDACTICA 16 USUARIOS SAMBA EN UN CONTROLADOR DE DOMINIO LINUX SERVER

Manual de configuración de Thunderbird ÍNDICE

Trey-SAT Pag. 1. Manual de usuario

Ficheros Electrónicos

NORMA 34.14(SEPA) 05/11/2013

Kepler 8.0 USO DEL ERP

Herramienta Encuestas. MiAulario

Tutorial de Drupal para Editores de Sitios

GedicoPDA: software de preventa

Oficina Online. Manual del administrador

SISTEMA DE ATENCIÓN y GESTIÓN MANUAL DEL USUARIO. SAyGeS v2.0

MANUAL DE USUARIO. Se deben seguir los siguientes pasos para la correcta instalación del módulo descargable:

Transcripción:

TING! DESARROLLO DE MÓDULOS FORMACIÓN TÉCNICA MADRID 19-23 JULIO 2010 JULIO 2010 V2.0 ting! Tecnologías Inteligentes de Software S.L.

índice i. INTRODUCCIÓN ii. ESTRUCTURA DE UN MÓDULO a. ESTUDIO COMPLETO DE UN MÓDULO EXISTENTE b. DESCRIPCIÓN DE MÓDULOS BÁSICOS: BASE, SALE, PRODUCT, STOCK, PROJECT c. HERENCIA iii. iv. MAPEADOR ORM OBJETOS, CAMPOS Y MÉTODOS a. DEFINICIÓN DE OBJETOS b. CAMPOS SIMPLES, FUNCIONALES, RELACIONALES, PROPIEDADES, PREDEFINIDOS Y ESPECIALES c. RESTRICCIONES v. VISTAS Y EVENTOS a. ELEMENTOS DE LAS VISTAS: FIELD, BUTTON, SEPARATOR, LABEL,... b. ATRIBUTOS DE LOS ELEMENTOS: READONLY, VISIBLE, NOLABEL,... c. AGRUPACIÓN DE ELEMENTOS: GROUP, NOTEBOOK, PAGE,... d. ACCIONES, DOMINIOS e. MENÚS f. ATAJOS ENTRE OBJETOS vi. vii. viii. MENUS Y ACCIONES SEGURIDAD DE OBJETOS EJERCICIO PRÁCTICO

Introducción Una vez instalado, OpenERP tiene una estructura modular permitiendo añadir módulos según vaya siendo necesario. El uso de los módulos es la manera de ampliar la funcionalidad OpenERP. La instalación por defecto de OpenERP se compone de un núcleo y varios módulos dependiendo del tipo de instalación entre los cuales podemos distinguir: base: el módulo básico compuesto por ir.property, res.company, res.request, res.currency, res.user, res.partner este módulo siempre es instalado. crm: gestión de la relación con los Clientes / Proveedores. sale: gestión de ventas. mrp: fabricación y planificación de recursos.. Los nuevos módulos pueden programarse fácilmente y requieren un poco de práctica en XML y Python.

Estructura de un módulo Contenido de un módulo: (addons/nombre_de_modulo) terp.py subdirectorio security/ Objetos: nombre_de_modulo.py, y posiblemente otros init.py Archivos XML: nombre_de_modulo_view.xml nombre_de_modulo_workflow.xml (opcional) nombre_de_modulo_report.xml (opcional) nombre_de_modulo_wizard.xml (opcional) nombre_de_modulo_data.xml (opcional) nombre_de_modulo_demo.xml (opcional) posiblemente otros ficheros XML opcionales Subdirectorio report/ report_name.xml / report_name.xsl report_name.rml / report_name.sxw / report_name.py (opcional) report_name.py subdirectorio wizard/ init.py wizard_name.py ir_model_access.csv (permisos sobre objetos) modelo_security.xml (creación de grupos y acceso a opciones de menú) Subdirectorio i18n/ modulo.pot (plantilla) es_es.po fr_fr.po... SubdirectorioProcess, para incluir información de procesos Otros Es una buena estrategia crear directorios donde se contengan las modificaciones propias de módulos externos

Estructura de un módulo Los pasos básicos para generar un módulo son: Crear un subdirectorio en la raíz del servidor OpenERP dentro del directorio bin/addons. Crear un archivo con la descripción del módulo: terp.py Crear los archivos Python que contendrán los objetos. Crear los archivos xml para la obtención de datos (vistas, menús, datos de ejemplo,...) Opcionalmente crear listados, asistentes y flujos de trabajo. Los archivos xml ubicados en el directorio del módulo se pueden utilizar para modificar la estructura de la base de datos también son utilizados para otros propósitos entre los que podemos destacar: Cargar datos iniciales o datos de demostración. Declaración de vistas. Declaración de listados. Declaración de asistentes. Declaración de flujos de trabajo.

Estructura de un módulo La estructura general de los ficheros xml es la siguiente <?xml version="1.0"?> <openerp> <data> <record model="workflow" id=workflow_id> <field name="name">workflow.name</field> <field name="osv">resource.model</field> <field name="on_create">true False</field> </record> </data> </openerp> Ejemplo: sale_workflow.xml id (en el ejemplo "workflow_id") es un identificador del flujo de trabajo. Cada flujo de trabajo debe tener un identificador único. name (en el ejemplo "workflow.name") es el nombre del flujo de trabajo. El nombre del flujo de trabajo debe respetar la sintaxis de OpenERP "nombres punteados". osv (en el ejemplo "resource.model") es el nombre del objeto OpenERP que vamos a utilizar como modelo [- (Recuerde que OpenObjects hereda de osv.osv, de ahí "<field name="osv">')-]. on_create es verdadero cuando workflow.name se instancia automáticamente cuando resource.model es creado y falso en el caso contrario.

Estructura de un módulo init.py: El archivo init.py, como cualquier módulo de Python, es ejecutado al inicio del programa. En el incluiremos los archivos de Python que necesiten ser cargados.por lo tanto, si creamos un archivo "modulo.py", que contiene la descripción de nuestros objetos, tenemos que incluir una línea en init.py: import modulo terp.py : Cualquier módulo que creemos debe contener un un archivo con este nombre terp.py y debe estar ubicado en la raíz de nuestro módulo. Este archivo, que debe tener el formato Phyton es responsable de determinar: Los archivos XML que serán analizados durante la inicialización del servidor OpenERP. Las dependencias del módulo que hemos creado.

Estructura de un módulo Este archivo terp.py debe contener los siguientes valores de Python: name: nombre del módulo. version: versión del módulo description: descripción del módulo. author: autor del módulo website: sitio web del modulo license: licencia del módulo (por defecto GPL-2) depends: lista de módulos de los que depende este módulo. El módulo base se debe incluir casi siempre en las dependencias ya que algunos datos de este módulo son necesarios para las vistas, informes... init_xml: lista de archivos xml que se cargaran al iniciar el servidor OpenERP con la opción "- init=modulo". Las rutas de los archivos debe ser relativas al directorio donde está el módulo. update_xml: lista de archivos xml que se cargaran al iniciar el servidor OpenERP con la opción "-update=modulo". Las rutas de los archivos debe ser relativas al directorio donde está el módulo. installable: acepta valores true o false y determina si el módulo es instalable o no. active: acepta valores true o false y determina los si el módulo sera instalado cuando se cree la base de datos (por defecto false)

Mapeador ORM El mapeador se encuentra en la carpeta bin/osv, es una técnica de programación para convertir datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a objetos y el utilizado en una base de datos relacional. En nuestro caso: Python - PostgreSQL La estructura es sencilla: 4 ficheros: fields.py : donde se definen las estructuras básicas (columnas y tipos de campos) orm.py : donde se crean las clases que van a albergar los objetos y se define su funcionamiento íntimo. (En teoría, todo el SQL debería estar aquí...) osv.py: Instancia los objetos expression.py : permite evaluar expresiones complejas para dominios de datos (AND, OR, etc.)

Objetos (modelo) Todos los datos de OpenERP son accesibles a través de "objetos". Por ejemplo, existe un objeto "res.partner" para acceder a la información concerniente a las empresas (partners), un objeto "account.invoice" para acceder a los datos relativos a las facturas, etc. Localización: addons/nombre_modulo/nombre_modulo.py Existe un objeto para cada tipo de recurso, y no un objeto por recurso. Así tenemos un único objeto res.partner para manejar a todas las empresas y no un res.partner para cada empresa, es decir, existe un objeto por nivel. La principal consecuencia de éste hecho es que todos los métodos de los objetos tienen un parámetro común: el parámetro "ids". Este especifica sobre qué recursos (por ejemplo, sobre que empresa) el método debe aplicarse. Precisamente este parámetro contiene una lista de identificadores de recurso (ids) sobre los que se aplicará el método.

Objetos : tipos simples boolean integer float char parámetro opcional digits Ex: 'rate': fields.float('relative Change rate', digits=(12,6)) parámetro size text date datetime binary Ex: 'zip': fields.char('zip', size=24),

Objetos: Los elementos básicos... fields Heredan de una clase base denominada _column (columna), definida en fields.py Clase _column, atributos más importantes: _type : se utiliza para mapear su equivalente en la base de datos posteriormente (método get_pg_type de orm.py) class integer_big(_column): _type = 'integer_big'... type_dict = { fields.boolean: 'bool', fields.integer: 'int4', fields.integer_big: 'int8',...

Objetos: Atributos _multi : Se utiliza en campos 'funcionales' cuando el valor de varios campos se devuelve simultaneamente string: Almacena el valor de la cadena a mostrar (etiqueta) readonly: Especifica si el campo es de sólo lectura required: Si es obligatorio ( ojo! A nivel de base de datos...) size: el tamaño. Obligatorio para algunos tipos de campo como 'char' help: Cadena de texto para ayuda contextual change_default: Si es verdadero permite definir al usuario valores por defecto de otros campos basados en el valor de éste. ondelete: En campos relacionados permite definir a nivel de base de datos el comportamiento con los campos relacionados (... el ON DELETE CASCADE, SET NULL o en su caso RESTRICT). Por defecto set null translate: Si es verdadero, el contenido del campo será traducible _domain: si existe un dominio sobre el campo _context: información de contexto select : Permite definir si el campo se utilizará en los formularios de búsqueda de registros states: permite definir el valor de los demás atributos dependiendo del valor de la columna 'state'.

Objetos: boolean Ejemplo típico: campo 'active'. Si el campo 'active' existe para un objeto por defecto las búsquedas filtrarán solamente los registros activos. Si además no ponemos en campo 'active' un atributo 'select' no habrá forma de seleccionar nunca los registros no activos. base/res/partner/partner.py: 'active': fields.boolean('active'),ó base/res/partner/partner.py: 'customer': fields.boolean('customer', help="check this box if the partner if a customer."),

Objetos: integer Además de los usos habituales de los enteros se utiliza también en campos como 'sequence'. Es una convención dentro de la aplicación usar un campo llamado 'sequence' para ordenar los registros. Rango: -2147483648 a +2147483647 Ejemplo: product/product.py clase: product.category _columns = { 'name': fields.char('name', size=64, required=true, translate=true), 'complete_name': fields.function(_name_get_fnc, method=true, type="char", string='name'), 'parent_id': fields.many2one('product.category','parent Category', select=true), 'child_id': fields.one2many('product.category', 'parent_id', string='childs Categories'), 'sequence': fields.integer('sequence'), } _order = "sequence" Big Integer apenas se utiliza

Objetos: reference Se utiliza para crear una referencia a otro objeto que no es siempre del mismo tipo. Ejemplo: requests -> permite enlazar a los mensajes referencias a facturas, pedidos de ventas, tareas, etc. En la base de datos se almacena como una cadena de texto donde figura el nombre de modelo y su identificador: account.invoice,7 sería una referencia a la factura número 7. El campo se muestra como 2: un desplegable con los objetos a enlazar y un campo para seleccionarlo. (Ver ejemplo)

Objetos: char Son cadenas de texto. El campo 'name' es normalmente de tipo char. (Es un campo semiobligatorio por lo que podemos encontrar definiciones en prácticamente todas las clases). Obligatorio: indicar tamaño mediante atributo size Ejemplo: 'name':fields.char('name',size=64,invisible=true)

Objetos: text Texto (sin límite) Se utiliza normalmente para observaciones, etc. Es texto sin formato

Objetos: float Numéricos de punto flotante En la definición se pueden especificar los dígitos Se traduce en la base de datos por: double si no establecemos un número de dígitos numeric si los establecemos Ejemplo: en account/account_move_line.py La mayor parte de los campos numéricos tienes establecida una precisión El campo 'amount_currency' no la tiene...

Objetos: date, datetime, time Campos para almacenar valores de tiempo: date : fecha (sin hora) datetime : almacena fecha y hora time : hora (apenas utilizado) La forma de evitar problemas... AAAA-MM-DD HH:MM:SS

Objetos: binary Guarda datos binarios En muchas ocasiones se almacenan codificados en formato base64 Permite almacenar imágenes, ficheros, etc.

Objetos: selection En el objeto es un campo que puede tomar valores de una lista En la base de datos se mapea a un tipo text

Objetos: many2one Se utiliza para relaciones muchos a uno El mapeador crea una columna en la tabla muchos, clave foranea de la tabla uno. (La clave principal siempre es id) Ejemplo: lineas de pedido -> pedidos: 'order_id': fields.many2one('sale.order', 'Order Ref', required=true, ondelete='cascade', select=true) En la base de datos: CONSTRAINT sale_order_line_order_id_fkey FOREIGN KEY (order_id) REFERENCES sale_order (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE, Cuando creamos un campo many2one, la aplicación automáticamente genera en la base de datos la clave foránea, pero NO crea un índice sobre esa clave Si el campo en cuestión lleva un select, esto es, prevemos que vamos a utilizarlo en búsquedas, la aplicación genera un índice sobre dicho campo

Objetos: one2many Es la visión inversa de la relación anterior Es posible definir la relación en un sentido y no en el otro. La única consecuencia es que programáticamente no podremos utilizarla. En la base de datos no hay diferencia. Ejemplo: 'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=true, states={'draft':[('readonly',false)]}),

Objetos:many2many Permite crear relaciones muchos a muchos En la base de datos se utiliza una tabla intermedia (normalmente terminada en _rel) que almacena los identificadores de los registros relacionados Automáticamente se crean índices sobre ambas columnas

Objetos: function Existe la posibilidad de definir campos funcionales En principio éstos no tienen un mapeo a la base de datos excepto que utilicemos el argumento store=true, que almacena el resultado de la función en una columna en la base de datos del tipo adecuado. Existe la posibilidad de definir varios campos funcionales con la opción multi. De esta manera, se pueden calcular varios simultáneamente. Ejemplo: account/partner.py _columns = { 'credit': fields.function(_credit_debit_get, fnct_search=_credit_search, method=true, string='total Receivable', multi='dc', help="total amount this customer owns you."), 'debit': fields.function(_credit_debit_get, fnct_search=_debit_search, method=true, string='total Payable', multi='dc', help="total amount you have to pay to this supplier."),... def _credit_debit_get(self, cr, uid, ids, field_names, arg, context):...

Objetos: related Campos relacionados (derivan de los campos funcionales) En versiones antiguas, no era sencillo mostrar campos perteneciente a objetos relacionados (más allá de su nombre) Ejemplo: Un campo de alerta en clientes. Con este tipo de campos es posible acceder y mostrar esos campos alojados en otras tablas.

Objetos: serialized Es un tipo de campo diseñado para almacenar objetos serializados (persistentes) Utiliza el método repr() de Python para serializar los objetos por defecto, pero puede ser reemplazado por otro método mediante el parámetro serialize_func

Objetos: property La clase fields.property hereda de fields.function y sobreescribe los métodos read y write. El tipo de este campo es 'many2one', de modo que en la vista se representa de la misma manera que un campo many2one. Pero el valor de la propiedad se almacena en la clase ir.property (tabla ir_property) como un registro independiente. El valor almacenado es un campo del tipo 'reference' (referencia, no muchos a uno) porque cada propiedad puede apuntar a un objeto diferente. Si se editan los valores de las propiedades (en el menú de administración), estas están representadas como campos de tipo referencia.

Objetos: property (2) Cuando se lee una propiedad el programa devuelve la propiedad adjunta a la instancia del objeto que se está leyendo. Si el valor de la propiedad no está definido el sistema devolverá la propiedad por defecto. La definición de un a propiedad es almacenada en la clase ir.model.fields como cualquier otro campo. En la definición de la propiedad se pueden añadir los grupos que tienen permiso para modificarla.

Clases definidas en OpenERP class orm_template(object) / class orm(orm_template) Las clases que albergan los objetos con los que normalmente trabajamos descienden de la clase osv.osv que hereda de orm que a su vez hereda de orm_template. Todos los datos del ERP son accesibles a través de "objetos". Por ejemplo, existe un objeto "res.partner" para acceder a la información concerniente a las empresas (partners), un objeto "account.invoice" para acceder a los datos relativos a las facturas, etc.

Clases definidas en OpenERP La principal consecuencia de éste hecho es que todos los métodos de los objetos tienen un parámetro común: el parámetro "ids". Este especifica sobre qué recursos el método debe aplicarse. Normalmente llamaremos a un método con una serie de parámetros, de los cuales algunos prácticamente siempre están presentes: objeto.metodo(cr, uid, ids,...) cr : es una referencia al cursor que conecta a la base de datos uid: identificador de usuario que hace la petición ids: lista de identificadores

Objetos: orm_template y orm Principales atributos: _name = None _columns = {} _constraints = [] _defaults = {} _rec_name = 'name' _parent_name = 'parent_id' _parent_store = False _date_name = 'date' _order = 'id' _sequence = None _description = None _inherits = {} _table = None _sql_constraints = [] _log_access = True _table = None _sql = '' _auto = False

Objetos: orm_template y orm Principales métodos: _auto_init: se ejecuta automáticamente al cargar el objeto. En algunos casos se sobreescribe para añadir la creación de índices adicionales. (Ej: stock/stock.py) check_recursion: Se utiliza en estructuras arbóreas para prevenir ciclos infinitos. Si la estructura la hemos creado a mano también podemos utilizar el método pasándole como argumento parent el nombre del campo padre Browse: Se utiliza continuamente. Devuelve un conjunto de objetos navegables de una clase. Copy: Es el método que se invoca cuando duplicamos un registro. Puede ser interesante reescribirlo. Ejemplo: pedidos de venta Create: Se ejecuta al crear un nuevo objeto. En muchos casos puede ser interesante manipular éste método. Ejemplo: account.move.line (al crear un apunte contable) default_get: Devuelve los valores por defecto establecidos por un usuario, etc. Ejemplo de utilización: account.move.line

Objetos: orm_template y orm Principales métodos: distinct_field_get: Devuelve todos los distintos valores introducidos en un campo. Se utiliza normalmete para autocompletar campos (es automático). fields_get: Devuelve los campos pertenecientes a un objeto. Ejemplo de utilización: si fuesemos a escribir nuestra propia aplicación cliente utilizaríamos este método remotamente para obtener los campos y sus tipos. Hay un ejemplo de manipulación de este método en base/res/partner/partner.py en la definición de los bancos. export_data / import_data: Son los métodos utilizados en la importación / exportación de datos desde el cliente. El hecho de que sean métodos de clase nos permite sobreescribirlos, en caso necesario, para los objetos que queramos. (No hay un sólo caso en todo el repositorio, pero es posible hacerlo) fields_view_get: Devuelve la vista correspondiente a un objeto (en su contexto). Es el método que entre otras cosas se encarga de la aplicación de las herencias en las vistas. Ejemplo de manipulación: en stock/product.py o en ir/ir_model.py (ver éste último en funcionamiento)

Objetos: orm_template y orm Principales métodos: name_get: Es un método trivial que devuelve el valor del campo name o el especificado en _rec_name. Ejemplo de utilización: Las categorías de producto. name_search: Define la búsqueda a través del nombre de un objeto. Ejemplo de utilización: búsqueda de productos. _parent_store_compute: Para la optimización de determinadas consultas en la base de datos de estructuras arbóreas es preciso calcular para cada nodo sus ramas izquierda y derecha. Es este método el encargado de realizar el cálculo. Ejemplo de utilización: este tipo de estructuras se utilizan actualmente con las cuentas contables y las localizaciones de almacén. (enlace) perm_read: Permite consultar los permisos sobre un objeto y los datos de creación y última modificación. Este método es a veces conveniente ya que los campos internos (create_uid, create_date, etc.) son accesibles directamente sólo si los hemos redeclarado (en _columns). Con este método podemos acceder a leerlos sin necesidad de dicha declaración

Objetos: orm_template y orm Principales métodos: Read: Se utiliza para leer el contenido de diversos campos de un conjunto de registros. Se recomienda utilizar browse en lugar de read, ya que no es más lento y nos permite realizar lo mismo con una sintaxis más clara. search_count: Devuelve el número de registros como resultado de una búsqueda. search : Es otro de los métodos muy utilizados. Devuelve una lista de ids que cumplen con una serie de requisitos. Ejemplo de utilización: en stock/stock.py hay un bucle que recorre todas las localizaciones hijas de otra. Unlink: Para borrar o eliminar registros view_header_get: Se utiliza si queremos cambiar la etiqueta de una pestaña, dependiendo del contexto. Write: Es el método que se utiliza habitualmente para escribir valores en un objeto

RESUMEN: atributos de campo readonly (boolean) Valor por defecto: False. required (boolean) Valor por defecto: False. translate (boolean) Valor por defecto: False. change_default (boolean) Valor por defecto: False.

Objetos: Atributos de campo states Uso: establecer parámetros dependiendo del estado Sintaxis: {'nombre_estado': lista_atributos,...} donde lista_atributos es una lista de tuplas de la forma [('nombre_atributo', valor),...] Valor por defecto: {}. Ejemplo: 'partner_id': fields.many2one('res.partner', 'Partner', states={'posted': [('readonly',true)]}),

Objetos: campos complejos function (nombre_metodo, tipo_metodo,...) Ejemplo: def _get_installed_version(self, cr, uid, ids, field_name=none, arg=none, context={}): res = {} for m in...: res[m.id] =... return res 'installed_version': fields.function(_get_installed_version, method=true, string='installed version', type='char'), selection (opciones,...) Ejemplo: 'state': fields.selection( (('n','unconfirmed'),('c','confirmed')), 'State', required=true)

Objetos: campos relación many2one (obj,...) Ejemplo: 'commercial': fields.many2one('res.users', 'Commercial'), Parámetros opcionales: ondelete = cascade - Valor por defecto: set null domain = [('field_name', 'operator', value),...] - Valor por defecto: [] one2many (obj, campo_id,...) Ejemplo: 'address': fields.one2many('res.partner.address', 'partner_id', 'Contacts'),

Objetos: campos relación many2many (obj, rel, id1, id2) obj es el otro objeto relacionado rel es el nombre de la tabla que hace la relación id1 e id2 son los nombres de los campos en la tabla de relación Ejemplo: 'category_id': fields.many2many( res.partner.category', 'res_partner_category_rel', 'partner_id', 'category_id', 'Categories'),

Objetos: campos relación reference (string, optiones, size) Ejemplo: 'ref': fields.reference( 'Field label', selection = ((('object.name', 'Object Label'),...), size=128), Selección dinámica: <record model="res.request.link"> <field name="name">project Task</field> <field name="object">project.task</field> </record>

Objetos: valores por defecto Principios son funciones toman 4 parámetros (obj, cr, uid, context) Sintaxis: _defaults = { 'field_name': function,... } Ejemplo _defaults = { 'date': lambda obj,cr,uid,context: time.strftime('%y-%m-%d'), 'state': lambda *a: 'draft' }

Objetos: restricciones Principios: son restricciones en código Sintaxis: [(metodo, 'mensaje error', lista_campos),...] Example def _constraint_sum(self, cr, uid, ids):... return res < 1000 _constraints = [ (_constraint_sum, 'Error: el resultado debería ser < 1000.', ['name']) ]

Objetos: herencia simple Principios: Sintaxis: _inherit = 'object.name' Ejemplo: class custom_material(osv.osv): _name = 'network.material' _inherit = 'network.material' _columns = { 'manuf_warranty': fields.boolean('manufacturer warranty?'), } _defaults = { 'manuf_warranty': lambda *a: False, } custom_material()

Objetos: herencia compleja Principios: (ver ejemplo biblio) Sintaxis: _inherits = { 'nombre.objeto': nombre_columna,...} Ejemplo: Ver product.product y product.template

Objetos: otros atributos de objeto _table Valor por defecto: nombre del objeto (. sustutuidos por _ ) _rec_name Valor por defecto: 'name'. _order Valor por defecto: 'id'.

Objetos: acceso a los objetos Acceso directo (desde dentro de un objeto) self.pool.get('nombre.objeto') Ejemplo: partner_object = self.pool.get('res.partner') partner_object.nombre_del_metodo(parámetros_m etodo) Acceso a través de Netservice (en el servidor pero desde fuera de los objetos) service = netsvc.localservice("object_proxy") result = service.execute(user_id, object_name, method_name, parameters)

Objetos: acceso a los objetos Acceso XML-RPC sock = xmlrpclib.serverproxy('http://servidor:pu erto/xmlrpc/object') result = sock.execute(user_id, password, object_name, method_name, parameters)

Objetos: métodos predefinidos más importantes create def create(self, cr, uid, vals, context={}) devuelve el id search read def search(self, cr, uid, args, offset=0, limit=80) args = [('nombre_campo', 'operador', valor),...] devuelve lista de ids def read(self, cr, uid, ids, fields=none, context={}) devuelve lista de diccionarios: [{'nombre_campo': valor}]

Objetos: métodos predefinidos más importantes write def write(self, cr, uid, ids, vals, context={}) vals = {'field_name': value,...} devuelve True unlink def unlink(self, cr, uid, ids) devuelve True browse def browse(self, cr, uid, ids, offset=0, limit=2000) Ejemplo: addr_obj = self.pool.get('res.partner.address').browse(cr, uid, contact_id) contact_name = addr_obj.name contact_bank = addr_obj.partner_id.bank

Objetos: métodos predefinidos más importantes name_get def name_get(self, cr, uid, ids, context={}) Devuelve [(id, name),...] name_search

Vistas Vistas sirven para definir como mostrar los objetos. tienes que saber que la interfaz de usuario de OpenERP es dinámica. Esto quiere decir que no esta descrita estáticamente por algún código, pero es dinámicamente construida desde las descripciones en XML de la pantalla del cliente. Puede haber varias vistas para el mismo objeto Diferentes tipos de vista: Formularios form tree Tree (con atajos) Graph (* Versión 5) Calendar (* Versión 5)

Vistas: principios Acciones Abrir una ventana (form o tree) Imprimir un informe Ejecutar un wizar Items de Menú

Vistas: sintaxis Como los otros ficheros XML (usan las etiquetas record ) objeto que almacena vistas = ir.ui.view <openerp> <data> <record model= ir.ui.view id=... >... </record> </data> </openerp>

Vistas: sintaxis (formulario) <record model="ir.ui.view" id="view_id"> <field name="name">nombre_vista</field> <field name="model">nombre_objecto</field> <field name="type">form</field> <field name="arch" type="xml"> <form string="etiqueta"> <field name="nombre_campo".../>... </form> </field> </record>

Vista: ejemplo <record model="ir.ui.view" id="view_organisation_form"> <field name="name">account.organisation.form</field> <field name="model">account.organisation</field> <field name="type">form</field> <field name="arch" type="xml"> <form string="company"> <field name="partner_id"/> <field name="partner_contact_id"/> <field name="note"/> </form> </field> </record>

Menus y acciones Crean la acción abrir ventana Crean el correspondiente item de menú <record model="ir.actions.act_window" id="action_id"> <field name="name">action_name</field> <field name="res_model">object_name</field> <field name="view_type">form</field> <field name="view_id" ref="view_id"/> </record> <menuitem name="network/all Materials" action="action_id"/>

Seguridad de objetos Es importante definir permisos de acceso a los objetos de openerp para que puedan acceder a ellos otros usuarios que no sean administradores. Para ello es necesario definir politicas de seguridad a los módulos que se definirían, tal y como hemos visto en la estructura del módulo, dentro de la carpeta security y sobre los archivos ir_model_access.csv y modulo_security.xml Ir_model_access.csv: Este archivo contiene los permisos que se les dan a los objetos para un determinado grupo. Este archivo contiene las siguientes columnas: Id: Indica el identificador de esa línea de seguridad especifica Name: Nombre del registro Model_id:id: Identificador del modelo de objeto sobre el que se van a aplicar esos permisos. Ej: model_res_partner si se llama desde el módulo que lo crea. Si lo hiciesemos desde otro módulo se llamaría con: base.model_res_partner (Pertenece al módulo base) Group_id:id: Identificador del grupo de usuarios para el cual se están estableciendo los permisos. Ej: base.group_partner_manager

Seguridad de objetos ir_model_access.csv: Perm_read: Indica si al grupo definido le está permitida la lectura sobre ese objeto. Al ser boolean se define con 0 o 1 Perm_write: Indica si le está permitida la escritura sobre el objeto. Perm_create: Indica si se les permite crear esa clase de objetos. Perm_unlink: Indica si les está permitido borrar objetos de esa clase.

Seguridad de objetos Archivo modulo_security.xml: En este archivo se define la creación de grupos, reglas de registros y los permisos de un grupo sobre los menús. Creación de grupos: <record model="res.groups" id="group_system"> </record> <field name="name">administrator / Configuration</field> Permisos sobre menús: <record id="base.menu_security" model="ir.ui.menu"> </record> <field eval="[(6,0,[ref('base.group_erp_manager')])]" name="groups_id"/>

Seguridad de objetos Archivo modulo_security.xml: En este archivo se define la creación de grupos, reglas de registros y los permisos de un grupo sobre los menús. Creación de Reglas: Sirven para crear dominios especificos sobre los grupos que las tienen definidas. En el ejemplo se creará una regla para que los usuarios vean solamente sus ventas. <record model="ir.rule.group" id="filter_sale_orders_rule_group"> <field name="name">user Sale Orders</field> <field name="model_id" search="[('model','=','sale.order')]" model="ir.model"/> <field name="global" eval="false"/> </record> <record model="ir.rule" id="filter_sale_orders_rule"> <field name="field_id" search="[('model','=','sale.order'),('name','=','user_id')]" model="ir.model.fields"/> <field name="operator">in</field> <field name="operand">','.join(map(lambda x: str(x.id), user.child_id))</field> <field name="rule_group" ref="filter_sale_orders_rule_group"/> </record>

Seguridad de objetos Archivo modulo_security.xml: En este archivo se define la creación de grupos, reglas de registros y los permisos de un grupo sobre los menús. Asignación de reglas a grupos: A la hora de crear un grupo podemos asignarle las reglas definidas anteriormente: <record model="res.groups" id="group_system"> <field name="name">administrator / Configuration</field> <field name="rule_groups" eval="[(6,0,[ref('filter_sale_orders_rule_group')])]"/> </record>

Ejercicio práctico