Diferencia entre revisiones de «OpenERP»

De Jose Castillo Aliaga
Ir a la navegación Ir a la búsqueda
Línea 624: Línea 624:




{{nota|'''Nomenclatura d'OpenObject vers nomenclatura POO'''
OpenObject no utilitza la nomenclatura habitual de POO i no parla de classes i d’objectes. Així, les instàncies que gestiona (productes, clients, proveïdors…) s’anomenen recursos (en lloc d’objectes) i l’abstracció o definició de les instàncies s’anomena objecte (en lloc de classe). }}


= Enllaços =
= Enllaços =

Revisión del 10:03 13 sep 2013

OpenERP és un producte de codi obert que es distribueix sota dos tipus de desplegament: On-premise, sota els SO Linux i Windows, amb dues versions (Community, gratuïta, i Enterprise, de pagament); i el SaaS.

La llicència de la versió 6 i 7 és és AGPLv3 o AGPL+Private User.

L’OpenERP és desenvolupat sota una arquitectura web client-servidor de tres capes:

  • La base de dades en un servidor PostgreSQL
  • Un servidor OpenERP que conté tota la lògica de negoci
  • Un servidor web, que en la versió 6.x està ubicat conjuntament amb el servidor OpenERP
  • La capa client que té diverses possibilitats: web, GTK i possibles clients desenvolupats amb els protocols XML-RPC i Net-RPC


Instal·lació

Podem seguir aquest manual https://doc.openerp.com/7.0/es/install/#installation-link

Explotació i adequació

L’explotació i adequació de l’ERP d’una organització és una tasca imprescindible, ja que garanteix que el programari es mantingui en condicions de ser utilitzat per l’organització per tal de donar sortida a les seves necessitats. Per poder-ho dur a terme, per una banda cal identificar les necessitats (tasca pròpia de consultors) i, per una altra, tenir un coneixement profund de l’ERP, tant en les funcionalitats que facilita (tasca de consultors i implantadors) com en les qüestions tècniques vinculades a l’ERP (tasca d’analistes i programadors).

L’OpenERP és un programari de gestió empresarial desenvolupat sobre el framework OpenObject de tipus RAD (Rapid Application Development).

La facilitat dels entorns RAD rau en el fet que el desenvolupament d’aplicacions és molt simple pel programador, de manera que amb poc esforç es pot obtenir aplicacions d’altes prestacions.

L’OpenObject facilita diversos components que permeten construir l’aplicació:

Arquitectura MVC
  • La capa ORM (Object Relational Mapping) entre els objectes Python i la base de dades PostgreSQL. El dissenyador-programador no efectua el disseny de la base de dades; únicament dissenya classes, per les quals la capa ORM d’OpenObject n’efectuarà el mapat sobre el SGBD PostgreSQL.
  • Una arquitectura MVC (model-vista-controlador) en la qual el model resideix en les dades de les classes dissenyades amb Python, la vista resideix en els formularis, llistes, calendaris, gràfics… definits en fitxers XML i el controlador resideix en els mètodes definits en les classes que proporcionen la lògica de negoci.
  • Un sistema de fluxos de treball o workflows.
  • Dissenyadors d’informes.
  • Facilitats de traducció de l’aplicació a diversos idiomes.

Tal com es pot observar, són molts els components d’OpenObject a conèixer per poder adequar l’OpenERP a les necessitats de l’organització, en cas que les funcionalitats que aporta l’OpenERP, tot i ser moltes, no siguin suficients.

La base de dades d'OpenERP

En l’OpenERP no hi ha un disseny explícit de la base de dades, sinó que la base de dades d’una empresa d’OpenERP és el resultat del mapatge del disseny de classes de l’ERP cap el SGBD PostgreSQL que és el que proporciona la persistència necessària per als objectes.

En conseqüència, l’OpenERP no facilita cap disseny entitat-relació sobre la base de dades d’una empresa ni tampoc cap diagrama del model relacional.

Si sorgeix la necessitat de detectar la taula o les taules on resideix determinada informació, és perquè es coneix l’existència d’aquesta informació gestionada des de l’ERP i, per tant, es coneix algun formulari de l’ERP a través del qual s’introdueix la informació.

L’OpenERP possibilita, mitjançant els clients web i GTK, recuperar el nom de la classe Python que defineix la informació que s’introdueix a través d’un formulari i el nom de la dada membre de la classe corresponent a cada camp del formulari. Aquesta informació permet arribar a la taula i columna afectades, tenint en compte dues qüestions:

  • El nom de les classes Python d’OpenERP sempre són en minúscula (s’utilitza el guió baix per fer llegible els mots compostos) i segueix la nomenclatura nom_del_modul.nom1.nom2.nom3… en la qual s’utilitza el punt per indicar un cert nivell de jerarquia. Cada classe Python d’OpenERP és mapada en una taula de PostgreSQL amb moltes possibilitats que el seu nom coincideixi amb el nom de la classe, tot substituint els punts per guions baixos.
  • Els noms dels atributs d’una classe Python sempre són en minúscula (s’utilitza el guió baix per fer llegible els mots compostos). Cada dada membre d’una classe Python d’OpenERP que sigui persistent (una classe pot tenir dades membres calculades no persistents) és mapat com un atribut en la corresponent taula de PostgreSQL amb el mateix nom.
