P. 1
OpenERP Technical Memento v0.6.4

OpenERP Technical Memento v0.6.4

|Views: 3|Likes:

More info:

Published by: Edgard Andres Pimentel Rojas on Jul 19, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

07/19/2013

pdf

text

original

Open Source RAD with OpenObject

PREAMBLE OpenERP is a modern Enterprise Management Software, released

Control). You also need to install the required dependencies (PostgreSQL and a few Python libraries – see documentation on doc.openerp.com).
Compilation tip: OpenERP being Python-based, no compilation step is needed
1 2 3

under the AGPL license, and featuring CRM, HR, Sales, Accounting, Manufacturing, Inventory, Project Management, ... It is based on OpenObject, a modular, scalable, and intuitive Rapid Application Development (RAD) framework written in Python.

Typical bazaar checkout procedure (on Debian-based Linux) $ sudo apt-get install bzr # install bazaar version control $ bzr branch lp:openerp # retrieve source installer $ cd openerp && python ./bzr_set.py # fetch code and perform setup

OpenObject features a complete and modular toolbox for quickly building applications: integrated Object-Relationship Mapping (ORM) support, template-based Model-View-Controller (MVC) interfaces, a report generation system, automated internationalization, and much more. Python is a high-level dynamic programming language, ideal for RAD, combining power with clear syntax, and a core kept small by design.
Tip: Useful links • Main website, with OpenERP downloads: www.openerp.com • Functional & technical documentation: doc.openerp.com • Community resources: www.launchpad.net/open-object • Integration server: test,openobject.com • Learning Python: doc.python.org • OpenERP E-Learning platform: edu.openerp.com

Database creation

After installation, run the server and the client. From the GTK client, use File→Databases→New Database to create a new database (default super admin password is admin). Each database has its own modules and config, and demo data can be included.

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

'version' : '1.0', 'author' : 'OpenERP', 'description' : 'Ideas management module', 'category': 'Enterprise Innovation', 'website': 'http://www.openerp.com', 'depends' : ['base'], # list of dependencies, conditioning startup order 'update_xml' : [ # data files to load at module init 'security/groups.xml', # always load groups first! 'security/ir.model.access.csv', # load access rights after groups 'workflow/workflow.xml', 'view/views.xml', 'wizard/wizard.xml', 'report/report.xml', ], 'demo_xml': ['demo/demo.xml'], # demo data (for unit tests) 'active': False, # whether to install automatically at new DB creation }

Object Service – ORM

Building an OpenERP module: idea
CONTEXT

The code samples used in this memento are taken from a hypothetical idea module. The purpose of this module would be to help creative minds, who often come up with ideas that cannot be pursued immediately, and are too easily forgotten if not logged somewhere. It could be used to record these ideas, sort them and rate them.
Note: Modular development OpenObject uses modules as feature containers, to foster maintainable and robust development. Modules provide feature isolation, an appropriate level of abstraction, and obvious MVC patterns.

Key component of OpenObject, the Object Service (OSV) implements a complete Object-Relational mapping layer, freeing developers from having to write basic SQL plumbing. Business objects are declared as Python classes inheriting from the osv.osv class, which makes them part of the OpenObject Model, and magically persisted by the ORM layer. Predefined attributes are used in the Python class to specify a business object's characteristics for the ORM:
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

idea.py:

Installing OpenERP
OpenERP is distributed as packages/installers for most platforms, but can of course be installed from the source on any platform.

Composition of a module

OpenERP Architecture

A module may contain any of the following elements: • business objects: declared as Python classes extending the osv.osv OpenObject class, the persistence of these resources is completely managed by OpenObject ; • data: XML/CSV files with meta-data (views and workflows declaration), configuration data (modules parametrization) and demo data (optional but recommended for testing, e.g. sample ideas) ; • wizards: stateful interactive forms used to assist users, often available as contextual actions on resources ; • reports: RML (XML format), MAKO or OpenOffice report templates, to be merged with any kind of business data, and generate HTML, ODT or PDF reports.

Typical module structure
OpenERP uses the well-known client-server paradigm, with different pieces of software acting as client and server depending on the desired configuration.Client software OpenERP provides a thick desktop client (GTK+) on all platforms, and a web interface is also accessible using any modern browser.
Tip: Installation procedure The procedure for installing OpenERP is likely to evolve (dependencies and so on), so make sure to always check the specific documentation (packaged & on website) for the latest procedures. See http://doc.openerp.com/install

Each module is contained in its own directory within the server/bin/addons directory in the server installation.
Note: You can declare your own add-ons directory in the configuration file of OpenERP (passed to the server with the -c option) using the addons_path option.
4 5 6 7 8 9 10 11 12 13 14 15

Package installation
Windows Linux Mac

all-in-one installer, and separate installers for server, client, and webserver are on the website openerp-server and openerp-client packages are available via corresponding package manager (e.g. Synaptic on Ubuntu) look online for package installers for the GTK client, as well as tutorials for installing the server (e.g. devteam.taktik.be)

addons/ |- idea/ |- demo/ |- i18n/ |- report/ |- security/ |- view/ |- wizard/ |- workflow/ |- __init__.py |- __terp__.py |- idea.py

# # # # # # # # # # #

The module directory Demo and unit test population data Translation files Report definitions Declaration of groups and access rights Views (forms,lists), menus and actions Wizards definitions Workflow definitions Python package initialization (required) module declaration (required) Python classes, the module's objects

