Enable Dark Mode!
error-handling-in-odoo-15.jpg
By: Abhishek ET

Error Handling in Odoo 15

Technical Odoo 15

Handling errors is an important part of coding. We know that the Odoo Exceptions module gives us some default exception types like UserError, ValidationError, CacheMiss, AccessError, and so on. We use them or create new exceptions to raise exceptions in our code. While raising, We can handle these exceptions with Try and Except statements.

Raising Exceptions

We can raise exceptions based on any conditions in the code.

Here is an example code for raising an exception:

from odoo import models, _
from odoo.exceptions import UserError
class SaleOrder(models.Model):
_inherit = 'sale.order'
def action_confirm(self):
""" Raise an error on confirming the Sale Order if Tax = 0"""
if self.amount_tax == 0:
raise UserError(
_("You cannot confirm the Sale Order without Tax."))
return super(SaleOrder, self).action_confirm()

Here, an error message will be displayed in a pop-up.

error-handling-in-odoo-15-cybrosys

For more examples, visit Raising Exceptions in the Odoo 15.

There are other cases where we will get errors from code. For example division of a number with zero:

from odoo import fields, models

class SaleOrder(models.Model):
_inherit = 'sale.order'
test_tax = fields.Char(string='Test Tax')
def action_confirm(self):
""" Update Test Tax on confirming the Sale Order """
if self.amount_total/self.amount_tax:
self.test_tax = 'Success'
else:
self.test_tax = 'Failed'
return super(SaleOrder, self).action_confirm()

This code will give an error if the amount_tax is zero.

error-handling-in-odoo-15-cybrosys

The ZeroDivisionError is a built-in exception in python.

Built-in Exceptions

There are predefined built-in exceptions in python that give an error on the occurrence. Odoo will show these exceptions as server errors. Some built-in exceptions are listed below:

ExceptionDescription
ExceptionBase class for all exceptions
ZeroDivisionErrorRaised when the second operator in a division is zero
SyntaxErrorRaised when a syntax error occurs
NameErrorRaised when a variable does not exist
KeyErrorRaised when a key does not exist in a dictionary
ImportErrorRaised when an imported module does not exist (or could not be imported)
SystemErrorRaised when a system error occurs
ArithmeticErrorRaised when an error occurs in numeric calculations
EOFErrorRaised when the input() method hits an "end of file" condition (EOF)
RuntimeErrorRaised when an error occurs that does not belong to any specific exceptions
OSErrorRaised when a system-related operation causes an error
TabErrorRaised when indentation consists of tabs or spaces (when mixing tabs and spaces for indentation)
UnicodeErrorRaised when a unicode problem occurs
UnicodeTranslateErrorRaised when a unicode translation problem occurs
UnicodeDecodeErrorRaised when a unicode decoding problem occurs
UnicodeEncodeErrorRaised when a unicode encoding problem occurs
MemoryErrorRaised when a program runs out of memory
IndentationErrorRaised when indentation is not correct (4 spaces are recommended for the indentation by the PEP8 style guide)
FloatingPointErrorRaised when a floating point calculation fails
AssertionErrorRaised when an assert statement fails (mostly used in python tests in Odoo)
GeneratorExitRaised when a generator is closed (with the close() method)
StopIterationRaised when the next() method of an iterator has no further values
TypeErrorRaised when two different types are combined
KeyboardInterruptRaised when the user presses Ctrl+c, Ctrl+z, or Delete
OverflowErrorRaised when the result of a numeric calculation is too large
SystemExitRaised when the sys.exit() function is called
NotImplementedErrorRaised when an abstract method requires an inherited class to override the method
UnboundLocalErrorRaised when a local variable is referenced before assignment
LookupErrorRaised when errors raised can’t be found
ReferenceErrorRaised when a weak reference object does not exist
AttributeErrorRaised when attribute reference or assignment fails
ValueErrorRaised when there is a wrong value in a specified data type
IndexErrorRaised when an index of a sequence does not exist (mostly happens when an index is specified with an empty iterable object, empty recordset, or empty string)

