Odoo is a suite of open source business apps that cover all your company needs: CRM, eCommerce, accounting, inventory, point of sale, project management, etc.
This article provides an overview to get started with the Odoo connector in Peliqan. Please contact support if you have any additional questions or remarks.
Contents
- Contents
- Connect Odoo
- Sync custom models
- Sync custom fields
- Writeback to Odoo from Python scripts
- Basic writeback functions
- Generic functions
- Applying multiple filters in Odoo
- Custom fields
- Fields of type One2Many
- Fields of type Many2Many and One2Many
- Working with product template & attributes
Connect Odoo
In Peliqan, go to Connections > Add Connection > Select Odoo in the list > Enter the details of your Odoo instance.
Sync custom models
You can include custom modules in the ETL pipeline, by adding a comma-separated list with the names of your custom models in the field “Custom models”. These models will now also be synced to the data warehouse as tables.
Sync custom fields
Custom fields will automatically be added as columns in the tables in the data warehouse. If you add new custom fields in Odoo, perform a “Full resync” to include them in the data warehouse.
Writeback to Odoo from Python scripts
Basic writeback functions
Example to add a Product to Odoo:
odoo_api = pq.connect('Odoo')
product = {
'name': "My new product"
}
result = odoo_api.add('product', product)
st.json(result)
Example to update a Product in Odoo:
odoo_api = pq.connect('Odoo')
product = {
'id': 123,
'name': "My new product updated"
}
result = odoo_api.update('product', product)
st.json(result)
Generic functions
These functions can be used to work with any model in Odoo, a standard or custom model.
Add object from a given model:
odoo_api = pq.connect('Odoo')
object = {
"model": "product.template", # this could be a custom model
"payload": [
{
"name": "My new object"
}
],
"additional_params": {}
}
#result = odoo_api.add('object', object)
#st.json(result)
Update object from a given model:
object = {
"model": "product.template", # this could be a custom model
"payload": [
[123], # id of the object to update
{
"name": "My new product updated",
}
],
"additional_params": {}
}
result = odoo_api.update('object', object)
st.json(result)
Execute a custom method or action on an object, for example Confirm a quotation to turn it into a sales order:
odoo_api = pq.connect('Odoo')
object_method = {
'model': "sale.order",
'method': "action_confirm",
'payload': [[17]], # id of the quotation to update
'additional_params': {}
}
result = odoo_api.update('object_method', object_method)
st.json(result)
Get objects using paging, and a fields list (note that some Odoo models require a fields list to be given in order to get a response from the API):
odoo_api = pq.connect('Odoo')
object = {
'model': "product.product",
'payload': [
[
]
],
'additional_params': {
"order": "id desc",
"offset": 0,
"limit": 50, # maximum allowed by Odoo is 50
"fields": ["id", "name"]
},
}
result=odoo_api.get('object', object)
st.write(result)
Applying multiple filters in Odoo
→ One can use generic get_object endpoint which can help applying multiple filters in on API request with dynamically defining the Model name.
→ this will return the first page only, max. 50 results
→ Please find below the example of working with multiple filters:
# AND operator
odoo_api = pq.connect('Odoo')
object = {
'model': "product.product",
'payload':
[
['&',
['id', '=', 200],
['write_date', '>', '2024-09-01T00:00:00']
] ],
'additional_params': { },
}
result=odoo_api.get('object', object)
st.write(result)
# OR operator
odoo_api = pq.connect('Odoo')
object = {
'model': "product.product",
'payload':
[
['|',
['id', '=', 200],
['write_date', '>', '2024-09-01T00:00:00'],
['display_name']. '=' ,'Sample Product']
] ],
'additional_params': { },
}
result=odoo_api.get('object', object)
st.write(result)
Custom fields
Set value of a custom field:
odoo_api = pq.connect('Odoo')
product = {
'name': "My new product",
"x_my_custom_field": "Some value"
}
result = odoo_api.add('product', product)
st.json(result)
Fields of type One2Many
Examples of working with fields (basic or custom) of type one2many:
odoo_api = pq.connect('Odoo')
ADD_LINK = 4
REPLACE_LINKS = 6
# Add new product with one one2many field value
# Link this product to id 40
odoo_api = pq.connect('Odoo')
product = {
'name': "My new product",
"x_related_product": 40
}
result = odoo_api.add('product', product)
st.json(result)
Fields of type Many2Many and One2Many
Examples of working with fields (basic or custom) of type many2many or one2many:
odoo_api = pq.connect('Odoo')
ADD_LINK = 4
REPLACE_LINKS = 6
# Add new product with one many2many field value
# Link this product to id 40
odoo_api = pq.connect('Odoo')
product = {
'name': "My new product",
"x_related_product": [[ADD_LINK, 40]]
}
result = odoo_api.add('product', product)
st.json(result)
# Update product with id=47, replace many2many field values
# Link this product to ids 41 and 42
odoo_api = pq.connect('Odoo')
product = {
'id': 47,
'name': "My new product updated",
"x_related_product": [[REPLACE_LINKS, 0, [41, 42]]]
}
result = odoo_api.update('product', product)
st.json(result)
For a many2many and one2many fields, following value format is required:
[[ 0, 0, { values } ]]
link to a new record that needs to be created with the given values dictionary[[ 1, ID, { values } ]]
update the linked record with id = ID (write values on it)[[ 2, ID ]]
remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)[[ 3, ID ]]
cut the link to the linked record with id = ID (delete the relationship between the two objects but does not delete the target object itself)[[ 4, ID ]]
link to existing record with id = ID (adds a relationship)[[ 5 ]]
unlink all[[ 6, 0, [IDs] ]]
replace the list of linked IDs
Working with product template & attributes
Example to link attribute values (e.g. Small, Medium, Large) for an attribute (e.g. “Size”) to a product template (e.g. “Shoe”):
odoo_api = pq.connect('Odoo')
ADD_LINK = 4
REPLACE_LINKS = 6
# Create product template attribute line (= link attribute values to template)
# Odoo will automatically create product.template.attribute.value items and product variants (product.product)
obj = {
'model': 'product.template.attribute.line',
'payload': [{
'product_tmpl_id': product_tmpl_id, # e.g. Shoe
'attribute_id': attribute_id, # e.g. Size
'value_ids': [[ REPLACE_LINKS, 0, [value1_id, value2_id] ]] # e.g. Small, Medium
}],
'additional_params': {}
}
result = odoo_api.add('object', obj)
st.json(result)
line_id = result["detail"]["result"]
# Add additional attribute value
obj = {
'model': "product.template.attribute.line",
'payload': [[line_id], {'value_ids': [[ ADD_LINK, value3_id ]]}], # e.g. Large
'additional_params': {},
}
result = odoo_api.update('object', obj)
st.json(result)
# Get details of created line
search = {
'model': "product.template.attribute.line",
'payload': [[
['id', '=', line_id]
]],
'additional_params': {},
}
result = odoo_api.get('object', search)
st.json(result)
product_template_attribute_value1_id = result["product_template_value_ids_0"]
product_template_attribute_value2_id = result["product_template_value_ids_1"]
# Get details of attribute value 1 (to extract id of created product variant)
search = {
'model': "product.template.attribute.value",
'payload': [[
['id', '=', product_template_attribute_value1_id]
]],
'additional_params': {},
}
result = odoo_api.get('object', search)
st.json(result)
product_variant1_id = result["ptav_product_variant_ids_0"]
Odoo data model: