# SOME DESCRIPTIVE TITLE. # Copyright (C) Odoo S.A. # This file is distributed under the same license as the Odoo package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Odoo 14.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-03-18 13:49+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../content/developer.rst:9 msgid "Developer" msgstr "" #: ../../content/developer.rst:11 msgid "Learn through tutorials and get help using reference guides." msgstr "" #: ../../content/developer/glossary.rst:5 msgid "Glossary" msgstr "" #: ../../content/developer/glossary.rst:8 msgid "external id" msgstr "" #: ../../content/developer/glossary.rst:9 msgid "external identifier" msgstr "" #: ../../content/developer/glossary.rst:10 msgid "external identifiers" msgstr "" #: ../../content/developer/glossary.rst:12 msgid "string identifier stored in ``ir.model.data``, can be used to refer to a record regardless of its database identifier during data imports or export/import roundtrips." msgstr "" #: ../../content/developer/glossary.rst:16 msgid "External identifiers are in the form :samp:`{module}.{id}` (e.g. ``account.invoice_graph``). From within a module, the :samp:`{module}.` prefix can be left out." msgstr "" #: ../../content/developer/glossary.rst:20 msgid "Sometimes referred to as \"xml id\" or ``xml_id`` as XML-based :ref:`reference/data` make extensive use of them." msgstr "" #: ../../content/developer/glossary.rst:22 msgid "format string" msgstr "" #: ../../content/developer/glossary.rst:24 msgid "inspired by `jinja variables`_, format strings allow more easily mixing literal content and computed content (expressions): content between ``{{`` and ``}}`` is interpreted as an expression and evaluated, other content is interpreted as literal strings and displayed as-is" msgstr "" #: ../../content/developer/glossary.rst:29 msgid "GIS" msgstr "" #: ../../content/developer/glossary.rst:30 msgid "Geographic Information System" msgstr "" #: ../../content/developer/glossary.rst:32 msgid "any computer system or subsystem to capture, store, manipulate, analyze, manage or present spatial and geographical data." msgstr "" #: ../../content/developer/glossary.rst:34 msgid "minified" msgstr "" #: ../../content/developer/glossary.rst:35 msgid "minification" msgstr "" #: ../../content/developer/glossary.rst:37 msgid "process of removing extraneous/non-necessary sections of files (comments, whitespace) and possibly recompiling them using equivalent but shorter structures (`ternary operator`_ instead of ``if/else``) in order to reduce network traffic" msgstr "" #: ../../content/developer/howtos.rst:5 msgid "Tutorials" msgstr "" #: ../../content/developer/howtos/backend.rst:7 msgid "Building a Module" msgstr "" #: ../../content/developer/howtos/backend.rst:11 msgid "This tutorial requires :ref:`having installed Odoo `" msgstr "" #: ../../content/developer/howtos/backend.rst:14 msgid "Start/Stop the Odoo server" msgstr "" #: ../../content/developer/howtos/backend.rst:16 msgid "Odoo uses a client/server architecture in which clients are web browsers accessing the Odoo server via RPC." msgstr "" #: ../../content/developer/howtos/backend.rst:19 msgid "Business logic and extension is generally performed on the server side, although supporting client features (e.g. new data representation such as interactive maps) can be added to the client." msgstr "" #: ../../content/developer/howtos/backend.rst:23 msgid "In order to start the server, simply invoke the command :ref:`odoo-bin ` in the shell, adding the full path to the file if necessary:" msgstr "" #: ../../content/developer/howtos/backend.rst:31 msgid "The server is stopped by hitting ``Ctrl-C`` twice from the terminal, or by killing the corresponding OS process." msgstr "" #: ../../content/developer/howtos/backend.rst:35 msgid "Build an Odoo module" msgstr "" #: ../../content/developer/howtos/backend.rst:37 msgid "Both server and client extensions are packaged as *modules* which are optionally loaded in a *database*." msgstr "" #: ../../content/developer/howtos/backend.rst:40 msgid "Odoo modules can either add brand new business logic to an Odoo system, or alter and extend existing business logic: a module can be created to add your country's accounting rules to Odoo's generic accounting support, while the next module adds support for real-time visualisation of a bus fleet." msgstr "" #: ../../content/developer/howtos/backend.rst:45 msgid "Everything in Odoo thus starts and ends with modules." msgstr "" #: ../../content/developer/howtos/backend.rst:48 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:52 msgid "Composition of a module" msgstr "" #: ../../content/developer/howtos/backend.rst:50 msgid "An Odoo module can contain a number of elements:" msgstr "" #: ../../content/developer/howtos/backend.rst:54 msgid "Business objects" msgstr "" #: ../../content/developer/howtos/backend.rst:53 msgid "Declared as Python classes, these resources are automatically persisted by Odoo based on their configuration" msgstr "" #: ../../content/developer/howtos/backend.rst:57 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:62 msgid ":ref:`Object views `" msgstr "" #: ../../content/developer/howtos/backend.rst:57 msgid "Definition of business objects UI display" msgstr "" #: ../../content/developer/howtos/backend.rst:65 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:70 msgid ":ref:`Data files `" msgstr "" #: ../../content/developer/howtos/backend.rst:60 msgid "XML or CSV files declaring the model metadata :" msgstr "" #: ../../content/developer/howtos/backend.rst:62 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:67 msgid ":ref:`views ` or :ref:`reports `," msgstr "" #: ../../content/developer/howtos/backend.rst:63 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:68 msgid "configuration data (modules parametrization, :ref:`security rules `)," msgstr "" #: ../../content/developer/howtos/backend.rst:64 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:69 msgid "demonstration data" msgstr "" #: ../../content/developer/howtos/backend.rst:65 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:70 msgid "and more" msgstr "" #: ../../content/developer/howtos/backend.rst:68 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:73 msgid ":ref:`Web controllers `" msgstr "" #: ../../content/developer/howtos/backend.rst:68 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:73 msgid "Handle requests from web browsers" msgstr "" #: ../../content/developer/howtos/backend.rst:71 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:76 msgid "Static web data" msgstr "" #: ../../content/developer/howtos/backend.rst:71 msgid "Images, CSS or javascript files used by the web interface or website" msgstr "" #: ../../content/developer/howtos/backend.rst:74 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:85 #: ../../content/developer/misc/other/guidelines.rst:32 msgid "Module structure" msgstr "" #: ../../content/developer/howtos/backend.rst:76 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:87 msgid "Each module is a directory within a *module directory*. Module directories are specified by using the :option:`--addons-path ` option." msgstr "" #: ../../content/developer/howtos/backend.rst:83 msgid "most command-line options can also be set using :ref:`a configuration file `" msgstr "" #: ../../content/developer/howtos/backend.rst:86 #: ../../content/developer/howtos/rdtraining/01_architecture.rst:91 msgid "An Odoo module is declared by its :ref:`manifest `." msgstr "" #: ../../content/developer/howtos/backend.rst:88 msgid "A module is also a `Python package `_ with a ``__init__.py`` file, containing import instructions for various Python files in the module." msgstr "" #: ../../content/developer/howtos/backend.rst:93 msgid "For instance, if the module has a single ``mymodule.py`` file ``__init__.py`` might contain::" msgstr "" #: ../../content/developer/howtos/backend.rst:98 msgid "Odoo provides a mechanism to help set up a new module, :ref:`odoo-bin ` has a subcommand :ref:`scaffold ` to create an empty module:" msgstr "" #: ../../content/developer/howtos/backend.rst:106 msgid "The command creates a subdirectory for your module, and automatically creates a bunch of standard files for a module. Most of them simply contain commented code or XML. The usage of most of those files will be explained along this tutorial." msgstr "" #: ../../content/developer/howtos/backend.rst:110 msgid "Module creation" msgstr "" #: ../../content/developer/howtos/backend.rst:112 msgid "Use the command line above to create an empty module Open Academy, and install it in Odoo." msgstr "" #: ../../content/developer/howtos/backend.rst:116 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:17 msgid "Object-Relational Mapping" msgstr "" #: ../../content/developer/howtos/backend.rst:118 msgid "A key component of Odoo is the :abbr:`ORM (Object-Relational Mapping)` layer. This layer avoids having to write most :abbr:`SQL (Structured Query Language)` by hand and provides extensibility and security services\\ [#rawsql]_." msgstr "" #: ../../content/developer/howtos/backend.rst:122 msgid "Business objects are declared as Python classes extending :class:`~odoo.models.Model` which integrates them into the automated persistence system." msgstr "" #: ../../content/developer/howtos/backend.rst:126 msgid "Models can be configured by setting a number of attributes at their definition. The most important attribute is :attr:`~odoo.models.Model._name` which is required and defines the name for the model in the Odoo system. Here is a minimally complete definition of a model::" msgstr "" #: ../../content/developer/howtos/backend.rst:137 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:107 msgid "Model fields" msgstr "" #: ../../content/developer/howtos/backend.rst:139 msgid "Fields are used to define what the model can store and where. Fields are defined as attributes on the model class::" msgstr "" #: ../../content/developer/howtos/backend.rst:150 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:212 msgid "Common Attributes" msgstr "" #: ../../content/developer/howtos/backend.rst:152 msgid "Much like the model itself, its fields can be configured, by passing configuration attributes as parameters::" msgstr "" #: ../../content/developer/howtos/backend.rst:157 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:236 msgid "Some attributes are available on all fields, here are the most common ones:" msgstr "" #: ../../content/developer/howtos/backend.rst:159 msgid ":attr:`~odoo.fields.Field.string` (``unicode``, default: field's name)" msgstr "" #: ../../content/developer/howtos/backend.rst:160 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:239 msgid "The label of the field in UI (visible by users)." msgstr "" #: ../../content/developer/howtos/backend.rst:162 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:241 msgid ":attr:`~odoo.fields.Field.required` (``bool``, default: ``False``)" msgstr "" #: ../../content/developer/howtos/backend.rst:162 msgid "If ``True``, the field can not be empty, it must either have a default value or always be given a value when creating a record." msgstr "" #: ../../content/developer/howtos/backend.rst:164 msgid ":attr:`~odoo.fields.Field.help` (``unicode``, default: ``''``)" msgstr "" #: ../../content/developer/howtos/backend.rst:165 msgid "Long-form, provides a help tooltip to users in the UI." msgstr "" #: ../../content/developer/howtos/backend.rst:167 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:246 msgid ":attr:`~odoo.fields.Field.index` (``bool``, default: ``False``)" msgstr "" #: ../../content/developer/howtos/backend.rst:167 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:246 msgid "Requests that Odoo create a `database index`_ on the column." msgstr "" #: ../../content/developer/howtos/backend.rst:170 msgid "Simple fields" msgstr "" #: ../../content/developer/howtos/backend.rst:172 msgid "There are two broad categories of fields: \"simple\" fields which are atomic values stored directly in the model's table and \"relational\" fields linking records (of the same model or of different models)." msgstr "" #: ../../content/developer/howtos/backend.rst:176 msgid "Example of simple fields are :class:`~odoo.fields.Boolean`, :class:`~odoo.fields.Date`, :class:`~odoo.fields.Char`." msgstr "" #: ../../content/developer/howtos/backend.rst:180 msgid "Reserved fields" msgstr "" #: ../../content/developer/howtos/backend.rst:182 msgid "Odoo creates a few fields in all models\\ [#autofields]_. These fields are managed by the system and shouldn't be written to. They can be read if useful or necessary:" msgstr "" #: ../../content/developer/howtos/backend.rst:186 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:272 msgid ":attr:`~odoo.fields.Model.id` (:class:`~odoo.fields.Id`)" msgstr "" #: ../../content/developer/howtos/backend.rst:187 msgid "The unique identifier for a record in its model." msgstr "" #: ../../content/developer/howtos/backend.rst:188 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:274 msgid ":attr:`~odoo.fields.Model.create_date` (:class:`~odoo.fields.Datetime`)" msgstr "" #: ../../content/developer/howtos/backend.rst:189 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:275 msgid "Creation date of the record." msgstr "" #: ../../content/developer/howtos/backend.rst:190 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:276 msgid ":attr:`~odoo.fields.Model.create_uid` (:class:`~odoo.fields.Many2one`)" msgstr "" #: ../../content/developer/howtos/backend.rst:191 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:277 msgid "User who created the record." msgstr "" #: ../../content/developer/howtos/backend.rst:192 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:278 msgid ":attr:`~odoo.fields.Model.write_date` (:class:`~odoo.fields.Datetime`)" msgstr "" #: ../../content/developer/howtos/backend.rst:193 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:279 msgid "Last modification date of the record." msgstr "" #: ../../content/developer/howtos/backend.rst:195 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:282 msgid ":attr:`~odoo.fields.Model.write_uid` (:class:`~odoo.fields.Many2one`)" msgstr "" #: ../../content/developer/howtos/backend.rst:195 msgid "user who last modified the record." msgstr "" #: ../../content/developer/howtos/backend.rst:198 msgid "Special fields" msgstr "" #: ../../content/developer/howtos/backend.rst:200 msgid "By default, Odoo also requires a ``name`` field on all models for various display and search behaviors. The field used for these purposes can be overridden by setting :attr:`~odoo.models.Model._rec_name`." msgstr "" #: ../../content/developer/howtos/backend.rst:204 msgid "Define a model" msgstr "" #: ../../content/developer/howtos/backend.rst:206 msgid "Define a new data model *Course* in the *openacademy* module. A course has a title and a description. Courses must have a title." msgstr "" #: ../../content/developer/howtos/backend.rst:210 msgid "Data files" msgstr "" #: ../../content/developer/howtos/backend.rst:212 msgid "Odoo is a highly data driven system. Although behavior is customized using Python_ code part of a module's value is in the data it sets up when loaded." msgstr "" #: ../../content/developer/howtos/backend.rst:215 msgid "some modules exist solely to add data into Odoo" msgstr "" #: ../../content/developer/howtos/backend.rst:218 msgid "Module data is declared via :ref:`data files `, XML files with ```` elements. Each ```` element creates or updates a database record." msgstr "" #: ../../content/developer/howtos/backend.rst:232 msgid "``model`` is the name of the Odoo model for the record." msgstr "" #: ../../content/developer/howtos/backend.rst:233 msgid "``id`` is an :term:`external identifier`, it allows referring to the record (without having to know its in-database identifier)." msgstr "" #: ../../content/developer/howtos/backend.rst:235 msgid "```` elements have a ``name`` which is the name of the field in the model (e.g. ``description``). Their body is the field's value." msgstr "" #: ../../content/developer/howtos/backend.rst:238 msgid "Data files have to be declared in the manifest file to be loaded, they can be declared in the ``'data'`` list (always loaded) or in the ``'demo'`` list (only loaded in demonstration mode)." msgstr "" #: ../../content/developer/howtos/backend.rst:242 msgid "Define demonstration data" msgstr "" #: ../../content/developer/howtos/backend.rst:244 msgid "Create demonstration data filling the *Courses* model with a few demonstration courses." msgstr "" #: ../../content/developer/howtos/backend.rst:247 msgid "The content of the data files is only loaded when a module is installed or updated." msgstr "" #: ../../content/developer/howtos/backend.rst:250 msgid "After making some changes, do not forget to use :ref:`odoo-bin -u openacademy ` to save the changes to your database." msgstr "" #: ../../content/developer/howtos/backend.rst:257 msgid "Actions and Menus" msgstr "" #: ../../content/developer/howtos/backend.rst:259 msgid "Actions and menus are regular records in database, usually declared through data files. Actions can be triggered in three ways:" msgstr "" #: ../../content/developer/howtos/backend.rst:262 #: ../../content/developer/howtos/rdtraining/06_firstui.rst:63 msgid "by clicking on menu items (linked to specific actions)" msgstr "" #: ../../content/developer/howtos/backend.rst:263 #: ../../content/developer/howtos/rdtraining/06_firstui.rst:64 msgid "by clicking on buttons in views (if these are connected to actions)" msgstr "" #: ../../content/developer/howtos/backend.rst:264 #: ../../content/developer/howtos/rdtraining/06_firstui.rst:65 msgid "as contextual actions on object" msgstr "" #: ../../content/developer/howtos/backend.rst:266 msgid "Because menus are somewhat complex to declare there is a ```` shortcut to declare an ``ir.ui.menu`` and connect it to the corresponding action more easily." msgstr "" #: ../../content/developer/howtos/backend.rst:283 msgid "The action must be declared before its corresponding menu in the XML file." msgstr "" #: ../../content/developer/howtos/backend.rst:285 msgid "Data files are executed sequentially, the action's ``id`` must be present in the database before the menu can be created." msgstr "" #: ../../content/developer/howtos/backend.rst:288 msgid "Define new menu entries" msgstr "" #: ../../content/developer/howtos/backend.rst:290 msgid "Define new menu entries to access courses under the OpenAcademy menu entry. A user should be able to :" msgstr "" #: ../../content/developer/howtos/backend.rst:293 msgid "display a list of all the courses" msgstr "" #: ../../content/developer/howtos/backend.rst:294 msgid "create/modify courses" msgstr "" #: ../../content/developer/howtos/backend.rst:297 msgid "Basic views" msgstr "" #: ../../content/developer/howtos/backend.rst:299 msgid "Views define the way the records of a model are displayed. Each type of view represents a mode of visualization (a list of records, a graph of their aggregation, …). Views can either be requested generically via their type (e.g. *a list of partners*) or specifically via their id. For generic requests, the view with the correct type and the lowest priority will be used (so the lowest-priority view of each type is the default view for that type)." msgstr "" #: ../../content/developer/howtos/backend.rst:307 msgid ":ref:`View inheritance ` allows altering views declared elsewhere (adding or removing content)." msgstr "" #: ../../content/developer/howtos/backend.rst:311 msgid "Generic view declaration" msgstr "" #: ../../content/developer/howtos/backend.rst:313 msgid "A view is declared as a record of the model ``ir.ui.view``. The view type is implied by the root element of the ``arch`` field:" msgstr "" #: ../../content/developer/howtos/backend.rst:327 msgid "The view's content is XML." msgstr "" #: ../../content/developer/howtos/backend.rst:330 msgid "The ``arch`` field must thus be declared as ``type=\"xml\"`` to be parsed correctly." msgstr "" #: ../../content/developer/howtos/backend.rst:334 #: ../../content/developer/howtos/backend.rst:855 msgid "Tree views" msgstr "" #: ../../content/developer/howtos/backend.rst:336 msgid "Tree views, also called list views, display records in a tabular form." msgstr "" #: ../../content/developer/howtos/backend.rst:338 msgid "Their root element is ````. The simplest form of the tree view simply lists all the fields to display in the table (each field as a column):" msgstr "" #: ../../content/developer/howtos/backend.rst:351 msgid "Form views" msgstr "" #: ../../content/developer/howtos/backend.rst:353 #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:85 msgid "Forms are used to create and edit single records." msgstr "" #: ../../content/developer/howtos/backend.rst:356 msgid "Their root element is ``
``. They are composed of high-level structure elements (groups, notebooks) and interactive elements (buttons and fields):" msgstr "" #: ../../content/developer/howtos/backend.rst:385 msgid "Customise form view using XML" msgstr "" #: ../../content/developer/howtos/backend.rst:387 msgid "Create your own form view for the Course object. Data displayed should be: the name and the description of the course." msgstr "" #: ../../content/developer/howtos/backend.rst:390 msgid "Notebooks" msgstr "" #: ../../content/developer/howtos/backend.rst:392 msgid "In the Course form view, put the description field under a tab, such that it will be easier to add other tabs later, containing additional information." msgstr "" #: ../../content/developer/howtos/backend.rst:396 msgid "Form views can also use plain HTML for more flexible layouts:" msgstr "" #: ../../content/developer/howtos/backend.rst:423 #: ../../content/developer/howtos/backend.rst:928 #: ../../content/developer/howtos/backend.rst:970 msgid "Search views" msgstr "" #: ../../content/developer/howtos/backend.rst:425 msgid "Search views customize the search field associated with the list view (and other aggregated views). Their root element is ```` and they're composed of fields defining which fields can be searched on:" msgstr "" #: ../../content/developer/howtos/backend.rst:436 msgid "If no search view exists for the model, Odoo generates one which only allows searching on the ``name`` field." msgstr "" #: ../../content/developer/howtos/backend.rst:439 msgid "Search courses" msgstr "" #: ../../content/developer/howtos/backend.rst:441 msgid "Allow searching for courses based on their title or their description." msgstr "" #: ../../content/developer/howtos/backend.rst:444 #: ../../content/developer/howtos/website.rst:644 msgid "Relations between models" msgstr "" #: ../../content/developer/howtos/backend.rst:446 msgid "A record from a model may be related to a record from another model. For instance, a sale order record is related to a client record that contains the client data; it is also related to its sale order line records." msgstr "" #: ../../content/developer/howtos/backend.rst:450 msgid "Create a session model" msgstr "" #: ../../content/developer/howtos/backend.rst:452 msgid "For the module Open Academy, we consider a model for *sessions*: a session is an occurrence of a course taught at a given time for a given audience." msgstr "" #: ../../content/developer/howtos/backend.rst:455 msgid "Create a model for *sessions*. A session has a name, a start date, a duration and a number of seats. Add an action and a menu item to display them. Make the new model visible via a menu item." msgstr "" #: ../../content/developer/howtos/backend.rst:460 #: ../../content/developer/reference/javascript/javascript_reference.rst:2054 msgid "Relational fields" msgstr "" #: ../../content/developer/howtos/backend.rst:462 msgid "Relational fields link records, either of the same model (hierarchies) or between different models." msgstr "" #: ../../content/developer/howtos/backend.rst:465 msgid "Relational field types are:" msgstr "" #: ../../content/developer/howtos/backend.rst:472 msgid ":class:`Many2one(other_model, ondelete='set null') `" msgstr "" #: ../../content/developer/howtos/backend.rst:468 msgid "A simple link to an other object::" msgstr "" #: ../../content/developer/howtos/backend.rst:472 msgid "`foreign keys `_" msgstr "" #: ../../content/developer/howtos/backend.rst:486 msgid ":class:`One2many(other_model, related_field) `" msgstr "" #: ../../content/developer/howtos/backend.rst:475 msgid "A virtual relationship, inverse of a :class:`~odoo.fields.Many2one`. A :class:`~odoo.fields.One2many` behaves as a container of records, accessing it results in a (possibly empty) set of records::" msgstr "" #: ../../content/developer/howtos/backend.rst:484 msgid "Because a :class:`~odoo.fields.One2many` is a virtual relationship, there *must* be a :class:`~odoo.fields.Many2one` field in the :samp:`{other_model}`, and its name *must* be :samp:`{related_field}`" msgstr "" #: ../../content/developer/howtos/backend.rst:494 msgid ":class:`Many2many(other_model) `" msgstr "" #: ../../content/developer/howtos/backend.rst:489 msgid "Bidirectional multiple relationship, any record on one side can be related to any number of records on the other side. Behaves as a container of records, accessing it also results in a possibly empty set of records::" msgstr "" #: ../../content/developer/howtos/backend.rst:496 msgid "Many2one relations" msgstr "" #: ../../content/developer/howtos/backend.rst:498 msgid "Using a many2one, modify the *Course* and *Session* models to reflect their relation with other models:" msgstr "" #: ../../content/developer/howtos/backend.rst:501 msgid "A course has a *responsible* user; the value of that field is a record of the built-in model ``res.users``." msgstr "" #: ../../content/developer/howtos/backend.rst:503 msgid "A session has an *instructor*; the value of that field is a record of the built-in model ``res.partner``." msgstr "" #: ../../content/developer/howtos/backend.rst:505 msgid "A session is related to a *course*; the value of that field is a record of the model ``openacademy.course`` and is required." msgstr "" #: ../../content/developer/howtos/backend.rst:507 msgid "Adapt the views." msgstr "" #: ../../content/developer/howtos/backend.rst:509 msgid "Inverse one2many relations" msgstr "" #: ../../content/developer/howtos/backend.rst:511 msgid "Using the inverse relational field one2many, modify the models to reflect the relation between courses and sessions." msgstr "" #: ../../content/developer/howtos/backend.rst:514 msgid "Multiple many2many relations" msgstr "" #: ../../content/developer/howtos/backend.rst:516 msgid "Using the relational field many2many, modify the *Session* model to relate every session to a set of *attendees*. Attendees will be represented by partner records, so we will relate to the built-in model ``res.partner``. Adapt the views accordingly." msgstr "" #: ../../content/developer/howtos/backend.rst:522 #: ../../content/developer/reference/addons/views.rst:184 #: ../../content/developer/reference/javascript/javascript_reference.rst:412 msgid "Inheritance" msgstr "" #: ../../content/developer/howtos/backend.rst:525 msgid "Model inheritance" msgstr "" #: ../../content/developer/howtos/backend.rst:527 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:108 msgid "Odoo provides two *inheritance* mechanisms to extend an existing model in a modular way." msgstr "" #: ../../content/developer/howtos/backend.rst:530 msgid "The first inheritance mechanism allows a module to modify the behavior of a model defined in another module:" msgstr "" #: ../../content/developer/howtos/backend.rst:533 msgid "add fields to a model," msgstr "" #: ../../content/developer/howtos/backend.rst:534 msgid "override the definition of fields on a model," msgstr "" #: ../../content/developer/howtos/backend.rst:535 msgid "add constraints to a model," msgstr "" #: ../../content/developer/howtos/backend.rst:536 msgid "add methods to a model," msgstr "" #: ../../content/developer/howtos/backend.rst:537 msgid "override existing methods on a model." msgstr "" #: ../../content/developer/howtos/backend.rst:539 msgid "The second inheritance mechanism (delegation) allows to link every record of a model to a record in a parent model, and provides transparent access to the fields of the parent record." msgstr "" #: ../../content/developer/howtos/backend.rst:548 msgid ":attr:`~odoo.models.Model._inherit`" msgstr "" #: ../../content/developer/howtos/backend.rst:549 msgid ":attr:`~odoo.models.Model._inherits`" msgstr "" #: ../../content/developer/howtos/backend.rst:552 msgid "View inheritance" msgstr "" #: ../../content/developer/howtos/backend.rst:554 msgid "Instead of modifying existing views in place (by overwriting them), Odoo provides view inheritance where children \"extension\" views are applied on top of root views, and can add or remove content from their parent." msgstr "" #: ../../content/developer/howtos/backend.rst:558 msgid "An extension view references its parent using the ``inherit_id`` field, and instead of a single view its ``arch`` field is composed of any number of ``xpath`` elements selecting and altering the content of their parent view:" msgstr "" #: ../../content/developer/howtos/backend.rst:579 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:197 msgid "``expr``" msgstr "" #: ../../content/developer/howtos/backend.rst:579 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:197 msgid "An XPath_ expression selecting a single element in the parent view. Raises an error if it matches no element or more than one" msgstr "" #: ../../content/developer/howtos/backend.rst:595 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:213 msgid "``position``" msgstr "" #: ../../content/developer/howtos/backend.rst:582 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:200 msgid "Operation to apply to the matched element:" msgstr "" #: ../../content/developer/howtos/backend.rst:584 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:202 msgid "``inside``" msgstr "" #: ../../content/developer/howtos/backend.rst:585 msgid "appends ``xpath``'s body at the end of the matched element" msgstr "" #: ../../content/developer/howtos/backend.rst:587 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:205 #: ../../content/developer/reference/addons/views.rst:282 #: ../../content/developer/reference/javascript/qweb.rst:530 msgid "``replace``" msgstr "" #: ../../content/developer/howtos/backend.rst:587 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:205 msgid "replaces the matched element with the ``xpath``'s body, replacing any ``$0`` node occurrence in the new body with the original element" msgstr "" #: ../../content/developer/howtos/backend.rst:589 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:207 #: ../../content/developer/reference/addons/views.rst:288 #: ../../content/developer/reference/javascript/qweb.rst:524 msgid "``before``" msgstr "" #: ../../content/developer/howtos/backend.rst:590 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:208 msgid "inserts the ``xpath``'s body as a sibling before the matched element" msgstr "" #: ../../content/developer/howtos/backend.rst:591 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:209 #: ../../content/developer/reference/addons/views.rst:285 #: ../../content/developer/reference/javascript/qweb.rst:526 msgid "``after``" msgstr "" #: ../../content/developer/howtos/backend.rst:592 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:210 msgid "inserts the ``xpaths``'s body as a sibling after the matched element" msgstr "" #: ../../content/developer/howtos/backend.rst:595 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:213 #: ../../content/developer/reference/addons/views.rst:308 #: ../../content/developer/reference/javascript/qweb.rst:535 msgid "``attributes``" msgstr "" #: ../../content/developer/howtos/backend.rst:594 msgid "alters the attributes of the matched element using special ``attribute`` elements in the ``xpath``'s body" msgstr "" #: ../../content/developer/howtos/backend.rst:599 msgid "When matching a single element, the ``position`` attribute can be set directly on the element to be found. Both inheritances below will give the same result." msgstr "" #: ../../content/developer/howtos/backend.rst:613 msgid "Alter existing content" msgstr "" #: ../../content/developer/howtos/backend.rst:615 msgid "Using model inheritance, modify the existing *Partner* model to add an ``instructor`` boolean field, and a many2many field that corresponds to the session-partner relation" msgstr "" #: ../../content/developer/howtos/backend.rst:618 msgid "Using view inheritance, display this fields in the partner form view" msgstr "" #: ../../content/developer/howtos/backend.rst:621 #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:193 msgid "Domains" msgstr "" #: ../../content/developer/howtos/backend.rst:623 msgid "In Odoo, :ref:`reference/orm/domains` are values that encode conditions on records. A domain is a list of criteria used to select a subset of a model's records. Each criteria is a triple with a field name, an operator and a value." msgstr "" #: ../../content/developer/howtos/backend.rst:627 msgid "For instance, when used on the *Product* model the following domain selects all *services* with a unit price over *1000*::" msgstr "" #: ../../content/developer/howtos/backend.rst:632 msgid "By default criteria are combined with an implicit AND. The logical operators ``&`` (AND), ``|`` (OR) and ``!`` (NOT) can be used to explicitly combine criteria. They are used in prefix position (the operator is inserted before its arguments rather than between). For instance to select products \"which are services *OR* have a unit price which is *NOT* between 1000 and 2000\"::" msgstr "" #: ../../content/developer/howtos/backend.rst:644 msgid "A ``domain`` parameter can be added to relational fields to limit valid records for the relation when trying to select records in the client interface." msgstr "" #: ../../content/developer/howtos/backend.rst:647 msgid "Domains on relational fields" msgstr "" #: ../../content/developer/howtos/backend.rst:649 msgid "When selecting the instructor for a *Session*, only instructors (partners with ``instructor`` set to ``True``) should be visible." msgstr "" #: ../../content/developer/howtos/backend.rst:652 msgid "More complex domains" msgstr "" #: ../../content/developer/howtos/backend.rst:654 msgid "Create new partner categories *Teacher / Level 1* and *Teacher / Level 2*. The instructor for a session can be either an instructor or a teacher (of any level)." msgstr "" #: ../../content/developer/howtos/backend.rst:659 msgid "Computed fields and default values" msgstr "" #: ../../content/developer/howtos/backend.rst:661 msgid "So far fields have been stored directly in and retrieved directly from the database. Fields can also be *computed*. In that case, the field's value is not retrieved from the database but computed on-the-fly by calling a method of the model." msgstr "" #: ../../content/developer/howtos/backend.rst:666 msgid "To create a computed field, create a field and set its attribute :attr:`~odoo.fields.Field.compute` to the name of a method. The computation method should simply set the value of the field to compute on every record in ``self``." msgstr "" #: ../../content/developer/howtos/backend.rst:671 msgid "``self`` is a collection" msgstr "" #: ../../content/developer/howtos/backend.rst:674 msgid "The object ``self`` is a *recordset*, i.e., an ordered collection of records. It supports the standard Python operations on collections, like ``len(self)`` and ``iter(self)``, plus extra set operations like ``recs1 + recs2``." msgstr "" #: ../../content/developer/howtos/backend.rst:679 msgid "Iterating over ``self`` gives the records one by one, where each record is itself a collection of size 1. You can access/assign fields on single records by using the dot notation, like ``record.name``." msgstr "" #: ../../content/developer/howtos/backend.rst:699 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:59 msgid "Dependencies" msgstr "" #: ../../content/developer/howtos/backend.rst:701 msgid "The value of a computed field usually depends on the values of other fields on the computed record. The ORM expects the developer to specify those dependencies on the compute method with the decorator :func:`~odoo.api.depends`. The given dependencies are used by the ORM to trigger the recomputation of the field whenever some of its dependencies have been modified::" msgstr "" #: ../../content/developer/howtos/backend.rst:720 msgid "Computed fields" msgstr "" #: ../../content/developer/howtos/backend.rst:722 msgid "Add the percentage of taken seats to the *Session* model" msgstr "" #: ../../content/developer/howtos/backend.rst:723 msgid "Display that field in the tree and form views" msgstr "" #: ../../content/developer/howtos/backend.rst:724 msgid "Display the field as a progress bar" msgstr "" #: ../../content/developer/howtos/backend.rst:727 msgid "Default values" msgstr "" #: ../../content/developer/howtos/backend.rst:729 msgid "Any field can be given a default value. In the field definition, add the option ``default=X`` where ``X`` is either a Python literal value (boolean, integer, float, string), or a function taking a recordset and returning a value::" msgstr "" #: ../../content/developer/howtos/backend.rst:738 #: ../../content/developer/howtos/rdtraining/08_relations.rst:115 msgid "The object ``self.env`` gives access to request parameters and other useful things:" msgstr "" #: ../../content/developer/howtos/backend.rst:741 #: ../../content/developer/howtos/rdtraining/08_relations.rst:118 msgid "``self.env.cr`` or ``self._cr`` is the database *cursor* object; it is used for querying the database" msgstr "" #: ../../content/developer/howtos/backend.rst:743 #: ../../content/developer/howtos/rdtraining/08_relations.rst:120 msgid "``self.env.uid`` or ``self._uid`` is the current user's database id" msgstr "" #: ../../content/developer/howtos/backend.rst:744 #: ../../content/developer/howtos/rdtraining/08_relations.rst:121 msgid "``self.env.user`` is the current user's record" msgstr "" #: ../../content/developer/howtos/backend.rst:745 #: ../../content/developer/howtos/rdtraining/08_relations.rst:122 msgid "``self.env.context`` or ``self._context`` is the context dictionary" msgstr "" #: ../../content/developer/howtos/backend.rst:746 #: ../../content/developer/howtos/rdtraining/08_relations.rst:123 msgid "``self.env.ref(xml_id)`` returns the record corresponding to an XML id" msgstr "" #: ../../content/developer/howtos/backend.rst:747 #: ../../content/developer/howtos/rdtraining/08_relations.rst:124 msgid "``self.env[model_name]`` returns an instance of the given model" msgstr "" #: ../../content/developer/howtos/backend.rst:749 msgid "Active objects – Default values" msgstr "" #: ../../content/developer/howtos/backend.rst:751 msgid "Define the start_date default value as today (see :class:`~odoo.fields.Date`)." msgstr "" #: ../../content/developer/howtos/backend.rst:753 msgid "Add a field ``active`` in the class Session, and set sessions as active by default." msgstr "" #: ../../content/developer/howtos/backend.rst:757 msgid "Onchange" msgstr "" #: ../../content/developer/howtos/backend.rst:759 msgid "The \"onchange\" mechanism provides a way for the client interface to update a form whenever the user has filled in a value in a field, without saving anything to the database." msgstr "" #: ../../content/developer/howtos/backend.rst:763 msgid "For instance, suppose a model has three fields ``amount``, ``unit_price`` and ``price``, and you want to update the price on the form when any of the other fields is modified. To achieve this, define a method where ``self`` represents the record in the form view, and decorate it with :func:`~odoo.api.onchange` to specify on which field it has to be triggered. Any change you make on ``self`` will be reflected on the form." msgstr "" #: ../../content/developer/howtos/backend.rst:792 msgid "For computed fields, valued ``onchange`` behavior is built-in as can be seen by playing with the *Session* form: change the number of seats or participants, and the ``taken_seats`` progressbar is automatically updated." msgstr "" #: ../../content/developer/howtos/backend.rst:796 msgid "Warning" msgstr "" #: ../../content/developer/howtos/backend.rst:798 msgid "Add an explicit onchange to warn about invalid values, like a negative number of seats, or more participants than seats." msgstr "" #: ../../content/developer/howtos/backend.rst:802 msgid "Model constraints" msgstr "" #: ../../content/developer/howtos/backend.rst:804 #: ../../content/developer/howtos/rdtraining/11_constraints.rst:12 msgid "Odoo provides two ways to set up automatically verified invariants: :func:`Python constraints ` and :attr:`SQL constraints `." msgstr "" #: ../../content/developer/howtos/backend.rst:808 msgid "A Python constraint is defined as a method decorated with :func:`~odoo.api.constrains`, and invoked on a recordset. The decorator specifies which fields are involved in the constraint, so that the constraint is automatically evaluated when one of them is modified. The method is expected to raise an exception if its invariant is not satisfied::" msgstr "" #: ../../content/developer/howtos/backend.rst:823 msgid "Add Python constraints" msgstr "" #: ../../content/developer/howtos/backend.rst:825 msgid "Add a constraint that checks that the instructor is not present in the attendees of his/her own session." msgstr "" #: ../../content/developer/howtos/backend.rst:828 msgid "SQL constraints are defined through the model attribute :attr:`~odoo.models.Model._sql_constraints`. The latter is assigned to a list of triples of strings ``(name, sql_definition, message)``, where ``name`` is a valid SQL constraint name, ``sql_definition`` is a table_constraint_ expression, and ``message`` is the error message." msgstr "" #: ../../content/developer/howtos/backend.rst:834 msgid "Add SQL constraints" msgstr "" #: ../../content/developer/howtos/backend.rst:836 msgid "With the help of `PostgreSQL's documentation`_ , add the following constraints:" msgstr "" #: ../../content/developer/howtos/backend.rst:839 msgid "CHECK that the course description and the course title are different" msgstr "" #: ../../content/developer/howtos/backend.rst:840 msgid "Make the Course's name UNIQUE" msgstr "" #: ../../content/developer/howtos/backend.rst:842 msgid "Exercise 6 - Add a duplicate option" msgstr "" #: ../../content/developer/howtos/backend.rst:844 msgid "Since we added a constraint for the Course name uniqueness, it is not possible to use the \"duplicate\" function anymore (:menuselection:`Form --> Duplicate`)." msgstr "" #: ../../content/developer/howtos/backend.rst:848 msgid "Re-implement your own \"copy\" method which allows to duplicate the Course object, changing the original name into \"Copy of [original name]\"." msgstr "" #: ../../content/developer/howtos/backend.rst:852 msgid "Advanced Views" msgstr "" #: ../../content/developer/howtos/backend.rst:857 msgid "Tree views can take supplementary attributes to further customize their behavior:" msgstr "" #: ../../content/developer/howtos/backend.rst:885 #: ../../content/developer/reference/addons/views.rst:978 #: ../../content/developer/reference/addons/views.rst:1413 #: ../../content/developer/reference/addons/views.rst:1534 msgid "``decoration-{$name}``" msgstr "" #: ../../content/developer/howtos/backend.rst:861 #: ../../content/developer/reference/addons/views.rst:965 #: ../../content/developer/reference/addons/views.rst:1409 msgid "allow changing the style of a row's text based on the corresponding record's attributes." msgstr "" #: ../../content/developer/howtos/backend.rst:864 #: ../../content/developer/reference/addons/views.rst:104 #: ../../content/developer/reference/addons/views.rst:968 msgid "Values are Python expressions. For each record, the expression is evaluated with the record's attributes as context values and if ``true``, the corresponding style is applied to the row. Here are some of the other values available in the context:" msgstr "" #: ../../content/developer/howtos/backend.rst:869 #: ../../content/developer/reference/addons/views.rst:109 #: ../../content/developer/reference/addons/views.rst:973 msgid "``uid``: the id of the current user," msgstr "" #: ../../content/developer/howtos/backend.rst:870 #: ../../content/developer/reference/addons/views.rst:110 #: ../../content/developer/reference/addons/views.rst:974 msgid "``today``: the current local date as a string of the form ``YYYY-MM-DD``," msgstr "" #: ../../content/developer/howtos/backend.rst:871 #: ../../content/developer/reference/addons/views.rst:111 #: ../../content/developer/reference/addons/views.rst:975 msgid "``now``: same as ``today`` with the addition of the current time. This value is formatted as ``YYYY-MM-DD hh:mm:ss``." msgstr "" #: ../../content/developer/howtos/backend.rst:874 msgid "``{$name}`` can be ``bf`` (``font-weight: bold``), ``it`` (``font-style: italic``), or any `bootstrap contextual color `_ (``danger``, ``info``, ``muted``, ``primary``, ``success`` or ``warning``)." msgstr "" #: ../../content/developer/howtos/backend.rst:890 #: ../../content/developer/reference/addons/views.rst:1393 msgid "``editable``" msgstr "" #: ../../content/developer/howtos/backend.rst:888 msgid "Either ``\"top\"`` or ``\"bottom\"``. Makes the tree view editable in-place (rather than having to go through the form view), the value is the position where new rows appear." msgstr "" #: ../../content/developer/howtos/backend.rst:892 msgid "List coloring" msgstr "" #: ../../content/developer/howtos/backend.rst:894 msgid "Modify the Session tree view in such a way that sessions lasting less than 5 days are colored blue, and the ones lasting more than 15 days are colored red." msgstr "" #: ../../content/developer/howtos/backend.rst:899 msgid "Calendars" msgstr "" #: ../../content/developer/howtos/backend.rst:901 msgid "Displays records as calendar events. Their root element is ```` and their most common attributes are:" msgstr "" #: ../../content/developer/howtos/backend.rst:907 #: ../../content/developer/reference/addons/views.rst:410 #: ../../content/developer/reference/addons/views.rst:962 #: ../../content/developer/reference/addons/views.rst:1344 msgid "``color``" msgstr "" #: ../../content/developer/howtos/backend.rst:905 msgid "The name of the field used for *color segmentation*. Colors are automatically distributed to events, but events in the same color segment (records which have the same value for their ``@color`` field) will be given the same color." msgstr "" #: ../../content/developer/howtos/backend.rst:909 msgid "``date_start``" msgstr "" #: ../../content/developer/howtos/backend.rst:910 msgid "record's field holding the start date/time for the event" msgstr "" #: ../../content/developer/howtos/backend.rst:911 msgid "``date_stop`` (optional)" msgstr "" #: ../../content/developer/howtos/backend.rst:912 msgid "record's field holding the end date/time for the event" msgstr "" #: ../../content/developer/howtos/backend.rst:914 #: ../../content/developer/reference/addons/views.rst:897 #: ../../content/developer/reference/addons/views.rst:1019 #: ../../content/developer/reference/addons/views.rst:1437 #: ../../content/developer/reference/addons/views.rst:1495 #: ../../content/developer/reference/addons/views.rst:1684 #: ../../content/developer/reference/addons/views.rst:1729 #: ../../content/developer/reference/addons/views.rst:1845 msgid "``string``" msgstr "" #: ../../content/developer/howtos/backend.rst:914 msgid "record's field to define the label for each calendar event" msgstr "" #: ../../content/developer/howtos/backend.rst:922 msgid "Calendar view" msgstr "" #: ../../content/developer/howtos/backend.rst:924 msgid "Add a Calendar view to the *Session* model enabling the user to view the events associated to the Open Academy." msgstr "" #: ../../content/developer/howtos/backend.rst:930 msgid "Search view ```` elements can have a ``@filter_domain`` that overrides the domain generated for searching on the given field. In the given domain, ``self`` represents the value entered by the user. In the example below, it is used to search on both fields ``name`` and ``description``." msgstr "" #: ../../content/developer/howtos/backend.rst:935 #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:180 msgid "Search views can also contain ```` elements, which act as toggles for predefined searches. Filters must have one of the following attributes:" msgstr "" #: ../../content/developer/howtos/backend.rst:938 #: ../../content/developer/reference/addons/views.rst:850 #: ../../content/developer/reference/addons/views.rst:1803 #: ../../content/developer/reference/addons/views.rst:1880 msgid "``domain``" msgstr "" #: ../../content/developer/howtos/backend.rst:939 msgid "add the given domain to the current search" msgstr "" #: ../../content/developer/howtos/backend.rst:942 #: ../../content/developer/howtos/web.rst:1710 #: ../../content/developer/reference/addons/data.rst:72 #: ../../content/developer/reference/addons/views.rst:852 #: ../../content/developer/reference/addons/views.rst:1275 #: ../../content/developer/reference/addons/views.rst:1483 #: ../../content/developer/reference/addons/views.rst:1608 #: ../../content/developer/reference/addons/views.rst:1805 #: ../../content/developer/reference/addons/views.rst:1873 #: ../../content/developer/reference/addons/views.rst:1975 msgid "``context``" msgstr "" #: ../../content/developer/howtos/backend.rst:941 msgid "add some context to the current search; use the key ``group_by`` to group results on the given field name" msgstr "" #: ../../content/developer/howtos/backend.rst:961 msgid "To use a non-default search view in an action, it should be linked using the ``search_view_id`` field of the action record." msgstr "" #: ../../content/developer/howtos/backend.rst:964 msgid "The action can also set default values for search fields through its ``context`` field: context keys of the form :samp:`search_default_{field_name}` will initialize *field_name* with the provided value. Search filters must have an optional ``@name`` to have a default and behave as booleans (they can only be enabled by default)." msgstr "" #: ../../content/developer/howtos/backend.rst:972 msgid "Add a button to filter the courses for which the current user is the responsible in the course search view. Make it selected by default." msgstr "" #: ../../content/developer/howtos/backend.rst:974 msgid "Add a button to group courses by responsible user." msgstr "" #: ../../content/developer/howtos/backend.rst:977 #: ../../content/developer/reference/addons/views.rst:945 msgid "Gantt" msgstr "" #: ../../content/developer/howtos/backend.rst:981 msgid "The gantt view requires the web_gantt module which is present in :ref:`the enterprise edition ` version." msgstr "" #: ../../content/developer/howtos/backend.rst:984 msgid "Horizontal bar charts typically used to show project planning and advancement, their root element is ````." msgstr "" #: ../../content/developer/howtos/backend.rst:995 msgid "Gantt charts" msgstr "" #: ../../content/developer/howtos/backend.rst:997 msgid "Add a Gantt Chart enabling the user to view the sessions scheduling linked to the Open Academy module. The sessions should be grouped by instructor." msgstr "" #: ../../content/developer/howtos/backend.rst:1001 msgid "Graph views" msgstr "" #: ../../content/developer/howtos/backend.rst:1003 msgid "Graph views allow aggregated overview and analysis of models, their root element is ````." msgstr "" #: ../../content/developer/howtos/backend.rst:1007 msgid "Pivot views (element ````) a multidimensional table, allows the selection of filers and dimensions to get the right aggregated dataset before moving to a more graphical overview. The pivot view shares the same content definition as graph views." msgstr "" #: ../../content/developer/howtos/backend.rst:1012 msgid "Graph views have 4 display modes, the default mode is selected using the ``@type`` attribute." msgstr "" #: ../../content/developer/howtos/backend.rst:1019 msgid "Bar (default)" msgstr "" #: ../../content/developer/howtos/backend.rst:1016 msgid "a bar chart, the first dimension is used to define groups on the horizontal axis, other dimensions define aggregated bars within each group." msgstr "" #: ../../content/developer/howtos/backend.rst:1019 msgid "By default bars are side-by-side, they can be stacked by using ``@stacked=\"True\"`` on the ````" msgstr "" #: ../../content/developer/howtos/backend.rst:1021 msgid "Line" msgstr "" #: ../../content/developer/howtos/backend.rst:1022 msgid "2-dimensional line chart" msgstr "" #: ../../content/developer/howtos/backend.rst:1024 msgid "Pie" msgstr "" #: ../../content/developer/howtos/backend.rst:1024 msgid "2-dimensional pie" msgstr "" #: ../../content/developer/howtos/backend.rst:1026 msgid "Graph views contain ```` with a mandatory ``@type`` attribute taking the values:" msgstr "" #: ../../content/developer/howtos/backend.rst:1029 #: ../../content/developer/reference/addons/views.rst:1153 #: ../../content/developer/reference/addons/views.rst:1735 msgid "``row`` (default)" msgstr "" #: ../../content/developer/howtos/backend.rst:1030 msgid "the field should be aggregated by default" msgstr "" #: ../../content/developer/howtos/backend.rst:1032 #: ../../content/developer/reference/addons/views.rst:1158 #: ../../content/developer/reference/addons/views.rst:1739 msgid "``measure``" msgstr "" #: ../../content/developer/howtos/backend.rst:1032 msgid "the field should be aggregated rather than grouped on" msgstr "" #: ../../content/developer/howtos/backend.rst:1043 msgid "Graph views perform aggregations on database values, they do not work with non-stored computed fields." msgstr "" #: ../../content/developer/howtos/backend.rst:1046 msgid "Graph view" msgstr "" #: ../../content/developer/howtos/backend.rst:1048 msgid "Add a Graph view in the Session object that displays, for each course, the number of attendees under the form of a bar chart." msgstr "" #: ../../content/developer/howtos/backend.rst:1052 #: ../../content/developer/reference/addons/views.rst:1177 msgid "Kanban" msgstr "" #: ../../content/developer/howtos/backend.rst:1054 msgid "Used to organize tasks, production processes, etc… their root element is ````." msgstr "" #: ../../content/developer/howtos/backend.rst:1057 msgid "A kanban view shows a set of cards possibly grouped in columns. Each card represents a record, and each column the values of an aggregation field." msgstr "" #: ../../content/developer/howtos/backend.rst:1060 msgid "For instance, project tasks may be organized by stage (each column is a stage), or by responsible (each column is a user), and so on." msgstr "" #: ../../content/developer/howtos/backend.rst:1063 msgid "Kanban views define the structure of each card as a mix of form elements (including basic HTML) and :ref:`reference/qweb`." msgstr "" #: ../../content/developer/howtos/backend.rst:1066 msgid "Kanban view" msgstr "" #: ../../content/developer/howtos/backend.rst:1068 msgid "Add a Kanban view that displays sessions grouped by course (columns are thus courses)." msgstr "" #: ../../content/developer/howtos/backend.rst:1072 msgid "Security" msgstr "" #: ../../content/developer/howtos/backend.rst:1074 msgid "Access control mechanisms must be configured to achieve a coherent security policy." msgstr "" #: ../../content/developer/howtos/backend.rst:1078 msgid "Group-based access control mechanisms" msgstr "" #: ../../content/developer/howtos/backend.rst:1080 msgid "Groups are created as normal records on the model ``res.groups``, and granted menu access via menu definitions. However even without a menu, objects may still be accessible indirectly, so actual object-level permissions (read, write, create, unlink) must be defined for groups. They are usually inserted via CSV files inside modules. It is also possible to restrict access to specific fields on a view or object using the field's groups attribute." msgstr "" #: ../../content/developer/howtos/backend.rst:1088 msgid "Access rights" msgstr "" #: ../../content/developer/howtos/backend.rst:1090 msgid "Access rights are defined as records of the model ``ir.model.access``. Each access right is associated to a model, a group (or no group for global access), and a set of permissions: read, write, create, unlink. Such access rights are usually created by a CSV file named after its model: ``ir.model.access.csv``." msgstr "" #: ../../content/developer/howtos/backend.rst:1102 msgid "Add access control through the Odoo interface" msgstr "" #: ../../content/developer/howtos/backend.rst:1104 msgid "Create a new user \"John Smith\". Then create a group \"OpenAcademy / Session Read\" with read access to the *Session* model." msgstr "" #: ../../content/developer/howtos/backend.rst:1107 msgid "Add access control through data files in your module" msgstr "" #: ../../content/developer/howtos/backend.rst:1109 msgid "Using data files," msgstr "" #: ../../content/developer/howtos/backend.rst:1111 msgid "Create a group *OpenAcademy / Manager* with full access to all OpenAcademy models" msgstr "" #: ../../content/developer/howtos/backend.rst:1113 msgid "Make *Session* and *Course* readable by all users" msgstr "" #: ../../content/developer/howtos/backend.rst:1116 msgid "Record rules" msgstr "" #: ../../content/developer/howtos/backend.rst:1118 msgid "A record rule restricts the access rights to a subset of records of the given model. A rule is a record of the model ``ir.rule``, and is associated to a model, a number of groups (many2many field), permissions to which the restriction applies, and a domain. The domain specifies to which records the access rights are limited." msgstr "" #: ../../content/developer/howtos/backend.rst:1124 msgid "Here is an example of a rule that prevents the deletion of leads that are not in state ``cancel``. Notice that the value of the field ``groups`` must follow the same convention as the method :meth:`~odoo.models.Model.write` of the ORM." msgstr "" #: ../../content/developer/howtos/backend.rst:1141 msgid "Record rule" msgstr "" #: ../../content/developer/howtos/backend.rst:1143 msgid "Add a record rule for the model Course and the group \"OpenAcademy / Manager\", that restricts ``write`` and ``unlink`` accesses to the responsible of a course. If a course has no responsible, all users of the group must be able to modify it." msgstr "" #: ../../content/developer/howtos/backend.rst:1151 msgid "Wizards" msgstr "" #: ../../content/developer/howtos/backend.rst:1153 msgid "Wizards describe interactive sessions with the user (or dialog boxes) through dynamic forms. A wizard is simply a model that extends the class :class:`~odoo.models.TransientModel` instead of :class:`~odoo.models.Model`. The class :class:`~odoo.models.TransientModel` extends :class:`~odoo.models.Model` and reuse all its existing mechanisms, with the following particularities:" msgstr "" #: ../../content/developer/howtos/backend.rst:1160 msgid "Wizard records are not meant to be persistent; they are automatically deleted from the database after a certain time. This is why they are called *transient*." msgstr "" #: ../../content/developer/howtos/backend.rst:1163 msgid "Wizard records may refer to regular records or wizard records through relational fields(many2one or many2many), but regular records *cannot* refer to wizard records through a many2one field." msgstr "" #: ../../content/developer/howtos/backend.rst:1167 msgid "We want to create a wizard that allow users to create attendees for a particular session, or for a list of sessions at once." msgstr "" #: ../../content/developer/howtos/backend.rst:1170 msgid "Define the wizard" msgstr "" #: ../../content/developer/howtos/backend.rst:1172 msgid "Create a wizard model with a many2one relationship with the *Session* model and a many2many relationship with the *Partner* model." msgstr "" #: ../../content/developer/howtos/backend.rst:1176 msgid "Launching wizards" msgstr "" #: ../../content/developer/howtos/backend.rst:1178 msgid "Wizards are simply :ref:`window actions ` with a ``target`` field set to the value ``new``, which opens the view (usually :ref:`a form `) in a separate dialog. The action may be triggered via a menu item, but is more generally triggered by a button." msgstr "" #: ../../content/developer/howtos/backend.rst:1184 msgid "An other way to launch wizards is through the :menuselection:`Action` menu of a tree or form view. This is done through the ``binding_model_id`` field of the action. Setting this field will make the action appear on the views of the model the action is \"bound\" to." msgstr "" #: ../../content/developer/howtos/backend.rst:1201 msgid "While wizards use regular views and buttons, normally clicking any button in a form would first save the form then close the dialog. Because this is often undesirable in wizards, a special attribute ``special=\"cancel\"`` is available which immediately closes the wizard without saving the form." msgstr "" #: ../../content/developer/howtos/backend.rst:1206 msgid "Launch the wizard" msgstr "" #: ../../content/developer/howtos/backend.rst:1208 msgid "Define a form view for the wizard." msgstr "" #: ../../content/developer/howtos/backend.rst:1209 msgid "Add the action to launch it in the context of the *Session* model." msgstr "" #: ../../content/developer/howtos/backend.rst:1210 msgid "Define a default value for the session field in the wizard; use the context parameter ``self._context`` to retrieve the current session." msgstr "" #: ../../content/developer/howtos/backend.rst:1213 msgid "Register attendees" msgstr "" #: ../../content/developer/howtos/backend.rst:1215 msgid "Add buttons to the wizard, and implement the corresponding method for adding the attendees to the given session." msgstr "" #: ../../content/developer/howtos/backend.rst:1218 msgid "Register attendees to multiple sessions" msgstr "" #: ../../content/developer/howtos/backend.rst:1220 msgid "Modify the wizard model so that attendees can be registered to multiple sessions." msgstr "" #: ../../content/developer/howtos/backend.rst:1224 #: ../../content/developer/misc/i18n.rst:5 msgid "Internationalization" msgstr "" #: ../../content/developer/howtos/backend.rst:1226 msgid "Each module can provide its own translations within the i18n directory, by having files named LANG.po where LANG is the locale code for the language, or the language and country combination when they differ (e.g. pt.po or pt_BR.po). Translations will be loaded automatically by Odoo for all enabled languages. Developers always use English when creating a module, then export the module terms using Odoo's gettext POT export feature (:menuselection:`Settings --> Translations --> Import/Export --> Export Translation` without specifying a language), to create the module template POT file, and then derive the translated PO files. Many IDE's have plugins or modes for editing and merging PO/POT files." msgstr "" #: ../../content/developer/howtos/backend.rst:1237 msgid "The Portable Object files generated by Odoo are published on `Transifex `__, making it easy to translate the software." msgstr "" #: ../../content/developer/howtos/backend.rst:1252 msgid "By default Odoo's POT export only extracts labels inside XML files or inside field definitions in Python code, but any Python string can be translated this way by surrounding it with the function :func:`odoo._` (e.g. ``_(\"Label\")``)" msgstr "" #: ../../content/developer/howtos/backend.rst:1257 msgid "Translate a module" msgstr "" #: ../../content/developer/howtos/backend.rst:1259 msgid "Choose a second language for your Odoo installation. Translate your module using the facilities provided by Odoo." msgstr "" #: ../../content/developer/howtos/backend.rst:1263 msgid "Reporting" msgstr "" #: ../../content/developer/howtos/backend.rst:1266 msgid "Printed reports" msgstr "" #: ../../content/developer/howtos/backend.rst:1268 msgid "Odoo uses a report engine based on :ref:`reference/qweb`, `Twitter Bootstrap`_ and Wkhtmltopdf_." msgstr "" #: ../../content/developer/howtos/backend.rst:1271 msgid "A report is a combination two elements:" msgstr "" #: ../../content/developer/howtos/backend.rst:1273 msgid "an ``ir.actions.report`` which configures various basic parameters for the report (default type, whether the report should be saved to the database after generation,…)" msgstr "" #: ../../content/developer/howtos/backend.rst:1294 msgid "Because it largerly a standard action, as with :ref:`howto/module/wizard` it is generally useful to add the report as a *contextual item* on the tree and / or form views of the model being reported on via the ``binding_model_id`` field." msgstr "" #: ../../content/developer/howtos/backend.rst:1299 msgid "Here we are also using ``binding_type`` in order for the report to be in the *report* contextual menu rather than the *action* one. There is no technical difference but putting elements in the right place helps users." msgstr "" #: ../../content/developer/howtos/backend.rst:1303 msgid "A standard :ref:`QWeb view ` for the actual report:" msgstr "" #: ../../content/developer/howtos/backend.rst:1317 msgid "the standard rendering context provides a number of elements, the most important being:" msgstr "" #: ../../content/developer/howtos/backend.rst:1320 #: ../../content/developer/reference/addons/reports.rst:70 msgid "``docs``" msgstr "" #: ../../content/developer/howtos/backend.rst:1321 msgid "the records for which the report is printed" msgstr "" #: ../../content/developer/howtos/backend.rst:1323 #: ../../content/developer/reference/addons/reports.rst:31 #: ../../content/developer/reference/addons/security.rst:124 msgid "``user``" msgstr "" #: ../../content/developer/howtos/backend.rst:1323 msgid "the user printing the report" msgstr "" #: ../../content/developer/howtos/backend.rst:1325 msgid "Because reports are standard web pages, they are available through a URL and output parameters can be manipulated through this URL, for instance the HTML version of the *Invoice* report is available through http://localhost:8069/report/html/account.report_invoice/1 (if ``account`` is installed) and the PDF version through http://localhost:8069/report/pdf/account.report_invoice/1." msgstr "" #: ../../content/developer/howtos/backend.rst:1336 msgid "If it appears that your PDF report is missing the styles (i.e. the text appears but the style/layout is different from the html version), probably your wkhtmltopdf_ process cannot reach your web server to download them." msgstr "" #: ../../content/developer/howtos/backend.rst:1340 msgid "If you check your server logs and see that the CSS styles are not being downloaded when generating a PDF report, most surely this is the problem." msgstr "" #: ../../content/developer/howtos/backend.rst:1343 msgid "The wkhtmltopdf_ process will use the ``web.base.url`` system parameter as the *root path* to all linked files, but this parameter is automatically updated each time the Administrator is logged in. If your server resides behind some kind of proxy, that could not be reachable. You can fix this by adding one of these system parameters:" msgstr "" #: ../../content/developer/howtos/backend.rst:1349 msgid "``report.url``, pointing to an URL reachable from your server (probably ``http://localhost:8069`` or something similar). It will be used for this particular purpose only." msgstr "" #: ../../content/developer/howtos/backend.rst:1353 msgid "``web.base.url.freeze``, when set to ``True``, will stop the automatic updates to ``web.base.url``." msgstr "" #: ../../content/developer/howtos/backend.rst:1356 msgid "Create a report for the Session model" msgstr "" #: ../../content/developer/howtos/backend.rst:1358 msgid "For each session, it should display session's name, its start and end, and list the session's attendees." msgstr "" #: ../../content/developer/howtos/backend.rst:1362 msgid "Dashboards" msgstr "" #: ../../content/developer/howtos/backend.rst:1364 msgid "Define a Dashboard" msgstr "" #: ../../content/developer/howtos/backend.rst:1366 msgid "Define a dashboard containing the graph view you created, the sessions calendar view and a list view of the courses (switchable to a form view). This dashboard should be available through a menuitem in the menu, and automatically displayed in the web client when the OpenAcademy main menu is selected." msgstr "" #: ../../content/developer/howtos/backend.rst:1373 msgid "WebServices" msgstr "" #: ../../content/developer/howtos/backend.rst:1375 msgid "The web-service module offer a common interface for all web-services :" msgstr "" #: ../../content/developer/howtos/backend.rst:1377 msgid "XML-RPC" msgstr "" #: ../../content/developer/howtos/backend.rst:1378 msgid "JSON-RPC" msgstr "" #: ../../content/developer/howtos/backend.rst:1380 msgid "Business objects can also be accessed via the distributed object mechanism. They can all be modified via the client interface with contextual views." msgstr "" #: ../../content/developer/howtos/backend.rst:1384 msgid "Odoo is accessible through XML-RPC/JSON-RPC interfaces, for which libraries exist in many languages." msgstr "" #: ../../content/developer/howtos/backend.rst:1388 msgid "XML-RPC Library" msgstr "" #: ../../content/developer/howtos/backend.rst:1390 msgid "The following example is a Python 3 program that interacts with an Odoo server with the library ``xmlrpc.client``::" msgstr "" #: ../../content/developer/howtos/backend.rst:1409 msgid "Add a new service to the client" msgstr "" #: ../../content/developer/howtos/backend.rst:1411 msgid "Write a Python program able to send XML-RPC requests to a PC running Odoo (yours, or your instructor's). This program should display all the sessions, and their corresponding number of seats. It should also create a new session for one of the courses." msgstr "" #: ../../content/developer/howtos/backend.rst:1447 msgid "Instead of using a hard-coded course id, the code can look up a course by name::" msgstr "" #: ../../content/developer/howtos/backend.rst:1458 msgid "JSON-RPC Library" msgstr "" #: ../../content/developer/howtos/backend.rst:1460 msgid "The following example is a Python 3 program that interacts with an Odoo server with the standard Python libraries ``urllib.request`` and ``json``. This example assumes the **Productivity** app (``note``) is installed::" msgstr "" #: ../../content/developer/howtos/backend.rst:1504 msgid "Examples can be easily adapted from XML-RPC to JSON-RPC." msgstr "" #: ../../content/developer/howtos/backend.rst:1508 msgid "There are a number of high-level APIs in various languages to access Odoo systems without *explicitly* going through XML-RPC or JSON-RPC, such as:" msgstr "" #: ../../content/developer/howtos/backend.rst:1511 msgid "https://github.com/akretion/ooor" msgstr "" #: ../../content/developer/howtos/backend.rst:1512 msgid "https://github.com/OCA/odoorpc" msgstr "" #: ../../content/developer/howtos/backend.rst:1513 msgid "https://github.com/nicolas-van/openerp-client-lib" msgstr "" #: ../../content/developer/howtos/backend.rst:1514 msgid "http://pythonhosted.org/OdooRPC" msgstr "" #: ../../content/developer/howtos/backend.rst:1515 msgid "https://github.com/abhishek-jaiswal/php-openerp-lib" msgstr "" #: ../../content/developer/howtos/backend.rst:1517 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:288 msgid "it is possible to :ref:`disable the automatic creation of some fields `" msgstr "" #: ../../content/developer/howtos/backend.rst:1519 msgid "writing raw SQL queries is possible, but requires care as it bypasses all Odoo authentication and security mechanisms." msgstr "" #: ../../content/developer/howtos/company.rst:6 msgid "Multi-company Guidelines" msgstr "" #: ../../content/developer/howtos/company.rst:10 msgid "This tutorial requires good knowledge of Odoo. Please refer to the :ref:`basic tutorial ` first if needed." msgstr "" #: ../../content/developer/howtos/company.rst:13 msgid "As of version 13.0, a user can be logged in multiple companies at once. This allows the user to access information from multiple companies but also to create/edit records in a multi-company environment." msgstr "" #: ../../content/developer/howtos/company.rst:17 msgid "If not handled correctly, it may be the source of a lot of inconsistent multi-company behaviors. For instance, a user logged in both companies A and B could create a sales order in company A and add products belonging to company B to it. It is only when the user will log out from company B that access errors will occur for the sales order." msgstr "" #: ../../content/developer/howtos/company.rst:22 msgid "To correctly manage multi-company behaviors, Odoo's ORM provides multiple features:" msgstr "" #: ../../content/developer/howtos/company.rst:24 msgid ":ref:`Company-dependent fields `" msgstr "" #: ../../content/developer/howtos/company.rst:25 msgid ":ref:`Multi-company consistency `" msgstr "" #: ../../content/developer/howtos/company.rst:26 msgid ":ref:`Default company `" msgstr "" #: ../../content/developer/howtos/company.rst:27 msgid ":ref:`Views `" msgstr "" #: ../../content/developer/howtos/company.rst:28 msgid ":ref:`Security rules `" msgstr "" #: ../../content/developer/howtos/company.rst:33 msgid "Company-dependent fields" msgstr "" #: ../../content/developer/howtos/company.rst:35 msgid "When a record is available from multiple companies, we must expect that different values will be assigned to a given field depending on the company from which the value is set." msgstr "" #: ../../content/developer/howtos/company.rst:38 msgid "For the field of a same record to support several values, it must be defined with the attribute `company_dependent` set to `True`." msgstr "" #: ../../content/developer/howtos/company.rst:57 msgid "The `_compute_display_info` method is decorated with `depends_context('company')` (see :attr:`~odoo.api.depends_context`) to ensure that the computed field is recomputed depending on the current company (`self.env.company`)." msgstr "" #: ../../content/developer/howtos/company.rst:61 msgid "When a company-dependent field is read, the current company is used to retrieve its value. In other words, if a user is logged in companies A and B with A as main company and creates a record for company B, the values of company-dependent fields will be that of company A." msgstr "" #: ../../content/developer/howtos/company.rst:65 msgid "To read the values of company-dependent fields set from another company than the current one, we need to ensure the company we are using is the correct one. This can be done with :meth:`~odoo.models.Model.with_company`, which updates the current company." msgstr "" #: ../../content/developer/howtos/company.rst:80 msgid "Whenever you are computing/creating/... things that may behave differently in different companies, you should make sure whatever you are doing is done in the right company. It doesn't cost much to always use `with_company` to avoid problems later on." msgstr "" #: ../../content/developer/howtos/company.rst:101 msgid "Multi-company consistency" msgstr "" #: ../../content/developer/howtos/company.rst:103 msgid "When a record is made shareable between several companies by the mean of a `company_id` field, we must take care that it cannot be linked to the record of another company through a relational field. For instance, we do not want to have a sales order and its invoice belonging to different companies." msgstr "" #: ../../content/developer/howtos/company.rst:107 msgid "To ensure this multi-company consistency, you must:" msgstr "" #: ../../content/developer/howtos/company.rst:109 msgid "Set the class attribute `_check_company_auto` to `True`." msgstr "" #: ../../content/developer/howtos/company.rst:110 msgid "Define relational fields with the attribute `check_company` set to `True` if their model has a `company_id` field." msgstr "" #: ../../content/developer/howtos/company.rst:113 msgid "On each :meth:`~odoo.models.Model.create` and :meth:`~odoo.models.Model.write`, automatic checks will be triggered to ensure the multi-company consistency of the record." msgstr "" #: ../../content/developer/howtos/company.rst:127 msgid "The field `company_id` must not be defined with `check_company=True`." msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:1 msgid "Check the companies of the values of the given field names." msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../content/developer/misc/api/iap.rst:0 #: ../../../odoo/odoo/http.py:docstring of odoo.http.route:0 #: ../../../odoo/odoo/http.py:docstring of odoo.http.WebRequest:0 #: ../../../odoo/odoo/http.py:docstring of odoo.http.WebRequest.csrf_token:0 #: ../../../odoo/odoo/http.py:docstring of odoo.http.HttpRequest.make_response:0 #: ../../../odoo/odoo/http.py:docstring of odoo.http.HttpRequest.render:0 #: ../../../odoo/odoo/http.py:docstring of odoo.http.Response:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../content/developer/reference/addons/mixins.rst:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Field:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Field:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Char:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Float:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Binary:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Html:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Image:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Monetary:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Selection:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Text:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.add:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Date.context_today:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.end_of:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.start_of:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.subtract:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Date.to_date:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Date.to_string:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.add:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Datetime.context_timestamp:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.end_of:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.start_of:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.tools.date_utils.subtract:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Datetime.to_datetime:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Datetime.to_string:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Many2one:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.One2many:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Many2many:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Many2many:0 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Many2oneReference:0 #: ../../../odoo/odoo/api.py:docstring of odoo.api.returns:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.with_company:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.with_env:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.invalidate_cache:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.create:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.copy:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.default_get:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.name_create:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.write:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.flush:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.browse:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.search:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.name_search:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.read:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.read_group:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.fields_get:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.fields_view_get:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.filtered:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.mapped:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.sorted:0 #: ../../../odoo/odoo/exceptions.py:docstring of odoo.exceptions.RedirectWarning:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.BaseCase.browse_ref:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.BaseCase.ref:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.BaseCase.browse_ref:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.BaseCase.ref:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.BaseCase.browse_ref:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.BaseCase.ref:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.Form:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._populate:0 #: ../../../odoo/odoo/tools/populate.py:docstring of odoo.tools.populate.cartesian:0 #: ../../../odoo/odoo/tools/populate.py:docstring of odoo.tools.populate.compute:0 #: ../../../odoo/odoo/tools/populate.py:docstring of odoo.tools.populate.iterate:0 #: ../../../odoo/odoo/tools/populate.py:docstring of odoo.tools.populate.randint:0 #: ../../../odoo/odoo/tools/populate.py:docstring of odoo.tools.populate.randomize:0 #: ../../content/developer/reference/javascript/qweb.rst:0 msgid "Parameters" msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:3 msgid "names of relational fields to check" msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:0 #: ../../../odoo/odoo/api.py:docstring of odoo.api.Environment.company:0 #: ../../../odoo/odoo/api.py:docstring of odoo.api.Environment.companies:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.create:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.write:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.search:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.read:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.read_group:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.fields_view_get:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.unlink:0 #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel.ensure_one:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.Form.save:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.O2MProxy.edit:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.O2MProxy.new:0 #: ../../../odoo/odoo/tests/common.py:docstring of odoo.tests.common.O2MProxy.remove:0 msgid "Raises" msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:4 msgid "if the `company_id` of the value of any field is not in `[False, self.company_id]` (or `self` if :class:`~odoo.addons.base.models.res_company`)." msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:8 msgid "For :class:`~odoo.addons.base.models.res_users` relational fields, verifies record company is in `company_ids` fields." msgstr "" #: ../../../odoo/odoo/models.py:docstring of odoo.models.BaseModel._check_company:11 msgid "User with main company A, having access to company A and B, could be assigned or linked to records in company B." msgstr "" #: ../../content/developer/howtos/company.rst:132 msgid "The `check_company` feature performs a strict check ! It means that if a record has no `company_id` (i.e. the field is not required), it cannot be linked to a record whose `company_id` is set." msgstr "" #: ../../content/developer/howtos/company.rst:138 msgid "When no domain is defined on the field and `check_company` is set to `True`, a default domain is added: `['|', '('company_id', '=', False), ('company_id', '=', company_id)]`" msgstr "" #: ../../content/developer/howtos/company.rst:144 msgid "Default company" msgstr "" #: ../../content/developer/howtos/company.rst:146 msgid "When the field `company_id` is made required on a model, a good practice is to set a default company. It eases the setup flow for the user or even guarantees its validity when the company is hidden from the view. Indeed, the company is usually hidden if the user does not have access to multiple companies (i.e. when the user does not have the group `base.group_multi_company`)." msgstr "" #: ../../content/developer/howtos/company.rst:168 #: ../../content/developer/reference/addons/views.rst:6 #: ../../content/developer/reference/javascript/javascript_reference.rst:1422 msgid "Views" msgstr "" #: ../../content/developer/howtos/company.rst:170 msgid "As stated in :ref:`above `, the company is usually hidden from the view if the user does not have access to multiple companies. This is tested with the group `base.group_multi_company`." msgstr "" #: ../../content/developer/howtos/company.rst:197 msgid "Security rules" msgstr "" #: ../../content/developer/howtos/company.rst:199 msgid "When working with records shared across companies or restricted to a single company, we must take care that a user does not have access to records belonging to other companies." msgstr "" #: ../../content/developer/howtos/company.rst:202 msgid "This is achieved with security rules based on `company_ids`, which contains the current companies of the user (the companies the user checked in the multi-company widget)." msgstr "" #: ../../content/developer/howtos/company.rst:229 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:96 #: ../../content/developer/howtos/web.rst:137 #: ../../content/developer/howtos/web.rst:1878 #: ../../content/developer/howtos/website.rst:490 #: ../../content/developer/misc/api/iap.rst:121 #: ../../content/developer/misc/api/iap.rst:225 #: ../../content/developer/misc/api/iap.rst:407 #: ../../content/developer/misc/api/iap.rst:409 #: ../../content/developer/misc/api/iap.rst:510 #: ../../content/developer/misc/i18n/translations.rst:21 #: ../../content/developer/reference/addons/actions.rst:176 #: ../../../odoo/odoo/api.py:docstring of odoo.api:3 #: ../../content/developer/reference/addons/orm.rst:620 #: ../../content/developer/reference/addons/orm.rst:622 #: ../../content/developer/reference/addons/orm.rst:737 #: ../../content/developer/reference/addons/orm.rst:894 #: ../../content/developer/reference/addons/security.rst:28 #: ../../content/developer/reference/addons/security.rst:186 #: ../../content/developer/reference/addons/views.rst:13 #: ../../content/developer/reference/addons/views.rst:70 #: ../../content/developer/reference/addons/views.rst:81 #: ../../content/developer/reference/addons/views.rst:179 #: ../../content/developer/reference/addons/views.rst:241 #: ../../content/developer/reference/addons/views.rst:818 #: ../../content/developer/reference/addons/views.rst:938 #: ../../content/developer/reference/addons/views.rst:940 #: ../../content/developer/reference/addons/views.rst:1223 #: ../../content/developer/reference/addons/views.rst:1302 #: ../../content/developer/reference/addons/views.rst:1318 #: ../../content/developer/reference/addons/views.rst:1485 #: ../../content/developer/reference/addons/views.rst:2127 #: ../../content/developer/reference/javascript/qweb.rst:342 #: ../../content/developer/reference/javascript/qweb.rst:423 msgid "Todo" msgstr "" #: ../../content/developer/howtos/company.rst:229 msgid "check_company on company_dependent fields." msgstr "" #: ../../content/developer/howtos/profilecode.rst:3 msgid "Profiling Odoo code" msgstr "" #: ../../content/developer/howtos/profilecode.rst:7 msgid "This tutorial requires :ref:`having installed Odoo ` and :doc:`writing Odoo code `" msgstr "" #: ../../content/developer/howtos/profilecode.rst:11 msgid "Graph a method" msgstr "" #: ../../content/developer/howtos/profilecode.rst:13 msgid "Odoo embeds a profiler of code. This embedded profiler output can be used to generate a graph of calls triggered by the method, number of queries, percentage of time taken in the method itself as well as the time that the method took and its sub-called methods." msgstr "" #: ../../content/developer/howtos/profilecode.rst:25 msgid "This produces a file called /temp/prof.profile" msgstr "" #: ../../content/developer/howtos/profilecode.rst:27 msgid "A tool called *gprof2dot* will produce a graph with this result:" msgstr "" #: ../../content/developer/howtos/profilecode.rst:33 msgid "A tool called *xdot* will display the resulting graph:" msgstr "" #: ../../content/developer/howtos/profilecode.rst:40 msgid "Log a method" msgstr "" #: ../../content/developer/howtos/profilecode.rst:42 msgid "Another profiler can be used to log statistics on a method:" msgstr "" #: ../../content/developer/howtos/profilecode.rst:52 msgid "The statistics will be displayed into the logs once the method to be analysed is completely reviewed." msgstr "" #: ../../content/developer/howtos/profilecode.rst:83 msgid "Dump stack" msgstr "" #: ../../content/developer/howtos/profilecode.rst:85 msgid "Sending the SIGQUIT signal to an Odoo process (only available on POSIX) makes this process output the current stack trace to log, with info level. When an odoo process seems stuck, sending this signal to the process permit to know what the process is doing, and letting the process continue his job." msgstr "" #: ../../content/developer/howtos/profilecode.rst:91 msgid "Tracing code execution" msgstr "" #: ../../content/developer/howtos/profilecode.rst:93 msgid "Instead of sending the SIGQUIT signal to an Odoo process often enough, to check where the processes are performing worse than expected, we can use the `py-spy`_ tool to do it for us." msgstr "" #: ../../content/developer/howtos/profilecode.rst:98 msgid "Install py-spy" msgstr "" #: ../../content/developer/howtos/profilecode.rst:105 msgid "Record executed code" msgstr "" #: ../../content/developer/howtos/profilecode.rst:107 msgid "As py-spy is installed, we now record the executed code lines. This tool will record, multiple times a second, the stacktrace of the process." msgstr "" #: ../../content/developer/howtos/profilecode.rst:118 msgid "where is the process ID of the odoo process you want to graph." msgstr "" #: ../../content/developer/howtos/profilecode.rst:120 msgid "To open profile.json you can use online tool `speedscope.app`_." msgstr "" #: ../../content/developer/howtos/profilecode.rst:122 msgid "To open profile.svg you should use browser, because other viewer may not support interactive part." msgstr "" #: ../../content/developer/howtos/rdtraining.rst:32 #: ../../content/developer/howtos/rdtraining.rst:60 #: ../../content/developer/howtos/rdtraining.rst:32 #: ../../content/developer/howtos/rdtraining.rst:60 msgid "Advanced Topics" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:7 msgid "Getting Started" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:9 msgid "Welcome to the Getting Started Odoo tutorial! If you reached this page that means you are interested in the development of your own Odoo module. It might also mean that you recently joined the Odoo company for a rather technical position. In any case, your journey to the technical side of Odoo starts here." msgstr "" #: ../../content/developer/howtos/rdtraining.rst:14 msgid "This training is split in two parts. The first part is the 'Core Training': its objective is to give you an insight of the most important parts of the Odoo development framework. The chapters should be followed in their given order since they cover the development of a new Odoo application from scratch in an incremental way. In other words, each chapter depends on the previous one." msgstr "" #: ../../content/developer/howtos/rdtraining.rst:20 msgid "The second part covers a set of 'Advanced' topics. Each topic can be followed independently, but requires the 'Core Training'. Note that some advanced topics cover basic features of an Odoo module, so it's a good idea to give them a quick look." msgstr "" #: ../../content/developer/howtos/rdtraining.rst:24 msgid "All topics are built around a business case we will enhance along the way. The reader is expected to actively take part in the training by writing the solution for each exercise." msgstr "" #: ../../content/developer/howtos/rdtraining.rst:27 msgid "Ready? Let's get started!" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:30 msgid "Core Training" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:40 msgid ":doc:`rdtraining/01_architecture`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:41 msgid ":doc:`rdtraining/02_setup`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:42 msgid ":doc:`rdtraining/03_newapp`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:43 msgid ":doc:`rdtraining/04_basicmodel`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:44 msgid ":doc:`rdtraining/05_securityintro`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:45 msgid ":doc:`rdtraining/06_firstui`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:46 msgid ":doc:`rdtraining/07_basicviews`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:47 msgid ":doc:`rdtraining/08_relations`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:48 msgid ":doc:`rdtraining/09_compute_onchange`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:49 msgid ":doc:`rdtraining/10_actions`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:50 msgid ":doc:`rdtraining/11_constraints`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:51 msgid ":doc:`rdtraining/12_sprinkles`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:52 msgid ":doc:`rdtraining/13_inheritance`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:53 msgid ":doc:`rdtraining/14_other_module`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:54 msgid ":doc:`rdtraining/15_qwebintro`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:55 msgid ":doc:`rdtraining/16_guidelines_pr`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:58 msgid "Advanced topics" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:70 msgid ":doc:`rdtraining/B_acl_irrules`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:71 msgid ":doc:`rdtraining/C_data`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:72 msgid ":doc:`rdtraining/E_unittest`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:73 msgid ":doc:`rdtraining/J_reports`" msgstr "" #: ../../content/developer/howtos/rdtraining.rst:74 msgid ":doc:`rdtraining/K_dashboard`" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:5 msgid "Chapter 1: Architecture Overview" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:8 msgid "Multitier application" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:10 msgid "Odoo follows a `multitier architecture`_, meaning that the presentation, the business logic and the data storage are separated. More specifically, it uses a three-tier architecture (image from Wikipedia):" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:18 msgid "The presentation tier is a combination of HTML5, JavaScript and CSS. The logic tier is exclusively written in Python, while the data tier only supports PostgreSQL as an RDBMS." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:21 msgid "Depending on the scope of your module, Odoo development can be done in any of these tiers. Therefore, before going any further, it may be a good idea to refresh your memory if you don't have an intermediate level in these topics." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:25 msgid "In order to go through this tutorial, you will need a very basic knowledge of HTML and an intermediate level of Python. Advanced topics will require more knowledge in the other subjects. There are plenty of tutorials freely accessible, so we cannot recommend one over another since it depends on your background." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:30 msgid "For reference this is the official `Python tutorial`_." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:33 msgid "Odoo modules" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:35 msgid "Both server and client extensions are packaged as *modules* which are optionally loaded in a *database*. A module is a collection of functions and data that target a single purpose." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:39 msgid "Odoo modules can either add brand new business logic to an Odoo system or alter and extend existing business logic. One module can be created to add your country's accounting rules to Odoo's generic accounting support, while a different module can add support for real-time visualisation of a bus fleet." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:44 msgid "Everything in Odoo starts and ends with modules." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:46 msgid "Terminology: developers group their business features in Odoo *modules*. The main user-facing modules are flagged and exposed as *Apps*, but a majority of the modules aren't Apps. *Modules* may also be referred to as *addons* and the directories where the Odoo server finds them form the ``addons_path``." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:54 msgid "An Odoo module **can** contain a number of elements:" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:59 msgid ":ref:`Business objects `" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:57 msgid "A business object (e.g. an invoice) is declared as a Python class. The fields defined in these classes are automatically mapped to database columns thanks to the :abbr:`ORM (Object-Relational Mapping)` layer." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:62 msgid "Define UI display" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:65 msgid "XML or CSV files declaring the model data:" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:76 msgid "Images, CSS or JavaScript files used by the web interface or website" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:78 msgid "None of these elements are mandatory. Some modules may only add data files (e.g. country-specific accounting configuration), while others may only add business objects. During this training, we will create business objects, object views and data files. :ref:`Web controllers ` and :ref:`static web data ` are advanced topics." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:93 msgid "When an Odoo module includes business objects (i.e. Python files), they are organized as a `Python package `_ with a ``__init__.py`` file. This file contains import instructions for various Python files in the module." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:98 msgid "Here is a simplified module directory:" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:112 msgid "Odoo Editions" msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:114 msgid "Odoo is available in `two versions`_: Odoo Enterprise (licensed & shared sources) and Odoo Community (open-source). In addition to services such as support or upgrades, the Enterprise version provides extra functionalities to Odoo. From a technical point-of-view, these functionalities are simply new modules installed on top of the modules provided by the Community version." msgstr "" #: ../../content/developer/howtos/rdtraining/01_architecture.rst:119 msgid "Ready to start? Before writing actual code, let's go to the :ref:`next chapter ` to review the Odoo installation process. Even if Odoo is already running on your system, we strongly suggest you go through this chapter to make sure we start on the same page during the development of our new application." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:5 msgid "Chapter 2: Development Environment Set-up" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:7 msgid "There are multiple ways to install Odoo depending on the intended use case." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:9 msgid "This document attempts to describe the installation options for an internal Odoo R&D developer. We assume that you are installing your development environment on a standard Odoo laptop with Linux Mint installed and up-to-date. At the time of writing, we are using a vanilla Linux Mint 20 (Ubuntu 20.04) as a starting point." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:15 msgid "If you are using another environment, you can refer to :ref:`setup/install/source`." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:19 msgid "Fetch the sources & configure git" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:22 msgid "Install and configure git" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:24 msgid "The very first step of the installation process is to install the `git version control system `__ because the Odoo source code is managed on GitHub. Once installed, you can set your name and email:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:34 msgid "Configure GitHub" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:36 msgid "To fetch the sources and contribute to Odoo's development you will need a GitHub account. We recommend using your trigram (xyz) followed by '-odoo' as your username: 'xyz-odoo'. If you prefer, you can also use your personal GitHub account." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:41 msgid "The easiest way to authenticate with GitHub is to use an SSH connection. Using the SSH authentication will allow you to connect to GitHub without supplying your username and password every time." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:46 msgid "The following instructions are based on the official `GitHub documentation `__." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:49 msgid "Here is a step-by-step procedure:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:52 msgid "Generate a new SSH key, add it to the ssh-agent and copy the SSH key to your clipboard." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:62 msgid "In Github:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:65 msgid "In the upper-right corner of any page, click your profile photo, then click Settings" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:69 msgid "In the user settings sidebar, click SSH and GPG keys." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:73 msgid "Click New SSH key or Add SSH key." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:77 msgid "In the \"Title\" field, add a descriptive label for the new key." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:78 msgid "Paste your key into the \"Key\" field." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:82 msgid "Click Add SSH key." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:86 msgid "Fetch the sources" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:88 msgid "All the Odoo sources will be located in `$HOME/src/`" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:97 msgid "Cloning the repositories will take a while, enjoy a cup of coffee while you wait." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:99 msgid "You may need to ask your manager for read rights to fetch the enterprise repository." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:104 #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:34 msgid "Configure development repository" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:106 msgid "To contribute to Odoo's development you will need to `fork the repository `__, create a branch containing your code in the fork and submit a `Pull Request `__ to the Odoo repository." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:112 msgid "If you are lucky enough to work at Odoo, the forks already exist. They are called `odoo-dev/odoo` and `odoo-dev/enterprise`." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:129 msgid "Useful git commands" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:131 msgid "Here are some useful git commands for your day-to-day work." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:133 msgid "Change branch: When you change branches, both repositories (odoo and enterprise) must be synchronized, i.e. both need to be in the same branch." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:145 msgid "Fetch and rebase:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:159 msgid "Install the dependencies" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:162 #: ../../content/developer/howtos/rdtraining/11_constraints.rst:69 #: ../../content/developer/misc/other/guidelines.rst:397 #: ../../content/developer/reference/addons/security.rst:450 #: ../../content/developer/reference/addons/security.rst:452 #: ../../content/developer/reference/addons/testing.rst:665 #: ../../content/developer/reference/javascript/qweb.rst:334 msgid "Python" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:164 msgid "Odoo requires Python 3.6 or later, if your computer is up-to-date you should already be at this version or higher." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:167 msgid "You can check your Python version with:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:174 msgid "Install pip3 and libraries" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:176 msgid "For libraries using native code, installation of development tools and native dependencies is required before installing the Python dependencies of Odoo." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:185 msgid "Install odoo requirements" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:195 msgid "Install wkhtmltopdf" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:197 msgid "wkhtmltopdf is a library to render HTML into PDF. Odoo uses it to create PDF reports. wkhtmltopdf is not installed through pip and must be installed manually in version 0.12.5 to support headers and footers." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:210 msgid "Right-to-left interface support" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:212 msgid "In order to support right-to-left (RTL) languages, we need `rtlcss` to convert the CSS files:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:220 msgid "Install PostgreSQL" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:222 msgid "As seen in :ref:`howto/rdtraining/01_architecture`, Odoo uses PostgreSQL as a RDBMS. In the context of a development machine, the easiest approach is to install it locally. Then we can create a PostgreSQL user corresponding to our current user:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:232 msgid "Some useful SQL commands:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:246 msgid "Run the server" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:249 msgid "Running odoo-bin" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:251 msgid "Once all dependencies are set up, Odoo can be launched by running odoo-bin, the command-line interface of the server." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:258 msgid "There are multiple :ref:`command-line arguments ` that you can use to configure the server. In this training you will only need some of them." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:263 msgid "The database that is going to be used." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:267 msgid "A comma-separated list of directories in which modules are stored. These directories are scanned for modules." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:272 msgid "Prevents the worker from using more than CPU seconds for each request." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:276 msgid "Prevents the worker from taking longer than seconds to process a request." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:278 msgid "The last two can be used to prevent the worker from being killed when debugging the source code." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:280 msgid "You may face an error similar to `AttributeError: module '$MODULE_NAME' has no attribute '$ATTRIBUTE'`" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:282 msgid "In this case you may need to re-install the module with `$ pip install --upgrade --force-reinstall $MODULE_NAME`" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:284 msgid "If this error occurs with more than one module then you may need to re-install all the requirements with `$ pip3 install --upgrade --force-reinstall -r requirements.txt`" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:287 msgid "You can also clear the python cache to solve the issue" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:296 msgid "Log in to Odoo" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:298 msgid "Open `http://localhost:8069/` on your browser. We recommend you use: `Firefox `__, `Chrome `__ (`Chromium `__ the open source equivalent) or any other browser with development tools." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:304 msgid "To log in as the administrator user, you can use the following credentials:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:306 msgid "email = `admin`" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:307 msgid "password = `admin`" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:310 msgid "The developer mode" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:312 msgid "The Developer or Debug Mode gives you access to additional (advanced) tools." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:314 msgid "This is useful for training and we assume that the user is in developer mode for the rest of the tutorials." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:316 msgid "To activate the developer or debug mode you can follow the steps `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:319 msgid "Extra tools" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:322 msgid "Code Editor" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:324 msgid "If you are working at Odoo, many of your colleagues are using `VSCode`_ (`VSCodium`_ the open source equivalent), `Sublime Text`_, `Atom`_ or `PyCharm`_. However you are free to choose your preferred editor." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:328 msgid "Don't forget to configure your linters correctly. Using a linter can help you by showing syntax and semantic warnings or errors. Odoo source code tries to respect Python and JavaScript standards, but some of them can be ignored." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:332 msgid "For Python, we use PEP8 with these options ignored:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:334 #: ../../content/developer/misc/other/guidelines.rst:410 msgid "E501: line too long" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:335 #: ../../content/developer/misc/other/guidelines.rst:411 msgid "E301: expected 1 blank line, found 0" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:336 #: ../../content/developer/misc/other/guidelines.rst:412 msgid "E302: expected 2 blank lines, found 1" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:338 msgid "For JavaScript, we use ESLint and you can find a `configuration file example here`_." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:348 msgid "Administrator tools for PostgreSQL" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:350 msgid "You can manage your PostgreSQL databases using the command line as demonstrated earlier or using a GUI application such as `pgAdmin `__ or `DBeaver `__." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:353 msgid "To connect the GUI application to your database we recommend you connect using the Unix socket." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:355 msgid "Host name/address = /var/run/postgresql" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:356 msgid "Port = 5432" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:357 msgid "Username = $USER" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:361 msgid "Python Debugging" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:363 msgid "When facing a bug or trying to understand how the code works, simply printing things out can go a long way, but a proper debugger can save a lot of time." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:366 msgid "You can use a classic Python library debugger (`pdb `__, `pudb `__ or `ipdb `__) or you can use your editor's debugger. To avoid difficult configurations in the beginning, it is easier if you use a library debugger." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:371 msgid "In the following example we use ipdb, but the process is similar with other libraries." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:373 msgid "Install the library:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:379 msgid "Trigger (breakpoint):" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:385 #: ../../content/developer/reference/addons/views.rst:159 #: ../../content/developer/reference/addons/views.rst:1903 #: ../../content/developer/reference/addons/views.rst:1940 #: ../../content/developer/reference/addons/views.rst:1966 msgid "Example:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:398 msgid "Here is a list of commands:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:402 msgid "Without an argument, print the list of available commands. With a command as an argument, print help about that command." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:407 msgid "The value of the ``expression`` is pretty-printed using the ``pprint`` module." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:411 msgid "Print a stack trace, with the most recent frame at the bottom." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:415 msgid "Move the current frame one level down in the stack trace (to a newer frame)." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:419 msgid "Move the current frame one level up in the stack trace (to an older frame)." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:423 msgid "Continue the execution until the next line in the current function is reached or it returns." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:427 msgid "Continue the execution and only stop when a breakpoint is encountered." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:431 msgid "Execute the current line, stop at the first possible occasion (either in a function that is called or on the next line in the current function)." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:436 msgid "Quit the debugger. The program being executed is aborted." msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:440 msgid "To avoid killing the worker when debugging, you can add these arguments when launching the server: `--limit-time-cpu=9999 --limit-time-real=9999` Another solution is to add them directly in the `~/.odoorc` file:" msgstr "" #: ../../content/developer/howtos/rdtraining/02_setup.rst:451 msgid "Now that your server is running, it's time to start :ref:`writing your own application `!" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:5 msgid "Chapter 3: A New Application" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:7 msgid "The purpose of this chapter is to lay the foundation for the creation of a completely new Odoo module. We will start from scratch with the minimum needed to have our module recognized by Odoo. In the upcoming chapters, we will progressively add features to build a realistic business case." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:12 msgid "The Real Estate Advertisement module" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:14 msgid "Our new module will cover a business area which is very specific and therefore not included in the standard set of modules: real estate. It is worth noting that before developing a new module, it is good practice to verify that Odoo doesn't already provide a way to answer the specific business case." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:19 msgid "Here is an overview of the main list view containing some advertisements:" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:25 msgid "The top area of the form view summarizes important information for the property, such as the name, the property type, the postcode and so on. The first tab contains information describing the property: bedrooms, living area, garage, garden..." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:33 msgid "The second tab lists the offers for the property. We can see here that potential buyers can make offers above or below the expected selling price. It is up to the seller to accept an offer." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:40 msgid "Here is a quick video showing the workflow of the module." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:42 msgid "Hopefully, this video will be recorded soon :-)" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:45 msgid "Prepare the addon directory" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:47 msgid "**Reference**: the documentation related to this topic can be found in :ref:`manifest `." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:52 msgid "**Goal**: the goal of this section is to have Odoo recognize our new module, which will be an empty shell for now. It will be listed in the Apps:" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:59 msgid "The first step of module creation is to create a new directory. To ease the development, we suggest you first create the directory ``/home/$USER/src/custom``. In this directory we add another directory ``estate``, which is our module." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:63 msgid "A module must contain at least 2 files: the ``__manifest__.py`` file and a ``__init__.py`` file. The ``__init__.py`` file can remain empty for now and we'll come back to it in the next chapter. On the other hand, the ``__manifest__.py`` file must describe our module and cannot remain empty. Its only required field is the ``name``, but it usually contains much more information." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:68 msgid "Take a look at the `CRM file `__ as an example. In addition to providing the description of the module (``name``, ``category``, ``summary``, ``website``...), it lists its dependencies (``depends``). A dependency means that the Odoo framework will ensure that these modules are installed before our module is installed. Moreover, if one of these dependencies is uninstalled, then our module and **any other that depends on it will also be uninstalled**. Think about your favorite Linux distribution package manager (``apt``, ``dnf``, ``pacman``...): Odoo works in the same way." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:77 msgid "Create the required addon files." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:79 msgid "Create the following folders and files:" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:81 msgid "``/home/$USER/src/custom/estate/__init__.py``" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:82 msgid "``/home/$USER/src/custom/estate/__manifest__.py``" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:84 msgid "The ``__manifest__.py`` file should only define the name and the dependencies of our modules. The only necessary framework module for now is ``base``." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:88 msgid "Restart the Odoo server and add the ``custom`` folder to the ``addons-path``:" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:94 msgid "Go to Apps, click on Update Apps List, search for ``estate`` and... tadaaa, your module appears! Did it not appear? Maybe try removing the default 'Apps' filter ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:97 msgid "Make your module an 'App'." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:99 msgid "Add the appropriate key to your ``__manifest__.py`` so that the module appears when the 'Apps' filter is on." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:102 msgid "You can even install the module! But obviously it's an empty shell, so no menu will appear." msgstr "" #: ../../content/developer/howtos/rdtraining/03_newapp.rst:104 msgid "All good? If yes, then let's :ref:`create our first model `!" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:5 msgid "Chapter 4: Models And Basic Fields" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:7 msgid "At the end of the :ref:`previous chapter `, we were able to create an Odoo module. However, at this point it is still an empty shell which doesn't allow us to store any data. In our real estate module, we want to store the information related to the properties (name, description, price, living area...) in a database. The Odoo framework provides tools to facilitate database interactions." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:13 msgid "Before moving forward in the exercise, make sure the ``estate`` module is installed, i.e. it must appear as 'Installed' in the Apps list." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:19 msgid "**Reference**: the documentation related to this topic can be found in the :ref:`reference/orm/model` API." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:24 msgid "**Goal**: at the end of this section, the table ``estate_property`` should be created:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:35 msgid "A key component of Odoo is the `ORM`_ layer. This layer avoids having to manually write most `SQL`_ and provides extensibility and security services\\ [#rawsql]_." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:39 msgid "Business objects are declared as Python classes extending :class:`~odoo.models.Model`, which integrates them into the automated persistence system." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:43 msgid "Models can be configured by setting attributes in their definition. The most important attribute is :attr:`~odoo.models.Model._name`, which is required and defines the name for the model in the Odoo system. Here is a minimum definition of a model::" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:54 msgid "This definition is enough for the ORM to generate a database table named ``test_model``. The ``.`` in the model ``_name`` is automatically converted into a ``_`` by the ORM. By convention all models are located in a ``models`` directory and each model is defined in its own Python file." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:59 msgid "Take a look at how the ``crm_recurring_plan`` table is defined and how the corresponding Python file is imported:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:62 msgid "The model is defined in the file ``crm/models/crm_recurring_plan.py`` (see `here `__)" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:64 msgid "The file ``crm_recurring_plan.py`` is imported in ``crm/models/__init__.py`` (see `here `__)" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:66 msgid "The folder ``models`` is imported in ``crm/__init__.py`` (see `here `__)" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:69 msgid "Define the real estate properties model." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:71 msgid "Based on example given in the CRM module, create the appropriate files and folder for the ``estate_property`` table." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:74 msgid "When the files are created, add a minimum definition for the ``estate.property`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:77 msgid "Any modification of the Python files requires a restart of the Odoo server. When we restart the server, we will add the parameters ``-d`` and ``-u``:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:84 msgid "``-u estate`` means we want to upgrade the ``estate`` module, i.e. the ORM will apply database schema changes. In this case it creates a new table. ``-d rd-demo`` means that the upgrade should be performed on the ``rd-demo`` database. ``-u`` should always be used in combination with ``-d``." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:89 msgid "During the startup you should see the following warnings:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:99 msgid "If this is the case, then you should be good! To be sure, double check with ``psql`` as demonstrated in the **Goal**." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:102 msgid "Add a description." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:104 msgid "Add a ``_description`` to your model to get rid of one of the warnings." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:109 msgid "**Reference**: the documentation related to this topic can be found in the :ref:`reference/orm/fields` API." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:112 msgid "Fields are used to define what the model can store and where they are stored. Fields are defined as attributes in the model class::" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:123 msgid "The ``name`` field is a :class:`~odoo.fields.Char` which will be represented as a Python unicode ``str`` and a SQL ``VARCHAR``." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:127 #: ../../content/developer/misc/api/iap.rst:636 msgid "Types" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:131 msgid "**Goal**: at the end of this section, several basic fields should have been added to the table ``estate_property``:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:167 msgid "There are two broad categories of fields: 'simple' fields, which are atomic values stored directly in the model's table, and 'relational' fields, which link records (of the same or different models)." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:171 msgid "Simple field examples are :class:`~odoo.fields.Boolean`, :class:`~odoo.fields.Float`, :class:`~odoo.fields.Char`, :class:`~odoo.fields.Text`, :class:`~odoo.fields.Date` and :class:`~odoo.fields.Selection`." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:175 msgid "Add basic fields to the Real Estate Property table." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:177 msgid "Add the following basic fields to the table:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:180 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:253 #: ../../content/developer/howtos/rdtraining/08_relations.rst:71 #: ../../content/developer/howtos/rdtraining/08_relations.rst:178 #: ../../content/developer/howtos/rdtraining/08_relations.rst:241 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:173 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:215 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:262 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:149 #: ../../content/developer/howtos/rdtraining/C_data.rst:175 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:300 msgid "Field" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:180 #: ../../content/developer/howtos/rdtraining/08_relations.rst:71 #: ../../content/developer/howtos/rdtraining/08_relations.rst:178 #: ../../content/developer/howtos/rdtraining/08_relations.rst:241 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:173 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:215 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:262 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:149 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:300 msgid "Type" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:182 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:255 #: ../../content/developer/howtos/rdtraining/08_relations.rst:73 #: ../../content/developer/howtos/rdtraining/08_relations.rst:180 #: ../../content/developer/howtos/rdtraining/C_data.rst:177 #: ../../content/developer/reference/addons/static/res.country.state.csv:1 msgid "name" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:182 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:184 #: ../../content/developer/howtos/rdtraining/08_relations.rst:73 #: ../../content/developer/howtos/rdtraining/08_relations.rst:180 msgid "Char" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:183 #: ../../content/developer/howtos/rdtraining/C_data.rst:179 msgid "description" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:183 msgid "Text" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:184 #: ../../content/developer/howtos/rdtraining/C_data.rst:180 msgid "postcode" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:185 #: ../../content/developer/howtos/rdtraining/C_data.rst:181 msgid "date_availability" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:185 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:176 msgid "Date" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:186 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:256 #: ../../content/developer/howtos/rdtraining/C_data.rst:182 msgid "expected_price" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:186 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:187 #: ../../content/developer/howtos/rdtraining/08_relations.rst:243 msgid "Float" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:187 #: ../../content/developer/howtos/rdtraining/C_data.rst:183 msgid "selling_price" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:188 #: ../../content/developer/howtos/rdtraining/C_data.rst:184 msgid "bedrooms" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:188 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:189 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:190 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:193 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:175 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:217 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:264 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:302 msgid "Integer" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:189 #: ../../content/developer/howtos/rdtraining/C_data.rst:185 msgid "living_area" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:190 #: ../../content/developer/howtos/rdtraining/C_data.rst:186 msgid "facades" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:191 #: ../../content/developer/howtos/rdtraining/C_data.rst:187 msgid "garage" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:191 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:192 msgid "Boolean" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:192 #: ../../content/developer/howtos/rdtraining/C_data.rst:188 msgid "garden" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:193 #: ../../content/developer/howtos/rdtraining/C_data.rst:189 msgid "garden_area" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:194 #: ../../content/developer/howtos/rdtraining/C_data.rst:190 msgid "garden_orientation" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:194 #: ../../content/developer/howtos/rdtraining/08_relations.rst:244 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:303 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:305 msgid "Selection" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:197 msgid "The ``garden_orientation`` field must have 4 possible values: 'North', 'South', 'East' and 'West'. The selection list is defined as a list of tuples, see `here `__ for an example." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:202 msgid "When the fields are added to the model, restart the server with ``-u estate``" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:208 msgid "Connect to ``psql`` and check the structure of the table ``estate_property``. You'll notice that a couple of extra fields were also added to the table. We will revisit them later." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:216 msgid "**Goal**: at the end of this section, the columns ``name`` and ``expected_price`` should be not nullable in the table ``estate_property``:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:231 msgid "Much like the model itself, fields can be configured by passing configuration attributes as parameters::" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:238 msgid ":attr:`~odoo.fields.Field.string` (``str``, default: field's name)" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:241 msgid "If ``True``, the field can not be empty. It must either have a default value or always be given a value when creating a record." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:243 msgid ":attr:`~odoo.fields.Field.help` (``str``, default: ``''``)" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:244 msgid "Provides long-form help tooltip for users in the UI." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:248 msgid "Set attributes for existing fields." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:250 msgid "Add the following attributes:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:253 #: ../../content/developer/reference/javascript/javascript_reference.rst:2024 msgid "Attribute" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:255 #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:256 #: ../../content/developer/howtos/rdtraining/08_relations.rst:73 #: ../../content/developer/howtos/rdtraining/08_relations.rst:180 #: ../../content/developer/howtos/rdtraining/08_relations.rst:245 #: ../../content/developer/howtos/rdtraining/08_relations.rst:246 msgid "required" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:259 msgid "After restarting the server, both fields should be not nullable." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:262 msgid "Automatic Fields" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:264 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/fields/automatic`." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:267 msgid "You may have noticed your model has a few fields you never defined. Odoo creates a few fields in all models\\ [#autofields]_. These fields are managed by the system and can't be written to, but they can be read if useful or necessary:" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:273 msgid "The unique identifier for a record of the model." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:281 msgid "User who last modified the record." msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:284 msgid "Now that we have created our first model, let's :ref:`add some security `!" msgstr "" #: ../../content/developer/howtos/rdtraining/04_basicmodel.rst:290 msgid "writing raw SQL queries is possible, but requires caution as this bypasses all Odoo authentication and security mechanisms." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:5 msgid "Chapter 5: Security - A Brief Introduction" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:7 msgid "In the :ref:`previous chapter `, we created our first table intended to store business data. In a business application such as Odoo, one of the first questions to consider is who\\ [#who]_ can access the data. Odoo provides a security mechanism to allow access to the data for specific groups of users." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:12 msgid "The topic of security is covered in more detail in :ref:`howto/rdtraining/B_acl_irrules`. This chapter aims to cover the minimum required for our new module." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:16 msgid "Data Files (CSV)" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:18 msgid "Odoo is a highly data driven system. Although behavior is customized using Python code, part of a module's value is in the data it sets up when loaded. One way to load data is through a CSV file. One example is the `list of country states `__ which is loaded at installation of the ``base`` module." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:33 #: ../../content/developer/howtos/rdtraining/06_firstui.rst:83 msgid "``id`` is an :term:`external identifier`. It can be used to refer to the record (without knowing its in-database identifier)." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:35 msgid "``country_id:id`` refers to the country by using its :term:`external identifier`." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:36 msgid "``name`` is the name of the state." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:37 msgid "``code`` is the code of the state." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:39 msgid "These three fields are `defined `__ in the ``res.country.state`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:43 msgid "By convention, a file importing data is located in the ``data`` folder of a module. When the data is related to security, it is located in the ``security`` folder. When the data is related to views and actions (we will cover this later), it is located in the ``views`` folder. Additionally, all of these files must be declared in the ``data`` list within the ``__manifest__.py`` file. Our example file is defined `in the manifest of the base module `__." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:50 msgid "Also note that the content of the data files is only loaded when a module is installed or updated." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:55 msgid "The data files are sequentially loaded following their order in the ``__manifest__.py`` file. This means that if data ``A`` refers to data ``B``, you must make sure that ``B`` is loaded before ``A``." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:59 msgid "In the case of the country states, you will note that the `list of countries `__ is loaded **before** the `list of country states `__. This is because the states refer to the countries." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:65 msgid "Why is all this important for security? Because all the security configuration of a model is loaded through data files, as we'll see in the next section." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:69 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:137 #: ../../content/developer/reference/addons/security.rst:45 msgid "Access Rights" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:71 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/security/acl`." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:76 msgid "**Goal**: at the end of this section, the following warning should not appear anymore:" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:82 msgid "When no access rights are defined on a model, Odoo determines that no users can access the data. It is even notified in the log:" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:89 msgid "Access rights are defined as records of the model ``ir.model.access``. Each access right is associated with a model, a group (or no group for global access) and a set of permissions: create, read, write and unlink\\ [#unlink]_. Such access rights are usually defined in a CSV file named ``ir.model.access.csv``." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:95 msgid "Here is an example for our previous ``test.model``:" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:102 msgid "``id`` is an :term:`external identifier`." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:103 msgid "``name`` is the name of the ``ir.model.access``." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:104 msgid "``model_id/id`` refers to the model which the access right applies to. The standard way to refer to the model is ``model_``, where ```` is the ``_name`` of the model with the ``.`` replaced by ``_``. Seems cumbersome? Indeed it is..." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:107 msgid "``group_id/id`` refers to the group which the access right applies to. We will cover the concept of groups in the :ref:`advanced topic ` dedicated to the security." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:109 msgid "``perm_read,perm_write,perm_create,perm_unlink``: read, write, create and unlink permissions" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:111 msgid "Add access rights." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:113 msgid "Create the ``ir.model.access.csv`` file in the appropriate folder and define it in the ``__manifest__.py`` file." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:116 msgid "Give the read, write, create and unlink permissions to the group ``base.group_user``." msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:118 msgid "Tip: the warning message in the log gives you most of the solution ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:120 msgid "Restart the server and the warning message should have disappeared!" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:122 msgid "It's now time to finally :ref:`interact with the UI `!" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:124 msgid "meaning which Odoo user (or group of users)" msgstr "" #: ../../content/developer/howtos/rdtraining/05_securityintro.rst:126 msgid "'unlink' is the equivalent of 'delete'" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:5 msgid "Chapter 6: Finally, Some UI To Play With" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:7 msgid "Now that we've created our new :ref:`model ` and its corresponding :ref:`access rights `, it is time to interact with the user interface." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:11 msgid "At the end of this chapter, we will have created a couple of menus in order to access a default list and form view." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:15 msgid "Data Files (XML)" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:17 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/data`." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:20 msgid "In :ref:`howto/rdtraining/05_securityintro`, we added data through a CSV file. The CSV format is convenient when the data to load has a simple format. When the format is more complex (e.g. load the structure of a view or an email template), we use the XML format. For example, this `help field `__ contains HTML tags. While it would be possible to load such data through a CSV file, it is more convenient to use an XML file." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:28 msgid "The XML files must be added to the same folders as the CSV files and defined similarly in the ``__manifest__.py``. The content of the data files is also sequentially loaded when a module is installed or updated, therefore all remarks made for CSV files hold true for XML files. When the data is linked to views, we add them to the ``views`` folder." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:33 msgid "In this chapter we will load our first action and menus though an XML file. Actions and menus are standard records in the database." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:38 msgid "When performance is important, the CSV format is preferred over the XML format. This is the case in Odoo where loading a CSV file is faster than loading an XML file." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:41 msgid "In Odoo, the user interface (actions, menus and views) is largely defined by creating and composing records defined in an XML file. A common pattern is Menu > Action > View. To access records the user navigates through several menu levels; the deepest level is an action which triggers the opening of a list of the records." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:47 #: ../../content/developer/misc/other/iot.rst:138 #: ../../content/developer/reference/addons/actions.rst:6 msgid "Actions" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:49 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/actions`." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:54 msgid "**Goal**: at the end of this section, an action should be loaded in the system. We won't see anything yet in the UI, but the file should be loaded in the log:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:61 msgid "Actions can be triggered in three ways:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:67 msgid "We will only cover the first case in this chapter. The second case will be covered in a :ref:`later chapter ` while the last is the focus of an advanced topic. In our Real Estate example, we would like to link a menu to the ``estate.property`` model, so we are able to create a new record. The action can be viewed as the link between the menu and the model." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:73 msgid "A basic action for our ``test.model`` is:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:85 msgid "``model`` has a fixed value of ``ir.actions.act_window`` (:ref:`reference/actions/window`)." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:86 msgid "``name`` is the name of the action." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:87 msgid "``res_model`` is the model which the action applies to." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:88 msgid "``view_mode`` are the views that will be available; in this case they are the list (tree) and form views. We'll see :ref:`later ` that there can be other view modes." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:91 msgid "Examples can be found everywhere in Odoo, but `this `__ is a good example of a simple action. Pay attention to the structure of the XML data file since you will need it in the following exercise." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:96 msgid "Add an action." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:98 msgid "Create the ``estate_property_views.xml`` file in the appropriate folder and define it in the ``__manifest__.py`` file." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:101 msgid "Create an action for the model ``estate.property``." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:103 msgid "Restart the server and you should see the file loaded in the log." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:106 msgid "Menus" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:108 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/data/shortcuts`." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:113 msgid "**Goal**: at the end of this section, three menus should be created and the default view is displayed:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:128 msgid "To reduce the complexity in declaring a menu (``ir.ui.menu``) and connecting it to the corresponding action, we can use the ```` shortcut ." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:131 msgid "A basic menu for our ``test_model_action`` is:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:137 msgid "The menu ``test_model_menu_action`` is linked to the action ``test_model_action``, and the action is linked to the model ``test.model``. As previously mentioned, the action can be seen as the link between the menu and the model." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:141 msgid "However, menus always follow an architecture, and in practice there are three levels of menus:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:143 msgid "The root menu, which is displayed in the App switcher (the Odoo Community App switcher is a dropdown menu)" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:145 msgid "The first level menu, displayed in the top bar" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:146 msgid "The action menus" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:156 msgid "The easiest way to define the structure is to create it in the XML file. A basic structure for our ``test_model_action`` is:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:167 msgid "The name for the third menu is taken from the name of the ``action``." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:169 msgid "Add menus." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:171 msgid "Create the ``estate_menus.xml`` file in the appropriate folder and define it in the ``__manifest__.py`` file. Remember the sequential loading of the data files ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:174 msgid "Create the three levels of menus for the ``estate.property`` action created in the previous exercise. Refer to the **Goal** of this section for the expected result." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:177 msgid "Restart the server and **refresh the browser**\\ [#refresh]_. You should now see the menus, and you'll even be able to create your first real estate property advertisement!" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:181 msgid "Fields, Attributes And View" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:185 msgid "**Goal**: at the end of this section, the selling price should be read-only and the number of bedrooms and the availability date should have default values. Additionally the selling price and availability date values won't be copied when the record is duplicated." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:193 msgid "The reserved fields ``active`` and ``state`` are added to the ``estate.property`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:195 msgid "So far we have only used the generic view for our real estate property advertisements, but in most cases we want to fine tune the view. There are many fine-tunings possible in Odoo, but usually the first step is to make sure that:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:199 msgid "some fields have a default value" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:200 msgid "some fields are read-only" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:201 msgid "some fields are not copied when duplicating the record" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:203 msgid "In our real estate business case, we would like the following:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:205 msgid "The selling price should be read-only (it will be automatically filled in later)" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:206 msgid "The availability date and the selling price should not be copied when duplicating a record" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:207 msgid "The default number of bedrooms should be 2" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:208 msgid "The default availability date should be in 3 months" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:211 msgid "Some New Attributes" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:213 msgid "Before moving further with the view design, let's step back to our model definition. We saw that some attributes, such as ``required=True``, impact the table schema in the database. Other attributes will impact the view or provide default values." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:217 msgid "Add new attributes to the fields." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:219 msgid "Find the appropriate attributes (see :class:`~odoo.fields.Field`) to:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:221 msgid "set the selling price as read-only" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:222 msgid "prevent copying of the availability date and the selling price values" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:224 msgid "Restart the server and refresh the browser. You should not be able to set any selling prices. When duplicating a record, the availability date should be empty." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:228 msgid "Default Values" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:230 msgid "Any field can be given a default value. In the field definition, add the option ``default=X`` where ``X`` is either a Python literal value (boolean, integer, float, string) or a function taking a model and returning a value::" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:237 msgid "The ``name`` field will have the value 'Unknown' by default while the ``last_seen`` field will be set as the current time." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:240 msgid "Set default values." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:242 msgid "Add the appropriate default attributes so that:" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:244 msgid "the default number of bedrooms is 2" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:245 msgid "the default availability date is in 3 months" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:247 msgid "Tip: this might help you: :meth:`~odoo.fields.Date.today`" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:249 msgid "Check that the default values are set as expected." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:252 msgid "Reserved Fields" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:254 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/orm/fields/reserved`." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:257 msgid "A few field names are reserved for pre-defined behaviors. They should be defined on a model when the related behavior is desired." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:260 msgid "Add active field." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:262 msgid "Add the ``active`` field to the ``estate.property`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:264 msgid "Restart the server, create a new property, then come back to the list view... The property will not be listed! ``active`` is an example of a reserved field with a specific behavior: when a record has ``active=False``, it is automatically removed from any search. To display the created property, you will need to specifically search for inactive records." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:273 msgid "Set a default value for active field." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:275 msgid "Set the appropriate default value for the ``active`` field so it doesn't disappear anymore." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:277 msgid "Note that the default ``active=False`` value was assigned to all existing records." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:279 msgid "Add state field." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:281 msgid "Add a ``state`` field to the ``estate.property`` model. Five values are possible: New, Offer Received, Offer Accepted, Sold and Canceled. It must be required, should not be copied and should have its default value set to 'New'." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:285 msgid "Make sure to use the correct type!" msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:287 msgid "The ``state`` will be used later on for several UI enhancements." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:289 msgid "Now that we are able to interact with the UI thanks to the default views, the next step is obvious: we want to define :ref:`our own views `." msgstr "" #: ../../content/developer/howtos/rdtraining/06_firstui.rst:292 msgid "A refresh is needed since the web client keeps a cache of the various menus and views for performance reasons." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:5 msgid "Chapter 7: Basic Views" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:7 msgid "We have seen in the :ref:`previous chapter ` that Odoo is able to generate default views for a given model. In practice, the default view is **never** acceptable for a business application. Instead, we should at least organize the various fields in a logical manner." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:12 msgid "Views are defined in XML files with actions and menus. They are instances of the ``ir.ui.view`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:15 msgid "In our real estate module, we need to organize the fields in a logical way:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:17 msgid "in the list (tree) view, we want to display more than just the name." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:18 msgid "in the form view, the fields should be grouped." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:19 msgid "in the search view, we must be able to search on more than just the name. Specifically, we want a filter for the 'Available' properties and a shortcut to group by postcode." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:23 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:317 #: ../../content/developer/reference/addons/views.rst:1374 msgid "List" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:25 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/views/list`." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:30 msgid "**Goal**: at the end of this section, the list view should look like this:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:36 msgid "List views, also called tree views, display records in a tabular form." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:38 msgid "Their root element is ````. The most basic version of this view simply lists all the fields to display in the table (where each field is a column):" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:48 msgid "A simple example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:51 msgid "Add a custom list view." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:53 msgid "Define a list view for the ``estate.property`` model in the appropriate XML file. Check the **Goal** of this section for the fields to display." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:56 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:378 #: ../../content/developer/howtos/rdtraining/14_other_module.rst:117 msgid "Tips:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:58 msgid "do not add the ``editable=\"bottom\"`` attribute that you can find in the example above. We'll come back to it later." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:60 msgid "some field labels may need to be adapted to match the reference." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:63 msgid "As always, you need to restart the server (do not forget the ``-u`` option) and refresh the browser to see the result." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:68 msgid "You will probably use some copy-paste in this chapter, therefore always make sure that the ``id`` remains unique for each view!" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:72 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:234 #: ../../content/developer/reference/addons/views.rst:728 msgid "Form" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:74 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/views/form`." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:79 msgid "**Goal**: at the end of this section, the form view should look like this:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:87 msgid "Their root element is ````. They are composed of high-level structure elements (groups and notebooks) and interactive elements (buttons and fields):" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:110 msgid "It is possible to use regular HTML tags such as ``div`` and ``h1`` as well as the the ``class`` attribute (Odoo provides some built-in classes) to fine-tune the look." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:113 msgid "A simple example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:116 msgid "Add a custom form view." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:118 msgid "Define a form view for the ``estate.property`` model in the appropriate XML file. Check the **Goal** of this section for the expected final design of the page." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:121 msgid "This might require some trial and error before you get to the expected result ;-) It is advised that you add the fields and the tags one at a time to help understand how it works." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:124 msgid "In order to avoid relaunching the server every time you do a modification to the view, it can be convenient to use the ``--dev xml`` parameter when launching the server:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:131 msgid "This parameter allows you to just refresh the page to view your view modifications." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:134 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:385 #: ../../content/developer/reference/addons/views.rst:1822 msgid "Search" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:136 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/views/search`." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:141 msgid "**Goal**: at the end of this section, the search view should look like this:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:155 msgid "Search views are slightly different from the list and form views since they don't display *content*. Although they apply to a specific model, they are used to filter other views' content (generally aggregated views such as :ref:`reference/views/list`). Beyond the difference in use case, they are defined the same way." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:160 msgid "Their root element is ````. The most basic version of this view simply lists all the fields for which a shortcut is desired:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:170 msgid "The default search view generated by Odoo provides a shortcut to filter by ``name``. It is very common to add the fields which the user is likely to filter on in a customized search view." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:173 msgid "Add a custom search view." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:175 msgid "Define a search view for the ``estate.property`` model in the appropriate XML file. Check the first image of this section's **Goal** for the list of fields." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:178 msgid "After restarting the server, it should be possible to filter on the given fields." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:183 msgid "``domain``: adds the given domain to the current search" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:184 msgid "``context``: adds some context to the current search; uses the key ``group_by`` to group results on the given field name" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:187 msgid "A simple example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:190 msgid "Before going further in the exercise, it is necessary to introduce the 'domain' concept." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:195 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/orm/domains`." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:198 msgid "In Odoo, a domain encodes conditions on records: a domain is a list of criteria used to select a subset of a model's records. Each criterion is a triplet with a *field name*, an *operator* and a *value*. A record satisfies a criterion if the specified field meets the condition of the operator applied to the value." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:203 msgid "For instance, when used on the *Product* model the following domain selects all *services* with a unit price greater than *1000*::" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:208 msgid "By default criteria are combined with an implicit AND, meaning *every* criterion needs to be satisfied for a record to match a domain. The logical operators ``&`` (AND), ``|`` (OR) and ``!`` (NOT) can be used to explicitly combine criteria. They are used in prefix position (the operator is inserted before its arguments rather than between). For instance, to select products 'which are services *OR* have a unit price which is *NOT* between 1000 and 2000'::" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:221 msgid "Add filter and Group By." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:223 msgid "The following should be added to the previously created search view:" msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:225 msgid "a filter which displays available properties, i.e. the state should be 'New' or 'Offer Received'." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:227 msgid "the ability to group results by postcode." msgstr "" #: ../../content/developer/howtos/rdtraining/07_basicviews.rst:229 msgid "Looking good? At this point we are already able to create models and design a user interface which makes sense business-wise. However, a key component is still missing: the :ref:`link between models `." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:5 msgid "Chapter 8: Relations Between Models" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:7 msgid "The :ref:`previous chapter ` covered the creation of custom views for a model containing basic fields. However, in any real business scenario we need more than one model. Moreover, links between models are necessary. One can easily imagine one model containing the customers and another one containing the list of users. You might need to refer to a customer or a user on any existing business model." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:13 msgid "In our real estate module, we want the following information for a property:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:15 msgid "the customer who bought the property" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:16 msgid "the real restate agent who sold the property" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:17 msgid "the property type: house, apartment, penthouse, castle..." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:18 msgid "a list of tags characterizing the property: cozy, renovated..." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:19 msgid "a list of the offers received" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:22 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:304 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:306 msgid "Many2one" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:24 msgid "**Reference**: the documentation related to this topic can be found in :class:`~odoo.fields.Many2one`." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:29 #: ../../content/developer/howtos/rdtraining/08_relations.rst:136 #: ../../content/developer/howtos/rdtraining/08_relations.rst:199 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:26 #: ../../content/developer/howtos/rdtraining/10_actions.rst:27 #: ../../content/developer/howtos/rdtraining/11_constraints.rst:24 #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:20 #: ../../content/developer/howtos/rdtraining/14_other_module.rst:18 msgid "**Goal**: at the end of this section:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:31 msgid "a new ``estate.property.type`` model should be created with the corresponding menu, action and views." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:37 msgid "three Many2one fields should be added to the ``estate.property`` model: property type, buyer and seller." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:43 msgid "In our real estate module, we want to define the concept of property type. A property type is, for example, a house or an apartment. It is a standard business need to categorize properties according to their type, especially to refine filtering." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:47 msgid "A property can have **one** type, but the same type can be assigned to **many** properties. This is supported by the **many2one** concept." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:50 msgid "A many2one is a simple link to another object. For example, in order to define a link to the ``res.partner`` in our test model, we can write::" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:55 msgid "By convention, many2one fields have the ``_id`` suffix. Accessing the data in the partner can then be easily done with::" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:62 msgid "`foreign keys `_" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:64 msgid "In practice a many2one can be seen as a dropdown list in a form view." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:66 msgid "Add the Real Estate Property Type table." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:68 msgid "Create the ``estate.property.type`` model and add the following field:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:71 #: ../../content/developer/howtos/rdtraining/08_relations.rst:178 #: ../../content/developer/howtos/rdtraining/08_relations.rst:241 #: ../../content/developer/reference/addons/views.rst:68 msgid "Attributes" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:76 #: ../../content/developer/howtos/rdtraining/08_relations.rst:183 msgid "Add the menus as displayed in this section's **Goal**" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:77 msgid "Add the field ``property_type_id`` into your ``estate.property`` model and its form, tree and search views" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:80 msgid "This exercise is a good recap of the previous chapters: you need to create a :ref:`model `, set the :ref:`model `, add an :ref:`action and a menu `, and :ref:`create a view `." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:86 msgid "Tip: do not forget to import any new Python files in ``__init__.py``, add new data files in ``__manifest.py__`` or add the access rights ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:89 msgid "Once again, restart the server and refresh to see the results!" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:91 msgid "In the real estate module, there are still two missing pieces of information we want on a property: the buyer and the salesperson. The buyer can be any individual, but on the other hand the salesperson must be an employee of the real estate agency (i.e. an Odoo user)." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:95 msgid "In Odoo, there are two models which we commonly refer to:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:97 msgid "``res.partner``: a partner is a physical or legal entity. It can be a company, an individual or even a contact address." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:99 msgid "``res.users``: the users of the system. Users can be 'internal', i.e. they have access to the Odoo backend. Or they can be 'portal', i.e. they cannot access the backend, only the frontend (e.g. to access their previous orders in eCommerce)." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:103 msgid "Add the buyer and the salesperson." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:105 msgid "Add a buyer and a salesperson to the ``estate.property`` model using the two common models mentioned above. They should be added in a new tab of the form view, as depicted in this section's **Goal**." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:108 msgid "The default value for the salesperson must be the current user. The buyer should not be copied." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:110 msgid "Tip: to get the default value, check the note below or look at an example `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:126 msgid "Now let's have a look at other types of links." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:129 msgid "Many2many" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:131 msgid "**Reference**: the documentation related to this topic can be found in :class:`~odoo.fields.Many2many`." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:138 msgid "a new ``estate.property.tag`` model should be created with the corresponding menu and action." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:144 msgid "tags should be added to the ``estate.property`` model:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:150 msgid "In our real estate module, we want to define the concept of property tags. A property tag is, for example, a property which is 'cozy' or 'renovated'." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:153 msgid "A property can have **many** tags and a tag can be assigned to **many** properties. This is supported by the **many2many** concept." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:156 msgid "A many2many is a bidirectional multiple relationship: any record on one side can be related to any number of records on the other side. For example, in order to define a link to the ``account.tax`` model on our test model, we can write::" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:162 msgid "By convention, many2many fields have the ``_ids`` suffix. This means that several taxes can be added to our test model. It behaves as a list of records, meaning that accessing the data must be done in a loop::" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:169 msgid "A list of records is known as a *recordset*, i.e. an ordered collection of records. It supports standard Python operations on collections, such as ``len()`` and ``iter()``, plus extra set operations like ``recs1 | recs2``." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:173 msgid "Add the Real Estate Property Tag table." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:175 msgid "Create the ``estate.property.tag`` model and add the following field:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:184 msgid "Add the field ``tag_ids`` to your ``estate.property`` model and in its form and tree views" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:186 msgid "Tip: in the view, use the ``widget=\"many2many_tags\"`` attribute as demonstrated `here `__. The ``widget`` attribute will be explained in detail in :ref:`a later chapter of the training `. For now, you can try to adding and removing it and see the result ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:192 msgid "One2many" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:194 msgid "**Reference**: the documentation related to this topic can be found in :class:`~odoo.fields.One2many`." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:201 msgid "a new ``estate.property.offer`` model should be created with the corresponding form and tree view." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:202 msgid "offers should be added to the ``estate.property`` model:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:208 msgid "In our real estate module, we want to define the concept of property offers. A property offer is an amount a potential buyer offers to the seller. The offer can be lower or higher than the expected price." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:212 msgid "An offer applies to **one** property, but the same property can have **many** offers. The concept of **many2one** appears once again. However, in this case we want to display the list of offers for a given property so we will use the **one2many** concept." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:216 msgid "A one2many is the inverse of a many2one. For example, we defined on our test model a link to the ``res.partner`` model thanks to the field ``partner_id``. We can define the inverse relation, i.e. the list of test models linked to our partner::" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:222 msgid "The first parameter is called the ``comodel`` and the second parameter is the field we want to inverse." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:225 msgid "By convention, one2many fields have the ``_ids`` suffix. They behave as a list of records, meaning that accessing the data must be done in a loop::" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:233 msgid "Because a :class:`~odoo.fields.One2many` is a virtual relationship, there *must* be a :class:`~odoo.fields.Many2one` field defined in the comodel." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:236 msgid "Add the Real Estate Property Offer table." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:238 msgid "Create the ``estate.property.offer`` model and add the following fields:" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:241 #: ../../content/developer/howtos/rdtraining/C_data.rst:175 #: ../../content/developer/howtos/rdtraining/C_data.rst:175 msgid "Values" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:243 msgid "price" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:244 msgid "status" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:244 msgid "no copy" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:244 msgid "Accepted, Refused" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:245 msgid "partner_id" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:245 msgid "Many2one (``res.partner``)" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:246 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:304 msgid "property_id" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:246 msgid "Many2one (``estate.property``)" msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:249 msgid "Create a tree view and a form view with the ``price``, ``partner_id`` and ``status`` fields. No need to create an action or a menu." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:251 msgid "Add the field ``offer_ids`` to your ``estate.property`` model and in its form view as depicted in this section's **Goal**." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:254 msgid "There are several important things to notice here. First, we don't need an action or a menu for all models. Some models are intended to be accessed only through another model. This is the case in our exercise: an offer is always accessed through a property." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:258 msgid "Second, despite the fact that the ``property_id`` field is required, we did not include it in the views. How does Odoo know which property our offer is linked to? Well that's part of the magic of using the Odoo framework: sometimes things are defined implicitly. When we create a record through a one2many field, the corresponding many2one is populated automatically for convenience." msgstr "" #: ../../content/developer/howtos/rdtraining/08_relations.rst:264 msgid "Still alive? This chapter is definitely not the easiest one. It introduced a couple of new concepts while relying on everything that was introduced before. The :ref:`next chapter ` will be lighter, don't worry ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:5 msgid "Chapter 9: Computed Fields And Onchanges" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:7 msgid "The :ref:`relations between models ` are a key component of any Odoo module. They are necessary for the modelization of any business case. However, we may want links between the fields within a given model. Sometimes the value of one field is determined from the values of other fields and other times we want to help the user with data entry." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:13 msgid "These cases are supported by the concepts of computed fields and onchanges. Although this chapter is not technically complex, the semantics of both concepts is very important. This is also the first time we will write Python logic. Until now we haven't written anything other than class definitions and field declarations." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:19 #: ../../../odoo/odoo/fields.py:docstring of odoo.fields.Field:89 #: ../../content/developer/reference/addons/orm.rst:232 msgid "Computed Fields" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:21 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/fields/compute`." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:28 msgid "In the property model, the total area and the best offer should be computed:" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:34 msgid "In the property offer model, the validity date should be computed and can be updated:" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:40 msgid "In our real estate module, we have defined the living area as well as the garden area. It is then natural to define the total area as the sum of both fields. We will use the concept of a computed field for this, i.e. the value of a given field will be computed from the value of other fields." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:44 msgid "So far fields have been stored directly in and retrieved directly from the database. Fields can also be *computed*. In this case, the field's value is not retrieved from the database but computed on-the-fly by calling a method of the model." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:49 msgid "To create a computed field, create a field and set its attribute :attr:`~odoo.fields.Field.compute` to the name of a method. The computation method should set the value of the computed field for every record in ``self``." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:54 msgid "By convention, :attr:`~odoo.fields.Field.compute` methods are private, meaning that they cannot be called from the presentation tier, only from the business tier (see :ref:`howto/rdtraining/01_architecture`). Private methods have a name starting with an underscore ``_``." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:61 msgid "The value of a computed field usually depends on the values of other fields in the computed record. The ORM expects the developer to specify those dependencies on the compute method with the decorator :func:`~odoo.api.depends`. The given dependencies are used by the ORM to trigger the recomputation of the field whenever some of its dependencies have been modified::" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:80 msgid "``self`` is a collection." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:83 msgid "The object ``self`` is a *recordset*, i.e. an ordered collection of records. It supports the standard Python operations on collections, e.g. ``len(self)`` and ``iter(self)``, plus extra set operations such as ``recs1 | recs2``." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:88 msgid "Iterating over ``self`` gives the records one by one, where each record is itself a collection of size 1. You can access/assign fields on single records by using the dot notation, e.g. ``record.name``." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:92 msgid "Many examples of computed fields can be found in Odoo. `Here `__ is a simple one." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:96 msgid "Compute the total area." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:98 msgid "Add the ``total_area`` field to ``estate.property``. It is defined as the sum of the ``living_area`` and the ``garden_area``." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:101 msgid "Add the field in the form view as depicted on the first image of this section's **Goal**." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:103 msgid "For relational fields it's possible to use paths through a field as a dependency::" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:113 msgid "The example is given with a :class:`~odoo.fields.Many2one`, but it is valid for :class:`~odoo.fields.Many2many` or a :class:`~odoo.fields.One2many`. An example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:117 msgid "Let's try it in our module with the following exercise!" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:119 msgid "Compute the best offer." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:121 msgid "Add the ``best_price`` field to ``estate.property``. It is defined as the highest (i.e. maximum) of the offers' ``price``." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:124 msgid "Add the field to the form view as depicted in the first image of this section's **Goal**." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:126 msgid "Tip: you might want to try using the :meth:`~odoo.models.BaseModel.mapped` method. See `here `__ for a simple example." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:131 msgid "Inverse Function" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:133 msgid "You might have noticed that computed fields are read-only by default. This is expected since the user is not supposed to set a value." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:136 msgid "In some cases, it might be useful to still be able to set a value directly. In our real estate example, we can define a validity duration for an offer and set a validity date. We would like to be able to set either the duration or the date with one impacting the other." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:140 msgid "To support this Odoo provides the ability to use an ``inverse`` function::" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:159 msgid "An example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:162 msgid "A compute method sets the field while an inverse method sets the field's dependencies." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:165 msgid "Note that the ``inverse`` method is called when saving the record, while the ``compute`` method is called at each change of its dependencies." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:168 msgid "Compute a validity date for offers." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:170 msgid "Add the following fields to the ``estate.property.offer`` model:" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:173 msgid "Default" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:175 msgid "validity" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:175 msgid "7" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:176 msgid "date_deadline" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:179 msgid "Where ``date_deadline`` is a computed field which is defined as the sum of two fields from the offer: the ``create_date`` and the ``validity``. Define an appropriate inverse function so that the user can set either the date or the validity." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:183 msgid "Tip: the ``create_date`` is only filled in when the record is created, therefore you will need a fallback to prevent crashing at time of creation." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:186 msgid "Add the fields in the form view and the list view as depicted on the second image of this section's **Goal**." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:189 #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:275 msgid "Additional Information" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:191 msgid "Computed fields are **not stored** in the database by default. Therefore it is **not possible** to search on a computed field unless a ``search`` method is defined. This topic is beyond the scope of this training, so we won't cover it. An example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:196 msgid "Another solution is to store the field with the ``store=True`` attribute. While this is usually convenient, pay attention to the potential computation load added to your model. Lets re-use our example::" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:208 msgid "Every time the partner ``name`` is changed, the ``description`` is automatically recomputed for **all the records** referring to it! This can quickly become prohibitive to recompute when millions of records need recomputation." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:212 msgid "It is also worth noting that a computed field can depend on another computed field. The ORM is smart enough to correctly recompute all the dependencies in the right order... but sometimes at the cost of degraded performance." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:216 msgid "In general performance must always be kept in mind when defining computed fields. The more complex is your field to compute (e.g. with a lot of dependencies or when a computed field depends on other computed fields), the more time it will take to compute. Always take some time to evaluate the cost of a computed field beforehand. Most of the time it is only when your code reaches a production server that you realize it slows down a whole process. Not cool :-(" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:223 msgid "Onchanges" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:225 msgid "**Reference**: the documentation related to this topic can be found in :func:`~odoo.api.onchange`:" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:230 msgid "**Goal**: at the end of this section, enabling the garden will set a default area of 10 and an orientation to North." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:237 msgid "In our real estate module, we also want to help the user with data entry. When the 'garden' field is set, we want to give a default value for the garden area as well as the orientation. Additionally, when the 'garden' field is unset we want the garden area to reset to zero and the orientation to be removed. In this case, the value of a given field modifies the value of other fields." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:243 msgid "The 'onchange' mechanism provides a way for the client interface to update a form without saving anything to the database whenever the user has filled in a field value. To achieve this, we define a method where ``self`` represents the record in the form view and decorate it with :func:`~odoo.api.onchange` to specify which field it is triggered by. Any change you make on ``self`` will be reflected on the form::" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:264 msgid "In this example, changing the partner will also change the name and the description values. It is up to the user whether or not to change the name and description values afterwards. Also note that we do not loop on ``self``, this is because the method is only triggered in a form view, where ``self`` is always a single record." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:269 msgid "Set values for garden area and orientation." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:271 msgid "Create an ``onchange`` in the ``estate.property`` model in order to set values for the garden area (10) and orientation (North) when garden is set to True. When unset, clear the fields." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:277 msgid "Onchanges methods can also return a non-blocking warning message (`example `__)." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:281 msgid "How to use them?" msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:283 msgid "There is no strict rule for the use of computed fields and onchanges." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:285 msgid "In many cases, both computed fields and onchanges may be used to achieve the same result. Always prefer computed fields since they are also triggered outside of the context of a form view. Never ever use an onchange to add business logic to your model. This is a **very bad** idea since onchanges are not automatically triggered when creating a record programmatically; they are only triggered in the form view." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:291 msgid "The usual pitfall of computed fields and onchanges is trying to be 'too smart' by adding too much logic. This can have the opposite result of what was expected: the end user is confused from all the automation." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:295 msgid "Computed fields tend to be easier to debug: such a field is set by a given method, so it's easy to track when the value is set. Onchanges, on the other hand, may be confusing: it is very difficult to know the extent of an onchange. Since several onchange methods may set the same fields, it easily becomes difficult to track where a value is coming from." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:300 msgid "When using stored computed fields, pay close attention to the dependencies. When computed fields depend on other computed fields, changing a value can trigger a large number of recomputations. This leads to poor performance." msgstr "" #: ../../content/developer/howtos/rdtraining/09_compute_onchange.rst:304 msgid "In the :ref:`next chapter`, we'll see how we can trigger some business logic when buttons are clicked." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:5 msgid "Chapter 10: Ready For Some Action?" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:7 msgid "So far we have mostly built our module by declaring fields and views. We just introduced business logic in the :ref:`previous chapter ` thanks to computed fields and onchanges. In any real business scenario, we would want to link some business logic to action buttons. In our real estate example, we would like to be able to:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:12 msgid "cancel or set a property as sold" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:13 msgid "accept or refuse an offer" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:15 msgid "One could argue that we can already do these things by changing the state manually, but this is not really convenient. Moreover, we want to add some extra processing: when an offer is accepted we want to set the selling price and the buyer for the property." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:20 msgid "Action Type" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:22 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/actions` and :ref:`reference/exceptions`." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:29 msgid "You should be able to cancel or set a property as sold:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:35 msgid "A canceled property cannot be sold and a sold property cannot be canceled. For the sake of clarity, the ``state`` field has been added on the view." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:38 msgid "You should be able to accept or refuse an offer:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:44 msgid "Once an offer is accepted, the selling price and the buyer should be set:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:50 msgid "In our real estate module, we want to link business logic with some buttons. The most common way to do this is to:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:53 msgid "Add a button in the view, for example in the ``header`` of the view:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:66 msgid "and link this button to business logic:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:82 msgid "By assigning ``type=\"object\"`` to our button, the Odoo framework will execute a Python method with ``name=\"action_do_something\"`` on the given model." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:85 msgid "The first important detail to note is that our method name isn't prefixed with an underscore (``_``). This makes our method a **public** method, which can be called directly from the Odoo interface (through an RPC call). Until now, all methods we created (compute, onchange) were called internally, so we used **private** methods prefixed by an underscore. You should always define your methods as private unless they need to be called from the user interface." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:91 msgid "Also note that we loop on ``self``. Always assume that a method can be called on multiple records; it's better for reusability." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:94 msgid "Finally, a public method should always return something so that it can be called through XML-RPC. When in doubt, just ``return True``." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:97 msgid "There are hundreds of examples in the Odoo source code. One example is this `button in a view `__ and its `corresponding Python method `__" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:102 msgid "Cancel and set a property as sold." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:104 msgid "Add the buttons 'Cancel' and 'Sold' to the ``estate.property`` model. A canceled property cannot be set as sold, and a sold property cannot be canceled." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:107 msgid "Refer to the first image of the **Goal** for the expected result." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:109 msgid "Tip: in order to raise an error, you can use the :ref:`UserError` function. There are plenty of examples in the Odoo source code ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:112 msgid "Add the buttons 'Accept' and 'Refuse' to the ``estate.property.offer`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:114 msgid "Refer to the second image of the **Goal** for the expected result." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:116 msgid "Tip: to use an icon as a button, have a look `at this example `__." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:119 msgid "When an offer is accepted, set the buyer and the selling price for the corresponding property." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:121 msgid "Refer to the third image of the **Goal** for the expected result." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:123 msgid "Pay attention: in real life only one offer can be accepted for a given property!" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:126 msgid "Object Type" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:128 msgid "In :ref:`howto/rdtraining/06_firstui`, we created an action that was linked to a menu. You may be wondering if it is possible to link an action to a button. Good news, it is! One way to do it is:" msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:136 msgid "We use ``type=\"action\"`` and we refer to the :term:`external identifier` in the ``name``." msgstr "" #: ../../content/developer/howtos/rdtraining/10_actions.rst:138 msgid "In the :ref:`next chapter ` we'll see how we can prevent encoding incorrect data in Odoo." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:5 msgid "Chapter 11: Constraints" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:7 msgid "The :ref:`previous chapter ` introduced the ability to add some business logic to our model. We can now link buttons to business code, but how can we prevent users from entering incorrect data? For example, in our real estate module nothing prevents users from setting a negative expected price." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:17 msgid "SQL" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:19 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/orm/models` and in the `PostgreSQL's documentation`_." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:26 msgid "Amounts should be (strictly) positive" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:32 msgid "Property types and tags should have a unique name" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:38 msgid "SQL constraints are defined through the model attribute :attr:`~odoo.models.Model._sql_constraints`. This attribute is assigned a list of triples containing strings ``(name, sql_definition, message)``, where ``name`` is a valid SQL constraint name, ``sql_definition`` is a table_constraint_ expression and ``message`` is the error message." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:44 msgid "You can find a simple example `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:47 msgid "Add SQL constraints." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:49 msgid "Add the following constraints to their corresponding models:" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:51 msgid "A property expected price must be strictly positive" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:52 msgid "A property selling price must be positive" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:53 msgid "An offer price must be strictly positive" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:54 msgid "A property tag name and property type name must be unique" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:56 msgid "Tip: search for the ``unique`` keyword in the Odoo codebase for examples of unique names." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:58 msgid "Restart the server with the ``-u estate`` option to see the result. Note that you might have data that prevents a SQL constraint from being set. An error message similar to the following might pop up:" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:65 msgid "For example, if some offers have a price of zero, then the constraint can't be applied. You can delete the problematic data in order to apply the new constraints." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:71 msgid "**Reference**: the documentation related to this topic can be found in :func:`~odoo.api.constrains`." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:76 msgid "**Goal**: at the end of this section, it will not possible to accept an offer lower than 90% of the expected price." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:83 msgid "SQL constraints are an efficient way of ensuring data consistency. However it may be necessary to make more complex checks which require Python code. In this case we need a Python constraint." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:86 msgid "A Python constraint is defined as a method decorated with :func:`~odoo.api.constrains` and is invoked on a recordset. The decorator specifies which fields are involved in the constraint. The constraint is automatically evaluated when any of these fields are modified . The method is expected to raise an exception if its invariant is not satisfied::" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:103 msgid "A simple example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:106 msgid "Add Python constraints." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:108 msgid "Add a constraint so that the selling price cannot be lower than 90% of the expected price." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:110 msgid "Tip: the selling price is zero until an offer is validated. You will need to fine tune your check to take this into account." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:115 msgid "Always use the :meth:`~odoo.tools.float_utils.float_compare` and :meth:`~odoo.tools.float_utils.float_is_zero` methods when working with floats!" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:118 msgid "Ensure the constraint is triggered every time the selling price or the expected price is changed!" msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:120 msgid "SQL constraints are usually more efficient than Python constraints. When performance matters, always prefer SQL over Python constraints." msgstr "" #: ../../content/developer/howtos/rdtraining/11_constraints.rst:123 msgid "Our real estate module is starting to look good. We added some business logic, and now we make sure the data is consistent. However, the user interface is still a bit rough. Let's see how we can improve it in the :ref:`next chapter `." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:5 msgid "Chapter 12: Add The Sprinkles" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:7 msgid "Our real estate module now makes sense from a business perspective. We created :ref:`specific views `, added several :ref:`action buttons ` and :ref:`constraints `. However our user interface is still a bit rough. We would like to add some colors to the list views and make some fields and buttons conditionally disappear. For example, the 'Sold' and 'Cancel' buttons should disappear when the property is sold or canceled since it is no longer allowed to change the state at this point." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:15 msgid "This chapter covers a very small subset of what can be done in the views. Do not hesitate to read the reference documentation for a more complete overview." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:18 msgid "**Reference**: the documentation related to this chapter can be found in :ref:`reference/views`." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:22 msgid "Inline Views" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:26 msgid "**Goal**: at the end of this section, a specific list of properties should be added to the property type view:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:33 msgid "In the real estate module we added a list of offers for a property. We simply added the field ``offer_ids`` with:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:40 msgid "The field uses the specific view for ``estate.property.offer``. In some cases we want to define a specific list view which is only used in the context of a form view. For example, we would like to display the list of properties linked to a property type. However, we only want to display 3 fields for clarity: name, expected price and state." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:45 msgid "To do this, we can define *inline* list views. An inline list view is defined directly inside a form view. For example:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:81 msgid "In the form view of the ``test.model``, we define a specific list view for ``test.model.line`` with fields ``field_1`` and ``field_2``." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:84 msgid "An example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:87 msgid "Add an inline list view." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:89 msgid "Add the ``One2many`` field ``property_ids`` to the ``estate.property.type`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:90 msgid "Add the field in the ``estate.property.type`` form view as depicted in the **Goal** of this section." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:94 #: ../../content/developer/reference/javascript/javascript_reference.rst:491 msgid "Widgets" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:96 msgid "**Reference**: the documentation related to this section can be found in :ref:`reference/js/widgets`." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:101 msgid "**Goal**: at the end of this section, the state of the property should be displayed using a specific widget:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:108 msgid "Four states are displayed: New, Offer Received, Offer Accepted and Sold." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:110 msgid "Whenever we've added fields to our models, we've (almost) never had to worry about how these fields would look like in the user interface. For example, a date picker is provided for a ``Date`` field and a ``One2many`` field is automatically displayed as a list. Odoo chooses the right 'widget' depending on the field type." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:115 msgid "However, in some cases, we want a specific representation of a field which can be done thanks to the ``widget`` attribute. We already used it for the ``tag_ids`` field when we used the ``widget=\"many2many_tags\"`` attribute. If we hadn't used it, then the field would have displayed as a list." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:120 msgid "Each field type has a set of widgets which can be used to fine tune its display. Some widgets also take extra options. An exhaustive list can be found in :ref:`reference/js/widgets`." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:123 msgid "Use the status bar widget." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:125 msgid "Use the ``statusbar`` widget in order to display the ``state`` of the ``estate.property`` as depicted in the **Goal** of this section." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:128 msgid "Tip: a simple example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:131 msgid "Same field multiple times in a view" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:133 msgid "Add a field only **once** to a list or a form view. Adding it multiple times is not supported." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:137 msgid "List Order" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:139 msgid "**Reference**: the documentation related to this section can be found in :ref:`reference/orm/models`." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:144 msgid "**Goal**: at the end of this section, all lists should display by default in a deterministic order. Property types can be ordered manually." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:147 msgid "During the previous exercises, we created several list views. However, at no point did we specify which order the records had to be listed in by default. This is a very important thing for many business cases. For example, in our real estate module we would want to display the highest offers on top of the list." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:153 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:182 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:215 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:262 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:248 #: ../../content/developer/reference/addons/orm.rst:90 msgid "Model" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:155 msgid "Odoo provides several ways to set a default order. The most common way is to define the ``_order`` attribute directly in the model. This way, the retrieved records will follow a deterministic order which will be consistent in all views including when records are searched programmatically. By default there is no order specified, therefore the records will be retrieved in a non-deterministic order depending on PostgreSQL." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:161 msgid "The ``_order`` attribute takes a string containing a list of fields which will be used for sorting. It will be converted to an order_by_ clause in SQL. For example:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:175 msgid "Our records are ordered by descending ``id``, meaning the highest comes first." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:177 msgid "Add model ordering." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:179 msgid "Define the following orders in their corresponding models:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:182 msgid "Order" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:184 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:304 msgid "``estate.property``" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:184 msgid "Descending ID" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:185 msgid "``estate.property.offer``" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:185 msgid "Descending Price" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:186 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:264 msgid "``estate.property.tag``" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:186 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:187 msgid "Name" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:187 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:217 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:306 msgid "``estate.property.type``" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:191 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:318 msgid "View" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:193 msgid "Ordering is possible at the model level. This has the advantage of a consistent order everywhere a list of records is retrieved. However, it is also possible to define a specific order directly in a view thanks to the ``default_order`` attribute (`example `__)." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:199 msgid "Manual" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:201 msgid "Both model and view ordering allow flexibility when sorting records, but there is still one case we need to cover: the manual ordering. A user may want to sort records depending on the business logic. For example, in our real estate module we would like to sort the property types manually. It is indeed useful to have the most used types appear at the top of the list. If our real estate agency mainly sells houses, it is more convenient to have 'House' appear before 'Apartment'." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:207 msgid "To do so, a ``sequence`` field is used in combination with the ``handle`` widget. Obviously the ``sequence`` field must be the first field in the ``_order`` attribute." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:210 msgid "Add manual ordering." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:212 #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:259 msgid "Add the following field:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:217 msgid "Sequence" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:220 msgid "Add the sequence to the ``estate.property.type`` list view with the correct widget." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:222 msgid "Tip: you can find an example here: `model `__ and `view `__." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:228 msgid "Attributes and options" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:230 msgid "It would be prohibitive to detail all the available features which allow fine tuning of the look of a view. Therefore, we'll stick to the most common ones." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:238 msgid "**Goal**: at the end of this section, the property form view will have:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:240 msgid "Conditional display of buttons and fields" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:241 msgid "Tag colors" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:248 msgid "In our real estate module, we want to modify the behavior of some fields. For example, we don't want to be able to create or edit a property type from the form view. Instead we expect the types to be handled in their appropriate menu. We also want to give tags a color. In order to add these behavior customizations, we can add the ``options`` attribute to several field widgets." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:253 msgid "Add widget options." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:255 msgid "Add the appropriate option to the ``property_type_id`` field to prevent the creation and the editing of a property type from the property form view. Have a look at the :ref:`Many2one widget documentation ` for more info." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:264 msgid "Color" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:267 msgid "Then add the appropriate option to the ``tag_ids`` field to add a color picker on the tags. Have a look at the :ref:`FieldMany2ManyTags widget documentation ` for more info." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:271 msgid "In :ref:`howto/rdtraining/06_firstui`, we saw that reserved fields were used for specific behaviors. For example, the ``active`` field is used to automatically filter out inactive records. We added the ``state`` as a reserved field as well. It's now time to use it! A ``state`` field is used in combination with a ``states`` attribute in the view to display buttons conditionally." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:277 msgid "Add conditional display of buttons." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:279 msgid "Use the ``states`` attribute to display the header buttons conditionally as depicted in this section's **Goal** (notice how the 'Sold' and 'Cancel' buttons change when the state is modified)." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:282 msgid "Tip: do not hesitate to search for ``states=`` in the Odoo XML files for some examples." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:284 msgid "More generally, it is possible to make a field ``invisible``, ``readonly`` or ``required`` based on the value of other fields thanks to the ``attrs`` attribute. Note that ``invisible`` can also be applied to other elements of the view such as ``button`` or ``group``." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:288 msgid "The ``attrs`` is a dictionary with the property as a key and a domain as a value. The domain gives the condition in which the property applies. For example:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:298 msgid "This means that the ``description`` field is invisible when ``is_partner`` is ``False``. It is important to note that a field used in an ``attrs`` **must** be present in the view. If it should not be displayed to the user, we can use the ``invisible`` attribute to hide it." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:302 msgid "Use ``attrs``." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:304 msgid "Make the garden area and orientation invisible in the ``estate.property`` form view when there is no garden." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:306 msgid "Make the 'Accept' and 'Refuse' buttons invisible once the offer state is set." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:307 msgid "Do not allow adding an offer when the property state is 'Offer Accepted', 'Sold' or 'Canceled'. To do this use the ``readonly`` ``attrs``." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:312 msgid "Using a (conditional) ``readonly`` attribute in the view can be useful to prevent data entry errors, but keep in mind that it doesn't provide any level of security! There is no check done server-side, therefore it's always possible to write on the field through a RPC call." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:321 msgid "**Goal**: at the end of this section, the property and offer list views should have color decorations. Additionally, offers and tags will be editable directly in the list, and the availability date will be hidden by default." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:333 msgid "When the model only has a few fields, it can be useful to edit records directly through the list view and not have to open the form view. In the real estate example, there is no need to open a form view to add an offer or create a new tag. This can be achieved thanks to the ``editable`` attribute." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:337 msgid "Make list views editable." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:339 msgid "Make the ``estate.property.offer`` and ``estate.property.tag`` list views editable." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:341 msgid "On the other hand, when a model has a lot of fields it can be tempting to add too many fields in the list view and make it unclear. An alternative method is to add the fields, but make them optionally hidden. This can be achieved thanks to the ``optional`` attribute." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:345 msgid "Make a field optional." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:347 msgid "Make the field ``date_availability`` on the ``estate.property`` list view optional and hidden by default." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:350 msgid "Finally, color codes are useful to visually emphasize records. For example, in the real estate module we would like to display refused offers in red and accepted offers in green. This can be achieved thanks to the ``decoration-{$name}`` attribute (see :ref:`reference/js/widgets` for a complete list):" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:362 msgid "The records where ``is_partner`` is ``True`` will be displayed in green." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:364 msgid "Add some decorations." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:366 msgid "On the ``estate.property`` list view:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:368 msgid "Properties with an offer received are green" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:369 msgid "Properties with an offer accepted are green and bold" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:370 msgid "Properties sold are muted" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:372 msgid "On the ``estate.property.offer`` list view:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:374 msgid "Refused offers are red" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:375 msgid "Accepted offers are green" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:376 msgid "The state should not be visible anymore" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:380 msgid "Keep in mind that **all** fields used in attributes must be in the view!" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:381 msgid "If you want to test the color of the \"Offer Received\" and \"Offer Accepted\" states, add the field in the form view and change it manually (we'll implement the business logic for this later)." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:387 msgid "**Reference**: the documentation related to this section can be found in :ref:`reference/views/search` and :ref:`reference/views/search/defaults`." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:392 msgid "**Goal**: at the end of this section, the available properties will be filtered by default, and searching on the living area returns results where the area is larger than the given number." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:400 msgid "Last but not least, there are some tweaks we would like to apply when searching. First of all, we want to have our 'Available' filter applied by default when we access the properties. To make this happen, we need to use the ``search_default_{$name}`` action context, where ``{$name}`` is the filter name. This means that we can define which filter(s) will be activated by default at the action level." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:405 msgid "Here is an example of an `action `__ with its `corresponding filter `__." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:410 msgid "Add a default filter." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:412 msgid "Make the 'Available' filter selected by default in the ``estate.property`` action." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:414 msgid "Another useful improvement in our module would be the ability to search efficiently by living area. In practice, a user will want to search for properties of 'at least' the given area. It is unrealistic to expect users would want to find a property of an exact living area. It is always possible to make a custom search, but that's inconvenient." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:419 msgid "Search view ```` elements can have a ``filter_domain`` that overrides the domain generated for searching on the given field. In the given domain, ``self`` represents the value entered by the user. In the example below, it is used to search on both ``name`` and ``description`` fields." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:432 msgid "Change the living area search." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:434 msgid "Add a ``filter_domain`` to the living area to include properties with an area equal to or greater than the given value." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:438 msgid "Stat Buttons" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:442 msgid "**Goal**: at the end of this section, there will be a stat button on the property type form view which shows the list of all offers related to properties of the given type when it is clicked on." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:449 msgid "If you've already used some functional modules in Odoo, you've probably already encountered a 'stat button'. These buttons are displayed on the top right of a form view and give a quick access to linked documents. In our real estate module, we would like to have a quick link to the offers related to a given property type as depicted in the **Goal** of this section." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:454 msgid "At this point of the tutorial we have already seen most of the concepts to do this. However, there is not a single solution and it can still be confusing if you don't know where to start from. We'll describe a step-by-step solution in the exercise. It can always be useful to find some examples in the Odoo codebase by looking for ``oe_stat_button``." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:459 msgid "The following exercise might be a bit more difficult than the previous ones since it assumes you are able to search for examples in the source code on your own. If you are stuck there is probably someone nearby who can help you ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:463 msgid "The exercise introduces the concept of :ref:`reference/fields/related`. The easiest way to understand it is to consider it as a specific case of a computed field. The following definition of the ``description`` field:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:474 msgid "is equivalent to:" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:488 msgid "Every time the partner name is changed, the description is modified." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:490 msgid "Add a stat button to property type." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:492 msgid "Add the field ``property_type_id`` to ``estate.property.offer``. We can define it as a related field on ``property_id.property_type_id`` and set it as stored." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:495 msgid "Thanks to this field, an offer will be linked to a property type when it's created. You can add the field to the list view of offers to make sure it works." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:498 msgid "Add the field ``offer_ids`` to ``estate.property.type`` which is the One2many inverse of the field defined in the previous step." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:501 msgid "Add the field ``offer_count`` to ``estate.property.type``. It is a computed field that counts the number of offers for a given property type (use ``offer_ids`` to do so)." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:504 msgid "At this point, you have all the information necessary to know how many offers are linked to a property type. When in doubt, add ``offer_ids`` and ``offer_count`` directly to the view. The next step is to display the list when clicking on the stat button." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:508 msgid "Create a stat button on ``estate.property.type`` pointing to the ``estate.property.offer`` action. This means you should use the ``type=\"action\"`` attribute (go back to the end of :ref:`howto/rdtraining/10_actions` if you need a refresher)." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:512 msgid "At this point, clicking on the stat button should display all offers. We still need to filter out the offers." msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:515 msgid "On the ``estate.property.offer`` action, add a domain that defines ``property_type_id`` as equal to the ``active_id`` (= the current record, `here is an example `__)" msgstr "" #: ../../content/developer/howtos/rdtraining/12_sprinkles.rst:519 msgid "Looking good? If not, don't worry, the :ref:`next chapter ` doesn't require stat buttons ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:5 msgid "Chapter 13: Inheritance" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:7 msgid "A powerful aspect of Odoo is its modularity. A module is dedicated to a business need, but modules can also interact with one another. This is useful for extending the functionality of an existing module. For example, in our real estate scenario we want to display the list of a salesperson's properties directly in the regular user view." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:12 msgid "But before going through the specific Odoo module inheritance, let's see how we can alter the behavior of the standard CRUD (Create, Retrieve, Update or Delete) methods." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:16 msgid "Python Inheritance" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:22 msgid "It should not be possible to delete a property which is not new or canceled." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:28 msgid "When an offer is created, the property state should change to 'Offer Received'" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:29 msgid "It should not be possible to create an offer with a lower price than an existing offer" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:35 msgid "In our real estate module, we never had to develop anything specific to be able to do the standard CRUD actions. The Odoo framework provides the necessary tools to do them. In fact, such actions are already included in our model thanks to classical Python inheritance::" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:48 msgid "Our ``class TestModel`` inherits from :class:`~odoo.models.Model` which provides :meth:`~odoo.models.Model.create`, :meth:`~odoo.models.Model.read`, :meth:`~odoo.models.Model.write` and :meth:`~odoo.models.Model.unlink`." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:52 msgid "These methods (and any other method defined on :class:`~odoo.models.Model`) can be extended to add specific business logic::" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:70 msgid "The decorator :func:`~odoo.api.model` is necessary for the :meth:`~odoo.models.Model.create` method because the content of the recordset ``self`` is not relevant in the context of creation, but it is not necessary for the other CRUD methods." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:74 msgid "In Python 3, ``super()`` is equivalent to ``super(TestModel, self)``. The latter may be necessary when you need to call the parent method with a modified recordset." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:79 msgid "It is very important to **always** call ``super()`` to avoid breaking the flow. There are only a few very specific cases where you don't want to call it." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:81 msgid "Make sure to **always** return data consistent with the parent method. For example, if the parent method returns a ``dict()``, your override must also return a ``dict()``." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:84 msgid "Add business logic to the CRUD methods." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:86 msgid "Prevent deletion of a property if its state is not 'New' or 'Canceled'" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:88 msgid "Tip: override :meth:`~odoo.models.Model.unlink` and remember that ``self`` can be a recordset with more than one record." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:91 msgid "At offer creation, set the property state to 'Offer Received'. Also raise an error if the user tries to create an offer with a lower amount than an existing offer." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:94 msgid "Tip: the ``property_id`` field is available in the ``vals``, but it is an ``int``. To instantiate an ``estate.property`` object, use ``self.env[model_name].browse(value)`` (`example `__)" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:99 msgid "Model Inheritance" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:101 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/orm/inheritance`." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:104 msgid "In our real estate module, we would like to display the list of properties linked to a salesperson directly in the Settings / Users & Companies / Users form view. To do this, we need to add a field to the ``res.users`` model and adapt its view to show it." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:110 msgid "The first inheritance mechanism allows modules to modify the behavior of a model defined in an another module by:" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:113 msgid "adding fields to the model," msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:114 msgid "overriding the definition of fields in the model," msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:115 msgid "adding constraints to the model," msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:116 msgid "adding methods to the model," msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:117 msgid "overriding existing methods in the model." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:119 msgid "The second inheritance mechanism (delegation) allows every record of a model to be linked to a parent model's record and provides transparent access to the fields of this parent record." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:127 msgid "In Odoo, the first mechanism is by far the most used. In our case, we want to add a field to an existing model, which means we will use the first mechanism. For example::" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:137 msgid "A practical example where two fields are added to a model can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:141 msgid "By convention, each inherited model is defined in its own Python file. In our example, it would be ``models/inherited_model.py``." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:144 msgid "Add a field to Users." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:146 msgid "Add the following field to ``res.users``:" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:151 msgid "property_ids" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:151 msgid "One2many inverse of ``user_id`` to ``estate.property``" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:154 msgid "Add a domain to the field so it only lists the available properties." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:156 msgid "Now let's add the field to the view and check that everything is working well!" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:159 msgid "View Inheritance" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:161 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/views/inheritance`." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:166 msgid "**Goal**: at the end of this section, the list of available properties linked to a salesperson should be displayed in their user form view" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:173 msgid "Instead of modifying existing views in place (by overwriting them), Odoo provides view inheritance where children 'extension' views are applied on top of root views. These extension can both add and remove content from their parent view." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:177 msgid "An extension view references its parent using the ``inherit_id`` field. Instead of a single view, its ``arch`` field contains a number of ``xpath`` elements that select and alter the content of their parent view:" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:203 msgid "appends ``xpath``'s body to the end of the matched element" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:212 msgid "alters the attributes of the matched element using the special ``attribute`` elements in the ``xpath``'s body" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:215 msgid "When matching a single element, the ``position`` attribute can be set directly on the element to be found. Both inheritances below have the same result." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:228 msgid "An example of a view inheritance extension can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:231 msgid "Add fields to the Users view." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:233 msgid "Add the ``property_ids`` field to the ``base.view_users_form`` in a new notebook page." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:235 msgid "Tip: an example an inheritance of the users' view can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:238 msgid "Inheritance is extensively used in Odoo due to its modular concept. Do not hesitate to read the corresponding documentation for more info!" msgstr "" #: ../../content/developer/howtos/rdtraining/13_inheritance.rst:241 msgid "In the :ref:`next chapter `, we will learn how to interact with other modules." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:5 msgid "Chapter 14: Interact With Other Modules" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:7 msgid "In the :ref:`previous chapter `, we used inheritance to modify the behavior of a module. In our real estate scenario, we would like to go a step further and be able to generate invoices for our customers. Odoo provides an Invoicing module, so it would be neat to create an invoice directly from our real estate module, i.e. once a property is set to 'Sold', an invoice is created in the Invoicing application." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:14 msgid "Concrete Example: Account Move" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:20 msgid "A new module ``estate_account`` should be created" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:21 msgid "When a property is sold, an invoice should be issued for the buyer" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:27 msgid "Any time we interact with another module, we need to keep in mind the modularity. If we intend to sell our application to real estate agencies, some may want the invoicing feature but others may not want it." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:32 msgid "Link Module" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:34 msgid "The common approach for such use cases is to create a 'link' module. In our case, the module would depend on ``estate`` and ``account`` and would include the invoice creation logic of the estate property. This way the real estate and the accounting modules can be installed independently. When both are installed, the link module provides the new feature." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:39 msgid "Create a link module." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:41 msgid "Create the ``estate_account`` module, which depends on the ``estate`` and ``account`` modules. For now, it will be an empty shell." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:44 msgid "Tip: you already did this at the :ref:`beginning of the tutorial `. The process is very similar." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:47 msgid "When the ``estate_account`` module appears in the list, go ahead and install it! You'll notice that the Invoicing application is installed as well. This is expected since your module depends on it. If you uninstall the Invoicing application, your module will be uninstalled as well." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:54 msgid "Invoice Creation" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:56 msgid "It's now time to generate the invoice. We want to add functionality to the ``estate.property`` model, i.e. we want to add some extra logic for when a property is sold. Does that sound familiar? If not, it's a good idea to go back to the :ref:`previous chapter ` since you might have missed something ;-)" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:61 msgid "As a first step, we need to extend the action called when pressing the :ref:`'Sold' button ` on a property. To do so, we need to create a :ref:`model inheritance ` in the ``estate_account`` module for the ``estate.property`` model. For now, the overridden action will simply return the ``super`` call. Maybe an example will make things clearer::" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:75 msgid "A practical example can be found `here `__." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:78 msgid "Add the first step of invoice creation." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:80 msgid "Create a ``estate_property.py`` file in the correct folder of the ``estate_account`` module." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:81 msgid "``_inherit`` the ``estate.property`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:82 msgid "Override the ``action_sold`` method (you might have named it differently) to return the ``super`` call." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:85 msgid "Tip: to make sure it works, add a ``print`` or a debugger breakpoint in the overridden method." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:87 msgid "Is it working? If not, maybe check that all Python files are correctly imported." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:89 msgid "If the override is working, we can move forward and create the invoice. Unfortunately, there is no easy way to know how to create any given object in Odoo. Most of the time, it is necessary to have a look at its model to find the required fields and provide appropriate values." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:93 msgid "A good way to learn is to look at how other modules already do what you want to do. For example, one of the basic flows of Sales is the creation of an invoice from a sales order. This looks like a good starting point since it does exactly what we want to do. Take some time to read and understand the `_create_invoices `__ method. When you are done crying because this simple task looks awfully complex, we can move forward in the tutorial." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:100 msgid "To create an invoice, we need the following information:" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:102 msgid "a ``partner_id``: the customer" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:103 msgid "a ``move_type``: it has several `possible values `__" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:104 msgid "a ``journal_id``: the accounting journal" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:106 msgid "This is enough to create an empty invoice." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:108 msgid "Add the second step of invoice creation." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:110 msgid "Create an empty ``account.move`` in the override of the ``action_sold`` method:" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:112 msgid "the ``partner_id`` is taken from the current ``estate.property``" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:113 msgid "the ``move_type`` should correspond to a 'Customer Invoice'" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:114 msgid "the ``journal_id`` must be a ``sale`` journal (when in doubt, have a look `here `__)" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:119 msgid "to create an object, use ``self.env[model_name].create(values)``, where ``values`` is a ``dict``." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:121 msgid "the ``create`` method doesn't accept recordsets as field values." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:123 msgid "When a property is set to 'Sold', you should now have a new customer invoice created in Invoicing / Customers / Invoices." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:126 msgid "Obviously we don't have any invoice lines so far. To create an invoice line, we need the following information:" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:129 msgid "``name``: a description of the line" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:130 msgid "``quantity``" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:131 msgid "``price_unit``" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:133 msgid "Moreover, an invoice line needs to be linked to an invoice. The easiest and most efficient way to link a line to an invoice is to include all lines at invoice creation. To do this, the ``invoice_line_ids`` field is included in the ``account.move`` creation, which is a :class:`~odoo.fields.One2many`. One2many and Many2many use special 'commands' described in :ref:`reference/orm/models/crud`. This format is a list of triplets executed sequentially, where each triplet is a command to execute on the set of records. Here is a simple example to include a One2many field ``line_ids`` at creation of a ``test.model``::" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:159 msgid "Add the third step of invoice creation." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:161 msgid "Add two invoice lines during the creation of the ``account.move``. Each property sold will be invoiced following these conditions:" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:164 msgid "6% of the selling price" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:165 msgid "an additional 100.00 from administrative fees" msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:167 msgid "Tip: Add the ``invoice_line_ids`` at creation following the example above. For each line, we need a ``name``, ``quantity`` and ``price_unit``." msgstr "" #: ../../content/developer/howtos/rdtraining/14_other_module.rst:170 msgid "This chapter might be one of the most difficult that has been covered so far, but it is the closest to what Odoo development will be in practice. In the :ref:`next chapter `, we will introduce the templating mechanism used in Odoo." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:5 msgid "Chapter 15: A Brief History Of QWeb" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:7 msgid "So far the interface design of our real estate module has been rather limited. Building a list view is straightforward since only the list of fields is necessary. The same holds true for the form view: despite the use of a few tags such as ```` or ````, there is very little to do in terms of design." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:12 msgid "However, if we want to give a unique look to our application, it is necessary to go a step further and be able to design new views. Moreover, other features such as PDF reports or website pages need another tool to be created with more flexibility: a templating_ engine." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:16 msgid "You might already be familiar with existing engines such as Jinja (Python), ERB (Ruby) or Twig (PHP). Odoo comes with its own built-in engine: :ref:`reference/qweb`. QWeb is the primary templating engine used by Odoo. It is an XML templating engine and used mostly to generate HTML fragments and pages." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:21 msgid "You probably already have come across the `kanban board`_ in Odoo where the records are displayed in a card-like structure. We will build such a view for our real estate module." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:25 msgid "Concrete Example: A Kanban View" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:27 msgid "**Reference**: the documentation related to this topic can be found in :ref:`reference/views/kanban`." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:32 msgid "**Goal**: at the end of this section a Kanban view of the properties should be created:" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:38 msgid "In our estate application, we would like to add a Kanban view to display our properties. Kanban views are a standard Odoo view (like the form and list views), but their structure is much more flexible. In fact, the structure of each card is a mix of form elements (including basic HTML) and QWeb. The definition of a Kanban view is similar to the definition of the list and form views, except that their root element is ````. In its simplest form, a Kanban view looks like:" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:57 msgid "Let's break down this example:" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:59 msgid "````: defines a list of :ref:`reference/qweb` templates. Kanban views *must* define at least one root template ``kanban-box``, which will be rendered once for each record." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:61 msgid "````: ```` is a placeholder element for QWeb directives. In this case, it is used to set the ``name`` of the template to ``kanban-box``" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:63 msgid "``
``: the ``oe_kanban_global_click`` makes the ``
`` clickable to open the record." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:65 msgid "````: this will add the ``name`` field to the view." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:67 msgid "Make a minimal kanban view." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:69 msgid "Using the simple example provided, create a minimal Kanban view for the properties. The only field to display is the ``name``." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:72 msgid "Tip: you must add ``kanban`` in the ``view_mode`` of the corresponding ``ir.actions.act_window``." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:75 msgid "Once the Kanban view is working, we can start improving it. If we want to display an element conditionally, we can use the ``t-if`` directive (see :ref:`reference/qweb/conditionals`)." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:94 msgid "We added a few things:" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:96 msgid "``t-if``: the ``
`` element is rendered if the condition is true." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:97 msgid "``record``: an object with all the requested fields as its attributes. Each field has two attributes ``value`` and ``raw_value``. The former is formatted according to current user parameters and the latter is the direct value from a :meth:`~odoo.models.Model.read`." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:101 msgid "In the above example, the field ``name`` was added in the ```` element, but ``state`` is outside of it. When we need the value of a field but don't want to display it in the view, it is possible to add it outside of the ```` element." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:105 msgid "Improve the Kanban view." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:107 msgid "Add the following fields to the Kanban view: expected price, best price, selling price and tags. Pay attention: the best price is only displayed when an offer is received, while the selling price is only displayed when an offer is accepted." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:111 #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:121 msgid "Refer to the **Goal** of the section for a visual example." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:113 msgid "Let's give the final touch to our view: the properties must be grouped by type by default. You might want to have a look at the various options described in :ref:`reference/views/kanban`." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:116 msgid "Add default grouping." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:118 msgid "Use the appropriate attribute to group the properties by type by default. You must also prevent drag and drop." msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:123 msgid "Kanban views are a typical example of how it is always a good idea to start from an existing view and fine tune it instead of starting from scratch. There are many options and classes available, so... read and learn!" msgstr "" #: ../../content/developer/howtos/rdtraining/15_qwebintro.rst:127 msgid "It is now time to add the :ref:`final touches to our application and submit it on GitHub `!" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:5 msgid "Chapter 16: Polish Your Code And Submit Your PR" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:7 msgid "In the previous chapters we saw how to create a fully functional business application. Now we will prepare our code to be shared and learn how to share it." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:11 msgid "Coding guidelines" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:13 msgid "We will start refactoring the code to match to the Odoo coding guidelines. The guidelines aim to improve the quality of the Odoo Apps code." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:17 msgid "**Reference**: you will find the Odoo coding guidelines in :ref:`reference/guidelines`." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:19 msgid "Polish your code." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:21 msgid "Refactor your code to respect the coding guidelines. Don't forget to respect the module structure, the variable names, the method name convention, the model attribute order and the xml ids." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:26 msgid "Your first Pull Request (PR)" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:28 msgid "**The following is intended to be used by Odoo staff members only. All repositories mentioned are not accessible for third-parties.**" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:31 msgid "Now that your code respects the Odoo code guidelines and is polished up, let's share it with others." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:36 msgid "We will start by creating a git development environment for the 'custom' folder, like we did in the beginning for 'odoo' and 'enterprise'. The PR will target the `odoo/technical-training-sandbox` repository." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:39 msgid "To do this the first step is to `fork `__ in GitHub `this repository `__ to create your own development repository." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:44 msgid "After you successfully created your development repository, we will configure your existing `$HOME/src/custom` folder to be able to commit your work." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:59 msgid "Note that if your work is already in a :ref:`Git and GitHub configured folder ` the previous steps are not needed. This is the case when you start working in the 'odoo' or 'enterprise' folders." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:64 msgid "Branch, Commit & Push" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:66 msgid "Before creating the PR, a new working branch has to be created and used to commit the code. Afterwards the branch will be pushed to the development repository." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:69 msgid "Create your working branch:" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:75 msgid "Your branch name must follow the following name structure : --" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:77 msgid "Example: The branch master-sale-fixes-abc on odoo-dev/odoo is a branch containing fixes for the sales app in the odoo/odoo repository, to be deployed in master and done by ABC." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:80 msgid "Commit your code:" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:89 msgid "**Everyone reads your commit messages!**" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:91 msgid "The commit message is very important, follow the :ref:`Developer guidelines `." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:94 msgid "Push your new branch to your development repository:" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:100 msgid "NEVER use `git push --force` (or `git push -f`) with a branch that does not belong to you or in a stable branch. Never, never, never!" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:103 msgid "Remember that you can use `git status` at any point to check the current status of your branch" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:104 msgid "You can create git aliases to shorten some of these commands. Ask your colleagues if they use git aliases and get inspired by their work." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:108 msgid "Create your first PR" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:110 msgid "After pushing your branch to your development repository you will see an output similar to:" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:128 msgid "There are two ways to create the PR:" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:130 msgid "Click on the link displayed in the output of the push command." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:131 msgid "Open a browser in your development repository `https://github.com/xyz-odoo/technical-training-sandbox`. There will be a button to create a new pull request." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:136 msgid "You will notice that your commit message is used as the pull request message. This occurs if you have only 1 commit. If you have multiple commits, you can either make a summary of the commits as the PR message or if there aren't that many commits you can just copy/paste your commit messages as the PR message." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:143 msgid "Additional Info for Odoo Staff" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:145 msgid "Now that you know the basics, here are some more useful pages if you haven't seen them already:" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:147 msgid "Our `welcome `__ page has extra info about working at Odoo as well as additional `tutorials `__ that are both language and Odoo specific." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:151 msgid "Once you are ready to start doing tasks, it is important to note that Odoo follows a `rebasing workflow instead of merging `__ for your PRs. `This cheatsheet `__ describes how to do this flow. If you want to become more of a rebasing master, then `this tutorial `__ is extra useful." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:159 msgid "Test on the runbot" msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:161 msgid "Odoo has its own :abbr:`CI (Continuous integration)` server named `runbot `__. All commits, branches and PR will be tested to avoid regressions or breaking of the stable versions. All the runs that pass the tests are deployed on their own server with demo data." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:165 msgid "Play with the runbot." msgstr "" #: ../../content/developer/howtos/rdtraining/16_guidelines_pr.rst:167 msgid "Feel free to go to the runbot website and open the last stable version of Odoo to check out all the available applications and functionalities." msgstr "" #: ../../content/developer/howtos/rdtraining/A_i18n.rst:7 msgid "Advanced A: Internationalization" msgstr "" #: ../../content/developer/howtos/rdtraining/A_i18n.rst:9 #: ../../content/developer/howtos/rdtraining/D_mixins.rst:9 #: ../../content/developer/howtos/rdtraining/F_jstour.rst:9 #: ../../content/developer/howtos/rdtraining/G_website.rst:9 #: ../../content/developer/howtos/rdtraining/H_adv_views.rst:9 #: ../../content/developer/howtos/rdtraining/I_jswidget.rst:9 #: ../../content/developer/howtos/rdtraining/L_cron.rst:9 #: ../../content/developer/howtos/rdtraining/M_migration.rst:9 #: ../../content/developer/howtos/rdtraining/N_security.rst:9 #: ../../content/developer/howtos/rdtraining/O_perf.rst:9 msgid "Hopefully, this topic will be written soon :-)" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:5 msgid "Advanced B: ACL and Record Rules" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:9 msgid "This tutorial assumes you have completed the :ref:`Core Training `." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:12 #: ../../content/developer/howtos/rdtraining/J_reports.rst:12 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:12 msgid "To follow the exercise, it is recommended that you fetch the branch 14.0-core from the repository XXX, it contains a version of the module created during the core training we can use as a starting point." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:17 msgid "So far we have mostly concerned ourselves with implementing useful features. However in most business scenarios *security* quickly becomes a concern: currently," msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:21 msgid "Any employee (which is what ``group_user`` stands for) can create, read, update or delete properties, property types, or property tags." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:23 msgid "If ``estate_account`` is installed then only agents allowed to interact with invoicing can confirm sales as that's necessary to :ref:`create an invoice `." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:27 msgid "However:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:29 msgid "We do not want third parties to be able to access properties directly." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:30 msgid "Not all our employees may be real-estate agents (e.g. administrative personnel, property managers, ...), we don't want non-agents to see the available properties." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:33 msgid "Real-estate agents don't need or get to decide what property types or tags are *available*." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:35 msgid "Real-estate agents can have *exclusive* properties, we do not want one agent to be able to manage another's exclusivities." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:37 msgid "All real-estate agents should be able to confirm the sale of a property they can manage, but we do not want them to be able to validate or mark as paid any invoice in the system." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:43 msgid "We may actually be fine with some or most of these for a small business." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:45 msgid "Because it's easier for users to disable unnecessary security rules than it is to create them from nothing, it's better to err on the side of caution and limiting access: users can relax that access if necessary or convenient." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:50 msgid "Groups" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:54 msgid "The documentation related to this topic can be found in :ref:`the security reference `." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:57 msgid ":ref:`The guidelines ` document the format and location of master data items." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:60 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:142 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:207 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:276 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:320 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:401 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:472 msgid "**Goal**" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:62 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:144 msgid "At the end of this section," msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:64 msgid "We can make employees *real-estate agents* or *real-estate managers*." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:65 msgid "The ``admin`` user is a real-estate manager." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:66 msgid "We have a new *real-estate agent* employee with no access to invoicing or administration." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:69 msgid "It would not be practical to attach individual security rules to employees any time we need a change so *groups* link security rules and users. They correspond to roles that can be assigned to employees." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:73 msgid "For most Odoo applications [#app]_ a good baseline is to have *user* and *manager* (or administrator) roles: the manager can change the configuration of the application and oversee the entirety of its use while the user can well, use the application [#appuser]_." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:78 msgid "This baseline seems sufficient for us:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:80 msgid "Real estate managers can configure the system (manage available types and tags) as well as oversee every property in the pipeline." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:82 msgid "Real estate agents can manage the properties under their care, or properties which are not specifically under the care of any agent." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:85 msgid "In keeping with Odoo's data-driven nature, a group is no more than a record of the ``res.groups`` model. They are normally part of a module's :ref:`master data `, defined in one of the module's data files." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:89 msgid "As simple example `can be found here `_." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:91 msgid "what is the *category_id*?" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:93 msgid "``category_id`` a *module category*, it is automatically generated from the :ref:`category defined in module manifest files `." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:96 msgid "the demo module needs to have the category set, to *Real Estate/Brokerage*, ideally the newapp part would already do that" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:102 msgid "Create the ``security.xml`` file in the appropriate folder and add it to the ``__manifest__.py`` file." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:105 msgid "Add a record creating a group with the id ``estate_group_user``, the name \"Agent\" and the category ``base.module_category_real_estate_brokerage``." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:108 msgid "Below that, add a record creating a group with the id ``estate_group_manager``, the name \"Manager\" and the category ``base.module_category_real_estate_brokerage``. The ``estate_group_manager`` group needs to imply ``estate_group_user``." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:115 msgid "Since we modified data files, remember to restart Odoo and update the module using ``-u estate``." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:118 msgid "If you go to :menuselection:`Settings --> Manage Users` and open the ``admin`` user (\"Mitchell Admin\"), you should see a new section:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:123 msgid "Set the admin user to be a *Real Estate manager*." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:127 msgid "Via the web interface, create a new user with only the \"real estate agent\" access. The user should not have any Invoicing or Administration access." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:130 msgid "Use a private tab or window to log in with the new user (remember to set a password), as the real-estate agent you should only see the real estate application, and possibly the Discuss (chat) application:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:139 msgid "The documentation related to this topic can be found at :ref:`reference/security/acl`." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:146 msgid "Employees who are not at least real-estate agents will not see the real-estate application." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:148 msgid "Real-estate agents will not be able to update the property types or tags." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:150 msgid "Access rights were first introduced in :ref:`howto/rdtraining/05_securityintro`." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:152 msgid "Access rights are a way to give users access to models *via* groups: associate an access right to a group, then all users with that group will have the access." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:155 msgid "For instance we don't want real-estate agents to be able to modify what property types are available, so we would not link that access to the \"user\" group." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:158 msgid "Access rights can only give access, they can't remove it: when access is checked, the system looks to see if *any* access right associated with the user (via any group) grants that access." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:163 msgid "group" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:163 msgid "create" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:163 msgid "read" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:163 msgid "update" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:163 msgid "delete" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:165 msgid "A" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:165 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:165 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:166 #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:167 msgid "X" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:166 msgid "B" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:167 msgid "C" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:170 msgid "A user with the groups A and C will be able to do anything but delete the object while one with B and C will be able to read or update, but not search or read." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:175 msgid "The group of an access right can be omitted, this means the ACL applies to *every user*, this is a useful but risky fallback as depending on the applications installed it can grant even non-users access to the model." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:178 msgid "If no access right applies to a user, they are not granted access (default-deny)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:180 msgid "If a menu item points to a model to which a user doesn't have access and has no submenus which the user can see, the menu will not be displayed." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:183 msgid "Update the access rights file to:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:185 msgid "Give full access to all objects to your Real Estate Manager group." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:186 msgid "Give agents (real estate users) only read access to types and tags." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:187 msgid "Give nobody the right to delete properties." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:188 msgid "Check that your agent user is not able to alter types or tags, or to delete properties, but that they can otherwise create or update properties." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:194 msgid "Remember to give different xids to your ``ir.model.access`` records otherwise they will overwrite one another." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:197 msgid "Since the \"demo\" user was not made a real-estate agent or manager, they should not even be able to see the real-estate application. Use a private tab or window to check for this (the \"demo\" user has the password \"demo\")." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:202 #: ../../content/developer/reference/addons/security.rst:83 msgid "Record Rules" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:204 msgid "The documentation related to this topic can be found at :ref:`reference/security/rules`." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:209 msgid "At the end of this section, agents will not be able to see the properties exclusive to their colleagues; but managers will still be able to see everything." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:213 msgid "Access rights can grant access to an entire model but often we need to be more specific: while an agent can interact with properties in general we may not want them to update or even see properties managed by one of their colleagues." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:217 msgid "Record *rules* provide that precision: they can grant or reject access to individual records:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:233 msgid "The :ref:`reference/orm/domains` is how access is managed: if the record passes then access is granted, otherwise access is rejected." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:238 msgid "Because rules tends to be rather complex and not created in bulk, they're usually created in XML rather than the CSV used for access rights." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:241 msgid "The rule above:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:243 msgid "Only applies to the \"create\", \"update\" (write) and \"delete\" (unlink) operations: here we want every employee to be able to see other users' records but only the author / assignee can update a record." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:246 msgid "Is :ref:`non-global ` so we can provide an additional rule for e.g. managers." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:248 msgid "Allows the operation if the current user (``user.id``) is set (e.g. created, or is assigned) on the record, or if the record has no associated user at all." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:253 msgid "If no rule is defined or applies to a model and operation, then the operation is allowed (*default-allow*), this can have odd effects if access rights are not set up correctly (are too permissive)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:259 msgid "Define a rule which limits agents to only being able to see or modify properties which have no salesperson, or for which they are the salesperson." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:262 msgid "You may want to create a second real-estate agent user, or create a few properties for which the salesperson is a manager or some other user." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:265 msgid "Verify that your real estate manager(s) can still see all properties. If not, why not? Remember:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:268 msgid "The ``estate_group_manager`` group needs to imply ``estate_group_user``." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:271 msgid "Security Override" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:274 msgid "Bypassing Security" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:278 msgid "At the end of this section, agents should be able to confirm property sales without needing invoicing access." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:281 msgid "If you try to mark a property as \"sold\" as the real estate agent, you should get an access error:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:286 msgid "This happens because ``estate_account`` tries to create an invoice during the process, but creating an invoice requires the right to all invoice management." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:289 msgid "We want agents to be able to confirm a sale without them having full invoicing access, which means we need to *bypass* the normal security checks of Odoo in order to create an invoice *despite* the current user not having the right to do so." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:294 msgid "There are two main ways to bypass existing security checks in Odoo, either wilfully or as a side-effect:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:297 msgid "The ``sudo()`` method will create a new recordset in \"sudo mode\", this ignores all access rights and record rules (although hard-coded group and user checks may still apply)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:300 msgid "Performing raw SQL queries will bypass access rights and record rules as a side-effect of bypassing the ORM itself." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:305 msgid "Update ``estate_account`` to bypass access rights and rules when creating the invoice." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:310 msgid "These features should generally be avoided, and only used with extreme care, after having checked that the current user and operation should be able to bypass normal access rights validation." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:314 msgid "Operations performed in such modes should also rely on user input as little as possible, and should validate it to the maximum extent they can." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:318 msgid "Programmatically checking security" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:322 msgid "At the end of this section, the creation of the invoice should be resilient to security issues regardless to changes to ``estate``." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:325 msgid "In Odoo, access rights and record rules are only checked *when performing data access via the ORM* e.g. creating, reading, searching, writing, or unlinking a record via ORM methods. Other methods do *not* necessarily check against any sort of access rights." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:330 msgid "In the previous section, we bypassed the record rules when creating the invoice in ``action_sold``. This bypass can be reached by any user without any access right being checked:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:334 msgid "Add a print to ``action_sold`` in ``estate_account`` before the creation of the invoice (as creating the invoice accesses the property, therefore triggers an ACL check) e.g.::" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:340 msgid "Execute ``bypass.py`` in ``estate_account``, giving it the name of your database, and the name of your version of ``action_sold`` (unless you named it ``action_sold`` then it's fine)" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:344 msgid "You should see ``reached`` in your Odoo log, followed by an access error." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:346 msgid "Just because you're already in Python code does not mean any access right or rule has or will be checked." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:349 msgid "*Currently* the accesses are implicitly checked by accessing data on ``self`` as well as calling ``super()`` (which does the same and *updates* ``self``), triggering access errors and cancelling the transaction \"uncreating\" our invoice." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:354 msgid "*However* if this changes in the future, or we add side-effects to the method (e.g. reporting the sale to a government agency), or bugs are introduced in ``estate``, ... it would be possible for non-agents to trigger operations they should not have access to." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:359 msgid "Therefore when performing non-CRUD operations, or legitimately bypassing the ORM or security, or when triggering other side-effects, it is extremely important to perform *explicit security checks*." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:363 msgid "Explicit security checks can be performed by:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:365 msgid "Checking who the current user is (``self.env.user``) and match them against specific models or records." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:367 msgid "Checking that the current user has specific groups hard-coded to allow or deny an operation (``self.env.user.has_group``)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:369 msgid "Calling the ``check_access_rights(operation)`` method on a recorset, this verifies whether the current user has access to the model itself." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:371 msgid "Calling ``check_access_rule(operations)`` on a non-empty recorset, this verifies that the current user is allowed to perform the operation on *every* record of the set." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:375 msgid "Checking access rights and checking record rules are separate operations, if you're checking record rules you usually want to also check access rights beforehand." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:381 msgid "Before creating the invoice, use ``check_access_rights`` and ``check_access_rule`` to ensure that the current user can update properties in general, and this specific property in particular." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:385 msgid "Re-run the bypass script, check that the error occurs before the print." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:390 msgid "Multi-company security" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:394 msgid ":ref:`reference/howtos/company` for an overview of multi-company facilities in general, and :ref:`multi-company security rules ` this in particular." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:398 msgid "Documentation on rules in general can, again, be found at :ref:`reference/security/rules`." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:403 msgid "At the end of this section, agents should only have access to properties of their agency (or agencies)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:406 msgid "For one reason or an other we might need to manage our real-estate business as multiple companies e.g. we might have largely autonomous agencies, or a franchise setup, or multiple brands (possibly from having acquired other real-estate businesses) which remain legally or financially separate from one another." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:412 msgid "Odoo can be used to manage multiple companies inside the same system, however the actual handling is up to individual modules: Odoo itself provides the tools to manage the issue like company-dependent fields and *multi-company rules*, which is what we're going to concern ourselves with." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:417 msgid "We want different agencies to be \"siloed\" from one another, with properties belonging to a given agency and users (whether agents or managers) only able to see properties linked to their agency." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:421 msgid "As before, because this is based on non-trivial records it's easier for a user to relax rules than to tighten them so it makes sense to default to a relatively stronger security model." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:425 msgid "Multi-company rules are simply record rules based on the ``company_ids`` or ``company_id`` fields:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:428 msgid "``company_ids`` is all the companies to which the current user has access" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:429 msgid "``company_id`` is the currently active company (the one the user is currently working in / for)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:432 msgid "Multi-company rules will *usually* use the former i.e. check if the record is associated with *one* of the companies the user has access to:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:448 msgid "Multi-company rules are usually :ref:`global `, otherwise there is a high risk that additional rules would allow bypassing the muti-company rules." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:454 msgid "Add a ``company_id`` field to ``estate.property``, it should be required (we don't want agency-less properties), and should default to the current user's current company." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:457 msgid "Create a new company, with a new estate agent in that company." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:458 msgid "The manager should be a member of both companies." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:459 msgid "The old agent should only be a member of the old company." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:460 msgid "Create a few properties in each company (either use the company selector as the manager or use the agents). Unset the default salesman to avoid triggering *that* rule." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:463 msgid "All agents can see all companies, which is not desirable, add the record rule restricting this behaviour." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:466 msgid "remember to ``--update`` your module when you change its model or data" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:470 msgid "Visibility != security" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:474 msgid "At the end of this section, real-estate agents should not see the Settings menu of the rea-estate application, but should still be able to set the property type or tags." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:478 msgid "Specific Odoo models can be associated directly with groups (or companies, or users). It is important to figure out whether this association is a *security* or a *visibility* feature before using it:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:482 msgid "*Visibility* features mean a user can still access the model or record otherwise, either through an other part of the interface or by :doc:`perform operations remotely using RPC <../../misc/api/odoo>`, things might just not be visible in the web interface in some contexts." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:486 msgid "*Security* features mean a user can not access records, fields or operations." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:488 msgid "Here are some examples:" msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:490 msgid "Groups on *model fields* (in Python) are a security feature, users outside the group will not be able to retrieve the field, or even know it exists." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:493 msgid "Example: in server actions, `only system users can see or update Python code `_." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:495 msgid "Groups on *view elements* (in XML) are a visibility feature, users outside the group will not be able to see the element or its content in the form but they will otherwise be able to interact with the object (including that field)." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:499 msgid "Example: `only managers have an immediate filter to see their teams' leaves `_." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:501 msgid "Groups on menus and actions are visibility features, the menu or action will not be shown in the interface but that doesn't prevent directly interacting with the underlying object." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:505 msgid "Example: `only system administrators can see the elearning settings menu `_." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:510 msgid "Real Estate agents can not add property types or tags, and can see their options from the Property form view when creating it." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:513 msgid "The Settings menu just adds noise to their interface, it should only be visible to managers." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:516 msgid "Despite not having access to the Property Types and Property Tags menus anymore, agents can still access the underlying objects since they can still select tags or a type to set on their properties." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:520 msgid "An Odoo Application is a group of related modules covering a business area or field, usually composed of a base module and a number of expansions on that base to add optional or specific features, or link to other business areas." msgstr "" #: ../../content/developer/howtos/rdtraining/B_acl_irrules.rst:525 msgid "For applications which would be used by most or every employees, the \"application user\" role might be done away with and its abilities granted to all employees directly e.g. generally all employees can submit expenses or take time off." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:5 msgid "Advanced C: Master and Demo Data" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:7 #: ../../content/developer/howtos/rdtraining/E_unittest.rst:7 msgid "This tutorial assumes you followed the Core Training." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:9 #: ../../content/developer/howtos/rdtraining/E_unittest.rst:9 msgid "To do the exercise, fetch the branch 14.0-core from the repository XXX. It contains a basic module we will use as a starting point" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:13 msgid "Data Types" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:16 msgid "Master Data" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:18 msgid "Master data is usually part of the technical or business requirements for the module. In other words, such data is often necessary for the module to work properly. This data will always be installed when installing the module." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:22 msgid "We already met technical data previously since we have defined :ref:`security rules`, :ref:`views` and :ref:`actions`. Those are one kind of master data." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:26 msgid "On top of technical data, business data can be defined: countries, currencies, units of measure but also complete country localization (legal reports, tax definitions, chart of account), and much more..." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:31 msgid "Demo Data" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:33 msgid "Next to master data which are requirements for the modules to work properly, we also like having data for demonstration purpose setups:" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:36 msgid "Help the sales representatives to make their demos quickly." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:37 msgid "Have a set of working data for developers to test the new features and see what it looks like with something they might not have created without it." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:39 msgid "Test that the data is loaded correctly, without raising an error." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:40 msgid "Be ready to use most of the features quickly when creating a new database." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:42 msgid "Demo data is automatically loaded when you start the server if you didn't say explicitly you don't want it. This can be done in the database manager or with the command line." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:65 msgid "Data Declaration" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:68 #: ../../content/developer/reference/addons/module.rst:11 msgid "Manifest" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:70 msgid "**Reference**: the documentation related to this topic can be found in :ref:`Module Manifests`." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:73 msgid "The data is declared either in CSV either in XML. Each file containing data must be added in the manifest for them to be loaded." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:76 msgid "The keys to use in the manifest to add new data are ``data`` for the master data and ``demo`` for the demo data. Both values should be a list of strings representing the relative path to the files declaring the data." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:80 msgid "Usually, the demo data is set in a ``demo`` folder, the views and actions are put in a ``views`` folder, the security related data is put in a ``security`` folder, and the other data is set in a ``data`` folder." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:84 msgid "If your work tree looks like this:" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:103 msgid "Your manifest should look like this:" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:126 msgid "CSV" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:128 msgid "**Reference**: the documentation related to this topic can be found in :ref:`CSV data files`." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:131 msgid "The easiest way to declare simple data is by using the CSV format. This is however limited in terms of features: use it for long lists of simple models, but prefer XML in the other cases." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:140 msgid "Your IDE has probably an extension to have a syntax highlighting of the CSV files" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:142 msgid "`Atom `__." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:143 msgid "`PyCharm/IntelliJ `__." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:144 msgid "`Vim `__." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:145 msgid "`Visual Studio `__." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:147 msgid "Add some standard Real Estate Property Types for the `estate` module: Residential, Commercial, Industrial and Land. These should always be installed." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:151 msgid "XML" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:153 msgid "**Reference**: the documentation related to this topic can be found in :ref:`Data Files`." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:156 msgid "When the data to create is a bit more complex it can be useful, or even needed, to do it in XML." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:172 msgid "Create some demo data for the `estate` module." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:177 #: ../../content/developer/howtos/rdtraining/C_data.rst:241 #: ../../content/developer/howtos/rdtraining/C_data.rst:242 #: ../../content/developer/howtos/rdtraining/C_data.rst:243 msgid "Big Villa" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:177 msgid "Trailer home" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:178 msgid "state" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:178 msgid "New" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:178 msgid "Canceled" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:179 msgid "A nice and big villa" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:179 msgid "Home in a trailer park" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:180 msgid "12345" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:180 msgid "54321" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:181 msgid "2020-02-02" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:181 msgid "1970-01-01" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:182 msgid "1,600,000" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:182 msgid "100,000" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:183 msgid "120,000" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:184 #: ../../content/developer/misc/api/extract_api.rst:122 msgid "6" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:184 #: ../../content/developer/misc/api/extract_api.rst:199 msgid "1" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:185 msgid "100" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:185 msgid "10" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:186 #: ../../content/developer/howtos/rdtraining/C_data.rst:186 msgid "4" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:187 #: ../../content/developer/howtos/rdtraining/C_data.rst:188 #: ../../content/developer/reference/addons/mixins.rst:154 #: ../../content/developer/reference/addons/mixins.rst:182 #: ../../content/developer/reference/addons/mixins.rst:192 msgid "True" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:187 msgid "False" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:189 msgid "100000" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:190 msgid "South" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:194 msgid "Data Extension" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:196 msgid "During the Core Training, we saw in the :ref:`howto/rdtraining/13_inheritance` chapter we could inherit (extend) an existing view. This was a special case of data extension: any data can be extended in a module." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:200 msgid "When you are adding new fields to an existing model in a new module, you might want to populate those fields on the records created in the modules you are depending on. This is done by giving the `xml_id` of the record you want to extend. It won't replace it, in this case we will set the ``field_c`` to the given value for both records." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:219 #: ../../content/developer/reference/addons/data.rst:104 msgid "``ref``" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:221 msgid "Related fields can be set using the ``ref`` key. The value of that key is the ``xml_id`` of the record you want to link. Remember the ``xml_id`` is composed of the name of the module where the data is first declared, followed by a dot, followed by the ``id`` of the record (just the ``id`` works too if you are in the module declaring it)." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:234 msgid "Create some demo data offers for the properties you created." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:236 msgid "Create offers using the partners defined in ``base``" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:239 msgid "Partner" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:239 msgid "Estate" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:239 msgid "Price" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:239 msgid "Validity" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:241 #: ../../content/developer/howtos/rdtraining/C_data.rst:242 msgid "Azure Interior" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:241 msgid "10000" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:241 #: ../../content/developer/howtos/rdtraining/C_data.rst:242 #: ../../content/developer/howtos/rdtraining/C_data.rst:243 msgid "14" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:242 msgid "1500000" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:243 msgid "Deco Addict" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:243 msgid "1500001" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:246 msgid "Both properties should be Residential properties." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:249 #: ../../content/developer/reference/addons/data.rst:145 msgid "``eval``" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:251 msgid "The value to assign to a field is not always a simple string and you might need to compute it. It can also be used to optimize the insertion of related values, or because a constraint forces you to add the related values in batch. See ::ref:`Add X2many fields `." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:263 msgid "The offers you added should always be in a date relative to the installation of the module." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:267 #: ../../content/developer/reference/addons/data.rst:98 #: ../../content/developer/reference/addons/data.rst:159 msgid "``search``" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:269 msgid "Sometimes, you need to call the ORM to do a ``search``. This is not feasible with the CSV format." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:282 msgid "In this code snippet, it is needed because the master data actually depends on the localization installed." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:286 #: ../../content/developer/reference/addons/data.rst:164 msgid "``function``" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:288 msgid "You might also need to execute python code when loading the data." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:296 msgid "Validate one of the demo data offers by using the \"Accept Offer\" button. Refuse the others." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:303 msgid "Add X2many fields" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:305 msgid "**Reference**: the documentation related to this topic can be found in :ref:`Common ORM methods`." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:308 msgid "If you need to add related data in a One2many or a Many2many field, you can do so by using the common ORM methods." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:334 msgid "Create one new Property, but this time with some offers created directly inside the One2many field linking to the Offers." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:338 #: ../../content/developer/howtos/website.rst:234 msgid "Accessing the data" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:340 msgid "You should never access demo data outside of the demo data declaration, not even in tests." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:343 msgid "There are multiple ways to access the master/demo data." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:345 msgid "In python code, you can use the ``env.ref(self, xml_id, raise_if_not_found=True)`` method. It returns the recordset linked to the ``xml_id`` you specify." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:348 msgid "In XML, you can use the `ref` key like this" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:358 msgid "It will call the ref method, and store the id of the record returned on the field ``related_id`` of the record of type ``tutorial.example`` with id ``id1``." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:361 msgid "In CSV, the title of the column must be suffixed with ``:id`` or ``/id``." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:370 msgid "In SQL, it is more complicated, see :ref:`the advanced section`." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:372 msgid "Data can always be deleted by the user. Always code defensively, taking this into account." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:379 msgid "Advanced" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:384 msgid "What is the XML id?" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:386 msgid "Because we don't want a column ``xml_id`` in every single SQL table of the database, we need a mechanism to store it. This is done with the ``ir.model.data`` model." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:389 msgid "It contains the name of the record (the ``xml_id``) along with the module in which it is defined, the model defining it, and the id of it." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:393 msgid "No update" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:395 msgid "The records created with the ``noupdate`` flag won't be updated when upgrading the module that created them, but it will be created if it didn't exist yet." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:398 msgid "``odoo-bin -i module`` will bypass this setting and always load the data. But normally one shouldn't do this on a production database." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:411 msgid "Import as SQL" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:413 msgid "In some cases, it makes sense to do the import directly in SQL. This is however discouraged as it bypasses all the features of the ORM, computed fields (including metadata) and python constraints." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:416 msgid "Generally using raw SQL also bypasses ACLs and increases the risks of injections." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:418 msgid "**Reference**: :ref:`Security in Odoo`" msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:420 msgid "It can help to speed the import time by a lot `with huge files `__." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:422 msgid "For more complex imports like for the `translations `__." msgstr "" #: ../../content/developer/howtos/rdtraining/C_data.rst:424 msgid "It can be necessary to `initialize the database `__." msgstr "" #: ../../content/developer/howtos/rdtraining/D_mixins.rst:7 msgid "Advanced D: Mixins" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:5 msgid "Advanced E: Python Unit Tests" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:12 msgid "**Reference**: `Odoo's Test Framework: Learn Best Practices `__ (Odoo Experience 2020) on Youtube." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:16 msgid "Writing tests is a necessity for multiple reasons. Here is a non exhaustive list:" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:18 msgid "Ensure it will not be broken in the future" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:19 msgid "Define the scope of your code" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:20 msgid "Give examples of use cases" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:21 msgid "It is one way to technically document the code" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:22 msgid "Help you develop by defining your goal before working towards it" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:25 msgid "Running Tests" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:27 msgid "Before knowing how to write tests, we need to know how to run them." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:79 msgid "Integration Bots" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:81 msgid "This section is only for Odoo employees and people that are contributing to `github.com/odoo`. We highly recommend having your own CI if it is not the case." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:84 msgid "When a test is written, it is important to make sure it always passes when modifications are applied to the source code. To automate this task, we use a development practice called Continuous Integration (CI). This is why we have some bots running all the tests at different moments. Whether you are working at Odoo or not, if you are trying to merge something inside `odoo/odoo`, `odoo/enterprise`, `odoo/upgrade` or on odoo.sh, you will have to go through the CI. If you are working on another project, you should think of adding your own CI." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:93 msgid "Runbot" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:95 msgid "**Reference**: the documentation related to this topic can be found in `Runbot FAQ `__." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:98 msgid "Most of the tests are run on `Runbot `__ every time a commit is pushed on GitHub." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:101 msgid "You can see the state of a commit/branch by filtering on the runbot dashboard." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:103 msgid "A **bundle** is created for each branch. A bundle consists of a configuration and contains the batches." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:106 msgid "A **batch** is a set of builds, depending on the parameters of the bundle. A batch is green (i.e. passes the tests) if all the builds are green." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:109 msgid "A **build** is when we launch a server. It can be divided in sub-builds. Usually there are builds for the community version, the enterprise version (only if there is an enterprise branch but you can force the build), and the migration of the branch. A build is green if every sub-build is green." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:114 msgid "A **sub-build** only does some parts of what a full build does. It is used to speed up the CI process. Generally it is used to split the post install tests in 4 parallel instances. A sub-build is green if all the tests are passing and there are no errors/warnings logged." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:119 msgid "All tests are run whatever the modifications done. Correcting a typo in an error message or refactoring a whole module triggers the same tests. It will install all the modules. This means something might not work if Runbot green but your changes depend on something you don't depend on." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:123 msgid "The localization modules (i.e. country-specific modules) are not installed on Runbot (except the generic one), some modules with external dependencies can be excluded also." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:125 msgid "There is a nightly build running additional tests, like module operations, localization, single module installs, multi-builds for nondeterministic bugs, etc. These are not kept in the standard CI to shorten the time of execution." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:129 msgid "You can also login on a build built by Runbot. There are 3 users usable: `admin`, `demo` and `portal`. The password is the same as the login. This is useful to quickly test things on different versions without having to build it locally. The full logs are also available; these are used for monitoring." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:135 msgid "Robodoo" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:137 msgid "You will most likely have to gain a little bit more experience before having the rights to summon robodoo, but here are a few remarks anyways." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:140 msgid "Robodoo is the guy spamming the CI status as tags on your PRs, but he is also the guy that kindly integrates your commits on the main repositories." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:143 msgid "When the last batch is green, the reviewer can ask robodoo to merge your PR (actually it is more a `rebase` than a `merge`). It will then go to the mergebot." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:147 msgid "Mergebot" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:149 msgid "`Mergebot `__ is the last testing phase before merging a PR." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:151 msgid "It will take the commits in your branch not yet present on the target, stage it and rerun the tests one more time, including the enterprise version even if you are only changing something in community." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:155 msgid "This step can fail with a `Staging failed` error message. This could be due to" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:157 msgid "a nondeterministic bug that is already on the target. If you are an Odoo employee, you can check those here: https://runbot.odoo.com/runbot/errors" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:159 msgid "a nondeterministic bug that you introduced but wasn't detected in the CI before" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:160 msgid "an incompatibility with another commit merged right before and what you are trying to merge" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:161 msgid "an incompatibility with the enterprise repository if you only did changes in the community repo" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:163 msgid "Always check that the issue does not come from you before asking the merge bot to retry: rebase your branch on the target and rerun the tests locally." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:167 msgid "Modules" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:169 msgid "Because Odoo is modular, the tests need to be modular also. This means the modules are defined in the module that adds the functionality you add; and that tests cannot depend on functionality coming from modules your module doesn't depend on." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:173 msgid "**Reference**: the documentation related to this topic can be found in :ref:`Special Tags`." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:194 msgid "If the behavior you want to test can be changed by the installation of another module, you need to ensure that the tag `at_install` is set; otherwise you can use the tag `post_install` to speed up the CI, and ensure it is not changed if it shouldn't." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:199 msgid "Writing a test" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:201 msgid "**Reference**: the documentation related to this topic can be found in `Python unittest `__. and :ref:`Testing Odoo`." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:205 msgid "Here are a few things to take into consideration before writing a test" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:207 msgid "The tests should be independent from the data currently in the database (including demo data)" msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:208 msgid "Tests should not impact the database by leaving/changing residual data. This is usually done by the test framework by doing a rollback. This is why you must never call ``cr.commit`` in a test (nor anywhere else in the business code)." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:211 msgid "For a bug fix, the test should fail before applying the fix and pass after." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:212 msgid "Don't test something that is already tested elsewhere; you can trust the ORM. Most of the tests in business modules should only test the business flows." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:214 msgid "You shouldn't need to flush data into the database." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:216 msgid "Remember that ``onchange`` only applies in the Form views, not by changing the attributes in python. This also applies in the tests. If you want to emulate a Form view, you can use ``odoo.tests.common.Form``." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:220 msgid "The tests should be located in a ``tests`` folder in the root of your module. Each test file name should start with `test_` and be imported in the ``__init__.py`` of the test folder. You shouldn't import the test folder/module in the ``__init__.py`` of the module." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:236 msgid "Some older tests are extending ``odoo.tests.common.TransactionCase``, but they are less scalable. The difference is that the setup is done per test method and not per test class. The data changed are rollbacked between each test in `SavepointCase` to have the same behavior as in `TransactionCase`." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:241 msgid "All the tests should extend ``odoo.tests.common.SavepointCase``. You usually define a ``setUpClass``, and the tests. After doing the `setUpClass`, you have an `env` available on the class and can start interacting with the ORM." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:245 msgid "These test classes are built on top of the ``unittest`` python module." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:288 msgid "For more readability, split your tests into multiple files depending on the scope of the tests. You can also have a Common class that most of the tests should inherit from; that common class can define the whole set up for the module. For instance in `account `__." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:293 msgid "Ensure no one can create an offer for a sold Property, and create a test for it." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:296 msgid "Someone keeps breaking the reset of Garden Area and Orientation when you uncheck the Garden checkbox. Make sure it doesn't happen again." msgstr "" #: ../../content/developer/howtos/rdtraining/E_unittest.rst:299 msgid "Tip: remember the note about `Form` a little bit above." msgstr "" #: ../../content/developer/howtos/rdtraining/F_jstour.rst:7 msgid "Advanced F: JS Tours" msgstr "" #: ../../content/developer/howtos/rdtraining/G_website.rst:7 msgid "Advanced G: Controllers & Website" msgstr "" #: ../../content/developer/howtos/rdtraining/H_adv_views.rst:7 msgid "Advanced H: Advanced Views" msgstr "" #: ../../content/developer/howtos/rdtraining/I_jswidget.rst:7 msgid "Advanced I: Custom JS Widget" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:5 msgid "Advanced J: PDF Reports" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:9 msgid "This tutorial assumes you have completed the :ref:`Core Training ` and have installed :ref:`wkhtmltopdf `." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:17 msgid "We were previously :ref:`introduced to QWeb ` in the Core Training where it was used to build a kanban view. Now we will expand on one of QWeb's other main uses: creating PDF reports. A common business requirement is the ability to create documents to send to customers and to use internally. These reports can be used to summarize and display information in an organized template to support the business in different ways. Odoo can additionally add our company's header and footer to our reports with minimal extra effort." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:24 msgid "The documentation related to this topic can be found in :ref:`reference/qweb`, :ref:`reference/reports/report` and the :ref:`reference/actions/report` section of the Actions reference." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:29 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:34 msgid "File Structure" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:31 msgid "The bulk of a PDF report is its QWeb template. It also typically needs a corresponding ``ir.actions.report`` to include the report within a module's business logic. There is no strict rule for the file names or where they are located, but these two parts are typically stored in 2 separate files within a ``report`` folder in the top level of your module's directory. If a module has many or multiple long report templates, then they are often organized in a logical manner across different files named after the report(s) they contain. All actions for the reports are usually stored in the same file ending with ``_report_views.xml`` regardless of the number of reports it contains." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:40 msgid "Therefore it is expected that your work tree will look something like:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:58 msgid "Note that you will often see other non-QWeb and non-XML files containing \"report\" in their name also within the report folder. These are unrelated to the reports covered in this tutorial and are covered in :ref:`another advanced topic `. For now you can think of them as customized views that use direct SQL queries (sometimes referred to as SQL Views)." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:63 msgid "Don't forget to add whatever files your template and action view will be located in to your ``__manifest__.py``. In this case you will want to add the files to the ``data`` list and remember that the files listed in a manifest are loaded sequentially!" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:68 msgid "Basic Report" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:72 msgid "**Goal**: at the end of this section, we will can print a report that displays all offers for a property." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:79 msgid "In our real estate example there are many useful reports that we could create. One simple report we can create is one that displays all of a property's offers." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:83 msgid "Report Data" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:85 msgid "Before we do anything we first need some data to populate our reports or else this tutorial won't be very interesting. When creating reports, you will need some data to test your report code and check that the resulting look is as expected. It is a good idea to test with data that will cover most or all of your expected use cases. A good representation set for our simple report is:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:90 msgid "At least 3 properties where 1 is \"sold\", 1 is \"offer received\" and 1 is \"new\"." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:91 msgid "At least 2-3 offers for our \"sold\" and \"offer received\" properties" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:93 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:116 msgid "If you don't have a set of data like this already, you can either:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:95 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:118 msgid "Complete :ref:`howto/rdtraining/C_data` (if you haven't done so already) and add the extra cases to your demo data (you may need to create a new database to load in the demo data)." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:97 #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:120 msgid "Manually create the data in your database." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:98 msgid "Copy this `data file `__ into a new directory (data) in your estate module and copy `these lines `__ into your __manifest__.py file (you may need to create a new database to load in the demo data)." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:103 msgid "Before continuing, click through your data in your database and make sure your data is as expected. Of course you can add the data after you write your report code, but then you will not be able to incrementally test portions of your code as you write it. This can make checking for mistakes and debugging your code more difficult in the long run for complicated reports." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:109 msgid "Minimal Template" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:111 msgid "A minimal viable template is viewable under the \"Minimal viable template\" section of the :ref:`reference/reports/templates` documentation. We can modify this example to build our minimal property offers template file:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:153 msgid "Most of the Odoo specific (i.e. non-HTML) items in our file are explained in the minimal viable template section. Some additional features in our template are:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:156 msgid "The use of the ``class=\"table\"`` attribute so our table has some nice formatting. Twitter Bootstrap (we're using its table class in this case) and FontAwesome (useful for adding icons) classes can be used in your report template." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:159 msgid "The use of ``t-set``, ``t-value``, ``t-foreach`` and ``t-as`` so that we can loop over all of the ``offer_ids``." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:161 msgid "If you are already familiar with website templating engines, then the QWeb directives (i.e. the `t-` commands) probably don't need much explanation and you can just look at its :ref:`documentation ` and skip ahead to the next subsection." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:165 msgid "Otherwise you are encouraged to read more about them ( `Wikipedia `__ has a good high level description), but the general idea is that QWeb provides the ability to dynamically generate web code based on Odoo data and simple commands. I.e. QWeb can access recordset data (and methods) and process simple programming operations such as setting and accessing temporary variables. For example, in the above example:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:171 msgid "``t-set`` creates a temporary variable called \"offers\" that has its value set by ``t-value`` to the current ``estate.property`` recordset's ``offer_ids``." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:173 msgid "the ``t-foreach`` and ``t-as`` usage is the equivalent to the Python:" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:180 msgid "Report Action" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:182 msgid "Now that we have a template, we need to make it accessible in our app via a ``ir.actions.report``. A practical example of ``ir.actions.report`` is `here `__ corresponding to `this template `__. Its contents are all explained in :ref:`the documentation `." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:189 msgid "An ``ir.actions.report`` is primarily used via the Print menu of a model's view. In the practical example, the ``binding_model_id`` specifies which model's views the report should show in and Odoo will auto-magically add it for you. Another common use case of the report action is to link it to a button like we learned in :ref:`howto/rdtraining/10_actions`. This is handy for reports that only make sense under specific conditions. For example, if we wanted to make a \"Final Sale\" report, then we can link it to a \"Print Sale Info\" button that appears in the form view only when the property is \"Sold\"." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:201 msgid "You may have noticed or are wondered why our report template loops through a recordset. When our template is passed more than one record, it can produce one PDF report for all of the records. Using the Print menu in the list view with multiple records selected will demonstrate this." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:206 msgid "Make a Report" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:208 msgid "Finally, you now know where to create your files and how the content of the files should look. Happy report making!" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:210 msgid "Make a report." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:212 msgid "Add the property offers report from the minimal template subsection to the Print menu of the Property views." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:214 msgid "Improve the report by adding more data. Refer to the **Goal** of this section to see what additional data you can add and feel free to add even more." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:217 msgid "Bonus: Make an extra flexible report by adding in some logic so that when there are no offers on a property then we don't create a table and instead write something about how there are no offers yet. Hint: you will need to use ``t-if`` and ``t-else``." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:221 msgid "Remember to check that your PDF reports match your data as expected." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:225 msgid "Sub-templates" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:229 msgid "**Goal**: at the end of this section, we will have a sub-template that we use in 2 reports." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:235 msgid "There are two main reasons for using sub-templates. One is to make the code easier to read when working with extra long or complicated templates. The other is to reuse code where possible. Our simple property offers report is useful, but listing property offers information can be useful for more than just one report template. One example is a report that lists all of a salesman's properties' offers." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:240 msgid "See if you can understand how to call a sub-template by reading the :ref:`documentation ` on it and/or by looking at an `example `__ (remember QWeb uses the same control flows regardless if it is for a report or a view in Odoo.)" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:245 msgid "Create and use a sub-template." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:247 msgid "Split the table portion of the offers into its own template. Remember to check that your original report still prints correctly afterwards." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:250 msgid "Add a new report for ``res.users`` that allows you to print all of the Real Estate Properties that are visible in their form view (i.e. in the \"Settings\" app). Include the offers for each of those saleman's properties in the same report. Hint: since the ``binding_model_id`` in this case will not be within the estate module, you will need to use ``ref=\"base.model_res_users\"``." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:255 msgid "Your end result should look similar to the image in the **Goal** of this section." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:257 msgid "Remember to check that your reports match your data as expected!" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:260 msgid "Report Inheritance" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:264 msgid "**Goal**: at the end of this section, we will inherit the property report in the ``estate_account`` module." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:271 msgid "Inheritance in QWeb uses the same ``xpath`` elements as :ref:`views inheritance `. A QWeb template refers to its parent template in a different way though. It is even easier to do by just adding the ``inherit_id`` attribute to the ``template`` element and setting it equal to the *module.parent_template_id*." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:275 msgid "We didn't add any new fields to any of the estate models in `estate_account`, but we can still add information to our existing property report. For example, we know that any \"Sold\" properties will already have an invoice created for them, so we can add this information to our report." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:279 msgid "Inherit a report." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:281 msgid "Extend the property report to include some information about the invoice. You can look at the **Goal** of this section for inspiration (i.e. print a line when the property is Done, otherwise print nothing)." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:284 msgid "Again, remember to check that your reports match your data as expected!" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:287 msgid "Additional Features" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:289 msgid "All of the following extra features are described further in the :ref:`reference/reports/report` documentation, including how to implement each of them." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:293 #: ../../content/developer/howtos/web.rst:1227 msgid "Translations" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:295 msgid "We all know Odoo is used in multiple languages thanks to automated and manual translating. QWeb reports are no exception! Note that sometimes the translations do not work properly if there are unnecessary spaces in your template's text content so try to avoid them when possible (especially leading spaces)." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:300 #: ../../content/developer/reference/addons/reports.rst:309 msgid "Reports are web pages" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:302 msgid "You probably are tired of hearing that QWeb creates HTML, but we're saying it again! One of the neat features about reports being written in QWeb is they can be viewed within the web browser. This can be useful if you want to embed a hyperlink that leads to a specific report. Note that the usual security checks will still apply to prevent unauthorized users from accessing the reports." msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:308 #: ../../content/developer/reference/addons/reports.rst:148 msgid "Barcodes" msgstr "" #: ../../content/developer/howtos/rdtraining/J_reports.rst:310 msgid "Odoo has a built-in barcode image creator that allows for barcodes to be embedded in your reports. Check out the corresponding `code `__ to see all the supported barcode types." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:5 msgid "Advanced K: Dashboards" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:9 msgid "This tutorial assumes you have completed the :ref:`Core Training ` and have access to Odoo Enterprise features." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:17 msgid "The term \"Dashboard\" is used in Odoo for objects that display data, but involves different implementations. This tutorial will only focus on the Enterprise view that is used to provide aggregated data visualization. They can be added as a ``view_mode`` to an existing model (i.e. a view you can switch to via the view buttons in the top right of a view), but they are also often used as a view for to a special model customized for data visualization. You may hear these special views referred to as SQL views." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:24 msgid "It is useful to note there is a \"Dashboard\" app in Odoo Community. This app allows users to create their own customized view of data, but the customization is only visible to each user and can only be viewed within the \"Dashboard\" app. Technically it is possible to make global dashboards using this ``board`` module, but it is much easier to do as an Enterprise view. Plus it looks nicer and has extra features not available in ``board``. Some other dashboards within Odoo also exist, but they are custom made and are beyond the scope of this tutorial." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:31 msgid "The documentation related to this topic can be found in :ref:`reference/views/dashboard`." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:36 msgid "You probably have already guessed that since dashboard views are an Enterprise view, they must have a dependency on an Enterprise module. The Enterprise module is ``web_dashboard``. Don't forget to add it to your manifest file! It is standard to add dashboards intended to be used as a ``view_mode`` for one of your module's models (in the ``model`` folder``) to the views directory (i.e. the same file that contains the other views for the same model)." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:42 msgid "It is standard to create a separate Enterprise module to add extra Enterprise views and features to a Community module. This is done in a similar manner as the module link technique covered within :ref:`howto/rdtraining/14_other_module`. The difference is that instead of linking 2 different modules, we are extending our `estate` module. We do this by creating a new module and adding both the Community module and its necessary Enterprise module dependencies to its manifest. You will commonly see \"enterprise\" in the module's directory name. To keep this tutorial simple, we will add dashboards to our existing ``estate`` module." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:50 msgid "SQL Views have 2 parts: their xml file (don't forget to add it to your manifest file) and their Python file (don't forget to add it to the appropriate ``__init.py__`` files). The former is the same format as the ``view_mode`` xml while the latter contains a custom model and SQL code to populate its fields. It is standard to add SQL view files to the ``report/`` directory. It is also common to include \"report\" in the name of the SQL view's files. You may be wondering why do we put the files in a report directory? We saw earlier that the dashboard is for data visualization, therefore it is not editable. You can think of dashboards as interactive reports where you can click on statistics, graphs, and charts to see the specific data contributing to them. Note it is also standard to store the xml code for :ref:`PDF report templates ` in the report directory." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:61 msgid "It is expected that your work tree will look something like:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:82 msgid "Dashboard View" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:86 msgid "**Goal**: at the end of this section, we will have a new dashboard view that displays different property statistics." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:93 msgid "Dashboards can display data in different ways, including:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:95 msgid "showing an ``aggregate`` of a field" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:96 msgid "using aggregated fields in a ``formula``" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:97 msgid "using a ``widget``" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:98 msgid "using another ``view`` as a subview" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:100 msgid "There are many useful statistics and visuals we can provide for our real estate example using these options. A full example to reference while doing the exercises in this section is `viewable here `__ (restricted github repository link)." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:106 msgid "Data" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:107 msgid "To fully enjoy our dashboard view, we will need good test data to populate it. Test data will allow us to check that the resulting look and statistics are correct. It is a good idea to test with data that will cover most or all of your expected use cases, but is also easy to verify with that your statistics are correct. In our goal's case we are looking at count, sum, average, minimum, and maximum statistics, therefore a good representation set for our dashboard is:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:113 msgid "At least 3 properties with different property types, expected prices, and average living area." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:114 msgid "At least 1 sold property and at least 1 canceled property" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:121 msgid "Copy this `data file `__ into a new directory called ``data`` in your estate module and copy `these lines `__ into your __manifest__.py file (you may need to create a new database to load in the demo data)." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:126 msgid "Click through your database data and make sure it is what you expect. Of course you can add the data after you write your dashboard code and then test that your view is working as expected." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:130 msgid "Aggregations" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:131 msgid "Building a dashboard view is very similar to what you have previously done in :ref:`howto/rdtraining/07_basicviews`. For the dashboard view, we use the `dashboard` root element and choose from its possible tags (see all the possibilities and their attributes in the :ref:`reference/views/dashboard` documentation). So a simple dashboard example is:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:145 msgid "In this example, ```` adds styling and ```` declares an aggregation. We indicate which ``field`` we want to aggregate, what ``string`` to display with the value, and how to aggregate it with the `group_operator` attribute. The `group_operator` can use any valid PostgreSQL aggregate function plus the special Odoo defined ``count_distinct``." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:150 msgid "Hopefully you remember how to add views to a window action `view_mode` (hint, it was covered in :ref:`howto/rdtraining/06_firstui`). Now let's make some dashboards!" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:153 msgid "Make a dashboard view." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:155 msgid "Create a dashboard of aggregated values for the ``estate.property`` model. You can look at the **Goal** of this section for some inspiration. Remember to check that your statistics are calculating as you expect and note that the calculated values take into consideration any applied view filters!" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:160 msgid "Bonus: Add in some aggregations that need a `domain` to make sense (remember domains were also covered in :ref:`howto/rdtraining/07_basicviews`)." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:164 msgid "Pie Charts" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:165 msgid "Adding pie charts to dashboards is a piece of cake using the `` element. An example is:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:175 msgid "In this example, we indicate that we're using the `pie_chart` widget with the `name` attribute, the ``title`` for the pie chart, and that we're grouping it by property type." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:178 msgid "Add some pie charts." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:180 msgid "Add the pie charts from the **Goal** of this section to your dashboard. Hint: you will need to add `'measure': selling_price` to your pie chart `attrs` if you want to show selling prices grouped by property type." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:184 msgid "Hover over and click on the pie charts to check your charts counts values and don't forget that filters will also apply to the charts." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:187 msgid "Bonus: Add a domain to your selling price pie chart to only include \"sold\" properties (i.e. not \"offer_accepted\" ones). Note that the `'` will need to be escaped since it is declared as part of the `attrs`." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:192 msgid "Subviews" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:193 msgid "Similar to how we can use the list view within the form view (we saw this automatically happen for One2many relationships in :ref:`howto/rdtraining/08_relations`), we can add other views within our dashboard view. The most commonly added are the pivot and graph views, but the cohort view is also an option. These views are covered in more depth in :ref:`howto/rdtraining/H_adv_views`. For this topic you are only required to know their names. A dashboard with only subviews is:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:206 msgid "The `ref` attribute can be added to `` elements to use a specific xml id for that view. If no xml id is provided for a graph or pivot view then the default view will be used. The cohort view will not work in the dashboard without a specific xml id. If you have already created some of these views then you are welcome to add them to your dashboard! Sample graph and pivot views are included in the `solution code `__ that you are welcome to use as well." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:214 msgid "Add subviews." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:216 msgid "Add in a graph and a pivot view to your dashboard. Try playing around with the layout of your subviews in relation to your pie charts and aggregated values and refer to the **Goal** of this section for an often used layout. Remember to check that your subviews are displaying your data as expected (and yes, they are also affected by the filters!)." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:222 msgid "SQL Views" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:226 msgid "This section expects you to have a basic knowledge of SQL. If you have little to no SQL knowledge then `this is a good tutorial to start with `__ and these `exercises `__ are good for those who need a refresher or extra practice." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:233 msgid "**Goal**: at the end of this section, we will have a new SQL view that displays different property statistics." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:241 msgid "Occasionally we want to show data that goes beyond what our model already has in it. We could add a lot of stored computed or related fields (non-stored fields cannot be aggregated or displayed in pie charts), but it would be impractical to store a bunch of fields only for this purpose. We can instead add a custom SQL view to minimize the computational load and keep our model clean of unnecessary fields." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:249 msgid "We will start with the more difficult part: our special report model. This file starts the same as any other model except that we add 2 attributes ``_auto`` and ``_rec_name``::" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:261 msgid "``_auto = False`` indicates that we do not want to store the model in the database and we will create a custom table by overriding the ``BaseModel.init()`` method. ``_rec_name`` indicates which of the model's fields represents a record's name (i.e. the name that will be used in the navigation breadcrumb when opening a record's form view). In this case I left it as 'id' because our property offers don't have a name. We will need the `tools` import later (i.e. ``odoo/odoo/tools``, which is full of all sort of useful helper methods you will probably use in the future). Note that it is standard to include ``report`` in the model name." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:269 msgid "Remember your new model will need to be added to your security file like you learned in :ref:`howto/rdtraining/05_securityintro`!" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:272 msgid "Then we define the fields we need for our dashboard the same way as any other model (like you learned in :ref:`howto/rdtraining/04_basicmodel`), except that every field is ``readonly=True``. After all, our model is for readonly purposes only." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:276 msgid "Now we override the ``BaseModel.init()`` method mentioned earlier::" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:287 msgid "We use ``tools.drop_view_if_exists`` to ensure that we don't create a conflicting view and then execute the SQL query. It is standard to separate the different parts of the query to allow for easier model extension. Exactly how the query is split up across methods is not standardized, but you will often see at minimum ``_select`` and ``_from`` methods [or something similar] and of course all of these methods will return strings. The columns from the SELECT will populate our model's fields so ensure that your column names match your field names or use alias names that match." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:295 msgid "Create report model." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:297 msgid "Create a report model with the following fields:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:300 msgid "Note" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:302 #: ../../content/developer/reference/addons/static/res.country.state.csv:1 msgid "id" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:302 msgid "Corresponds to ``id`` of ``estate.property.offer``" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:303 msgid "offer_state" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:303 msgid "Equals ``state`` choices of ``estate.property.offer``" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:305 msgid "property_state" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:305 msgid "Equals ``state`` choices of ``estate.property``" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:306 msgid "property_type_id" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:309 msgid "and write the SQL query necessary to populate the fields (hint, you will need 2 JOINs)." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:311 msgid "You won't be able to check if your model is correct until we create a view for it, but you are welcome to check your query directly in your database to see if the results are as you expect. If you struggle with this exercise, then `here is an example `__ to reference." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:319 msgid "Now that we have our model, we can make its dashboard view. There is no difference to how its made except that its file is located in the ``report`` folder. Since it is a new model not linked to any other model, we will also have to add a new menuitem to view our dashboard. Typically SQL views are added under a first level menu called ``Reporting` (because it's a report, surprise!). Do you remember how to add a ``menuitem``? If not, revisit :ref:`howto/rdtraining/06_firstui`) again." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:325 msgid "Create report view." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:327 msgid "Recreate the dashboard in the **Goal** of this section. Hint: it uses the ``formula`` element, which we did not need for our previous dashboard." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:330 msgid "Bonus: Create ``list`` and ``form`` views for your new report model so we don't have to see the ugly defaults when you click on your pie charts." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:334 msgid "Extra Tips" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:335 msgid "**Tip 1** A common mistake in SQL views is to not take into account the duplication of certain data due to table JOINs. For example, in our **Goal** we have a pie chart of the offers' property types. We may be tempted to add a similar pie chart with a domain to only include canceled properties, so we think we are only counting the number of canceled properties by property type. In reality we are still looking at all the offers per property so any property with more than 1 offer will be counted per offer. This example is easily double checked by clicking on the pie chart to see its list view:" msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:347 msgid "But for cases such as average aggregations or using a subview such as the pivot view, it is easy to miss this mistake. It is also easy to miss this mistake when you have insufficient test data. In order to add a number of properties canceled by property type pie chart to this report, we would either have to do a hack (too advanced for this tutorial) or simply exclude it from this report." msgstr "" #: ../../content/developer/howtos/rdtraining/K_dashboard.rst:353 msgid "**Tip 2** If you have a field that you do not want as a measure (i.e. in your pivot or graph views), then you can add ``store=False`` to it and it will not show." msgstr "" #: ../../content/developer/howtos/rdtraining/L_cron.rst:7 msgid "Advanced L: Scheduled & Server Actions" msgstr "" #: ../../content/developer/howtos/rdtraining/M_migration.rst:7 msgid "Advanced M: Migrations" msgstr "" #: ../../content/developer/howtos/rdtraining/N_security.rst:7 msgid "Advanced N: Security" msgstr "" #: ../../content/developer/howtos/rdtraining/O_perf.rst:7 msgid "Advanced O: Performances" msgstr "" #: ../../content/developer/howtos/themes.rst:4 msgid "Theme Tutorial" msgstr "" #: ../../content/developer/howtos/themes.rst:8 msgid "This tutorial provides a great overview of what you can do creating an Odoo theme. It is however incomplete. We are currently working on a new detailed theme tutorial, come back here soon to unleash the true power of Odoo themes!" msgstr "" #: ../../content/developer/howtos/themes.rst:15 msgid "Odoo celebrates freedom. Freedom for the designer to go further and freedom for the user to customize everything according to their needs." msgstr "" #: ../../content/developer/howtos/themes.rst:18 msgid "Ready to create your own theme? Great. Here are some things you should know before you begin. This tutorial is a guide to creating an Odoo theme." msgstr "" #: ../../content/developer/howtos/themes.rst:24 msgid "An introduction for web designers" msgstr "" #: ../../content/developer/howtos/themes.rst:26 msgid "If you are a web designer using Odoo for the first time, you are in the right place. This introduction will outline the basics of Odoo theme creation. Odoo’s team has created a framework that’s powerful and easy to use." msgstr "" #: ../../content/developer/howtos/themes.rst:30 msgid "From common CMS to Odoo" msgstr "" #: ../../content/developer/howtos/themes.rst:34 msgid "If you always think and work in the same way, you’ll probably get the same results. If you want something completely new, then try something different." msgstr "" #: ../../content/developer/howtos/themes.rst:38 msgid "Where is my header.php file?" msgstr "" #: ../../content/developer/howtos/themes.rst:40 msgid "This is usually the first question from a web designer used to working with Wordpress or Joomla and coming to Odoo for the first time." msgstr "" #: ../../content/developer/howtos/themes.rst:50 msgid "Indeed, when using common CMSs, you have to code several files (like header.php, page.php, post.php, etc.) in order to create a basic structure for your website. With those systems, this base structure acts as a design foundation that you have to update over time to ensure compatibility within your CMS. So, even after you have spent hours coding the files, you have not even started on the design yet." msgstr "" #: ../../content/developer/howtos/themes.rst:52 msgid "This **does not** apply to creating Odoo themes." msgstr "" #: ../../content/developer/howtos/themes.rst:56 msgid "We think that theme design should be simple (and powerful). When we created our Website Builder, we decided to start from scratch instead of relying on what already existed. This approach gave us the freedom to focus on the things that are really important for designers: styles, content and the logic behind them. No more struggling with technical stuff." msgstr "" #: ../../content/developer/howtos/themes.rst:59 msgid "Odoo default theme structure" msgstr "" #: ../../content/developer/howtos/themes.rst:65 msgid "Odoo comes with a default website structure. It is a very basic “theme” that provides minimal structure and layout. When you create a new theme, you are actually **extending** this. Indeed it’s always enabled in your setup and it acts exactly like the CMS’s base structure we mentioned above, except that you don’t have to create or maintain it. It will upgrade automatically within your Odoo installation and, since it is included in the Website Builder module, everything is smoothly integrated by default." msgstr "" #: ../../content/developer/howtos/themes.rst:70 msgid "As a result, you are totally free to focus on design while this structure does the job of providing integrations and functionality." msgstr "" #: ../../content/developer/howtos/themes.rst:80 msgid "**Main features:**" msgstr "" #: ../../content/developer/howtos/themes.rst:82 msgid "Basic layouts for pages, blog, eCommerce and much more" msgstr "" #: ../../content/developer/howtos/themes.rst:83 msgid "Website Builder integration" msgstr "" #: ../../content/developer/howtos/themes.rst:84 msgid "Basic Snippets" msgstr "" #: ../../content/developer/howtos/themes.rst:85 msgid "Automatic Sass compiling" msgstr "" #: ../../content/developer/howtos/themes.rst:86 msgid "Automatic Js and CSS minification and combination" msgstr "" #: ../../content/developer/howtos/themes.rst:90 msgid "**Main technologies:**" msgstr "" #: ../../content/developer/howtos/themes.rst:92 msgid "Twitter Bootstrap" msgstr "" #: ../../content/developer/howtos/themes.rst:93 msgid "jQuery" msgstr "" #: ../../content/developer/howtos/themes.rst:94 msgid "jQuery UI" msgstr "" #: ../../content/developer/howtos/themes.rst:95 msgid "underscore.js" msgstr "" #: ../../content/developer/howtos/themes.rst:98 msgid "Thinking \"modular\"" msgstr "" #: ../../content/developer/howtos/themes.rst:100 msgid "An Odoo theme is not a folder containing HTML or PHP files, it’s a modular framework written in XML. Never worked with XML files before? Don’t worry, after following the tutorial, you’ll be able to create your first theme with only basic knowledge of HTML." msgstr "" #: ../../content/developer/howtos/themes.rst:102 msgid "Using classical web design workflows, you usually code the layout of the entire page. The result of this is a “static” web page. You can update the content, of course, but your client will need you to work on making even basic changes." msgstr "" #: ../../content/developer/howtos/themes.rst:104 msgid "Creating themes for Odoo is a total change of perspective. Instead of defining the complete layout for a page, you can create blocks (snippets) and let the user choose where to “drag&drop” them, creating the page layout on their own. We call this modular design." msgstr "" #: ../../content/developer/howtos/themes.rst:107 msgid "Imagine an Odoo theme as a “list” of elements and options that you have to create or extend. As a designer, your goal is to style these elements in order to achieve a wonderful result, regardless of where the end user chooses to place them." msgstr "" #: ../../content/developer/howtos/themes.rst:110 msgid "Let’s take a tour of our “list” elements:" msgstr "" #: ../../content/developer/howtos/themes.rst:117 msgid "Snippets (or building-blocks)" msgstr "" #: ../../content/developer/howtos/themes.rst:119 msgid "A piece of HTML code. The user will drag&drop, modify and combine them using our built-in Website Builder interface. You can define sets of options and styles for each snippet. The user will choose from them according to their needs." msgstr "" #: ../../content/developer/howtos/themes.rst:124 msgid "Pages" msgstr "" #: ../../content/developer/howtos/themes.rst:126 msgid "These are normal web pages, except that they will be editable by the final user and that you can define an empty area that the user can “fill” by dragging snippets into it." msgstr "" #: ../../content/developer/howtos/themes.rst:137 msgid "Styles" msgstr "" #: ../../content/developer/howtos/themes.rst:139 msgid "Styles are defined using SCSS files (or you can use standard CSS files). You can define a style as **default** or **optional**. The default styles are always active in your theme, the optional styles can be enabled or disabled by the user." msgstr "" #: ../../content/developer/howtos/themes.rst:144 msgid "Functionalities" msgstr "" #: ../../content/developer/howtos/themes.rst:146 msgid "Thanks to Odoo’s modularity, everything can be personalized even more. This means there are endless possibilities for your creativity. Adding functionalities is easy and it’s simple to provide the end user with customizable options." msgstr "" #: ../../content/developer/howtos/themes.rst:150 msgid "Odoo's XML files, an overview" msgstr "" #: ../../content/developer/howtos/themes.rst:152 msgid "Any Odoo XML file starts with encoding specifications. After that, you have to write your code inside a ```` tag." msgstr "" #: ../../content/developer/howtos/themes.rst:165 msgid "Almost every element and option that you create has to be placed inside a ``