Odoo Technical Training
September 2019
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Index
● Objectives of this Program
● Reference material
● Preparing the development environment
● Getting started
● Debugging
● Case Study - Partner Certifications
● Get to know the OCA resources
● Key Business Apps in Odoo
● Integration with other systems
● Program Summary
2
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Objectives of this Program
3
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Objectives of this Program
● Understand the Odoo ecosystem.
● Learn different methods to set up an Odoo environment.
● Learn how to develop applications in Odoo, following practical cases.
● Understand how to adopt the best practices from the OCA and to collaborate with other OCA
members.
● Obtain a general understanding of the key Odoo Business Apps, and their technical
architecture.
● Learn the techniques to integrate Odoo with external systems.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Reference material
5
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Reference Material
● Odoo 12 Development Cookbok, Third Edition
https://www.packtpub.com/application-development/odoo-12-development-cookbook-third-edition
● Odoo Technical Documentation
https://www.odoo.com/documentation/12.0/
● OCA Guidelines
https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst
Copyright 2019 Eficent Business and IT Consulting Services S.L.
The Odoo Ecosystem
7
Copyright 2019 Eficent Business and IT Consulting Services S.L.
The Odoo Ecosystem
Partners
OCA Repos
LGPLv3
AGPL v3
Contributors
The Odoo Enterprise contract includes:
● Bugfix support
● Migration services Private
● Proprietary applications Repos
LGPLv3
https://www.odoo.com/page/editions AGPL v3
Private
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the Environment
9
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the Environment
Learning Objectives
● Install Odoo from source
● Use Pycharm as your development environment
● Manage Odoo databases
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
11
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
# Install system dependencies
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install python3-dev python3-pip
sudo apt-get install build-essential libxslt-dev libzip-dev libldap2-dev libsasl2-dev libssl-dev
sudo pip3 install virtualenv
# Install Postgres
sudo apt-get install postgresql
sudo -u postgres createuser --createdb $(whoami)
sudo -u postgres psql
psql=# alter user <username> with encrypted password '<password>';
# Install Odoo
mkdir ~/odoo-dev
cd ~/odoo-dev
git clone https://github.com/odoo/odoo.git -b 12.0 --depth=1
# Install python virtual environment
cd ~/odoo-dev
virtualenv -p python3 env
source ~/odoo-dev/env/bin/activate
pip install -r ~/odoo-dev/odoo/requirements.txt
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
Run Odoo in PyCharm
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Preparing the environment
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting Started
18
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Learning Objectives
● Installing add-on modules from GitHub
● Configuring the add-ons path
● Updating the add-on modules list
● Installing and upgrading local add-on modules
● Organizing the add-on module file structure
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Open the browser and access to http://localhost:8069/
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Install the “Contacts” app
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
Business requirement
Aeronix captures information about the gender of their contacts. It is needed to
find this field in the contact form.
First step would be to search if a module already solves this need in the OCA
(Odoo Community Association) repositories.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Clone the OCA repository partner-contact
Installing add-on modules from
cd ~/odoo-dev GitHub
git clone https://github.com/OCA/partner-contact.git -b 12.0
Configuring the addons path
● Add the new repo to the addons path in PyCharm
--addons-path=/home/<myuser>/od
oo-dev/odoo/addons,/home/<myuse
r>/odoo-dev/odoo/odoo/addons,/ho
me/<myuser>/odoo-dev/partner-con
tact
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Clone the OCA repository partner-contact
cd ~/odoo-dev
git clone https://github.com/OCA/partner-contact.git -b 12.0
● Add the new repo to the addons path in PyCharm
--addons-path=/home/<myuser>/od
oo-dev/odoo/addons,/home/<myuse
r>/odoo-dev/odoo/odoo/addons,/ho
me/<myuser>/odoo-dev/partner-con
tact
Stop and re-run Odoo
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Updating the available modules in Odoo
Go to “Settings > Activate the developer mode”
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Updating the available modules in Odoo
Updating the addons module list
Go to ‘Apps > Update Apps List’
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Install the module
Installing and upgrading local add-on
Search for the module in the apps modules
Tip: some modules are classified as “Apps”, but not all. Remove the filter
during your searches in the apps.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Review the results
Copyright 2019 Eficent Business and IT Consulting Services S.L.
● Organizing the add-on module file structure
Getting started
Organizing the add-on
Exercise module file structure
● Understanding the structure of an Odoo module
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Understanding what happened when you installed the odoo module
Go to ‘Settings / Technical / Database Structure / Models’
- The model ‘res.partner’ has been extended with a new field.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
- In the database, the table “res_partner” has been extended with a new column ‘gender’.
Install DBeaver
https://dbeaver.io/
In dbeaver, select the new database,
and run the following query:
select name, gender from res_partner;
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Understanding what happened when you installed the odoo module
Go to ‘Settings / Technical / User Interface / Views’
- The view Partner Gender is now included in the database.
- Partner Gender View is adding information to its inherited view
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
Business requirement
Aeronix captures information about contact’s driving license. It is needed to find
this field in the contact form.
First step would be to search if a module already solves this need in the OCA
(Odoo Community Association) repositories. In this case, the module does not
solve our necessities, a new one must be created.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
● Create your GitHub account
● Create a Fork in https://github.com/Eficent/odoo-training-tr
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Preparing our custom modules working directory
cd ~/odoo-dev/
git clone https://github.com/<my_github_user>/odoo-training-tr # Your forked repository
cd odoo-training-tr
git config --global user.email "<[email protected]>"
git config --global user.name "<my_gihub_name>"
printf 'My Odoo Custom Addons\n' > README.md
git add .
git commit -m 'Add Readme'
git push
Note
Now you will have to introduce your username and your password of GitHub.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● For simplicity we copy a similar example to our needs:
● We give a proper name to our new addon:
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Sequence of modifications in order to create the new custom module:
1st step: Changes in __manifest__.py
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
2nd step: Changes in README.rst
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
3rd step: Adding new field to entity res.partner
https://www.odoo.com/documentation/12.0/reference/orm.html#fields
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
4th step: Including the new field in the view
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Add the brand new custom_addons path in PyCharm
--addons-path=/home/<myuser>/od
oo-dev/odoo/addons,/home/<myuse
r>/odoo-dev/odoo/odoo/addons,/ho
me/<myuser>/odoo-dev/partner-con
tact,/home/<myuser>/odoo-dev/odo
o-training-tr
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Updating the available modules in Odoo to include our new module
Go to ‘Apps > Update Apps List’
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Install the module
Search for the module in the apps
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Our module is available!
We can install it now
Tip: You can automatically install the module by putting in the configuration parameters -i
<name_of_the_module> -d <database_name>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
● Review the results
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Getting started
Exercise
- In the database, the table “res_partner” has been extended with a new column ‘driving_license’.
Select a new database:
… and write on the script:
select name, driving_license from res_partner;
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Debugging
49
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Debugging
Learning Objectives
● Debug Odoo using Pycharm
● Understanding the debug mode options
● Useful odoo-bin inline options
● Using the Odoo Community Association maintainer quality tools
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Debugging
Key Concepts
Debug Odoo using Pycharm
○ Add breakpoints
○ Run in debugging mode
○ Debugging Shortcuts
■ F7 -> Step into
■ F8 -> Step over
■ F9 -> Resume program (Go to next breakpoint)
○ Debugger Control Panel
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Debugging
Key Concepts
Understanding the debug mode options
○ Activate the development mode
■ From Settings
■ Adding debug directly in URL
http://localhost:8069/web?debug#action=77&menu_id=4
■ Install Odoo Debug Plugin: Firefox or Chrome
○ Extra information in Field views (hovering a field in a form)
○ Open actual view information (Edit View option)
○ Open View (We can jump to any view in the system)
○ View Metadata (Information about last modification user)
○ Enable view items with group
<field name="request_date" groups="base.group_no_one"/>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Debugging
Key Concepts
Useful odoo-bin inline options
-d Select specific DB
-i Install a module
-u Update a module
--log-level=debug Display debug logs
--test-enable Enable test on install/upd
--without-demo=all Don’t load demo
data
--workers=0 Only one thread to debug
--dev=xml Odoo use xml file views
--stop-after-init Stop odoo after it is load
More info: ./odoo-bin --help
or
https://www.odoo.com/documentation/12.0/reference/cmdline.html
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Debugging
Exercise
Using the debug mode,
● Add breakpoints on certification module methods, and debug them.
● Add breakpoints on partner_certification_status on test and methods,
debug it without starting Odoo browser following the inline options
shown in the previous slide. (tip: Demo data required to do the test)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study
Partner Certifications
55
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Business case
Aeronix needs to record certifications documents of its suppliers, employees and customers to easily manage the
information. The requirements of this module are the following ones:
● Each certificate would be associated to one partner (supplier or customer). It would be designated with a
number as it must be unique. In this certification document it should be a record of the following fields:
○ Certification entity, standard certifications, description, owner...
○ Expiry date, expiry days (days left until expiration), expiry status.
● Standard certifications can be associated to more than one partner. These are general certifications that would
be included in the certification document referred to a unique partner. They must include name and
● Only partners which are certification entities can create certifications documents.
● In the contact form of each partner it must be shown a list of all certifications related to this partner.
● In the contact form it needs to be defined if the contact is a certification entity or not.
● When creating a certificate, only partners which are certification bodies must appear in the selection window
from the form view (hint: Create a domain)
● Create a button to add more days to Expiration Date [1 month]
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Functional design
Certification model Partner Standard model
Certification
● Number:VMA-002P Certificate owner
● Validation Date: ● Aero Fasteners Co.
09/20/2019
Certifying entity
● AEA Quality Advantage
Corporation
Certification Standard
● AS9003
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Learning Objectives
● Creating and installing a new add-on module ● Using external IDs and namespaces
● Completing the add-on module manifest ● Loading data using XML files
● Organizing the add-on module file structure ● Using the noupdate and forcecreate flags
● Adding models ● Loading data using CSV files
● Adding menu items and views ● Creating security groups and assigning them to users
● Adding Access Security ● Python test cases
● Understanding the model ● Defining a model based on an SQL view
○ Odoo fields and fields attributes ● Defining graph and pivot views
● Extending a model ● Creating QWeb-based PDF reports
● Changing existing views – view inheritance
● Extending a view
● Defining filters on record lists-Domain
● Defining model methods and using API decorators
● Extending the business logic defined in a model
● Reporting errors to the user
● Creating new records
● Updating values of recordset records
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
Creating and installing a new
1st step: create __manifest__.py and__init__.py files add-on module
Completing the add-on
module manifest
Key Concepts
The model layer
Data will be added in ● Data model
the following steps
● Access security
The view layer
● Add menu items
● Add form, tree
views
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Key concepts
● Sample template: https://github.com/OCA/maintainer-tools/tree/master/template/module
● Guidelines on how to name a module
https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst#1
1modules
● __manifest__.py
○ Copyrights
○ Licenses - LGPL, AGPL, OPL
○ version - see
https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTIN
G.rst#version-numbers
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
2nd Step: Creation of the model
from odoo import models, fields, api
from odoo import models,fields
class Certification(models.Model):
_name = 'certification'
Note
class CertificationStandard(models.Model):
_description = 'Certification' _name = 'certification.standard' ‘certification_standard.py’
_description = 'Certification Types’ model:
number = fields.Char() Needed to compile all the
date = fields.Date(string='Validation Date') name = fields.Char() certification types that the
description = fields.Text(string='Validation Details') description = fields.Text() company owns.
standard_id =
fields.Many2one(”certification.standard”)
owner_id = fields.Many2one("res.partner")
entity_id = fields.Many2one('res.partner')
Adding models
_name = [Defines internal global identifier for the Model, it gives the name to the database]
_description = [Title to the model]
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Key concepts
Odoo fields and fields
● Basic model fields attributes
● Odoo fields and fields attributes
https://www.odoo.com/documentation/12.0/reference/orm.html#fields
● Relational fields: Many2one, One2many, Many2many
● Text fields: Char, Text, HTML
● Numeric fields: Integer, Float, Monetary
● Datetime fields: Datetime, Date
● Computed fields: Fill fields automatically
● Other related fields: store/non store
● Most used attributes: required, readonly, compute, related, domain, store
Additional Exercise: Identify modules that use each one of these fields in the partner-contact repository
(https://github.com/OCA/partner-contact). Install and evaluate them.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
2nd Step: Creation of the model
from . import certification
from . import certification_standard
from . import models
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
3rd Step: Creation of views - Certification Tree view
<record id="certification_view_list" model="ir.ui.view">
<field name="name">Certification</field>
<field name="model">certification</field>
<field name="arch" type="xml">
<tree string="Certification">
<field name="number"/>
<field name="date"/>
<field name="standard_id"/>
<field name="entity_id"/>
<field name="owner_id"/>
</tree>
</field>
</record>
Adding views
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
3rd Step: Creation of views - Certification Form view
<record id="certification_form" model="ir.ui.view">
<field name="name">Certification</field>
<field name="model">certification</field>
<field name="arch" type="xml">
<form string="Certification">
<sheet>
<group>
<field name="number"/>
<field name="description"/>
<field name="date"/>
<field name="standard_id"/>
<field name="entity_id"/>
<field name="owner_id"/>
</group>
</sheet>
</form>
</field>
</record>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
3rd Step: Creation of views - Certification Action and Menu
<record id="certification" model="ir.actions.act_window">
<field name="name">Certification</field>
<field name="res_model">certification</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
name="Certification"
id="certification_menu"
sequence="5"
action="certification"/>
</odoo>
Adding menu items
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
3rd Step: Creation of views - Standard View
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="standard_view_list" model="ir.ui.view">
<field name="name">Standards</field>
<field name="model">certification.standard</field> Tree View
<field name="arch" type="xml">
<tree string="Standard">
<field name="name"/>
<field name="description"/>
</tree>
</field>
</record>
<record id="standard_form" model="ir.ui.view">
<field name="name">Standards</field>
<field name="model">certification.standard</field>
<field name="arch" type="xml">
<form string="Standard"> Form View
<sheet>
<group>
<field name="name"/>
<field name="description"/>
</group>
</sheet>
</form>
</field>
</record>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
3rd Step: Creation of views - Standard View
<record id="open_standard" model="ir.actions.act_window">
<field name="name">Standards</field>
<field name="res_model">certification.standard</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
Action Menu
id="Standard"
parent="certification_menu"
sequence="5"
action="open_standard"/>
</odoo>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create the certification module
4th Step: Create security folder with a 5th step: Add data on __manifest__.py
ir.access..model.csv file
{
'name': 'Certification',
'summary': "Defines certification for different purposes.",
'author': "Eficent, Odoo Community Association (OCA)",
'website': "https://github.com/<my_github_user>",
'category': 'Certification Management',
'version': '12.0.1.0.0',
'license': 'AGPL-3',
'depends': ['base'],
'data': ['security/ir.model.access.csv',
'views/certification_view.xml',
'views/res_partner_view.xml',
'views/standard_view.xml'
],
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 'demo': ['demo/certification_demo.xml'],
access_certification_user,certification.user,model_certification,base.group_user,1,1,1,1 'development_status': 'Beta',
access_certification_standard_user,certification.standard.user,model_standard,base.group_ 'maintainers': ['ceeficent']
user,1,1,1,1 }
Adding Access Security
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Additional exercise
Aeronix collects information referred to their employees identity documents. The
fields needed to be fulfilled are:
● Employee’s name
● Type (Passport, ID Card, Driving License)
● Identification number
This module must appear on the Main Menu.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Link certifications to partners
● Extending the res.partner model
from odoo import models, fields
class ResPartner(models.Model):
_inherit = 'res.partner'
certification_ids = fields.One2many(comodel_name='certification', inverse_name='owner_id')
is_certification_body = fields.Boolean(string='It is an entity', default='True',
help='Check this box if the contact is a certification entity')
Extending a model
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Link certifications to partners
● Extending res.partner view
Partner form
<page name='internal_notes' string="Internal Notes">
<field name="comment" placeholder="Internal note..."/>
</page>
<page name='sales_purchases' string="Sales &
Purchases">
<group name="container_row_2">
<odoo>
<record id="view_partner_form" model="ir.ui.view">
<field name="name">partner.certification.entity.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
Note <field name="arch" type="xml">
<field name="category_id" position="after">
Position: <field name="is_certification_body"/>
● After </field>
<xpath expr="//page[@name='internal_notes']" position="after">
● Before <page name ="certification" string="Certifications List">
● Inside <field name="certification_ids"/>
</page> Extending a view
● Replace
</xpath>
</field> Changing existing views –
</record>
</odoo> view inheritance
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Ensure data integrity in the certificate
● model method Defining model methods and using
● self and self.env API decorators
● API decorator(api.multi, api.model, api.constrains)
Reporting errors to the user
● Add: from odoo.exceptions import ValidationError
@api.constrains('entity_id')
def _check_entity_id(self):
if self.entity_id and self.entity_id.is_certification_body == False:
raise ValidationError('It is not a certification entity')
Reporting error to the user
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Set domain in the certification form
<record id="certification_form" model="ir.ui.view">
<field name="name">Certification</field>
<field name="model">certification</field>
<field name="arch" type="xml">
<form string="Certification">
<sheet>
<group>
<field name="number"/>
<field name="description"/>
<field name="date"/>
<field name="standard_id"/>
<field name="entity_id" domain="[('is_certification_body','=','True')]"/>
<field name="owner_id"/>
<field name="expiry_days"/>
<field name="expiry_status"/>
<field name="owner_id"/>
<button name="update_date_one_month" string="update date 1 month" type="object" />
</group>
</sheet>
</form>
</field>
</record>
Define filters on record list -
Domain
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Creation of a certification entity list
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="certification_bodies_view_list" model="ir.ui.view">
<field name="name">Certification Bodies</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<tree string="Certification Bodies">
<field name="name"/>
<field name="phone"/>
</tree>
</field>
</record>
<record id="action_certification_bodies" model="ir.actions.act_window">
<field name="name">Certification Bodies</field>
<field name="res_model">res.partner</field>
<field name="domain">[('is_certification_body', '=', True)]</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
id="certification.bodies"
parent="certification_menu"
sequence="5"
action="action_certification_bodies"/>
</odoo>
Note
For this view form it is needed to create a new .xml file.
In this case the domain is used to create a list which compiles all certification entities recorded in our
database.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Key Concepts
Defining filters on record lists – Domain
● Simple domain, list of 3 tuples: [(‘string’, ‘operator’, value)]
● Combination of simple domains using “&” (and operator) and “|” (or operators)
● From operator logic to domain logic:
○ From deeper logic block, move operator inside () at first place beginning. Repeat until all operators
have been move at first place. Then add commas between every element.
((A & B) | (C & D)) Operator logic
((&AB) | (&CD)) First iteration
|((&AB)(&CD)) Second iteration, no more operators to move -> Finished
[“|”, “&”, A, B, “&”, C, D] Domain logic
● Common usages
○ search([(‘entity_id’, ’=’, True)])
○ add a filter_domain to a field, for example:
■ <field name=”entity_id” domain=”[(‘entity_id’, ‘=’, True)]”/>
○ or directly in field definition:
■ entity_id = fields.Many2one(... domain=[(‘entity_id’, ‘=’, True)] ...)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Key Concepts
Domain operators
Operator (equivalent) Usage
= , != [(‘uid’, ‘=’, 1)], [(‘uid’, ‘!=’, 1)]
in, not in [(‘uid’, ‘in’, [‘1’,’2’,’3’])], [(‘uid’, ‘not in’, [‘1’,’2’,’3’])]
<, <=, >, >= [(‘date’, ‘>=’, self.date)]
like, not like name=‘Pepero’; [(‘name’, ‘like’, ‘Pepe’)]
ilike, not ilike Same as above case insensitive
child_of [('location_id', 'child_of', location_id.id)]
Used in models with parent_id
Look for locations children of main location_id
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Adding expiry information to the certificate Extending the business logic defined in a model
Updating values of recordset records
1st step: Add fields to the certificate model 4th step: Extend view
expiry_days = fields.Integer('Expiry Days', readonly=True, <group>
compute='_compute_expiry_days') <field name="number"/>
expiry_status = fields.Selection([ <field name="owner_id"/>
('expired', "Expired"), <field name="description"/>
('available', "Available") <field name="date"/>
], readonly=True, compute='_compute_expiry_days', store=True) <button name="update_date_one_month" string="Update the
validation date one month" type="object"/>
<field name="standard_id"/>
<field name="entity_id"/>
<field name="expiry_days"/>
<field name="expiry_status"/>
</group>
2nd step: Create a method which computes the expiry
status of each certification
3rd step: Add method updating expiry date by 1 month
@api.depends ('date')
def _compute_expiry_days(self):
@api.multi
if self.date:
def update_date_one_month(self):
self.expiry_days = (self.date - fields.Date.today()).days
self.ensure_one()
if self.expiry_days > 0:
if self.date:
self.expiry_status = 'available'
self.write({'date': self.date +
else:
timedelta(days=30)})
self.expiry_status = 'expired'
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Key Concepts
@api.multi
def update_date_one_month(self):
○ Direct Assignation self.ensure_one()
if self.date:
self.date += timedelta(days=30)
@api.multi
def update_date_one_month(self):
○ update() method self.ensure_one()
if self.date:
self.update({'date': self.date +
timedelta(days=30)})
@api.multi
def update_date_one_month(self):
self.ensure_one()
○ write() method if self.date:
self.write({'date': self.date +
timedelta(days=30)})
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Key Concepts
Odoo Shell: CLI in Odoo
# Open a new terminal in Pycharm.
$ export db_name=12.0-odoo-training-tai
$ ./home/$USER/odoo-dev/odoo/odoo-bin
--addons-path=/home/$USER/odoo-dev/odoo/addons,/home/$USER/odoo-dev/odoo/odoo/addons,/home/$U
SER/odoo-dev/partner-contact,/home/$USER/odoo-dev/odoo-training-tr shell -d $db_name
>>> self.env['certification'].create({'name': 'Test Certification 2', 'type': 'eucer'})
>>> test_certificate = self.env['certification'].search([('name', '=', 'Test Certification 2')])
>>> test_certificate.name # Test Certification 2
>>> entity = self.env['res.partner'].create({'name': 'Test Entity', 'entity': True})
>>> test_certificate.write({'entity_id': entity.id})
>>> test_certificate = self.env['certification'].search([('entity_id', '=', entity.id)])
>>> entity_mapped = self.env['certification'].search([('entity_id', '=', entity.id)]).mapped('entity_id')
>>> entity_mapped.name # Test Entity
>>> test_certificate.unlink() # Unlink certification
>>> entity.unlink() # Unlink partner
>>> env.cr.commit() # Commit changes to the database
>>> quit()
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Add demo data
2nd step: Define an Entity, a Supplier, a Standard 3rd step: Add path to __manifest__.py
1st step: Defining demo data directory
and a Certification for demo purposes
{
<?xml version="1.0" encoding="utf-8"?> 'name': 'Certification',
<odoo noupdate="1"> 'summary': "Defines certification for different purposes.",
'author': "Eficent, Odoo Community Association (OCA)",
<record id ="entity_demo"
'website': "https://github.com/<my_github_user>",
model="res.partner">
<field name="name">Entity Demo</field> 'category': 'Certification Management',
<field name="is_certification_body">True</field> 'version': '12.0.1.0.0',
</record> 'license': 'AGPL-3',
'depends': ['base'],
<record id ="supplier_demo" 'data': ['security/ir.model.access.csv',
model="res.partner"> 'views/certification_view.xml',
<field name="name">Supplier Demo</field> 'views/res_partner_view.xml',
<field name="is_certification_body">False</field> 'views/standard_view.xml'
</record> ],
Result in Odoo <record id ="standard_demo" 'demo': ['demo/certification_demo.xml'],
model="standard"> 'development_status': 'Beta',
<field name="name">Standard Demo</field> 'maintainers': ['ceeficent']
</record>
}
<record id ="certification_demo"
model="certification">
<field name="number">Demo Certification</field>
<field name="date">2019-12-31</field>
<field name="standard_id" eval="ref('standard_demo')"/> Loading data using XML files
<field name="entity_id" eval="ref('entity_demo')"/>
<field name="owner_id" eval="ref('supplier_demo')"/>
</record> Using the nonupdate flag
</odoo>
Using external IDs and namespaces
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Additional Exercise
Using the identity documents example, try to add some business logic to that
module.
● Add demo data in the identity documents module. It is mandatory to include
a passport record with its number and expiration date of a Demo Employee.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Define security groups to model Certification
● Defining security groups
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.module.category" id="module_category_certification">
<field name="name">Certification</field>
<field name="sequence">10</field>
</record>
<record id="group_certification_user" model="res.groups">
<field name="name">Certification User</field>
<field name="category_id" ref="module_category_certification"/>
</record>
<record id="group_certification_manager" model="res.groups">
<field name="name">Certification Manager</field>
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
<field name="implied_ids"
eval="[(4, ref('group_certification_user'))]"/>
<field name="category_id" ref="module_category_certification"/>
</record>
</odoo>
Creating security groups and
assigning them to users
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Add Access Control Limitations
Key Concepts
name Name identification
users Users that we want to belong in this group (generally, admin and root user)
implied_ids Inherited groups (generally, Managers belongs to Users group also)
category_id We can define a category to wrap similar groups (model ir_module_category)
domain_force * Not yet! Trickier statement. Coming soon, after explanation about domains.
<record id="group_certification_manager" model="res.groups">
<field name="name">Certification Manager</field>
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
<field name="implied_ids"
eval="[(4, ref('group_certification_user'))]"/>
<field name="category_id" ref="module_category_certification"/>
</record>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Add Access Control Limitations Loading data using CSV files
Key Concepts
id It must be an unique identificator in all system
name It will be displayed in ACL rules
model_id:id It needs model_ prefix and model name underscored (ex. model_res_partner)
group_id:id Group name. Namespace is required if group is defined in other module.
perm_* 1 to allow action, 0 to block action (1,0,0,0 Only read, 1,1,1,1 Full CRUD access)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Additional Exercise
Using the identity documents example, try to add some business logic to that
module.
● Only the managers can edit the information related to identity documents.
Create two different groups: managers and users. Then, establish the
appropriate security rules.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create a test
2nd step: Create a TestCertification class which will
1st step: Create a test directory
verify the expiry_status operation
import odoo.tests.common as common
class TestCertification(common.TransactionCase):
def setUp(self):
from . import test_certification super(TestCertification, self).setUp()
self.res_partner = self.env['res.partner']
self.partner = self.res_partner.create({
'name': "test1",
'email': "[email protected]"})
def test_certification(self):
certification = self.env['certification'].create({
'number': 'AAA',
'date': '2025-12-31'}) Python test cases
self.assertEqual(certification.expiry_status, 'available')
3rd step: Check if the test has run properly
2019-08-27 10:07:29,128 12621 INFO certification_v2 odoo.addons.certification_v2.tests.test_certification: Ran 1 test in 0.067s
2019-08-27 10:07:29,128 12621 INFO certification_v2 odoo.addons.certification_v2.tests.test_certification: OK
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
Defining a model based on an SQL view is used:
● To aggregate data from several models in a single table
● Perform operations on data
● Reporting and producing dashboard
Additional Business Requirements
Aeronix needs to define a Certification Analysis report in which they require to appear the following
information:
● The main objective is to obtain a table where there is a record of the certification entities with
the number of certificates they have emitted and their status.
● Certificates that have been emitted need to refer to the standard certification they have been
attached with.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
1st step: Create a new directory 2nd step: [Recommendation] Defining a model based on
named Reports Create a PostgreSQL Query an SQL view
SELECT
rp.id AS id,
rp.id AS entity_id,
cs.id AS standard_id,
c.expiry_status AS expiry_status,
count(c.id) AS certification_count
from res_partner AS rp
JOIN certification AS c
ON c.entity_id = rp.id
JOIN certification_standard AS cs
ON cs.id = c.standard_id
where rp.is_certification_body is True
GROUP BY
rp.id,
from . import certification_report rp.id,
cs.id,
c.expiry_status
Note
Remember to add it on the
Manifest and give Security to
the model.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
Include Query into certification_report.py
3rd step: Create certification_report.py model
def _select(self):
select_str = """
Define certification_report.py model: SELECT
rp.id AS id,
rp.id AS entity_id, Execute Query
from psycopg2.extensions import AsIs
cs.id AS standard_id,
c.expiry_status AS expiry_status, @api.model_cr
from odoo import tools count(c.id) AS certification_count def init(self):
from odoo import api, fields, models """
tools.drop_view_if_exists(self.env.cr,
return select_str
self._table)
def _from(self): self.env.cr.execute(
class CertificationReport(models.Model):
from_str = """ """
_name = "certification.report" res_partner AS rp CREATE or REPLACE VIEW %s as (%s
_description = "Certification Report" JOIN certification AS c FROM ( %s ) WHERE ( %s )
_auto = False ON c.entity_id = rp.id
JOIN certification_standard AS cs
%s)""",
ON cs.id = c.standard_id (AsIs(self._table), AsIs(self._select()),
entity_id = fields.Many2one('res.partner', readonly=True)
""" AsIs(self._from()), AsIs(self._where()),
certification_count = fields.Integer(readonly=True) return from_str AsIs(self._group_by())),
standard_id = fields.Many2one('certification.standard')
)
expiry_status = fields.Selection([ def _where(self):
('expired', "Expired"), where_str = """rp.is_certification_body is True"""
('available', "Available") return where_str
], readonly=True)
def _group_by(self):
group_by_str = """
GROUP BY
rp.id,
Note
rp.id,
_auto: Needs to be defined as False due to when creating a new model, Odoo wil
cs.id,
(by default)l create a new table. By positioning this class attribute to False, we
manage the table ourselves. c.expiry_status
"""
return group_by_str
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
4th step: View definition Defining graph and pivot
views
Pivot view: Graph view: Menu item and act_window:
<odoo> <record id="view_certification_report_graph" <act_window
<record id="view_certification_report_pivot" model="ir.ui.view"> id="action_report_certification"
model="ir.ui.view"> <field name="name">certification.report.graph</field> name="Certification Analysis"
<field name="name">certification.report.pivot</field> <field name="model">certification.report</field> res_model="certification.report"
<field name="model">certification.report</field> <field name="arch" type="xml"> view_mode="graph,pivot"
<field name="arch" type="xml"> <graph string="Certification Analysis">
target="current"/>
<pivot string="Certification Analysis" <field name="entity_id" type="column"/>
disable_linking="True"> <field name="standard_id" type="row"/>
<field name="expiry_status" type="column"/> <menuitem
<field name="entity_id" type="col"/>
<field name="expiry_status" type="row"/> <field name="certification_count" id="menu_report_certification"
<field name="standard_id" type="row"/> type="measure"/> parent="certification_menu"
<field name="certification_count" type="measure"/> </graph> action="action_report_certification"
</pivot> </field> sequence="25"/>
</field> </record> </odoo>
</record>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
5th step: Review results in Odoo
Graph view (I)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
5th step: Review results in Odoo
Graph view (II)
Available Expired Available Expired
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create analysis reports
5th step: Review results in Odoo
Pivot View (I) Pivot View (II)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create a QWeb-based PDF report
Creating QWeb-based PDF
reports
1st step: Create report_certification_pdf.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<report id="report_certification_pdf"
name="certification.certification_template_pdf"
model="certification"
string="Certification Report"
report_type="qweb-pdf" />
</odoo>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Case study - Partner Certifications
Create a QWeb-based PDF report
<?xml version="1.0" encoding="utf-8"?> 2nd step: Create certification_template_pdf.xml
<odoo>
<template id="certification_template_pdf">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc"> Note:
<t t-call="web.internal_layout"> Try to change for web external_layout
<div class="page">
<h1>Certification Number <t t-esc="doc.number"/></h1>
<table class="table table-condensed">
<thead>
<tr>
<th>Standard</th>
<th>Owner</th>
<th>Owner Category</th>
<th>Certification Body</th>
<th>Expiry Date</th>
</tr>
</thead>
<tbody>
<tr>
<td><t t-esc="doc.standard_id.name" /></td>
<td><t t-esc="doc.owner_id.name" /></td>
<td><t t-esc="doc.owner_id.category_id.name" /></td>
<td><t t-esc="doc.entity_id.name" /></td>
<td><t t-esc="doc.date" /></td>
</tr> PDF report
</tbody>
</table>
</div>
</t>
</t> 3rd step: Add both xml files to the __manifest__.py
</t>
</template>
</odoo>
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Get to know the OCA
Resources
97
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Get to know the OCA resources
https://docs.google.com/presentation/d/114JfhenNkEUDRKrjuIjwQzRKBtFjfJPPTR650feGqGQ
● What is the OCA?
● Target Groups that benefit from OCA
● Benefits to developers
● Benefits to business experts
● Benefits to integrators
● Benefits to customers
● OCA Projects
● Resources
○ Github
○ Maintainer tools
○ Runbot
○ Weblate
● How to contribute
● Sponsorship program
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Key Business
Apps
99
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Key Business Apps
● Review the areas of purchasing, inventory, accounting, maintenance.
● Identify the OCA related repositories and useful additional modules.
● Split in groups and create new modules that extend the functional areas.
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other
systems
101
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Learning Objectives
● Logging into/connecting Odoo with XML-RPC
● Searching/reading records through XML-RPC
● Creating/updating/deleting records through XML-RPC
● Calling methods through XML-RPC
● Using JSON-RPC
● The OCA odoorpc library
● Manipulate Postgres DB with psycopg2
● Server actions
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts
Logging into/connecting Odoo with XML-RPC
● Running Odoo instance required
(assumption in dev environment: from xmlrpc import client
http://localhost:8069) # Variables required
● XMLRPC python client. server_url = 'http://localhost:8069'
● common endpoint: /xmlrpc/2/common db_name = '12.0-odoo-training-tai'
○ Credentials not required username = 'admin'
password = 'admin'
● authenticate() method : # No authenticate required
○ returns user_id int if username and common = client.ServerProxy('%s/xmlrpc/2/common' % server_url)
password match with an user record # Check Odoo Version
version = common.version()
in the database. print(version)
○ method takes following arguments # Check user connection to database. Return user's ID
■ db_name user_id = common.authenticate(db_name, username, password, {})
print(user_id)
■ username
■ password
■ user environment agent
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts
Searching/reading records through XML-RPC
● object endpoint /xmlrpc/2/object -> Database operations
● execute_kw() method takes following arguments:
○ Database name
○ User ID (get from authenticate method)
○ Password
○ Model name, for example, ‘res.partner’
○ Method name, for example, search, read, search_read …
○ An Array of positional arguments
○ A dictionary for keyword arguments (optional), for example, context.
models = client.ServerProxy('%s/xmlrpc/2/object' % server_url)
if user_id:
search_domain = [('entity', '=', True)]
entity_partners = models.execute_kw(db_name, user_id, password,
'res.partner', 'search_read',
[search_domain, ['name', 'entity']],)
print(entity_partners)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts
Creating/updating/deleting records through XML-RPC
● Using execute_kw() method just changing method to:
○ create() allow batch creating adding parameters:
create_data = [{'name': 'XMLRPC Certificate'}, {'name': 'XMLRPC 2 Certificate'}]
certs = models.execute_kw(db_name, user_id, password, 'certification', 'create', [create_data])
○ write() to update records on batch also:
■ Do a previous search to get records to be modified or simply add ids in a array
■ Add dictionary with updates
from datetime import date
update_date = {'date': date.today().strftime("%Y-%m-%d")}
models.execute_kw(db_name, user_id, password, 'certification', 'write', [certs, update_date])
○ unlink() + array of ids to be unlink (unlink_ids = [...])
models.execute_kw(db_name, user_id, password, 'certification', 'unlink', [certs])
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts
Calling methods through XML-RPC
● Using execute_kw() it is possible also to call any public method different from previous ones:
● We can’t call private method (method prefixed with underscore _ ) from RPC.
● In our implementation of Attendance system:
○ We defined a method for register attendance on hr_attendance_rfid module:
https://github.com/OCA/hr/blob/12.0/hr_attendance_rfid/models/hr_employee.py#L22
○ RAS call it from:
https://github.com/Eficent/ras/blob/v1.2-release/lib/OdooXMLrpc.py#L98
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts import json, random , requests
server_url = 'http://localhost:8069'
db_name = '12.0-odoo-training-tai'
Using JSON RPC username = 'admin'
● Similar to XMLRPC but using JSON password = 'admin'
Formatting json_endpoint = "%s/jsonrpc" % server_url
● Interact with Odoo using HTTP requests headers = { "Content-Type" : "application/json" }
○ python libs like: request, urllib... def get_json_payload(service , method , *args):
● JSON-RPC uses jsonrpc 2.0 return json.dumps({
specification "jsonrpc" : "2.0",
"method" : 'call' ,
○ JSON Header required "params" : {
○ Payload formatting required "service" : service ,
"method" : method ,
● Result is found at ‘result’ key "args" : args ,
},
"id": random.randint( 0, 100000000 ),
})
payload = get_json_payload( "common" , "login" , db_name , username ,
password)
response = requests.post(json_endpoint , data=payload , headers=headers)
user_id = response.json()[ 'result' ]
if user_id:
print("Success: User id is" , user_id)
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts
The OCA odoorpc library: https://github.com/OCA/odoorpc
● User-friendly syntax to access Odoo data through RPC pip3 install OdooRPC
import odoorpc
def main():
server_url = input("Server URL: ")
server_port = input("Server Port: ")
username = input("User name: ")
pwd = input("Password: ")
# Instance OdooRPC class
odoo = odoorpc.ODOO(server_url, port=server_port)
odoo.config['timeout'] = 100000
# Login
odoo.login(db_name, username, pwd)
# Get a recordset
cert_model = odoo.env['certification']
cert_ids = cert_model.search([])
cert_recordset = cert_model.browse(cert_ids)
if __name__ == "__main__":
main()
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Integration with other systems
Key Concepts
Manipulate Postgres DB with psycopg2
● Execute SQL Queries using Python scripts def main():
db_name = input("Server URL: ")
● No system limitations, be careful. server_port = input("Server Port: ")
● Useful on DB data fixing username = input("User name: ")
pwd = input("Password: ")
# Define our connection string
conn_string = """dbname=%s user=%s
password=%s""" % (db_name, db_user, db_password)
# print the connection string we will use to connect
print "Connecting to database\n ->%s", conn_string
# get a connection, if a connect cannot be made an exception
# will be raised here
conn = psycopg2.connect(conn_string)
# conn.cursor will return a cursor object, you can use this
cursor
# to perform queries
Copyright 2019 Eficent Business and ITcr = conn.cursor()
Consulting Services S.L.
Program summary
110
Copyright 2019 Eficent Business and IT Consulting Services S.L.
Program Summary
● Objectives achieved
● Lessons learned
THANK YOU!!
Copyright 2019 Eficent Business and IT Consulting Services S.L.