[FIX] probably fix scrolling issue in left menu
[odoo/odoo.git] / doc / 03_module_dev_01.rst
index 2da148f..f35dab5 100644 (file)
-Module development
-==================
-
-Module Structure
-+++++++++++++++++
+.. _module-dev-structure:
+
+Module structure
+================
+
+A module can contain the following elements:
+
+ - **Business object** : declared as Python classes extending the class
+   osv.Model, the persistence of these resource is completly managed by
+   OpenERP's ORM.
+ - **Data** : XML/CSV files with meta-data (views and workflows declaration), 
+   configuration data (modules parametrization) and demo data (optional but 
+   recommended for testing),
+ - **Reports** : RML (XML format). HTML/MAKO or OpenOffice report templates, to
+   be merged with any kind of business data, and generate HTML, ODT or PDF
+   reports.
+
+.. figure:: _static/03_module_gen_view.png
+   :width: 75%
+   :alt: Module composition
+   :align: center
+   
+   Module composition
 
-All the modules are located in the source/addons directory. The following
-steps are necessary to create a new module:
+Each module is contained in its own directory within either the server/bin/addons 
+directory or another directory of addons, configured in server installation.
+To create a new module for example the 'OpenAcademy' module, the following
+steps are required:
 
-    * create a subdirectory in the source/addons directory
-    * create the import **__init__.py** file
-    * create a module description file: **__openerp__.py**
-    * create the **Python** file containing the **objects**
-    * create **.xml files** that create the data (views, menu entries, demo data, ...)
-    * optionally create **reports**, **wizards** or **workflows**.
+ - create a ``openacademy`` subdirectory in the source/addons directory
+ - create the module import file ``__init__.py``
+ - create the module manifield file ``__openerp__.py``
+ - create **Python** files containing **objects**
+ - create **.xml files** holding module data such as views, menu entries 
+   or demo data
+ - optionally create **reports** or **workflows**
 
-Python Module Descriptor File __init__.py
------------------------------------------
+Python import file __init__.py
+++++++++++++++++++++++++++++++
 
-The ``__init__.py`` file is, like any Python module, executed at the start
-of the program. It needs to import the Python files that need to be loaded.
+The ``__init__.py`` file is the Python import file, because an OpenERP module
+is also a regular Python module. The file should import all the other python
+file or submodules.
 
-So, if you create a "module.py" file, containing the description of your
-objects, you have to write one line in __init__.py::
+For example, if a module contains a single python file named ``openacademy.py``,
+the file should look like:
 
-    import module
+    import openacademy
 
-OpenERP Module Descriptor File __openerp__.py
----------------------------------------------
+Manifest file __openerp__.py
++++++++++++++++++++++++++++++++
 
 In the created module directory, you must add a **__openerp__.py** file.
-This file, which must be in Python format, is responsible to
+This file, which must be a Python dict literal, is responsible to
 
    1. determine the *XML files that will be parsed* during the initialization
       of the server, and also to
    2. determine the *dependencies* of the created module.
+   3. declare additional meta data
 
 This file must contain a Python dictionary with the following values:
 
-**name**
-
-    The (Plain English) name of the module.
-
-**version**
-
-    The version of the module.
-
-**description**
-
-    The module description (text).
-
-**author**
-
-    The author of the module.
-
-**website**
-
-    The website of the module.
-
-**license**
-
-    The license of the module (default:GPL-2).
+::
+
+  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.
+
+For the ``openacademy`` module, here is an example of ``__openerp__.py``
+declaration file:
 
-**depends**
-
-    List of modules on which this module depends. The base module must
-    almost always be in the dependencies because some necessary data for
-    the views, reports, ... are in the base module.
-
-**init_xml**
-
-    List of .xml files to load when the server is launched with the "--init=module"
-    argument. Filepaths must be relative to the directory where the module is.
-    OpenERP XML File Format is detailed in this section.
-
-**update_xml**
+.. code-block:: python
 
-    List of .xml files to load when the server is launched with the "--update=module"
-    launched. Filepaths must be relative to the directory where the module is.
-    OpenERP XML File Format is detailed in this section. The files in **update_xml**
-    concern: views, reports and wizards.
+    {
+        '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,
+    }
 
-**installable**
+Objects
++++++++
 
-    True or False. Determines if the module is installable or not.
+All OpenERP resources are objects: invoices, partners. Metadata are also object
+too: menus, actions, reports...  Object names are hierarchical, as in the
+following examples:
 
-**active**
+    * account.transfer : a money transfer
+    * account.invoice : an invoice
+    * account.invoice.line : an invoice line
 
-    True or False (default: False). Determines the modules that are installed
-    on the database creation.
+Generally, the first word is the name of the module: account, stock, sale.
 
-**Example**
+Those object are declared in python be subclassing osv.Model
 
-Here is an example of __openerp__.py file for the product module
+The ORM of OpenERP is constructed over PostgreSQL. It is thus possible to
+query the object used by OpenERP using the object interface (ORM) or by
+directly using SQL statements.
 
-.. code-block:: python
+But it is dangerous to write or read directly in the PostgreSQL database, as
+you will shortcut important steps like constraints checking or workflow
+modification.
 
-    {
-        "name" : "Products & Pricelists",
-        "version" : "1.1",
-        "author" : "Open",
-        "category" : "Generic Modules/Inventory Control",
-        "depends" : ["base", "account"],
-        "init_xml" : [],
-        "demo_xml" : ["product_demo.xml"],
-        "update_xml" : ["product_data.xml", "product_report.xml", "product_wizard.xml",
-                        "product_view.xml", "pricelist_view.xml"],
-        "installable": True,
-        "active": True
-    }
+.. .. figure::  images/pom_3_0_3.png
+..    :scale: 50
+..    :align: center
 
-The files that must be placed in init_xml are the ones that relate to the
-workflow definition, data to load at the installation of the software and
-the data for the demonstrations.
+..    *The Physical Objects Model of [OpenERP version 3.0.3]*
 
 
 XML Files
 +++++++++
 
-XML files located in the module directory are used to modify the structure of
-the database. They are used for many purposes, among which we can cite :
+XML files located in the module directory are used to initialize or update the
+the database when the module is installed or updated. They are used for many
+purposes, among which we can cite :
 
     * initialization and demonstration data declaration,
     * views declaration,
     * reports declaration,
-    * wizards declaration,
     * workflows declaration.
 
 General structure of OpenERP XML files is more detailed in the 
@@ -132,78 +151,113 @@ more about *initialization* and *demonstration data declaration* XML files. The
 following section are only related to XML specific to *actions, menu entries, 
 reports, wizards* and *workflows* declaration.
 
+Data can be inserted or updated into the PostgreSQL tables corresponding to the
+OpenERP objects using XML files. The general structure of an OpenERP XML file
+is as follows:
 
-Objects
-+++++++
+.. code-block:: xml
 
-All OpenERP resources are objects: menus, actions, reports, invoices, partners, ... OpenERP is based on an object relational mapping of a database to control the information. Object names are hierarchical, as in the following examples:
+   <?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>
 
-    * account.transfer : a money transfer
-    * account.invoice : an invoice
-    * account.invoice.line : an invoice line
+``<record>``
+////////////
 
-Generally, the first word is the name of the module: account, stock, sale.
+Defines a new record in a specified OpenERP model.
 
-Other advantages of an ORM;
+``@model`` (required)
 
-    * simpler relations : invoice.partner.address[0].city
-    * objects have properties and methods: invoice.pay(3400 EUR),
-    * inheritance, high level constraints, ...
+    Name of the model in which this record will be created/inserted.
 
-It is easier to manipulate one object (example, a partner) than several tables (partner address, categories, events, ...)
+``@id`` (optional)
 
+    :term:`external ID` for the record, also allows referring to this record in
+    the rest of this file or in other files (through ``field/@ref`` or the
+    :py:func:`ref() <openerp.tools.convert._ref>` function)
 
-.. figure::  images/pom_3_0_3.png
-   :scale: 50
-   :align: center
+A record tag generally contains multiple ``field`` tags specifying the values
+set on the record's fields when creating it. Fields left out will be set to
+their default value unless required.
 
-   *The Physical Objects Model of [OpenERP version 3.0.3]*
+``<field>``
+///////////
 
+In its most basic use, the ``field`` tag will set its body (as a string) as
+the value of the corresponding ``record``'s ``@name`` field.
 
-PostgreSQL and ORM
-------------------
+Extra attributes can either preprocess the body or replace its use entirely:
 