from osv import osv, fields class idea(osv.osv): idea _name = 'idea.idea' _columns = { 'name': fields.char('Title', size=64, required=True, translate=True), 'state': fields.selection([('draft','Draft'), ('confirmed','Confirmed')],'State',required=True,readonly=True), # Description is read-only when not draft! 'description': fields.text('Description', readonly=True, states={'draft': [('readonly', False)]} ), 'active': fields.boolean('Active'), 'invent_date': fields.date('Invent date'), # by convention, many2one fields end with '_id' 'inventor_id': fields.many2one('res.partner','Inventor'), 'inventor_country_id': fields.related('inventor_id','country', readonly=True, type='many2one', relation='res.country', string='Country'), # by convention, *2many fields end with '_ids' 'vote_ids': fields.one2many('idea.vote','idea_id','Votes'), 'sponsor_ids': fields.many2many('res.partner','idea_sponsor_rel', 'idea_id','sponsor_id','Sponsors'), 'score': fields.float('Score',digits=(2,1)), 'category_id' = many2one('idea.category', 'Category'), } _defaults = { 'active': lambda *a: 1, # ideas are active by default 'state': lambda *a: 'draft', # ideas are in draft state by default } def _check_name(self,cr,uid,ids): for idea in self.browse(cr, uid, ids): if 'spam' in idea.name: return False # Can't create ideas with spam! return True _sql_constraints = [('name_uniq','unique(name)', 'Idea must be unique!')] _constraints = [(_check_name,'Please avoid spam in ideas !', ['name'])] idea() # Instantiate the class

Predefined osv.osv attributes for business objects
_name (required) _columns (required) _defaults _auto _inherit _inherits

business object name, in dot-notation (in module namespace) dictionary {field names → object fields declarations } dictionary: { field names → functions providing defaults }
_defaults['name'] = lambda self,cr,uid,context: 'eggs'

The __init__.py file is the Python module descriptor, because an OpenERP module is also a regular Python module.
16 17

__init__.py:

if True (default) the ORM will create the database table – set to False to create your own table/view within the init() method
_name of the parent business object (for prototype inheritance)

# Import all files & directories containing python code import idea, wizard, report

Installing from source

There are two alternatives: using a tarball provided on the website, or directly getting the source using Bazaar (distributed Source Version

The __terp__.py (or __openerp__.py as of v5.2) is the OpenERP descriptor and contains a single Python dictionary with the actual declaration of the module: its name, dependencies, description, and composition.
18 19

for multiple / instance inheritance mechanism: dictionary mapping the _name of the parent business objects to the names of the corresponding foreign key fields to use list of tuples defining the Python constraints, in the form
(func_name, message, fields). (→70)

__terp__.py:
{

_constraints

'name' : 'Idea',

Copyright © 2010 Open Object Press - All rights reserved – See license on page 7.

p.1/7

context) type: type of simulated field (any other type besides 'function') fnct_search: function used to search on this field def fnct_search(obj. obj.5])] obj: model _name of simulated field if it is a relational field store. used in conjunction with _parent_store flag on object..context=context): sum_vote = sum([v. digits=None.pool..partner'.…) Functional field simulating a real field. allows faster parent_right access to tree structures (see also Performance Optimization section) create_date.2/7 ..) time(..) text (string.. 'priority': fields.. id name active sequence state parent_id Inheritance mechanisms Field for storing a file or binary content.partner. not a decimal type.context=None): res = {} # This loop generates only 2 queries thanks to browse()! for idea in self . and functional. value. 4 fields (create_uid.. fnct_search=None..get('object_name') may be used to obtain a model class from anywhere Common parameters. ids.gif') unique system identifier for the object (created by ORM. fnct_inv_arg=None.Predefined osv.. date of creation and last update date of create_uid .date('Start Date'). cr. message). write_uid. [('id'. see PostgreSQL documentation obj: _name of destination object (required) field_id: field name of inverse many2one. field_name. view_load=None.translate=False. Relational fields represent the relationships between objects (one2many. reference(string. multi=False.3. 'set null '.. in the form (name. booleans. used for workflows defines tree structure on records.XX) function(fnct.. uid.'in'.ids. (created by ORM. cr. or single integer when there is only one id • context: optional dictionary of contextual parameters. field_id.'Partner'). filters=None. group_name=None. strings. it's a float.arg.function(_score_calc.. arg.uid. type='float'. disabled if _log_access flag is set to False write_date. fnct_inv_arg.contact'. associated with an assistant widget selection: model _name of allowed objects types and corresponding label (same format as values for selection fields) (required) • size: size of text column used to store it (as text: 'model_name..boolean('Active'). id. ondelete='set null'.All rights reserved – See license on page 7. …) (→56) Inheriting from the osv. f2. …) list of tuples defining the SQL constraints. .f2. context) returns a dictionary { ids→values } with values of type type fnct_inv: function used to write a value in the field instead def fnct_inv(obj. selection. obj=None.png. etc.. e.) integer(. relational.object_id' ) (required) 'contact': fields. (→69) If True (default).uid. set _rec_name to specify another field to use for this purpose defines visibility: records with active set to False are hidden by default defines order and allows drag&drop reordering if included in list views defines life-cycle stages for the object. used by multiple methods related (f1. create_date.osv objects • self.g. cr. write_date) will be used to log record-level operations. field2. parent_left .g.osv attributes for business objects _sql_constraints _log_access ORM fields types boolean(. rel. .) char(string... args) returns a list of tuples arguments for search(). …) 'active': fields. computed rather than stored • • • • • • ORM fields types Common attributes supported by all fields (optional unless specified) • • • • • string: field label (required) required: True if mandatory readonly: True if not editable help: help tooltip select: 1 to include in search • views and optimize for list filtering (with database index) context: dictionary with contextual parameters (for relational fields) • change_default: True if field should be usable as condition for default values in clients • states: dynamic changes to this field's common attributes based on the state field (→42.: chained fields to reach target (f1 required) (→51) • type: type of target field • • • cr: database connection (cursor) uid: id of user performing the operation ids: list of record ids. Simple types are integers. made accessible via osv's perm_read() function Name of the field used to sort the records in lists (default: 'id') Alternative field to use as name.field. ORM fields types property(obj.) Special / Reserved field names binary(string.idea' def _score_calc(self .osv class makes all the ORM methods available on business objects.g. uid.reference('Contact'. uid. ('res. or from outside the class by first obtaining an instance via the ORM pool system.size. string.. If digits Dynamic attribute with specific access rights • obj: object (required) • type: type of equivalent field one2many ↔ many2one are symmetric Tip: relational fields symmetry Floating-point value with arbitrary precision and scale Field allowing selection among a set of predefined values is not provided. …) Shortcut field equivalent to browsing chained fields • f1. . 'cascade'. i. used to log creator.[ ('res. size. used by osv's name_get() (default: 'name') SQL code to create the table/view for this object (if _auto is False) – can be replaced by SQL execution in the init() method SQL table name to use (default: _name with dots '.'Contact')].idea' _inherit = 'idea. …) (→50) • • • • • • • • domain: optional restriction in the form of arguments for search (see search()) obj: _name of destination object (required) ondelete: deletion handling.45) digits: tuple (precision. p.) _order _rec_name _sql _table translate: True if field values can be translated by users • size: maximum size for char fields (→41. filters='*.browse(cr. fnct_inv=None. and enables child_of operator Field with dynamic relationship to any other object.type='float'.vote_ids]) avg_vote = sum_vote/len(idea. name. …. } Copyright © 2010 Open Object Press . if missing. last updater. etc. sql_def. and in that case any field with that name will be ignored. translate=False... do not add them) write_uid Relationship towards a parent object (using a foreign key) Virtual relationship towards multiple objects (inverse of many2one) one2many(obj.) A few field names are reserved for pre-defined behavior in OpenObject.osv): idea2 _name = 'idea. Relevant examples in the idea class above are indicated with the corresponding line numbers (→XX...) date(. Some of them are created automatically by the system. such as user language e. name.binary('Picture'.' replaced by underscores '_') • • • • • Text-based fields float(string. 128) Relational fields Common attributes supported by relational fields many2one(obj. type='float'. values: list of values (key-label tuples) or function returning such a list (required) (→42) filters: optional filename filters • • • many2many ↔ many2many are symmetric when inversed (swap field1 and field2) one2many ↔ many2one + many2one ↔ one2many = many2many selection(values.46) Simple fields fnct: function to compute the field value (required) def fnct(self.ids. 'start_date': fields. many2one.vote_ids) res[idea. e. scale) (→58) . floats. Functional fields are not stored in the database but calculated on-the-fly as Python functions. type='float'.method=True) } idea2() OSV generic accessor ORM Methods on osv. do not add it) defines the value used by default to display the record in lists.id] = avg_vote return res _columns = { # Replace static score with average of votes 'score':fields..*.cr. arg=None.. These methods may be invoked on the self object within the Python class itself (see examples in the table below). the record. field1.. multi: optimization mechanisms (see usage in Performance Section) class idea2(osv.e. store=False.) 'picture': fields. method=False. 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 Bidirectional multiple relationship between objects ORM usage sample of the current object (required) • field2: name of field in rel table storing the id of the target object (required) Functional fields ORM field types Objects may contain 3 types of fields: simple. …) (→55) Working with the ORM corresponding foreign key (required) obj: _name of destination object (required) rel: relationship table to use (required) field1: name of field in rel table storing the id many2many(obj. .[1. many2many).integer('Priority'). { 'lang': 'en_US'..vote for v in idea.) datetime(.

"perm_unlink" "access_idea_idea". }) ORM Methods on osv. user.uid. ids. not their ids #Operators: =. idea. name)] + args. limit=80): ids = [] if name and len(name) == 2: ids = self. menu. fields. limit=limit.actions..fields_view_get(cr.pool. fields. ('name'. args=None. '|'. context=None) Duplicates record with given id updating it with defaults values. perms[0]. returning a dictionary with a datas matrix. context=None) before saving the duplicated object # Countries can be searched by code or name def name_search(self.name</field> <field name="view_type">form|tree</field> <field name="view_mode">form.perm_read(cr. ['name'.rng. operator. 42) print 'Idea description:'. '='.group_user". actions. p. current_module=''. limit=limit. must be unique action name (required) specific view to open (if missing.search(cr.All rights reserved – See license on page 7. 'description' : 'spam & eggs'.vote". limit: same as for search() ) Common CSV syntax CSV files can also be added in update_xml. uid. idea.menu record and connect it with a corresponding action via an ir. '!='. XML files declared in a module's update_xml attribute contain record declarations in the following form: <?xml version="1.model. 'ilike'.idea') form_view = idea_obj. each one describing a field of the business object fields_view_get(cr.cr.read(cr.access. >=.uid.]. using the CSV filename to determine the target object model. [('code'. }) • defaults: dictionary of field values to change export_data(cr. repeat for multiple values Returns: list of dictionaries with requested field values write(cr. ids.name=''. uid.write(cr. name=''.object_xml_id"/> <field name="field2" eval="ref('module. [42.osv): idea (. mode='init'. operator='ilike'. context=None. uid."model_id:id".0 "access_idea_vote"."model_idea_idea". values.0. action) support a specific set of child entities and attributes.act_window" id="action_id"> <field name="name">action. and the records will be inserted by the OSV's import_data() method.rng <file> records matching the criteria. 'n/a') To construct a module. repeat for multiple values reconnects with object's xml_id. <menuitem id="menu_id" parent="parent_menu_id" name="label" icon="icon-code" action="action_id" groups="groupname1.graph</field> <field name="target">new</field> <field name="search_view_id" ref="search_view_id"/> </record> • fields: list of field names state for recovery Returns: a dictionary of the default values for fields (set on the object class. according to a RelaxNG grammar."idea..2f' % vote."perm_write". like. order=None. id.year)) return res eval used instead of element content to provide value as a Python expression. ['name'.search(cr.code for vote in idea..id many2many_field many2many_field:id many2many_field. Returns: True copy(cr."base. *_uid fields are replaced Returns: a list of ownership dictionaries for each requested record with the name of the user • returned dictionaries contain: object id (id).operator='ilike'.model. ids. context=None) • fields: optional list of field names to return (default: all fields) results = self. • values: dictionary of field values for the record Creates a new record with the specified value Returns: id of the new record search(cr.create(cr.uid. Used when exporting data via client menu.osv objects create(cr.get('idea.43]. #in. uid.inventor_id.fields_get('name')['size'] == 64) 96 97 98 99 100 101 <record model="object_model_name2" id="object_xml_id2"> <field name="field1" ref="module. user. list allowed modes for viewing records (form. ids.name_get(cr.context=None) self.ids) 102 103 104 one2many_field/field creates one2many destination record and sets field value ir. returns only the number of Returns a dictionary describing the composition of the requested view (including inherited views and extensions) name_get (cr. set to tree for a tree view only if view_type is form. args. roles.id column containing identifiers for relationships reconnect many2one using name_search() reconnect many2one based on object's xml_id reconnect many2one based on object's database id reconnects via name_search(). access rights.act_window.0. <. child_of. defaults.name</field> <field name="view_id" ref="view_id"/> <field name="domain">[list of 3-tuples (max 250 characters)]</field> <field name="context">{context dictionary (max 250 characters)}</field> <field name="res_model">object. the main mechanism is to insert data records declaring the module interface components.country_id. view_id=None.uid.. [('name'.size=64) (.) def test_fields_get(self.tree.ui.ids): res = [] for r in self.cr.description print 'Inventor country code:'. • fields: list of field names context=None) Returns a dictionary of field dictionaries. 'partner_id': 24. <=.1.3/7 . 'inventor_id']) print 'Inventor:'. view_type='form'. highest priority view of given type is used) tuple (see search() arguments) for filtering the content of the view context dictionary to pass to the view object model on which the view to open is defined set to form to open records in edit mode. but all share the following special attributes: id ref the unique (per module) XML identifier of this record (xml_id) used instead of element content to reference another record (works cross-module by prepending the module name) Returns: list of ids of records matching the given criteria • • • • args: list of tuples specifying search criteria offset: optional number of records to skip limit : optional max number of records to • • return order: optional columns to sort by (default: self.cr. uid. allowing to use dot-notation to browse fields and relations Returns: object or list of objects requested default_get(cr. uid.43]) Deletes records with the given ids Returns: True browse(cr.0" encoding="utf-8"?> <openerp> <data> <record model="object_model_name" id="object_xml_id"> <field name="field1">value1</field> <field name="field2">value2</field> </record> id name view_id domain context res_model view_type view_mode target search_view_id identifier of the action in table ir. { 'name': 'spam & eggs'.) set to new to open the view in a new window identifier of the search view to replace default search form (new in version 5.uid): assert(self.object_xml_id')"/> </record> </data> </openerp> Each type of record (view.uid): idea_obj = self."base. context=None. creator user id (create_uid ). repeat for multiple values reconnects with object's database id. context=context) if not ids: ids = self. .calendar.uid. context=context) return self. uid.search(cr.) _columns = { 'name' : fields. uid.0. details=True) defs = self. '%s (%s)' (r['name']. The ORM automatically reconnects relationships based on the following special column names: id (xml_id) many2one_field many2one_field:id many2one_field."model_idea_vote". Equivalent of search() on name + name_get() Updates records with given ids with the given values. data.osv objects fields_get (cr.append((r['id'].) • toolbar: True to include contextual actions def test_fields_view_get(self. uid.'active']) # active should be True by default assert defs['active'] Tip: use read() through webservice calls. uid. order='partner_id' ) Returns tuples with the text representation of requested objects for to-many relationships name_search(cr. filename=None) False) to make exported data compatible with import_data() (may prevent exporting some fields) Actions are declared as regular records and can be triggered in 3 ways: • by clicking on menu items linked to a specific action • by clicking on buttons in views. uid.context={}._order ) • count: if True. count=False) idea_id = self. ids."name". 'inventor_id': 45. [ '|'. or via the context) perm_read(cr. uid. For manual check use xmllint: xmllint –relaxng /path/to/import_xml. found in server/bin/import_xml. import_data(cr. offset=0. uid.ids['name'.'create_date']) res.group_user". fields=None.0 • • fields: list of field names context may contain import_comp (default: Menus and actions self. { 'name': 'Spam recipe'.43]) print 'creator:'. fields=None. limit=80) read(cr. '!'. ids.idea".1."perm_read".uid) # Ideas should be shown with invention date def name_get(self.. >. that can use the ref() method to find the database id for a given xml_id Tip: XML RelaxNG validation OpenObject validates the syntax and structure of XML files.'tree'."group_id:id". user. context=None) • values: dictionary of field values to update Returns list of object names matching the criteria. limit=None.data record. ids.43]. uid.actions.vote Imports given data in the given module Used when exporting data via client menu • • • • • • fields: list of field names data: data to import (see export_data()) mode: 'init' or 'update' for record creation current_module : module name noupdate: flag for record creation filename: optional file to store partial import Action declaration <record model="ir. ('partner_id'. toolbar=False) class idea(osv. uid."perm_create".groupname2" sequence="10"/> id identifier of the menuitem. .default_get(cr.get('create_uid'. context=None.uid. uid. uid. must be unique Copyright © 2010 Open Object Press . name)] + args.read(cr. if these are connected to actions • as contextual actions on an object 105 106 107 108 109 110 111 112 113 114 115 Fetches records as objects."idea.0. 'spam'). !=.model. parent_right #Prefix operators: '&' (default).. tree. ilike. args=[]. context={}) view_id: id of the view or None view_type: type of view to return if view_id is None ('form'. context=None) idea = self. etc. Returns: True unlink(cr.context=None) ORM Methods on osv.unlink(cr. '!' #Fetch non-spam partner shops + partner 34 ids = self.. 34). creation date (create_date). [42. results[0]['inventor_id'] • • • name: object name to search for operator : operator for name criterion args. Each module element is a regular data record: menus.vote_ids: print 'Vote %2. updater user id (write_uid ).address[0].cr. fields. parent_left. by the user preferences.[42. not in. views.. values.2) 116 117 Menu declaration The menuitem entity is a shortcut for declaring an ir. uid. but always browse() internally Building the module interface Common XML structure 88 89 90 91 92 93 94 95 • details : if True. used to provide completion for to-many relationships. uid. [42. noupdate=False. update date (write_date) perms = self.char('Name'. uid.browse(cr. context=None) Exports fields for selected objects.csv "id". context=None.

