Overriding Create, Write, & Unlink Methods in Odoo 17: A Guide

Odoo, a flexible open-source ERP platform, equips developers with the ability to precisely manage the creation, updating, and deletion of records using the "create," "write," and "unlink" methods. In this blog post, we will explore the importance of customizing these methods in Odoo 17, demonstrating how such customization empowers developers to tailor the data lifecycle to meet specific business requirements. The "create," "write," and "unlink" methods serve as pivotal stages in the lifecycle of records within the database: * The Create Method: Activated when a new record is added to a model. * The Write Method: Initiated when an existing record undergoes modification or update. * The Unlink Method: Executed when a record is deleted or detached from its parent model.

Overriding the Create Method:

As previously stated, the Create() method is called when a new record is generated for the designated model. For instance, in this scenario, we enforce the "mobile" field as obligatory by overriding the create method of the res.partner model.

class ResPartner(models.Model):
   _inherit = "res.partner"
   @api.model_create_multi
   def create(self, values):
       # Check if 'mobile' field is provided in the values
       if 'mobile' not in values or not values.get('mobile'):
           raise exceptions.ValidationError("Mobile is a mandatory field. "
                                            "Please provide a mobile number.")
       # Call the original create method to create the res.partner
       partner = super(ResPartner, self).create(values)
       return partner

The code breakdown is as follows:

- **class ResPartner(models.Model): _inherit = "res.partner"**: This line indicates that this model (ResPartner) is inheriting from the standard Odoo res.partner model. The "_inherit" model constraint is used for inheriting a model from its parent model.

- **@api.model_create_multi def create(self, values)**: This decorates the create method, denoting it as an Odoo API model method. The create method is invoked when a new record is created for the res.partner model.

- **if 'mobile' not in values or not values.get('mobile')**: This section checks whether the 'mobile' field is provided in the values and if it's not empty. If either condition is not met, it raises a validation error.

- **partner = super(ResPartner, self).create(values) return partner**: These lines call the original create method of the parent class (res.partner). This ensures that the standard behavior of creating a partner is maintained while enforcing the custom validation.

Overriding the Write Method:

As previously explained, the "write" method is triggered when an existing record undergoes an update. In the prior scenario, we customized the create method to make the mobile field mandatory. Consequently, it is impossible to create a new record without providing a mobile field. However, updating an existing record can still occur without including the mobile field. To address this, we need to override the write method, for instance.

def write(self, values):
   # Check if 'mobile' field is provided in the values
   if 'mobile' not in values or not values.get('mobile'):
       raise exceptions.ValidationError("Mobile is a mandatory field. "
                                        "Please provide a mobile number.")
   # Call the original write method to update the res.partner record
   result = super(ResPartner, self).write(values)
   return result

Code Explanation:

- **def write(self, values):** This function defines the write method, which is invoked when updating records for the res.partner model.

- **if 'mobile' in values and not values['mobile']:** This condition, similar to the previous one, verifies if the 'mobile' field exists in the values and if it's not empty. If the condition is not met, it raises a validation error.

- **result = super(ResPartner, self).write(values)** This line calls the original write method of the parent class (res.partner). It ensures that the standard behavior of updating a partner record is maintained while applying the custom validation.

Overriding the Unlink Method:

As previously stated, the unlink method is invoked when a record is deleted. Now, let's examine an example of raising an exception when a non-admin user attempts to delete a record by overriding the unlink method of (res.partner).

def unlink(self):
   # Check if the user is the admin
   if not self.env.user.has_group('base.group_erp_manager'):
       raise exceptions.UserError("Only the admin can delete partners.")
   # Call the original unlink method to delete the res.partner record
   result = super(ResPartner, self).unlink()
   return result

Explanation:
- **def unlink(self):** This defines the unlink method, which is called when deleting records for the res.partner model.
- **if not self.env.user.has_group('base.group_erp_manager'):** This condition verifies if the current user has admin privileges by checking if they belong to the 'base.group_erp_manager' group. It raises a user error if the user is not an admin.
- **result = super(ResPartner, self).unlink():** This line calls the original unlink method of the parent class (res.partner). It ensures that the standard behavior of deleting a partner record is maintained while applying the custom logic.

Setting Up Payment Acquirers for Online Transactions in Odoo 17 Accounting