-The ORM of OpenERP is constructed over PostgreSQL. It is thus possible to
-query the object used by OpenERP using the object interface or by directly
-using SQL statements.
+``@name`` (mandatory)
 
-But it is dangerous to write or read directly in the PostgreSQL database, as
-you will shortcut important steps like constraints checking or workflow
-modification.
+    Name of the field in the containing ``record``'s model
 
-.. note::
+``@type`` (optional)
 
-    The Physical Database Model of OpenERP
+    One of ``char``, ``int``, ``float``, ``list``, ``tuple``, ``xml`` or
+    ``html``, ``file`` or ``base64``. Converts the ``field``'s body to the
+    specified type (or validates the body's content)
 
-Pre-Installed Data
-------------------
+    * ``xml`` will join multiple XML nodes under a single ``<data>`` root
+    * in ``xml`` and ``html``, external ids can be referenced using
+      ``%(id_name)s``
+    * ``list`` and ``tuple``'s element are specified using ``<value>``
+      sub-nodes with the same attributes as ``field``.
+    * ``file`` expects a module-local path and will save the path prefixed with
+      the current module's name, separated by a ``,`` (comma). For use with
+      :py:func:`~openerp.modules.module.get_module_resource`.
+    * ``base64`` expects binary data, encodes it to base64 and sets it. Mostly
+      useful with ``@file``
 
-Data can be inserted or updated into the PostgreSQL tables corresponding to the
-OpenERP objects using XML files. The general structure of an OpenERP XML file
-is as follows:
+``@file``
 
-.. code-block:: xml
+    Can be used with types ``char`` and ``base64``, sources the field's content
+    from the specified file instead of the field's text body.
 
-   <?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>
+``@model``
+
+    Model used for ``@search``'s search, or registry object put in context for
+    ``@eval``. Required if ``@search`` but optional if ``@eval``.
+
+``@eval`` (optional)
+
+    A Python expression evaluated to obtain the value to set on the record
+
+``@ref`` (optional)
+
+    Links to an other record through its :term:`external id`. The module prefix
+    may be ommitted to link to a record defined in the same module.
+
+``@search`` (optional)
+
+    Search domain (evaluated Python expression) into ``@model`` to get the
+    records to set on the field.
 
-Fields content are strings that must be encoded as *UTF-8* in XML files.
+    Sets all the matches found for m2m fields, the first id for other field
+    types.
+
+**Example**
+
+.. code-block:: xml
+
+    <record model="ir.actions.report.xml" id="l0">
+         <field name="model">account.invoice</field>
+         <field name="name">Invoices List</field>
+         <field name="report_name">account.invoice.list</field>
+         <field name="report_xsl">account/report/invoice.xsl</field>
+         <field name="report_xml">account/report/invoice.xml</field>
+    </record>
 
 Let's review an example taken from the OpenERP source (base_demo.xml in the base module):
 
@@ -250,47 +304,6 @@ The field **company_id** is a many-to-one relation from the user object to the c
 
 This is a classical example of the use of **search** in demo data: here we do not really care about which partner we want to use for the test, so we give an empty list. Notice the **model** attribute is currently mandatory.
 
-Record Tag
-//////////
-
-**Description**
-
-The addition of new data is made with the record tag. This one takes a mandatory attribute : model. Model is the object name where the insertion has to be done. The tag record can also take an optional attribute: id. If this attribute is given, a variable of this name can be used later on, in the same file, to make reference to the newly created resource ID.
-
-A record tag may contain field tags. They indicate the record's fields value. If a field is not specified the default value will be used.
-
-**Example**
-
-.. code-block:: xml
-
-    <record model="ir.actions.report.xml" id="l0">
-         <field name="model">account.invoice</field>
-         <field name="name">Invoices List</field>
-         <field name="report_name">account.invoice.list</field>
-         <field name="report_xsl">account/report/invoice.xsl</field>
-         <field name="report_xml">account/report/invoice.xml</field>
-    </record>
-
-Field tag
-/////////
-
-The attributes for the field tag are the following:
-
-name : mandatory
-  the field name
-
-eval : optional
-  python expression that indicating the value to add
-  
-ref
-  reference to an id defined in this file
-
-model
-  model to be looked up in the search
-
-search
-  a query
-
 Function tag
 ////////////
 
@@ -311,69 +324,9 @@ eval
 
     <function model="ir.ui.menu" name="search" eval="[[('name','=','Operations')]]"/>
 
-Getitem tag
-///////////
-
-Takes a subset of the evaluation of the last child node of the tag.
-
-type : mandatory
-  int or list
-
-index : mandatory
-  int or string (a key of a dictionary)
-
-**Example**
-
-Evaluates to the first element of the list of ids returned by the function node
-
-.. code-block:: xml
-
-    <getitem index="0" type="list">
-        <function model="ir.ui.menu" name="search" eval="[[('name','=','Operations')]]"/>
-    </getitem>
-
-i18n
-""""
-
-Improving Translations
-//////////////////////
-
-.. describe:: Translating in launchpad
-
-Translations are managed by
-the `Launchpad Web interface <https://translations.launchpad.net/openobject>`_. Here, you'll
-find the list of translatable projects.
-
-Please read the `FAQ <https://answers.launchpad.net/rosetta/+faqs>`_ before asking questions.
-
-.. describe:: Translating your own module
-
-.. versionchanged:: 5.0
-
-Contrary to the 4.2.x version, the translations are now done by module. So,
-instead of an unique ``i18n`` folder for the whole application, each module has
-its own ``i18n`` folder. In addition, OpenERP can now deal with ``.po`` [#f_po]_
-files as import/export format. The translation files of the installed languages
-are automatically loaded when installing or updating a module. OpenERP can also
-generate a .tgz archive containing well organised ``.po`` files for each selected
-module.
-
-.. [#f_po] http://www.gnu.org/software/autoconf/manual/gettext/PO-Files.html#PO-Files
-
-Process
-"""""""
-
-Defining the process
-////////////////////
-
-Through the interface and module recorder.
-Then, put the generated XML in your own module.
 
 Views
-"""""
-
-Technical Specifications - Architecture - Views
-///////////////////////////////////////////////
++++++
 
 Views are a way to represent the objects on the client side. They indicate to the client how to lay out the data coming from the objects on the screen.
 
@@ -400,9 +353,9 @@ When you open an invoice, here is the chain of operations followed by the client
     * The client asks (with XML-RPC) to the server what views are defined for the invoice object and what are the data it must show.
     * The client displays the form according to the view
 
-.. figure::  images/arch_view_use.png
-   :scale: 50
-   :align: center
+.. .. figure::  images/arch_view_use.png
+..    :scale: 50
+..    :align: center
 
 To develop new objects
 //////////////////////
@@ -416,43 +369,6 @@ OpenERP uses a flexible and powerful reporting system. Reports are generated eit
 
 Reports are described more in details in the `Reporting <http://openobject.com/wiki/index.php/Developers:Developper%27s_Book/Reports>`_ chapter.
 
-Wizards
-"""""""
-
-Here's an example of a .XML file that declares a wizard.
-
-.. code-block:: xml
-
-    <?xml version="1.0"?>
-    <openerp>
-        <data>
-         <wizard string="Employee Info"
-                 model="hr.employee"
-                 name="employee.info.wizard"
-                 id="wizard_employee_info"/>
-        </data>
-    </openerp>
-
-A wizard is declared using a wizard tag. See "Add A New Wizard" for more information about wizard XML.
-
-also you can add wizard in menu using following xml entry
-
-.. code-block:: xml
-
-    <?xml version="1.0"?>
-    </openerp>
-         <data>
-         <wizard string="Employee Info"
-                 model="hr.employee"
-                 name="employee.info.wizard"
-                 id="wizard_employee_info"/>
-         <menuitem
-                 name="Human Resource/Employee Info"
-                 action="wizard_employee_info"
-                 type="wizard"
-                 id="menu_wizard_employee_info"/>
-         </data>
-    </openerp>
 
 Workflow
 """"""""
@@ -468,9 +384,9 @@ The workflows describe these interactions with graphs. One or several workflows
 
 Below is an example workflow used for sale orders. It must generate invoices and shipments according to certain conditions.
 
-.. figure::  images/arch_workflow_sale.png
-   :scale: 85
-   :align: center
+.. .. figure::  images/arch_workflow_sale.png
+..    :scale: 85
+..    :align: center
 
 
 In this graph, the nodes represent the actions to be done:
@@ -491,107 +407,23 @@ The squared nodes represent other Workflows;
     * the shipping
 
 
-Profile Module
-++++++++++++++
-
-The purpose of a profile is to initialize OpenERP with a set of modules directly after the database has been created. A profile is a special kind of module that contains no code, only *dependencies on other modules*.
-
-In order to create a profile, you only have to create a new directory in server/addons (you *should* call this folder profile_modulename), in which you put an *empty* __init__.py file (as every directory Python imports must contain an __init__.py file), and a __openerp__.py whose structure is as follows :
-
-.. code-block:: python
-
-    {
-         "name":"''Name of the Profile'',
-         "version":"''Version String''",
-         "author":"''Author Name''",
-         "category":"Profile",
-         "depends":[''List of the modules to install with the profile''],
-         "demo_xml":[],
-         "update_xml":[],
-         "active":False,
-         "installable":True,
-    }
-
-Here's the code of the file source/addons/profile_tools/__openerp__.py,
-which corresponds to the tools profile in OpenERP.
-
-.. code-block:: python
-
-    {
-        "name" : "Miscellaneous Tools",
-        "version" : "1.0",
-        "depends" : ["base", "base_setup"],
-        "author" : "OpenERP SA",
-        "category" : "Hidden/Dependency",
-        'complexity': "easy",
-        "description": """
-    Installer for extra Hidden like lunch, survey, idea, share, etc.
-    ================================================================
-    
-    Makes the Extra Hidden Configuration available from where you can install
-    modules like share, lunch, pad, idea, survey and subscription.
-        """,
-        'website': 'http://www.openerp.com',
-        'init_xml': [],
-        'update_xml': [
-        ],
-        'demo_xml': [],
-        'installable': True,
-        'auto_install': False,
-        'certificate' : '00557100228403879621',
-        'images': ['images/config_extra_Hidden.jpeg'],
-    }
-
-
-
-
-
-Action creation
----------------
-
-Linking events to action
-++++++++++++++++++++++++
-
-The available type of events are:
-
-    * **client_print_multi** (print from a list or form)
-    * **client_action_multi** (action from a list or form)
-    * **tree_but_open** (double click on the item of a tree, like the menu)
-    * **tree_but_action** (action on the items of a tree) 
-
-To map an events to an action:
-
-.. code-block:: xml
-
-    <record model="ir.values" id="ir_open_journal_period">
-        <field name="key2">tree_but_open</field>
-        <field name="model">account.journal.period</field>
-        <field name="name">Open Journal</field>
-        <field name="value" eval="'ir.actions.wizard,%d'%action_move_journal_line_form_select"/>
-        <field name="object" eval="True"/>
-    </record>
+i18n
+----
 
-If you double click on a journal/period (object: account.journal.period), this will open the selected wizard. (id="action_move_journal_line_form_select").
+.. versionchanged:: 5.0
 
-You can use a res_id field to allow this action only if the user click on a specific object.
+Each module has its own ``i18n`` folder. In addition, OpenERP can now deal with
+``.po`` [#f_po]_ files as import/export format. The translation files of the
+installed languages are automatically loaded when installing or updating a
+module.
 
-.. code-block:: xml
+Translations are managed by the `Launchpad Web interface
+<https://translations.launchpad.net/openobject>`_. Here, you'll find the list
+of translatable projects.
 
-    <record model="ir.values" id="ir_open_journal_period">
-        <field name="key2">tree_but_open</field>
-        <field name="model">account.journal.period</field>
-        <field name="name">Open Journal</field>
-        <field name="value" eval="'ir.actions.wizard,%d'%action_move_journal_line_form_select"/>
-        <field name="res_id" eval="3"/>
-        <field name="object" eval="True"/>
-    </record>
+Please read the `FAQ <https://answers.launchpad.net/rosetta/+faqs>`_ before asking questions.
 
-The action will be triggered if the user clicks on the account.journal.period n°3.
 
-When you declare wizard, report or menus, the ir.values creation is automatically made with these tags:
+.. [#f_po] http://www.gnu.org/software/autoconf/manual/gettext/PO-Files.html#PO-Files
 
-  * <wizard... />
-  * <menuitem... />
-  * <report... /> 
 
-So you usually do not need to add the mapping by yourself.