level • level elements are used to define the Gantt chart levels. bottom. terp-graph.4/7 .'='. gantt (search is new in 5. float_time. Specific attributes: • type: type of button: workflow (default). with the enclosed field used as label for that drill-down level 166 167 168 169 170 <gantt string="Ideas" date_start="invent_date" color="inventor_id"> <level object="idea. label. with optional label newline place-holder for completing the current line of the view label free-text caption or legend in the form group used to organise fields in groups with optional label (adds frame) notebook. required based on search tuples on other field values field automatic widgets depending on the corresponding field type. smaller is higher (default: 16) architecture of the view. p. pie (default) orientation : horizontal. <tree>. tree. Attributes: • string: label of the field. are created with type tree. with specific behavior: • first field in view is X axis. 2 for advanced only • nolabel: 1 to hide the field label • required: override required field attribute • readonly: override readonly field attribute • password: True to hide characters typed in this field • context: Python code declaring a context dictionary • domain: Python code declaring list of tuples for restricting values • on_change: Python method call to trigger when value is changed • completion: 1 to enable auto-completion of values when possible • groups: comma-separated list of group (id) allowed to see this field • widget: select alternative widget (url.opernerp.view" id="view_id"> <field name="name">view. Several views of the same type can be declared on the same object. Allowed elements field. separator. all groups can see it) integer index for ordering sibling menuitems (10.search.idea" link="id" domain="[]"> <field name="inventor_id"/> </level> </gantt> Charts (Graphs) Attributes Views used to display statistical charts (<graph> parent element) Tip: charts are most useful with custom views extracting ready-to-use statistics • • type: type of chart: bar.calendar. graph. group. pricelistdependent prices) <search string="Search Ideas"> <group col="6" colspan="4"> <filter string="My Ideas" icon="terp-partner" domain="[('inventor_id'. if any icon to use for this menu (e. functions may be called by view elements (via buttons of type object.) Form Elements Calendars Attributes Views and inheritance Generic view declaration Views form a hierarchy. and are declared with the search type.uid)]" help="My own ideas"/> <field name="name" select="1"/> <field name="description" select="1"/> <field name="inventor_id" select="1"/> <!-.g. properties • • 175 176 177 178 179 180 181 182 183 184 185 186 187 filter elements allow defining button for domain filters adding a context attribute to fields makes widgets that alter the value domain a dictionary of field names and their updated values a dictionary of field names and their updated domains of value search context (useful for context-sensitive fields. <graph>.name</field> <field name="model">object_name</field> <field name="type">form</field> # tree. progressbar) properties dynamic widget showing all available properties (no attribute) button clickable widget associated with actions.2) Dynamic views In addition to what can be done with states and attrs attributes.max) 171 172 173 174 <graph string="Total idea score by Inventor" type="bar"> <field name="inventor_id" /> <field name="score" operator="+"/> </graph> Search views (new in v5. gtk-ok) separator horizontal separator line for structuring views. After defining a search view with a unique id.com) list of groups that can see this menu item (if missing. … --> </field> </record> id name model type priority arch unique view identifier view name object model on which the view is defined (same as res_model in actions) view type: form.*. see various view types below Forms 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 (to view/edit records) Forms allow creation/edition or resources.gantt <field name="priority" eval="16"/> <field name="arch" type="xml"> <!-.All rights reserved – See license on page 7. email.ui. left. 2nd one is Y. add it to the action opening the list view using the search_view_id field in its declaration. Attributes: page • name: label for the tab/page • position : tabs position in notebook (inside. 3rd one is Z • 2 fields required. text_wiki. and a top-level <search> element.g. button. search. hierarchies as a side toolbar (example: the menu) Allowed elements field. and correspond to <form> elements. and will be used depending on their priorities. and have a <tree> parent element.g. filter.parent name action icon groups sequence id of the parent menu in the hierarchy Optional menu label (default: action name) identifier of action to execute. also for search (overrides field name) • select: 1 to show the field in normal search. or action • name: workflow signal. These functions may alter the view interface by returning a Python map with the following entries: Search views are used to customize the search panel on top of list views.**. notebook elements are tab containers for page elements.20. group.min.graph. top. Allowed elements all (see form elements below) <form string="Idea form"> <group col="6" colspan="4"> <group colspan="5" col="6"> <field name="name" select="1" colspan="6"/> <field name="inventor_id" select="1"/> <field name="inventor_country_id" /> <field name="score" select="2"/> </group> <group colspan="1" col="2"> <field name="active"/><field name="invent_date"/> </group> </group> <notebook colspan="4"> <page string="General"> <separator string="Description"/> <field colspan="4" name="description" nolabel="1"/> </page> <page string="Votes"> <field colspan="4" name="vote_ids" nolabel="1" select="1"> <tree> <field name="partner_id"/> <field name="vote"/> </tree> </field> </page> <page string="Sponsors"> <field colspan="4" name="sponsor_ids" nolabel="1" select="1"/> </page> </notebook> <field name="state"/> <button name="do_confirm" string="Confirm" icon="gtk-ok" type="object"/> </form> Common attributes for all elements: • string: label of the element • nolabel: 1 to hide the field label • colspan: number of column on which the field must span • rowspan: number of rows on which the field must span • col: number of column this element must allocate to its child elements • invisible: 1 to hide this element completely • eval: evaluate this Python code as element content (content is string by default) • attrs: Python map defining dynamic conditions on these attributes: readonly. invisible .2) view priority. right) Views used to display date fields as calendar events (<calendar> parent) • • • • • color: name of field for color segmentation date_start: name of field containing event start date/time day_length: length of a calendar day in hours (default: 8) date_stop: name of field containing event stop date/time or date_delay: name of field containing event duration Allowed elements 163 164 165 field (to define the label for each calendar event) <calendar string="Ideas" date_start="invent_date" color="inventor_id"> <field name="name"/> </calendar> Gantt Charts Bar chart typically used to show project schedule (<gantt> parent element) same as <calendar> Attributes Allowed elements field.30.following context field is for illustration only --> <field name="inventor_country_id" select="1" widget="selection" context="{'inventor_country': self}"/> </group> </search> warning a dictionary with a title and message to show a warning dialog Lists/Trees Attributes Lists include field elements. newline 159 160 161 162 • • • colors: list of colors mapped to Python conditions editable: top or bottom to allow in-place edit toolbar : set to True to display the top level of object <tree string="Idea Categories" toolbar="1" colors="blue:state==draft"> <field name="name"/> <field name="state"/> </tree> Copyright © 2010 Open Object Press . function name (without parentheses) or action to call (depending on type) • confirm: text of confirmation message when clicked • states: comma-separated list of states in which this button is shown • icon: optional icon (all GTK STOCK icons e. vertical Allowed elements field. e. separator. text_html..form. see doc. or on_change attributes on fields) to obtain dynamic behavior. newline. search. reference. By declaring an inherited view it is possible to add/remove features in a view. tree. calendar. filter.view content: <form>. 3rd one is optional • group attribute defines the GROUP BY field (set to 1) • operator attribute sets the aggregation operator to use for other fields when one field is grouped (+. STOCK_OPEN. image. object. 118 119 120 121 122 123 124 125 126 <record model="ir.

send workitem on it (default) • OR: send workitems on all valid transitions (0 or more).parser=customClass) kind <!-. invoking action to determine the record id of the record for which the subflow should be instantiated. xsl auto header groups menu keywords • 188 189 190 191 192 193 194 195 196 197 198 replace: replace match • after: placed after match unique report identifier name for the report (required) report title (required) object model on which the report is defined (required) path to report template sources (starting from addons)."model_idea_idea". 204 205 206 207 208 209 210 211 212 213 214 215 Tip: RML User Guide: www.category. Workflows. xml.report" rml="idea/report/idea.view</field> <field name="inherit_id" ref="id_category_list"/> <field name="arch" type="xml"> <xpath expr="/tree/field[@name='description']" position="after"> <field name="idea_ids" string="Number of ideas"/> </xpath> </field> </record> set to False to suppress report header (default: True) comma-separated list of groups allowed to view this report set to True to link the report with the Print icon (default: True) specify report type keyword (default: client_print_multi) Reports There are several report engines in OpenERP. by subclassing report_sxw.2) double brackets content is evaluated as a Python expression based on the following expressions Security Access control mechanisms must be combined to achieve a coherent security policy. Wizards Wizards describe stateful interactive sessions with the user through dynamic forms. as usual.ids.view"> <field name="name">id. terminating the workflow when all items reach it logical behavior of this node regarding incoming transitions: • XOR: activate on the first incoming transition (default) • AND: waits for all incoming transitions to become valid Wizard objects (osv_memory) 237 238 239 240 241 242 243 244 In-memory objects are created by extending osv.reportlab. However even without a menu.read. act_from.0 templates (. the workitem is deleted. monetary=False) can be used to format a date.cr.xml model --> <report id="idea_report" string="Print Ideas" model="idea.csv "id". time or amount according id name osv on_create unique workflow record identifier name for the workflow (required) object model on which the workflow is defined (required) if True.actions.wizard' _columns = { 'idea_age': fields. Alternative Report Formats (see doc.integer('Age (in days)').5/7 ."base. triggers.0 "access_idea_vote".osv import datetime class cleanup_wizard(osv. objects may still be accessible indirectly."model_idea_vote". specifying the appropriate position .1.sxw) converted to RML with sxw2rml tool.ui. p.odt) used to produce directly OpenOffice documents (.score ]]</para></td> </tr> </blockTable> </story> subflow_id action logical behavior of this node regarding outgoing transitions: • XOR: one valid transition necessary.model.ui. receiving a workitem for each workflow instance True to make it an 'end' node. etc.1. and the RML rendered in HTML or PDF RML templates rendered directly as HTML or PDF XML data + XSL:RML stylesheets to generate RML OpenOffice templates (.rml_path.com) sxw2rml rml xml. to produce reports from different sources and in many formats. object_model. They are usually inserted via CSV files inside modules. depending on report set to False to use a custom parser.improved idea categories list --> <record id="idea_category_list2" model="ir.0 Roles 221 222 223 224 225 226 Workflow Activities (nodes) <record id="act_confirmed" model="workflow. and define transitions."idea. grouping=True."perm_unlink" "access_idea_idea".write.'var'.transition"> <field name="act_from" ref="act_draft"/> <field name="act_to" ref="act_confirmed"/> <field name="signal">button_confirm</field> <field name="role_id" ref="idea_manager"/> <field name="condition">1 == 1</field> </record> Workflows Workflows may be associated with any object in OpenERP. and may add or modify existing elements in the view by referencing them through XPath expressions. • stopall to terminate the workflow upon activation if kind subflow.View Inheritance 203 to generate the RML template file from a ."group_id:id"."base. uid. Tip: The Web client features a graphical workflow editor.idea".group_user".1.context={}): 199 200 201 202 Copyright © 2010 Open Object Press .osv_memory: from osv import fields.'tag') repeats the current parent element named tag for each object in list .uid. wizards make use of the osv_memory in-memory persistence to allow constructing wizards from regular business objects and views. making the object available as var during each loop • setTag('tag1'.cleanup.activity"> <field name="name">confirmed</field> <field name="wkf_id" ref="wkf_idea"/> <field name="kind">function</field> <field name="action">action_confirmed()</field> </record> Roles are created as normal records on the res.vote".basic</field> <field name="osv">idea.py id wkf_id name flow_start flow_stop join_mode • unique activity identifier parent workflow identifier activity node label True to make it a 'begin' node. 234 235 236 Expressions used in OpenERP report templates [[ <content> ]] Predefined expressions: • objects contains the list of records to print • data comes from the wizard launching the report • user contains the current user (as per browse()) • time gives access to Python time module • repeatIn(list. If action returns no result. uid.'o'. Workflow declaration 216 217 218 219 220 Workflows are declared on objects that possess a state field (see the example idea class in the ORM section) <record id="wkf_idea" model="workflow"> <field name="name">idea. via the Customise→Manage Workflows link in lists and forms. and granted menu access via menu definitions.w3. date_time=False. act_to signal role_id condition identifiers of the source and destination activities name of a button of type workflow that triggers this transition reference to the role that user must have to trigger the transition (see Roles) Python expression that must evaluate to True for transition to be triggered Special expressions used inside report templates produce dynamic data and/or modify the report structure at rendering time. As of OpenERP v5.unlink) must be defined for groups.org/TR/xpath position • inside: placed inside match (default) • before: placed before match id name string model rml.group_user".groups model. for a function kind: def action_confirmed(self. The tokens that navigate in workflows are called workitems."idea."model_id:id".pdf Example RML report extract: <story> <blockTable style="Table"> <tr> <td><para style="Title">Idea name</para> </td> <td><para style="Title">Score</para> </td> </tr> <tr> <td><para>[[ repeatIn(objects. date=False.report.rml" > <!-. e.1. It is also possible to restrict access to specific fields on a view or object using the field's groups attribute.odt) (As of OpenERP 5. ids. with graphical tools.'tag2') replaces the parent RML tag1 with tag2 • removeParentNode('tag') removes parent RML element tag • formatLang(value.Use addons/base_report_designer/wizard/tiny_sxw2rml/tiny_sxw2rml. An inherited view references its parent view using the inherit_id field.All rights reserved – See license on page 7."perm_create".0.osv_memory): cleanup_wizard _name = 'idea. Custom report parsers may be written to support additional expressions.sxw template --> split_mode Existing views should be modifying through inherited views.access.name ]]</para></td> <td><para>[[ o. never directly.com/docs/rml2pdf-userguide.The following creates records in ir.xsl:rml odt2odt mako OpenOffice 1."name". cr.write(cr. { 'state' : 'confirmed' }) # … perform other tasks return True Workflow Transitions (edges) 227 228 229 230 231 232 233 Conditions are evaluated in this order: role_id. digits=2.rml_parse and declaring the report as follows: report_sxw. and are entirely customizable. a workitem is instantiated automatically for each new osv record ir. to the locale setLang('lang_code') sets the current language and locale for translations Report declaration <!-.openerp. so actual object-level permissions (create.1.idea</field> <field name="on_create" eval="1"/> </record> Group-based access control mechanisms Groups are created as normal records on the res. Tip: XPath reference can be found at www. condition expression <record id="trans_idea_draft_confirmed" model="workflow. ids): self. sxw. This function should also update the state field of the object. by embedding Python code and OpenERP expressions within any text file (As of OpenERP 5."perm_write".report_sxw(report_name.1. signal.2) Mako template library used to produce HTML output."perm_read". activities (nodes or actions) and transitions (conditions) are declared as XML records. id of the subflow to execute (use ref attribute or search with a tuple) object method call. Workflows are used to structure and manage the lifecycles of business objects and documents.g. used if kind is function or subflow. } def cleanup(self. sequentially • AND: send a workitem on all valid transitions at once (fork) type of action to perform when node is activated by a transition: • dummy to perform no operation when activated (default) • function to invoke a function determined by action • subflow to execute the subflow with subflow_id.idea" name="idea.'tr') ]] [[ o.list2</field> <field name="model">ir.roles model and used only to condition workflow transitions through transitions' role_id attribute.

