technical training log
TRANSCRIPT
-
8/2/2019 Technical Training Log
1/11
Setup of PG/OpenERP
sudo
createuser as postgres
\du
posgres.conf and pg_hba.conf edit in /etc/postgres/8.3/main/ invoke-rc.d posgtres-8.3 reload
openerp-server.py arguments
-c XXX.conf (avoid .openerp in $HOME)
-s (for save and create)
edit openerp conf file
db_user
db_password
db_host (False for unix socket with ident method by default)
db_port (False for unix socket with ident method by default)
addons_paths (to be able to update we use a separate tree) create new DB in open ERP client (watch out if name exists already!)
use minimal profile, extended interface
Day 1
introduction
get source from launchpad
config posgtres and openerp-server
add product module as example add shortcuts (views and objects)
architecture intro
client, server, ORM, OSV, RPC gateway, ...
techno
unit tests
useful for regression tests
bugfix check
speedup data provisioning
unique to Open ERP
intro data model user, group, role, right
introduction to views on users, roles, groups
example: add toolbar with 1rst level on the left (menu) in tree view with (toolbar=1)on product structure
requests intro, can attach any object (end of request => active = False)
database backup: warning: may need password in console (in windows notpossible, use a file with the password) can't pass it as argument to openerp, itwould be visible in process list ~/.pgpass [ON WINDOWS: %APPDATA%\PostgreSQL\pgpass.conf (%APPDATA% is
the 'Application Data' folder in your user profile] each line: host:port:db:user:password
i.e: localhost:5432:*:formation:formation
chmod 600 (otherwise ignored)
-
8/2/2019 Technical Training Log
2/11
db backup with pg_dump directly
pg_dump: pg_dump -h HOST -U USER -f PATH -Fc DB
e.g: pg_dump -h localhost -U formation -f /tmp/formation.backup -Fctechtraining
check that the dump is not empty!
-Fc makes it work with blocks, thus faster, and works with pg_restore
Stuff to backup:
Database Filesystem
server/addons
server/filestore (DMS/GED)
Create a new empty module [openacademy], or better idea?
IDE Tips:
gedit has a python console (to activate in plugins)
gedit also has a plugin for openerp modules
vim can have a python console too
Eclipse has pyDev
Structure of a new module: views in views/ subdirectory
menu.xml in view for generic actions
wizards in wizards/ with declarations in wizard
(...)
__init__.py
configure encoding
GPL header
configure the tabwidth (4 spaces) and use spaces and no tabs!
__terp__.py
'init_xml': list of files to download at module init / or when starting server -imodule (= reinstall)
'update_xml' : #list of files to download at module update when startingserver -u module
'demo_xml': #files containing demo_data, for unit_tests for example
'installable': #can't be installed via menu if False
'active': #automatic installation at new DB creation!
'certificate' : when module is certified, this is the certificate provided by Editor
Advice: always put ending comma in last item in lists, etc.
Important tip: into the module dir : python command-line to check syntax: eval(open('__terp__.py','r').read())
Reload module list and install (watch out for installable flag)
Datamodel for OpenAcademy module
cursus
training
trainer
participant
Create training.py
See menu definition to find object names (Ctrl+L on menu item)
Many-to-one relationships: name field xxx_id (UML names are inverted)
One-to-many relationships: name field xxx_ids (UML names are inverted)
lambda functions for defaults init (see ref)
reload/update module using openerp-server -c CONF -d DB -u MODULE
-
8/2/2019 Technical Training Log
3/11
If error File "/home/olivier/src/training/server/bin/osv/orm.py", line 1880, in_auto_initref = self.pool.get(f._obj)._table
/!\ missing dependency! Add the dependency in __terp__
Add a 'view' directory
Add a view : training.xml record for the view (type=tree)
record for the action
Add a generic menu
record for menu items
Add children menus in menu.xml
Reload server
Day 2
Install pgadmin3: sudo aptitude install pgadmin3
Form > View logs can display the 4 log fields (create_uid/date, write_uid/date)
Opening the cursus list works, and we can switch to the form: displays a defaultform
Create a better-looking form: view_openacademy_cursus_form Add search criteria (select=1 for simple, select=2 for advanced)
The criteria are displayed in List view, but are specified in the Form view, because the list viewdoes not necessarily have all the fields. The fields can also be defined in the List view, in case itis not defined in the Form view. It is also possible to do it on fields that are not in the form using"relate fields"
Add tabs with notebook container and pages
Organize columns with colspan
Add groups with col and colspan (default colspan = 2)
Add separator with label
Add newline
Add completion on many2one
Change nameget method / search method
Restriction on field (with domain: array of tuples) equivalent of WHERE clause
Domains with '|' operator
Special arguments for view design:
height, width
fill,expand
align
icon
Play with date fields with shortcuts (will be present in next version for int/float)
Define default values for fields
Using right)click->'set as default', possibly based on another field's value
By editing the menu (with Ctrl+L); then the resource, and passing it in thecontext ('default_' : '')
Or by specifying in the XML (how?)
Create triggers with 'attrs' dictionary
attrs= "{'required': [('product_id','!=', False)]}"
Debug RPC request (e.g. For completion that does not take the domain intoaccount)
start client with -l debug_rpc (requests only)
-
8/2/2019 Technical Training Log
4/11
start client with -l debug_rpc_answer (requests and answers)
Make fields readonly or invisible with conditions OR attributes
Create GROUP (need specific id) to be able to create conditions on it
New subdir security > groups.xml
Load it in __terp__
Add attribute "groups" to GUI element (need to prepend module namespace! : if nodot is encountered in the group, the current module name is prepended(openacademy)
Create the new class: Training
create the record
the view, menu, action
define _order to decide about the ORDER BY
Validation of XML in server/bin/import_xml.rng (RNG format=trade-off of DTD andXLMS)
Validation of sub-grammars in server/bin/addons/base/rng/...
Use addons as doc and examples
Validation of the XML (training.xml) using xmllint: xmllint --relaxng ../../server/bin/import_xml.rng view/training.xml
xmllint --relaxng ../../server/bin/import_xml.rng view/training.xml noout
XMLCopyEditor is an Ubuntu editor that validates based on an RNG sheet
xmllint can be used to test Xpath expressions: xmllint shell opens a shell
in which you can type 'xpath '
Create Calendar view for the trainings
Add calendar view
Add possible view modes in the action
Create Participant class
can use _rec_name = 'firstname' to have a class without a name attr
create many-to-many relation from trainingparticipant
create reverse many-to-many by extending the existing participant (watch out:_inherit (not inherits))
Export translations
Create i18n subdir
Extract template of translations: Admin>Translations>Export for this module
Install poedit via aptitude
Use ctrl+arrows to browse translations
Disable 'save compiled .mo" in poedit preferences
Copy the en_EN.po file to fr_FR.po for example
Merge translations with pot2po sudo apt-get install translate-toolkit
pot2po -i openacademy.pot -t fr_FR.po -o fr_FR.po -s 100
Watch out for the similarity factor (fuzziness), and order of parameters: -i is the input POT
-t is the PO to preserver
-o is the output to replace the PO
--nofuzzymatching or -s 100 can be used to avoid fuzzy mistakes
Addition of button in training form
add a button object in the form view, with validity states, and function target
add the corresponding function def in the class
Add an on_change processing to set the duration in the produce_delay field
-
8/2/2019 Technical Training Log
5/11
how to find the name of this field in the views (within the client)?
add an on_change to the view, calling a function onchangeproduct()
on_change triggers only for USER interactions, not programmatic
add warning in the dictionary returned to the view
Versioning of our code locally bzr init
bzr status
bzr add
bzr ci, with structured message [NEW], [I18N], [IMP], ???
bzr log??
How to package a bzr tree bzr export openacademy.zip ./openacademy
Important use of many2one one2many or many2many many2manysymmetricity
Many lengthy developments can be avoided by thinking of the symetricity of allrelationships, and the possible encoding interface they could add
Example of uses: product pricelist : if we want the list of prices in the product
planning hours analytic account (project) versus booking resources in theproject itself
Introduction to workflows: what it is, example
process history is persisted, cannot change status
single point of fixing
Workflow can be in Plugin>Workflow
Introduce/demo the trunk version
Day 3
Recap of day 2 with latest stuff.. possibly copy the complete module for people thatare lagging
Note: Watch out for "object NoneType does not have a _table attribute" or something similar ->means dependencies are not correctly declared in the __terp__, or the ordering of classes is not
correct in thecode?
Trick: edit the 'Views' view to add the priority, etc.. by copying those of the form.
Customize the search as well to display the only view inheriting from res.partner
Extension of an existing class, for example Product
find the object name (product.product) > e.g. via Ctrl-L on the correspondingmenu
define another "Product" class
do not forget to verify the dependency on product.product
find out where to attach in existing product view by opening it via admin menu
add the new view in training.xml
find out the "inherit_id" in the database
Explain pgadmin3 select module||'.'||name from ir_model_data where model='ir.ui.view'
and res_id=129 (where 129 is the record_id of the
product.normal.form.view in the client) OR find out the record id in the declaration of the view in the module
(product.xml) -> and reference it as ref="product.product_normal_form_view"
-
8/2/2019 Technical Training Log
6/11
Short XPath introduction
Select the field we are looking for using XPath to find our target
Choose the positioning: after, before, replace, inside (for pages)
Watch out: if you forget the position, the client will silently traceback!
This is a problem in the RNG, position and expr fields should be required! >
see BUG Rgrep for xpath in the code if you need examples
Note: former (pre-5.0) syntax did not use XPath
Watch out for the XPath expressions using wildcards, as they can be quitecostly!
Reload server
Now modify the training view to filter the products based on this new flag in thedomain for product_id... then test it
Implement a reverse one-to-many by adding a one2many relationship in Cursus totrainings (training_ids): one2many relationships are virtual
then add a tab to display these, with nolabel now we want to customize this list view, to hide the redundant 'Cursus' column
here
Inside a one2many field in a view, we can redefine the list view, form view, calendarviews to use. We can also make the field editable in place.
SQL Constraints/Python constraints can be added -> search _constraints and_sql_constraints in the code or document
See example in addons/crm/crm.py (check_recursion with sql_injection)
See the list of predefined fields for objects in doc (_auto, _inherits, _rec_name...)
Arbitratry SQL can be execute in init() method of osv objects (see the report
modules for examples) Add colors to the list :
colors="blue:state=='draft';#aabbcc:state=='confirmed'"
Workflows
Need a state field!
Define activities, and transitions
Create a subdirectory workflow in module
Create manager role in workflow/roles.xml
Add it in the __terp__ !
Note: Check the bzr status, for example: bzr status
bzr add
bzr diff
bzr ci
bzr revert = revert all changes done since last commit
bzr revno = shows the current revision number
bzr log [--line]
Create a workflow: name, osv, on_create = True
then declare the activities, and transitions in a separate XML file
name
wkf_id references the workflow Watch out: wkf_id is a ref!
with the begin node marked with flow_start and end node with flow_stop
and transitions
-
8/2/2019 Technical Training Log
7/11
act_from: ref to source Watch out: is a ref!
act_to: ref to destination Watch out: is a ref!
signal: exact name of the button defined in the view
condition (boolean python expression: must evaluate to True for transition toexecute)
role_id ref can be added to restrict by roles (button is disabled otherwise)
Watch out: is a ref! Add an action and kind can be added on the activity and are executed when
the activity becomes active
The workflow engine will check both sides of a transition before applying it
Printing the workflow will highlight the current activity
Execute plugin/greffon -> print the workflow
change the buttons to workflow
Change type to workflow instead of object in the views, and change the name ofthe button to the signal names!
Add a condition on a transition
add a min_part on the Training class
add this field in the view
change condition from True to a function call : check_participants()
view the condition in the client
read the min_participants field and print it
Watch out: add a default otherwise the client won't see that it was modified
Get the number of registered participants, and raise if it's too low
Complete the translations
Watch out that strings in python code is not imported in the pot by default!
Thus we need to from tools.translate import _and use it to surround
strings (underscore is a gettext alias in C world)
Re-export the pot file (do not specify the language)
Re-execute pot2po
Warning: there is an open bug about workflow RPC not passing context, andthus preventing the _() function translation to work. So this won't work totranslater the raise error message
Creation de Server Action pour automatiser des actions dans le client
all done via the GTK client
Day 4 We have not yet used a "field function", so let's create one:
in the Training class, add a field fields.function
type = float
multi = sums (means that the function should be called only once for severalrecords?)
method = True ???
store = True/False??
create a function before the field definition def _calculate(self, cr, uid, ids, field_name, arg, context=None)
the function returns a dictionary with record ids as keys, and with value beingdictionaries containing named values
we can use self.browse() to follow relationships easily
-
8/2/2019 Technical Training Log
8/11
watch out for operations on integers/floats
see examples in sale module (sale.py)
Ex: implement a margin field (list_price-sale_price)*num_participants
add it to the_calculate function
Display the summation in the tree view for margin and total_amount fields byadding a sum attribute
Check out the technical guide (introspection of module) in the actions of the module
Create a statistical view
start by with SQL query in pgadmin3 and write an appropriate statistics query
add a dummy class representing it in training.py,with all columns being readonly!
do not forget the_auto = False to prevent automatic creation of the table
add an init() function to create the view upon install/update of a module
Watch out: always put an explicit drop_view_if_exists before the creation ofthe view, because the replace cannot work if columns changed. (get it fromtools.sql import drop_view_if_exists)
declare the report view in training.xml
Add a "tree" view for the content of this pseudo table
Add an action to open this view
Add a menu and submenu to open the action
optional: bzr commit the new stuff
We can prepare a wizard directory using bzrmkdir wizard
Create an Invoice Wizard
Note: old wizard syntax and new wizard syntax are both support
Create a Python class for the wizard, inheriting from wizard.interface
the name of the wizard must be unique and is passed at instantiation (it shouldstart with the module name)
defines the states dictionary, initial one must be 'init', and 'end' state is implicit
create entry point in wizard directory in __init__.py
must also create an entry point in the module's __init__.py itself, by importingthe 'wizard' directory (which will automatically load __init__ inside the directory)
Bazaar pull for a given stable release only:
bzr pull -r tag:5.0.6
How to use the LOGGERS
import netsvc
logger = netsvc.Logger()
logger.notifyChannel('openacademy', netsvc.INFO, 'data: %r' % data)
Note: check implications, performance, shorter aliases?
Implement the invoice generation:
install account module
examine the account.invoice technical guide to study its fields
add a 'valid' state in the wizard states
create a function _invoice to receive the form data and process it
add_invoice to the actions array
set the type of the state to 'state'
set the state to 'end' to finish the wizard afterwards
Important: all form data is kept from one wizard step to the next!
Important: the wizard can work on one object or in list view on multiple id if wewant it, we can decide on this by using data['id'] or data['ids'] depending onwhat we want
-
8/2/2019 Technical Training Log
9/11
we can't use self.browse, so we need to request a connection from the pooler
import pooler
read the documentation to see how osv.osv.create() works
For a new invoice we need:
origin
partner_id
account_id
address_contact (billing)
This is tricky because there are several addresses. Luckily there's afunction that does it all for you in res.partner (base module): address_get
Watch out that a participant might not have a partner (for example add acheck/raise wizard.except_wizard for this case
instead of checking the presence of the partner and address at invoicecreation, we can do it before starting the wizard, in the actions of the init
state
wizard functions can also return a dictionary of fields to set/update
Important: there is a special syntax to ensure the insertion/update/deletion ofseveral records in the same transaction, ensuring that everything is rollbacked atthe same time.
[0,0,object] = one2many?
[6,0,object] = many2many?
[2,0,object] = unlink?
-> See the invoice.py _invoice() function
Optional: bzr commit
Create a graphical report now:
create a report subdir
if we want a custom parser (otherwise a default one is used): create a newtraining.py file with a Training class extending the report_sxw.rml_parse class
if that's the case we need the corresponding__init__ in the report directory,importing our class, and the corresponding import report in the__init__ ofthe module
setup the parser in the constructor
create the correponding report.xml file (add it to the __terp__)
specify auto=False to use the parser class we created
check that no parsing error occurs when starting the server, and that a printreport is now available on training objects
now to create the RML file, we'll convert an openoffice (writer) document to RMLusing the tiny_swx2rml
open an existing swx, such as addons/sale/report/order.swx , to import the
openerp styles
delete everything except the first line, then save it as a copy (in OO text 1.0)
access properties using [[ o.field ]] syntax
custom syntax properties could be supported by declaring correspondingfunctions in the parser class
after designing the report, convert it to RML:
python.../addons/base_report_designer/wizard/tiny_sxw2rml/tiny_sxw2rml.py training.sxw > training.rml
the RML file can be edited (see RML User Guide from ReportLabs)
not all the RML spec is supported, only a part of it (implemented by
-
8/2/2019 Technical Training Log
10/11
Fabien)
See OpenObject library project on launchpad created by Christophe(s)
DAY 5
Questions from other days
Example of wizard using osv_memory
addons/base/model/wizard/wizard_export_lang.py
_name starts with module name, and ends with wizard (by covention)
define a standard object with columns, etc., but with a state field
need to define the first state withing _defaults
any initialisation can be done in init(..), returning a {} with any fields set
need an actual view defined in XML, that we put within the wizard/ directory forcleaniness
an attribute "special = cancel" can be added to in the view, to preventre-opening the wizard after the corresponding action completes. This is notavailable with osv_osv
we have a regular action to open the wizard, except that we add a new
Important: the new wizards adds inheritance (was not possible in regularwizards)
creating act_window record to add contextual action menus
such as the links added to partners when the account module is installed(invoices, ...)
see Administration > Low-level objects > Links between client actions
Creating Graph view is very simple graph view with type={graph,pie}
select the X, Y axes as fields, with operators to generate "group by"'s
Creating Gant charts
Works only on the web client (eTiny)
Organized by levels, with link_id organizing
XXX to test
Review OpenERP menus (top bar and ctrl+t menu)
import/export data
Icons: icons can be added using gtk-* icons, passed in states in the wizard states,
or as icon attributes in views custom icons can also be added, but client-side, in bin/, and accessed by
prefixing their names by terp-
python docstring
XML-RPC trial
See the xmprpclib python module
try help xmlrpclib.ServerProxy in python interpretor
login on the server using xmlrpc
create a product (check the required fields by opening the NEW product form inthe GTK client)
Using CSV files to insert records create a security dir in the module
csv file must be names exactly as the object we want to insert record for
-
8/2/2019 Technical Training Log
11/11
first line contains the column identifiers (copy the one frombase/security/ir.model.access.csv)
usually modules have a CSV file for ir.model.access to implement access rights
all id's for access right should start with "access_"
watch out: no spaces are allowed between values in CSV
A few interesting SQL requests:
select module||'.'||name,res_id from ir_model_datawhere model='res.groups'and module = 'base'
select * from ir_model_data where model='ir.model'and module = 'openacademy'
select '20091010'::char(20);