Try and Except Statement

As we have discussed above, the built-in python exceptions and the manually added exceptions will stop the execution and show the corresponding error to the user. Sometimes there will be requirements like storing the errors in the record of a model or doing any functions on the failure of another function instead of showing an error to the user.

In the second example, the field Test Tax is not updated, and the state of sale order is not changed due to the error.

So, we can do it with the try and except statement. I am adding one more field to show the error in the Sale Order(models/sale_order.py):

# -*- coding: utf-8 -*-
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
test_tax = fields.Char(string='Test Tax')
capture_error = fields.Char(string='Error')
def action_confirm(self):
""" Update Test Tax and Error on confirming the Sale Order """
try:
if self.amount_total/self.amount_tax:
self.test_tax = 'Success'
except UserError as e:
self.capture_error = str(e)
self.test_tax = 'Failed'
except ZeroDivisionError as e:
self.capture_error = str(e)
self.test_tax = 'Failed'
except Exception as e:
self.capture_error = str(e)
self.test_tax = 'Failed'
else:
self.capture_error = 'No errors'
finally:
self.capture_error = 'Finally: ' + self.capture_error
return super(SaleOrder, self).action_confirm()

The XML code to add these fields in the form view of Sale Order(views/sale_order_views.xml):

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <record id="sale_order_view_form" model="ir.ui.view">
        <field name="name">sale.order.view.form.inherit.handling_errors</field>
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form" />
        <field name="arch" type="xml">
            <xpath expr="//field[@name='payment_term_id']" position="after">
                <field name="test_tax" readonly="1" />
                <field name="capture_error" readonly="1" />
            </xpath>
        </field>
    </record>
</odoo>

In the python code, a try and except statement is included. The try and except statement consists of a try block followed by one or more except block(s) and optional else and finally blocks.

We add the code for which we have to catch an error in the try block. Then we will add the except blocks to catch errors. If we are looking for any specific exceptions, we can add them. For example, UserError, ZeroDivisionError, and Exception have been added to the code above. The first exception will trigger. Since we have the error, float division by zero in the case below, the except block for ZeroDivision error will be triggered, and the value ‘Failed’ will be stored in Test Tax and the error message in the Error. The blocks for UserError and Exception will be skipped.

error-handling-in-odoo-15-cybrosys

If we have to catch all errors, then we will use the Exception.

Since it is the base class for exceptions, we can catch all the errors. If we are supposed to add multiple except blocks as we have here, the Exception should be added as the last one. Then we have the two optional blocks: else and finally. The else would trigger only if the code in the try block was executed successfully without an error. The value ‘Success’ will be stored in Test Tax and ‘No errors in the Error. At last, we have the final block. It will run in all cases. You can see that the ‘Finally: ‘ is added in both cases in the value stored in the Error field.

error-handling-in-odoo-15-cybrosys

In the first two examples: the execution is stopped, and the error message is displayed. But, in the last example, the entire function is executed and values in the fields are updated from the function, and the state of the sale order is changed.

In Odoo, we can use urllib.error, urllib3.exceptions, and requests. exceptions to manage the exceptions related to the HTTP connection and requests. An example is given below:

import requests

from odoo import api
@api.model
def _fetch_data(self, base_url, params, content_type=False):
result = {'values': dict()}
try:
response = requests.get(base_url, timeout=3, params=params)
response.raise_for_status()
if content_type == 'json':
result['values'] = response.json()
elif content_type in ('image', 'pdf'):
result['values'] = base64.b64encode(response.content)
else:
result['values'] = response.content
except requests.exceptions.HTTPError as e:
result['error'] = e.response.content
except requests.exceptions.ConnectionError as e:
result['error'] = str(e)
return result

Catching and handling the errors are important since they help us to manage the flow of the occurrence of errors.


If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment

 
whatsapp
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

London

Cybrosys Limited
Alpha House,
100 Borough High Street, London,
SE1 1LB, United Kingdom

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message