Per exemple: La classe Python sale.order d’OpenERP està pensada per descriure la capçalera de les comandes de venda i la corresponent taula a PostgreSQL és sale_order.

D’aquesta manera, coneixent el nom de la classe i el nom de la dada membre, és molt possible conèixer el nom de la taula i de la columna corresponents. Es pot configurar els clients web i GTK per tal que informin del nom de la classe i de la dada membre en situar el ratolí damunt les etiquetes dels camps dels formularis.

Debug mode.png

Figura 1.1 Activar el debug mode

Si observem la figura 1.2, podem observar com:

Dalt apareix un desplegable que diu depurar#574, és la vista per defecte per a analitzar els elements dels formularis.

El camp Referencia cliente es diu client_order_ref de l'objecte sale.order. Per tant, la columna client_order_ref de la taula sale_order.

Debug2.png

Figura 1.2 Dades de depuració


Respecte al desplegable de dalt, la resta d'opcions són:

  • View Fields que permet obtenir una llista dels camps de la vista actual, amb els paràmetres corresponents.
  • Fields View Get que mostra l’XML generat per la vista actual. Cal tenir en compte que si la vista s’ha generat a partir de diverses vistes XML heretant les unes de les altres, aquí se’n mostra el resultat final.
  • Manage Views que mostra un llistat de les vistes relacionades amb la vista actual. Des d’aquest punt es poden crear noves vistes, eliminar-les o editar-les, encara que és recomanable utilitzar aquesta funcionalitat només per consultar. Es recomana realitzar les modificacions creant nous mòduls, per no perdre les modificacions davant actualitzacions de l’ERP.
  • Edit TreeView, Edit SearchView, Edit Action i Edit Workflow que serveixen per accedir a l’edició de les vistes relacionades amb la vista actual.
  • Si estem editant un registre (mode formulari) o consultant-lo (mode pàgina), apareix una nova opció View Log (perm_read) que mostra informació relativa al registre actual.


Accés de només lectura a les dades

Les empreses acostumen a tenir, entre els seus responsables, usuaris finals que poden efectuar consultes no previstes a la base de dades i que, per aconseguir-ho, poden utilitzar eines gràfiques per elaborar consultes o fins i tot, si són prou espavilats, executar consultes SQL des d’una consola d’accés.

En aquesta situació, cal facilitar als usuaris que correspongui, un usuari per accedir al SGBD PostgreSQL amb els privilegis d’accés, en mode consulta, als objectes de la base de dades que correspongui. S’aconsella seguir els següents passos:

1. Crear els usuaris de SGBD amb les contrasenyes que corresponguin.

Amb pgAdmin és fàcil d'afegir un nou rol de login.

2. Donar els privilegis d’accés adequats als usuaris que corresponguin.

Desenvolupament de mòduls en OpenERP

Anem a desenvolupar un mòdul molt simple d'exemple mentre expliquem cóm se fan els mòduls. Aquest serà per a una academia que tindrà professors, cursos i alumnes.

Estructura bàsica dels mòduls

Un mòdul pot contenir els següents elements:

  • Objecte de negoci: declara com classes de Python qual hereta de la classe osv.Model, la persistència d'aquests recursos és manejada completament per l'ORM d'OpenERP.
  • Dades: Arxius XML/CSV amb les metadades (vistes i la declaració de fluxos de treball), les dades de configuració (parametrització de mòduls) i les dades de demostració.
  • Informes: RML (format XML). HTML / MAKO o plantilles d'informes d'OpenOffice, que es combinaran amb qualsevol tipus de dades de negocis i generar HTML, ODT o informes en PDF.


03 module gen view.png

Cada mòdul està contingut en el seu propi directori al servidor al directori de addons, configurat a la instal·lació del servidor. Per crear un nou mòdul, són necessaris els següents passos:

  • Crear un subdirectori en el directori de addons
  • Crear el __ init__.py per a l'importació d'arxius.
  • Crear el __ openerp__.py que és el que defineix el mòdul.
  • Crear arxius de Python que continguen objectes
  • Crear. xml que contenen dades de mòduls com ara vistes, entrades de menú o dades de demostració
  • Opcionalment crear informes i fluxos de treball
En ubuntu 13.04, si instal·lem amb apt-get, els mòduls enstan per defecte en /usr/lib/pymodules/python2.7/openerp/addons/

__init__.py

És l'arxiu d'importació de Python, perquè un mòdul d'OpenERP és també un mòdul ordinari de Python. L'arxiu ha d'importar tots els altres arxius python o submòduls.

Per exemple, si un mòdul conté un sol arxiu de python anomenat openacademy.py, l'arxiu ha de ser similar a:

    import openacademy

__openerp__.py

Aquest arxiu, que ha de ser un diccionari Python literal, és responsable de:

  • Determinar els arxius XML que es va a analitzar durant la inicialització del servidor
  • Determinar les dependències del mòdul creat.
  • Declarar metadades addicionals

Aquest fitxer ha de contenir un diccionari de Python amb els següents valors:

name             The name of the module in English.
version          The version of the module.
summary          Short description or keywords
description      The module description (text).
category         The categrory of the module
author           The author of the module.
website          URL of the website of the module.
license          The license of the module (default: AGPL-3).
depends          List of modules on which this module depends beside base.
data             List of .xml files to load when the module is installed or updated.
demo             List of additional .xml files to load when the module is installed or updated and demo flag is active.
installable      True or False. Determines whether the module is installable or not.
auto_install     True or False (default: False). If set to ``True``, the module is a link module. It will be installed as soon  as all its dependencies are installed.


En el cas de del nostre exemple de openacademy tindrà un aspecte similar a:

{
    'name' : "OpenAcademy",
    'version' : "1.0",
    'author' : "OpenERP SA",
    'category' : "Tools",
    'depends' : ['mail'],
    'data' : [
        'openacademy_view.xml',
        'openacademy_data.xml',
        'report/module_report.xml',
        'wizard/module_wizard.xml',
    ],
    'demo' : [
        'openacademy_demo.xml'
    ],
    'installable': True,
}


Objectes

Tots els recursos OpenERP són objectes: factures, socis. Les metadades també són objecte també: menús, accions, informes ... Els noms d'objectes són jeràrquics, com en els exemples següents:

        account.transfer: una transferència de diners
        account.invoice: una factura
        account.invoice.line: una línia de factura

En general, la primera paraula és el nom del mòdul.

Els objectes es declaren en python com a subclasse de osv.Model

El ORM d'OpenERP es construeix sobre PostgreSQL. Per tant, és possible consultar l'objecte utilitzat per OpenERP utilitzant la interfície d'objecte (ORM) o mitjançant l'ús d'instruccions SQL directament.

Però és perillós per escriure o llegir directament a la base de dades PostgreSQL, com es pot escurçar passos importants com la comprovació de restriccions o la modificació de flux de treball.


Arxius XML

Arxius XML ubicats al directori dels mòduls s'usen per inicialitzar o actualitzar la base de dades quan s'instal·la o actualitza el mòdul. S'utilitzen per a molts fins, entre els quals podem citar:

  • Inicialització i declaració de dades de demostració,
  • Declaració de vistes,
  • Declaració dels informes,
  • Declaració dels fluxos de treball

Les dades poden ser inserides o actualitzades en les taules de PostgreSQL corresponents als objectes OpenERP utilitzant fitxers XML. L'estructura general d'un fitxer XML OpenERP és el següent:

<?xml version="1.0"?>
<openerp>
  <data>
    <record model="model.name_1" id="id_name_1">
      <field name="field1"> "field1 content" </field>
      <field name="field2"> "field2 content" </field>
      (...)
    </record>
    <record model="model.name_2" id="id_name_2">
        (...)
    </record>
    (...)
  </data>
</openerp>

Exemple de Creació d'un mòdul bàsic

Anem a crear un mòdul per a una agència de viatjes.

En primer lloc creem un directori travel en la ruta dels addons de OpenERP.

Dins creem els fitxers __init__.py i __openerp__.py:

__init__.py:

import travel

__openerp__.py

{
   "name" : "Travel agency module",
   "version" : "1.1",
   "author" : "Tiny",
   "category" : "Generic Modules/Others",
   "website" : "http://www.openerp.com",
   "description": "A module to manage hotel bookings and a few other useful features.",
   "depends" : ["base"],
   "init_xml" : [],
   "update_xml" : ["travel_view.xml"],
   "active": True,
   "installable": True
}


Com es pot deduir, necessitem un fitxer travel.py que contindrà els objectes i un travel_view.xml que conté la vista del mòdul.

travel.py

from osv import osv, fields

class travel_hostel(osv.osv):
      _name = 'travel.hostel'
      _inherit = 'res.partner'
      _columns = {
      'rooms_id': fields.one2many('travel.room', 'hostel_id', 'Rooms'),
      'quality': fields.char('Quality', size=16),
      }
      _defaults = {
      }
travel_hostel()




Diseny de mòduls amb DIA

Dia és una aplicació gràfica de propòsit general per a la creació de diagrames, desenvolupada com a part del projecte GNOME. Està construïda de forma modular, amb diferents paquets de formes per a diferents necessitats.

A nosaltres ens interessa aquesta eina per a dissenyar els diagrames UML dels mòduls OpenERP que volem desenvolupar i generar-ne posteriorment el mòdul per a OpenERP, motiu pel qual haurem d’instal·lar Dia amb Python amb l’opció de generació de mòduls OpenERP. El mòdul està en la branca extra-addons [1]

Per a fer-ho anar, seguim aquest manual: [2]

El procés d’instal·lació de Dia amb Python amb l’opció de generació de mòduls OpenERP, incorpora un exemple de diagrama UML desenvolupat amb Dia (arxiu uml_test.dia facilitat per OpenERP) corresponent a un senzill mòdul de gestió escolar per a OpenERP. Utilitzarem aquest diagrama per iniciar-nos en el disseny de mòduls OpenERP mitjançant l’eina de diagramació Dia.

Umlexempledia.png


L’eina Dia permet desenvolupar diversos tipus de diagrama i, com que ens interessa els diagrames UML, caldrà tenir seleccionada la fulla UML a la caixa d’eines de la part esquerra de la pantalla de Dia.

L’exemple de la figura anterior correspon a un model per gestionar, en una escola que facilita cursos (en diverses edicions) i disposa de professors, els estudiants assistents als diversos cursos.