ids.form</field> <field name="model">idea. $msg->addParam(new xmlrpcval($arrayVal. PORT. for which libraries exist in many languages. to create the module template POT file.cleanup. } idea_id = sock. to construct dashboards. store = {'idea.USER. and setting _parent_store to True in your object class.ServerProxy(url) args = { 'name' : 'Another idea'.po | . $resp = $client->send($msg).date.function(_compute. "string")). fields.id] = { 'vote_sum': vote_sum.['vote']. p. put them before and access only the browsed objects inside the loop.i18n/ | .context={}): res = {} for idea in self. bug tracking.args) def _get_idea_from_vote(self.act_window"> <field name="name">Cleanup</field> <field name="type">ir. } Report Creator (view) and Report Designer (print) modules Community / Contributing OpenERP projects are hosted on LaunchPad(LP). .today()-datetime.idea'.uid) # Create a new idea url = 'http://%s:%d/xmlrpc/object' % (HOST.po or pt_BR. resp = $client->send($msg).and model-based mode where all changes performed after a given date on the given models (object types) are exported. where all operations (on business objects or user interface) are recorded until the recorder is stopped or paused.vote').view"> <field name="name">idea. string='Votes Average'. ).cleanup. $PASS $client = new xmlrpc_client("http://$HOST:$PORT/xmlrpc/common"). and recomputed on demand when the relevant trigger objects are modified. especially if you include them in tree views.6/7 . 278 279 280 281 282 283 285 284 286 287 288 289 290 291 292 293 Python example import xmlrpclib # .vote_ids) vote_sum = sum([v. PASS url = 'http://%s:%d/xmlrpc/common' % (HOST. define HOST.PORT) sock = xmlrpclib.10)}. which should then return a dictionary of values in its values map ◦ store: function fields with a store attribute will be stored in the database.. "string")). then export the module terms using OpenERP's gettext POT export feature (Administration>Translations>Export a Translation File without specifying a language). Translations will be loaded automatically by OpenERP for all enabled languages. "string")). The ORM will use a modified preorder tree traversal to be able to perform recursive operations (e. limit. 'vote_avg': (vote_sum/vote_num) if vote_num else 0.pot | . uid = $resp->value()->scalarval() echo "Logged in as $USER (uid:$uid)" // Create a new idea $arrayVal = array( 'name'=>new xmlrpcval("Another Idea". To optimize function fields. DB. $msg = new xmlrpcmsg('execute').idea_age) ids_to_del = idea_obj.vote': (_get_idea_from_vote. _('Label') ) Rapid Application Development Module recorder The base_module_record module can be used to export a set of changes in the form of a new module.act_window</field> <field name="res_model">idea. with a special target field used to open the wizard view in a new window.cleanup.idea_id. It should be used for all customizations that should be carried on through migrations and updates. 'inventor_id': uid. blueprints.. you may want to pay attention to the following antipatterns. pt.actions.execute(DB. but any Python string can be translated this way by surrounding it with the tools. "string")).fr. Tip: The GNU gettext format (Portable Object) used by OpenERP is integrated into LaunchPad. 'description' : 'This is another idea of mine'.vote': (_get_idea_from_vote. Many IDE's have plugins or modes for editing and merging PO/POT files.multi='votes').arg. e. "string")).po).net to be able to contribute.idea. child_of ) with database queries in O(1) instead of O(n) • Do not use function fields lightly. Create a free account on launchpad._ method (e.cr. $USER. available on sourceforge // .get('idea.PASS..uid.context=context) for v in vote_ids: res[v.ids_to_del) return {} cleanup_wizard() 317 318 319 320 $msg->addParam(new xmlrpcval("create".function(_compute. • Date.ids. <record id="wizard_idea_cleanup" model="ir. method=True.uid.uid.multi='votes').po where LANG is the locale code for the language.strftime('%Y-%m-%d 00:00:00'))].PORT) sock = xmlrpclib.. The resulting dashboards can then be exported using the base_module_record module. "struct")). The base_report_creator module can be used to automate the creation of custom statistics views. define $HOST.field_name. 'description'=>new xmlrpcval("This is another idea of mine" .context={}): res = {} vote_ids = self.idea". 'inventor_id'=>new xmlrpcval($uid.actions.browse(cr. to obtain consistent performance: • Do not place browse() calls inside loops.uid. "string")).PASS) print "Logged in as %s (uid:%d)" % (USER. by having files named LANG. • Avoid recursion on object hierarchies (objects with a parent_id relationship).ids.pool. Can commit on extra-addons branch Can confirm bugs and set milestones on bugs / blueprints Can create community branches where everyone can contribute 294 295 296 297 298 299 300 301 302 303 304 306 305 307 308 309 310 311 312 313 314 315 316 PHP example <? include('xmlrpc. $msg->addParam(new xmlrpcval("idea. WebServices – XML-RPC OpenERP is accessible through XML-RPC interfaces. $DB.ServerProxy(url) uid = sock. Can mark branches to be merged into official branch. "string")).'Please select a larger age') limit = datetime. The ORM will optimize the number of database queries based on the browsed attributes.id] = True # Store the idea identifiers in a set return res. roadmap.10)}. $PORT.All rights reserved – See license on page 7.pool.g. $msg->addParam(new xmlrpcval($DB. anyone can join Bazaar/LP restrictions Can merge and commit on official branches. Developers always use English when creating a module. "string"). $msg = new xmlrpcmsg("login").) # # # # # The module directory Translation files Translation Template (exported from OpenERP) French translation Brazilian Portuguese translation As Enterprise Management Software typically has to deal with large amounts of records. etc. $msg->addParam(new xmlrpcval($PASS.login(DB..uid.unlink(cr. $msg->addParam(new xmlrpcval($PASS. It has 2 modes: • Start/Pause/Stop mode.timedelta(days=wiz.ui. string='Votes Sum'. "int")). Launchpad groups Group* OpenERP Quality Team (~openerp) OpenERP Commiters (~openerp-commiter) OpenERP Drivers (~openerp-drivers) OpenERP Community (~openerp-community) Members OpenERP Core Team Selected active community members Selected active community members Open group. The format for the trigger specification is as follows: store = {'model': (_ref_fnct..ids): if wiz. and then derive the translated PO files.translate. <record id="action_idea_cleanup_wizard" model="ir. } return res _columns = { # These fields are recomputed whenever one of the votes changes 'vote_avg': fields.search(cr.context=context): vote_num = len(idea.0. "int").except_osv('UserError'.browse(cr.vote for v in idea.245 246 247 248 249 250 251 252 253 254 idea_obj = self.idea/ |.'idea. priority)} (see example below) 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 Tip: By default OpenERP's POT export only extracts labels inside XML files or inside field definitions in Python code. store = {'idea. method=True. 'vote_sum': fields. FAQs. where all project resources may be found: Bazaar branches.inc'). $msg->addParam(new xmlrpcval($uid.pt_BR. *Members of upper groups are also members of lower groups Copyright © 2010 Open Object Press .uid.browse(cr. $msg->addParam(new xmlrpcval($DB.wizard</field> <field name="view_type">form</field> <field name="view_mode">form</field> <field name="target">new</field> </record> |.idea') for wiz in self. or the language and country combination when they differ (e. two mechanisms are available: ◦ multi: all fields sharing the same multi attribute value will be computed with one single call to the function.context=context) idea_obj. // Use phpxmlrpc library.g. making it an online collaborative translation platform.'create'. USER. by adding parent_left and parent_right integer fields on your object.cr. "string") .wizard.uid.keys() def _compute(self.get('idea.g.vote_ids]) res[idea.ids.uid. [('create_date'.po | (. 321 322 323 324 325 326 Wizard execution 270 271 272 273 274 275 276 277 Such wizards are launched via regular action records.['vote']. $msg->addParam(new xmlrpcval($USER.idea_age <= 3: raise osv.wizard</field> <field name="type">form</field> <field name="arch" type="xml"> <form string="Idea Cleanup Wizard"> <label colspan="4" string="Select the age of ideas to cleanup"/> <field name="idea_age" string="Age (days)"/> <group colspan="4"> <button string="Cancel" special="cancel" icon="gtk-cancel"/> <button string="Cleanup" name="cleanup" type="object" icon="gtk-ok"/> </group> </form> </field> </record> Each module can provide its own translations within the i18n directory.g. '<' . ?> Performance Optimization Internationalization Views 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 Wizards use regular views and their buttons may use a special cancel attribute to close the wizard window when clicked.

Published by Open Object Press.All rights reserved – See license on page 7.a. Grand Rosière.License Copyright © 2010 Open Object Press. You can also print a copy to be read by yourself only. unless OpenERP s. All rights reserved. the publisher and the authors assume no responsibility for errors or omissions. (representing Open Object Press) gives you a written authorization for this. This helps to distribute and promote the Open ERP product. Due to this. or for damages resulting from the use of the information contained herein. modify or sell this work are strictly forbidden. Belgium Copyright © 2010 Open Object Press . It also helps us to create incentives to pay contributors and authors with the royalties.7/7 . p. You may take electronic copy of this work and distribute it if you don't change the content. grants to translate. We have contracts with different publishers in different countries to sell and distribute paper or electronic based versions of this work (translated or not) in bookstores. While every precaution has been taken in the preparation of this work.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->