En una situació com la presentada, a l’hora de desenvolupar un diagrama UML, és molt lògic pensar en un disseny que contingui classes per modelar els conceptes curs, professor, edicions dels cursos i estudiants, de forma similar al diagrama uml_test, el qual contempla:

  • Classe school.course, per modelar els cursos que facilita l’escola.
  • Classe school.event, per modelar les edicions dels cursos.
  • Classe abstracta school.professor, per modelar els professors.
  • Plantilla de classe school.student, per modelar els estudiants.

Una primera ullada del diagrama permet introduir els següents conceptes per mòduls OpenERP:

  • Tots els elements d’un diagrama cal escriure’ls en anglès (fins i tot les etiquetes i els textos informatius). Si ens interessa tenir-lo en un altre idioma, utilitzarem posteriorment les eines de traducció que facilita OpenERP.
  • Totes les classes s’anomenen en minúscules i es recomana incorporar, com a prefix, el nom del mòdul al què pertanyen.
  • Els noms de mòduls, classes i membres de les classes han de ser escrits en minúscula amb guions baixos per a fer llegibles els noms compostos.
  • La nomenclatura indicada és la que marca OpenERP i, com possiblement sabreu, és diferent de les nomenclatures recomanades en altres entorns de POO, com és el cas del llenguatge Java.

Com que els noms de les classes tenen el prefix school, deduïm que es tracta del diagrama d’un mòdul anomenat school. S’aconsella batejar el diagrama Dia amb el nom del corresponent mòdul, ja que en el procés de generació del mòdul a partir del diagrama, Dia proposa el nom del diagrama com a nom del mòdul, tot i que es pot canviar.

Continuem observant el diagrama. Per a la classe school.event del mòdul school, en tractar-se del model per les edicions dels cursos, potser hagués estat més encertat el nom school.course.event, de forma similar a la nomenclatura utilitzada per OpenERP per les comandes de venda i les seves línies (sale.order i sale.order.line).

En el diagrama UML, school.professor una classe abstracta i school.studentés una plantilla de classe. A l’hora de generar els mòduls per OpenERP, això no té cap efecte i les haguéssim pogut dissenyar com a classes normals.

Fixem-nos que cada classe del diagrama incorpora un estereotip (nom encerclat entre els símbols « i » per sobre del nom de la classe). El procés de generació de mòduls OpenERP a partir de diagrames Dia, interpreta el contingut del camp estereotip com la jerarquia de menús, dins OpenERP, on ubicar els formularis generats a partir del diagrama i s’utilitza el símbol / per separar els diversos nivells. És a dir, segons el diagrama de la figura 6, el formulari corresponent al manteniment dels cursos estarà en una opció de menú anomenada Courses, dins el submenú Configuration del menú principal Courses (doncs l’estereotip de la classe school.course és «Courses/Configuration/Courses»).

És aconsellable instal·lar el mòdul uml_test original facilitat per OpenERP, per poder comparar el disseny efectuat mitjançant l’eina Dia amb el resultat final dins OpenERP.

( Els addons en ubuntu si fem una instal·lació amb apt-get estan en /usr/lib/pymodules/python2.7/openerp/addons cal copiar el .zip del mòdul i actualitzar la llista. També pot estar en /usr/share/pyshared/openerp/addons)

El plugin de DIA està desactualitzat (en 2013) i genera mòduls per a versions anteriors a la 7. Per tant, cal fer algunes modificacions:

El fitxer __terp__.py cal renombrar-lo a __openerp__.py

Pot ser que __terp__.py tinga mal tancades algunes comilles.


En el diagrama observem que entre les classes hi ha uns connectors (associacions entre classes) que són únicament de caire informatiu i no tenen cap incidència en la generació del mòdul OpenERP. Les relacions entre les classes es defineix a través d’atributs relacionals dins cada classe; la facilitat de diagramació d’associacions entre classes que facilita l’eina Dia no és aprofitada pel mòdul uml_dia en generar els mòduls OpenERP; en conseqüència, la utilització dels connectors associatius de Dia serveixen, únicament, com a documentació gràfica.

Cal interpretar les associacions que observem com:

  • Un professor (fletxa de school.professor cap a school.course) pot impartir diversos cursos.
  • Un curs (fletxa de school.course cap a school.event) pot tenir diverses edicions.
  • Un curs pot tenir diversos estudiants i un estudiant pot cursar diversos cursos (fletxa amb doble sentit entre school.course i school.student).

Si seleccionem qualsevol de les associacions del diagrama i n’editem les propietats, observem que l’eina Dia, per a documentar encara més el diagrama, permet indicar els rols i la multiplicitat. Així, podríem retocar el diagrama per aconseguir un diagrama més documentat:


A1 continguts image 7.png

Figura Diagrama UML amb multiplicitats a les associacions


El diagrama de classes de les figures anteriors mostra únicament la capçalera de les classes (nom i estereotip) i aquestes classes poden contenir membres (dades i mètodes). Per a visualitzar dades i/o mètodes (atributs i/o operacions, segons nomenclatura de l’eina Dia) d’una classe, cal seleccionar la classe i editar les seves propietats (boto secundari del ratolí), i activar les caselles de verificació Atributs visibles i Operacions visibles. En activar-les per a totes les classes, obtenim la visualització següent:

A1 continguts image 8.png

Una ullada ràpida al diagrama ens permet afirmar que les seves classes no incorporen cap operació i únicament contenen atributs. Aprofitarem les classes d’aquest diagrama per exemplificar els diversos tipus d’atributs de les classes d’un mòdul OpenERP i com es defineixen en un diagrama dissenyat amb l’eina Dia.

Diseny d'atributs

Els atributs de les classes d’un mòdul OpenERP són bàsicament de tres categories: bàsics o simples, relacionals i funcionals.

Els atributs simples o bàsics són aquells destinats a contenir un valor concret (enter, real, booleà, cadena,…). Els atributs relacionals són aquells destinats a representar les relacions entre classes. Els atributs funcionals són uns camps especials perquè no s’emmagatzemen a la base de dades i es calculen en temps reals a partir d’altres atributs.

Fixem-nos, per exemple, en els vuit atributs de la classe school.course: set són simples o bàsics ( name, subject, hours_total, requirements, website, date i note) i un és relacional (prof_id).

Atributs simples o bàsics

Un diagrama Dia amb la visualització d’atributs activada, mostra per a cada atribut simple, la següent seqüència d’informació:

  1. atribut de visibilitat (+ per públic, - per privat i # per protegit)
  2. nom de l’atribut, seguit del símbol :
  3. tipus de l’atribut (boolean, integer, float, char, text, date, datetime, binary, selection, reference)
  4. símbol =
  5. etiqueta pel camp, entre cometes simples, d’obligada existència
  6. cap o més paràmetres, seguint la sintaxis nom=valor i separats per coma.

Així, la classe school.course, té un atribut public (símbol +), destinat a emmagatzemar el nom (name) del curs, amb etiqueta Course, de tipus caràcter (char) de 32 caràcters com a molt (paràmetre size) i amb obligatorietat de valor (required=‘True’ ). Fixem-nos que la definició del camp en el diagrama és:

+name: char = 'Course', size=32, required = 'True'
  • boolean Valors lògics Valors vàlids: True i False
  • integer Valors enters
  • float Valors reals Pot anar acompanyat d’un paràmetre digits destinat a indicar la precisió i l’escala de l’atribut. L’escala és el nombre de dígits després del punt decimal i la precisió és el nombre total de dígits significatius (abans i després del punt decimal). Si el paràmetre digits no és present, serà considerat com un nombre en punt flotant amb doble precisió.
  • date Valor data
  • datetime Valor data i hora en un mateix camp
  • char Cadena de longitud limitada És obligatori indicar el paràmetre size=valor, per indicar la màxima longitud permesa.
  • text Cadena de longitud il·limitada
  • binary Cadena binària
  • selection Un valor d’una llista de valors possibles predefinits En aquest cas, abans del valor de l’etiqueta del camp, cal indicar la llista de valors possibles, com a seqüència de parelles (valor, etiqueta):

[(valor1, etiqueta1), (valor2, etiqueta2),…]

  • reference Punter cap un objecte existent en OpenERP Els objectes d’OpenERP que es poden seleccionar per una referència es defineixen en el menú Settings|Personalització|Objectes de baix nivell|Sol·licituds|Tipus de referències en sol·licitudsd’OpenERP.

Com a exemple d’atribut selection podem observar l’atribut contract de la classe school.professor. Fixem-nos que la llista conté dos valors (trainee i named) pels que la visualització des del programa serà Trainee i Named, a no ser que apliquem un procés de traducció de l’aplicació (però a nivell de la base de dades, els valors emmagatzemats sempre seran trainee i named.

Paràmetres que poden acompanyar els atributs bàsics:

Nom Obli-gatori Atribut al què acompanya Significat
size char Llargada màxima de la cadena
digits No float Indicar la precisió i escala en format (p,s). Veure explicació del camp float a la taula.
required No Qualsevol Indicar l’obligatorietat de l’atribut amb el valor True. Per defecte, el seu valor és False.
readonly No Qualsevol Indicar que l’atribut és de només lectura, amb el valor True. Per defecte, el seu valor és False.
select No Qualsevol Exigir que a nivell de la base de dades es generi un índex per aquest camp per tal d’optimitzar els processos de recerca, amb el valor 1. Per defecte el seu valor és 0.
help No Qualsevol Indicar el missatge d’ajuda que OpenERP visualitza en situar el ratolí damunt l’etiqueta del camp. Provoca que l’etiqueta vagi acompanyada per un petit interrogant a l’extrem superior esquerre.
translate No char o text Indicar que el valor del camp pot ser traduït pels usuaris, amb el valor True. Per defecte, el seu valor és False.

En el client web, els camps amb l’atribut translate a True presenten, en mode edició, una banderola al final de la caixa de text que conté el valor del camp, per indicar que el camp és traduïble. Prement el ratolí damunt la banderola, s’obre una pantalla que recull tots els camps traduïbles del formulari i podem procedir a la seva traducció. Podeu comprovar-ho en el camp Nom del formulari de productes d’OpenERP.

La introducció dels diversos valors per definir un atribut simple des de l’eina Dia, s’efectua des de la pestanya Atributs de les propietats de la classe, seguint els criteris següents:

  • La visibilitat de l’atribut (public, private o protegit) s’escull en el camp Visibilitat.
  • El nom de l’atribut s’introdueix a l’apartat Nom.
  • El tipus de l’atribut s’introdueix a l’apartat Tipus.
  • El nom de l’etiqueta (entre cometes simples i obligatori), seguit de la seqüència de parelles paràmetre=valor que correspongui, separades per coma, s’introdueix a l’apartat Valor.
  • L’ajuda que acompanya al camp (paràmetre help), s’introdueix a l’apartat Comentari.

Podeu comprovar l’aplicació dels criteris anteriors tot editant les propietats de qualsevol dels atributs bàsics de les classes del diagrama uml_test.

Us heu adonat que, en els paràmetres presentats, no n’hi ha cap que faci referència a la definició d’un camp identificador de la classe?

En OpenObject, cada classe té un atribut identificador, de nom id, generat automàticament per la capa Object Relational Mapping (ORM) d’OpenObject, de manera que no s’ha d’indicar en la definició dels atributs de la classe. El valor de l’atribut id per a cada objecte és generat automàticament per OpenObject i identificarà l’objecte (el registre a nivell de la base de dades) per sempre més. Aquest identificador també s’utilitza per relacionar objectes (integritat referencial a nivell de base de dades).

Llavors, si l’atribut identificador dels objectes d’una classe el genera OpenObject, com podem definir un camp que identifiqui un objecte tal i com estem acostumats en multitud d’aplicacions informàtiques? Per exemple, fixem-nos en l’atribut IDNum de la classe school.student. L’ajuda introduïda diu, textualment: “This is the uniq ID of the student”. Com podem aconseguir que IDNum sigui, veritablement identificador? Doncs per això haurem d’utilitzar la restricció d’unicitat que facilita OpenObject, però que no podem indicar a través de l’eina Dia i ho haurem de fer, més endavant, via el llenguatge Python.

L’atribut id és,doncs, un atribut especial però no és l’únic. La següent taula presenta amb detall els atributs de classe bàsics especials a tenir en compte en desenvolupar en OpenObject.

Nom Tipus Explicació
id integer Atribut identificador dins la classe, utilitzat per identificar cada objecte (registre a nivell de base de dades) per sempre més i per establir les relacions entre objectes de diverses classes (integritat referencial a nivell de base de dades). El crea l’eina ORM d’OpenObject i, per tant, no s’ha d’indicar en dissenyar una classe.
create_date datetime Emmagatzema el moment temporal en què es crea l’objecte. El crea l’eina ORM.
write_date datetime Emmagatzema el moment temporal de la darrera modificació de l’objecte. El crea l’eina ORM.
create_uid integer Emmagatzema l’identificador (id) de l’usuari que va crear l’objecte. Aquest usuari és un objecte de la classe res.user (o registre de la taula res_user). El crea l’eina ORM.
write_uid integer Emmagatzema l’identificador (id) de l’usuari que ha modificat per darrera vegada l’objecte. Aquest usuari és un objedcte de la classe res.user (o registre de la taula res_user). El crea l’eina ORM.
name char És l’atribut que utilitza OpenObject quan ha de mostrar objectes en una llista desplegable. En conseqüència, aquest atribut és obligatori en qualsevol classe C susceptible de ser referenciada des d’altres classes, doncs en aquestes caldrà facilitar una llista desplegable per facilitar la selecció dels objectes de C.
active boolean És un atribut que afegirem a aquelles classes per les que interessi poder amagar objectes en algun moment de la seva vida. Podria servir, per exemple, per amagar objectes històrics sense eliminar-los. Un objecte inactiu ja no és accessible ni apareix per enlloc, fins que es torni a activar.
state selection És un atribut que afegirem a aquelles classes per les que interessi poder definir diversos estats del cicle de vida d’un objecte.
parent_id integer És un atribut que permet definir estructures jeràrquiques entre objectes de la mateixa classe. Acostuma a sorgir com a conseqüència d’una associació reflexiva en una classe.

Com a exemple de la utilització que fa OpenObject de l’atribut name, podem anar a consultar la llista de clients d’una empresa, on observarem la columna País, que mostra el contingut de l’atribut name del país al que pertany el client. Si anem a la base de dades a consultar el contingut de la taula res_partner_address (que conté les adreces dels clients), hi veurem el camp country_id, com a clau forana de l’atribut id de la taula res.country. A la llista de clients, però, no veiem el contingut de l’atribut country_id (que és el què relaciona el client amb el país) sinó el contingut de l’atribut name del país referenciat.

OpenERP té moltes classes que contenen l’atribut active, com per exemple la classe res.users (taula res_users). Així, per exemple, podeu anar a Settings|Usuaris, editar el registre Demo User, desmarcar la casella Actiu per deixar-lo no actiu i enregistrar el canvi. Podreu observar com el registre Demo User ha desaparegut de la llista d’usuaris i ja no sortirà mai més fins que el fem actiu. Per a fer actiu un registre inactiu, hem d’aconseguir accedir-hi per a canviar el valor de la casella Actiu i per aconseguir-ho ens hem de valer de la recerca avançada dels formularis, seleccionant el camp Actiu i indicant que volem veure els registres que el tenen a valor fals.

Com a exemple d’utilització de l’atribut state, podem fixar-nos en la classe sale.order corresponent a les comandes de venda. OpenERP hi defineix l’atributstatede tipus selection amb els següents valors que defineixen els diferents estats pels que pot passar una comanda de venda:

   [('draft', 'Quotation'),
   ('waiting_date', 'Waiting Schedule'),
   ('manual', 'To Invoice'),
   ('progress', 'In Progress'),
   ('shipping_except', 'Shipping Exception'),
   ('invoice_except', 'Invoice Exception'),
   ('done', 'Done'),
   ('cancel', 'Cancelled')
   ]

Un exemple d’utilització de l’atribut parent_id el trobem, en OpenERP, en la definició dels tercers (clients i proveïdors). Si editem un client/proveïdor, veurem com a l’apartat Informació General de la pestanya Vendes & Compres, es pot indicar quina és l’empresa pare que, en cas de tenir valor, és un altre tercer.

Atributs relacionals

Entre les classes d’OpenObject es pot establir tres tipus de relacions, de manera similar a les relacions entre les entitats en un model entitat-relació per a bases de dades. Es defineixen via atributs relacionals dins les classes. Tenim, en conseqüència, tres tipus d’atributs relacionals: molts a un, un a molts, molts a molts.

Atribut relacional “molts a un” (many2one)

L’atribut relacional “molts a un” (many2one), s’utilitza per representar una relació cap una classe pare, de molts a un, és a dir, molts objectes de la classe que conté l’atribut poden estar relacionats amb un mateix objecte de la classe pare.

En el diagrama uml_test observem molts atributs relacionals many2one.Un exemple el tenim a la classe school.event, on l’atribut course_id està destinat a contenir, per a cada objecte de la classe school.event, l’identificador de l’objecte pare de la classe school.course.

OpenERP mostra els camps many2one acompanyats per una llista per a seleccionar l’objecte de la classe pare. És a dir, en el formulari per gestionar els cursos (objectes de la classe school.event), el camp course_id, amb etiqueta Course, estarà acompanyat d’un desplegable per seleccionar el curs que correspongui d’entre els objectes de la classe school.course). Això obliga a que la classe referenciada pel camp many2one contingui el camp name.

A nivell de la base de dades, els atributs many2one es mapen en atributs dins la taula corresponent a la classe que els conté, amb restriccions d’integritat referencial cap l’atribut identificador de la taula referenciada. Continuant amb l’exemple de l’atribut course_id de la classe school.event, la taula school_event contindrà el camp course_id amb una restricció d’integritat referencial cap l’atribut id de la taula school_course(automàticament creat per OpenERP).

Per definir un atribut many2one en l’eina Dia, cal crear l’atribut indicant que és del tipus many2one i a l’espai valor introduir:

'classeReferenciada','etiquetaDelCamp',...

Els punts suspensius del final indiquen que es pot utilitzar alguns paràmetres opcionals. Concretament:

  • ondelete: Com actuar quan l’objecte referenciat per l’atribut sigui eliminat. Valors possibles: cascade,set null. Valor per defecte: set null.
  • required, readonly, select: Amb funcionament idèntic als camps no relacionals.

Podem observar que l’atribut course_id de la classe school.event té com a valor:

'school.course','Course',required=True

És conveni, entre els desenvolupadors en OpenERP, anomenar els atributs many2one, amb el nom de la classe a la que referencien (o darrer nivell) acompanyat de _id, com és el cas de l’atribut course_id.


Atribut relacional “un a molts” (one2many)

Un atribut relacional “un a molts” (one2many) s’utilitza per representar una relació cap una classe filla, d’un a molts, és a dir, un objecte de la classe que conté l’atribut pot estar relacionat amb molts objectes de la classe filla.

Tot atribut one2manyés complementari d’un atribut many2one que ha d’existir obligatòriament a la classe filla. Per definir un atribut one2many en l’eina Dia, cal crear l’atribut indicant que és del tipus one2many i a l’espai valor introduir:

'classeReferenciada','nomAtributClasseReferenciada','etiquetaDelCamp',... 

La classe filla (classeReferenciada) ha de contenir l’atribut nomAtributClasseReferenciada de tipus many2one apuntant a la classe on hi ha l’atribut one2many.

Els punts suspensius del final indiquen que es pot utilitzar alguns paràmetres opcionals. Concretament:

  • invisible: Per impedir que el seu contingut sigui visible en els formularis corresponents a la classe a la que pertany el camp. Valors possibles: True,False. Valor per defecte: False.
  • readonly: Amb funcionament idèntic als camps no relacionals.

És conveni, entre els desenvolupadors en OpenERP, anomenar els atributs one2many, amb el nom de la classe a la que referencien (o darrer nivell) acompanyat de _ids.

En el diagrama uml_dia observem l’atribut course_ids del tipusone2many a la classe school.professor, amb el següent contingut a l’espai valor:

'school.course', 'prof_id', 'Courses'

L’atribut course_ids de la classe school.professor relaciona un professor amb el conjunt de cursos que imparteix. En conseqüència, la classe school.course ha de contenir l’atribut prof_id de tipus ser many2one cap a la classe school.professor.


L’existència d’un atribut one2many implica l’existència d’un atribut many2one, però l’existència un atribut many2one no implica l’existència d’un atribut one2many. La definició dels atributs one2many té dos objectius:

  • Aconseguir que en les vistes (formularis) que continguin el camp one2many, aparegui una llista dels objectes referenciats (com mostra la zona apunta per la fletxa de la figura.11).
  • Facilitar l’accés, en desenvolupar mètodes (lògica de negoci) de la classe que conté el camp one2many, cap els objectes referenciats per l’objecte sobre el que s’executi el mètode.

El paràmetre invisible=True en un atribut one2many provoca que cap formulari on aparegui l’atribut incorpori la llista dels objectes referenciats. D’aquesta manera, l’atribut únicament pot servir per facilitar l’accés als objectes referenciats en els mètodes desenvolupats sobre la classe.

Si observem el diagrama uml_diaoriginal facilitat per OpenERP, podem observar que l’atributprof_id de la classe school.courseconté, a l’espai valor:

'res.partner','Professor',required=True

La definició de l’atribut prof_id a la classe school.course és errònia, ja que no apunta a la classe school.professor, sinó a la classe res.partner. El mòdul generat mantenint aquesta definició té un mal funcionament.

Atribut relacional “molts a molts” (many2many)

L’atribut relacional “molts a molts” (many2many) s’utilitza per representar una relació de molts a molts entre dos objectes, és a dir, quan cada objecte d’una classe A pot estar relacionat amb molts objectes d’una classe B i cada objecte d’una classe B pot estar relacionat amb molts objectes d’una classe A.

Un exemple de relació many2many el trobem entre les classes school.student i school.course, ja que un estudiant es pot inscriure a molts cursos i en un curs hi pot haver molts estudiants inscrits.

Per definir un atribut many2many en l’eina Dia cal crear l’atribut en alguna de les dues classes que relaciona, o en ambdues, indicant el tipus many2many i, a l’espai valor, introduir:

'classeReferenciada','nomTaulaRelacional','nomCampFKPropi','nomCampFKAltraClasse','etiquetaDelCamp'

Està acordat, entre els desenvolupadors en OpenERP, anomenar els atributs many2many, amb un nom (adequat a les dues classes que relaciona) acompanyat de _ids. Fixem-nos que la definició d’un atribut many2many implica la creació d’una taula relacional a la base de dades.

En el diagrama uml_dia observem l’atribut subscriptions del tipus many2many a la classe school.student, amb el següent contingut a l’espai valor:

'school.course','course_student_subscription_rel','course_id','student_id','Subscriptions'

L’atribut subscriptions relaciona la classe school.student (en la qual és definit) amb la classe school.course, fet que provocarà l’aparició d’una nova taula a la base de dades, de nom course_student_subscription_rel, que tindrà l’atribut course_id amb restricció d’integritat referencial cap a la classe school.student i l’atribut student_id amb restricció d’integritat referencial cap a la classe school.course.

L’atribut subscriptions presenta algunes anomalies de notació:

  • El nom no segueix el conveni, ja que seria bo que el seu nom finalitzés en _ids.
  • El nom de la taula relacional que es generarà a la base de dades seria bo que comencés amb el prefix school_, de la mateixa manera que la resta de taules vinculades a aquest mòdul.
  • Els noms assignats als tercer i quart paràmetres del contingut de l’espai valor haurien d’estar a l’inrevés, de manera que course_id fos el nom per fer referència a la classe school.course i student_id fos el nom per fer referència a la classe school.student.

Així doncs, seria millor redefinir l’atribut subscriptions, canviant-li el nom per course_ids i amb el següent contingut a l’espai valor:

'school.course','school_student_course_rel','student_id',
'course_id','Subscriptions to courses'

Un atribut many2many provoca que l’eina Dia, en generar el formulari per al manteniment dels objectes de la classe, hi incrusti una zona de tipus llista per accedir als registres de la classe referenciada per l’atribut many2many.


Disseny del model

L’eina de diagramació Dia, amb l’extensió per generar mòduls per a OpenERP, facilita el disseny de mòduls per OpenERP. Les possibilitats que permet l’eina Dia són, però, limitades i, en conseqüència, ens cal aprendre com escriure directament els mòduls utilitzant els llenguatges Python i XML.

Un mòdul d’OpenERP incorpora, en el seu interior, tots els elements del patró model-vista-controlador en el qual es basa el desenvolupament d’OpenObject. L’eina Dia permet definir el model via diagrama UML i l’extensió per generar mòduls per a OpenERP ens facilita el mòdul que conté:

  • El model, definit a través de llenguatge Python, corresponent al diagrama UML dissenyat.
  • Una vista, definida a través del llenguatge XML, generada de forma automàtica.
  • Un controlador buit, ja que l’eina Dia no permet dissenyar els mètodes.
El nostre objectiu final és dissenyar mòduls utilitzant directament el llenguatge Python pel model i el controlador, i el llenguatge XML per la vista.


Nomenclatura d'OpenObject vers nomenclatura POO OpenObject no utilitza la nomenclatura habitual de POO i no parla de classes i d’objectes. Així, les instàncies que gestiona (productes, clients, proveïdors…) s’anomenen recursos (en lloc d’objectes) i l’abstracció o definició de les instàncies s’anomena objecte (en lloc de classe).

Enllaços