This Odoo technical development blog is my way to contribute back to the Odoo Community, for all the selfless and great sharing by the community members.
Recently, I have a scenario to update my custom model's value when invoice is paid (ie, upon user registered a payment, the invoice's state will be changed to Paid).
There are a few options for me to update a field upon a change in another field.
1) @api.onchange
This is the most intuitive method.
You may use it when the field to be updated is in the same model and same form/view.
If i used the @api.onchange('state') in the inherited 'Account.invoice' model, it will not be triggered.
The following are possibilities that updating field is not working in onchange method:
a) If the field is readonly. To solve it, enable the force_save in the xml.
b) If you want to change another object's value, use the write method. Eg, In the vendor bill (account.invoice), when user change the unit price, you want to update the product's cost. So in the onchange_priceunit,
@api.onchange('price_unit')
def _onchange_price_unit(self):
product.write({'standard_price': price_unit})
c) If you model is to be used as a line item (Tree) in another model, if you encountered that on change method is not triggered or not saved, try to add this onchange field in the XML tree view (make this field invisible). Another classic example is that in Odoo 13 and above, if you add new field to the account.move.line (eg, Invoice line item), then you have to add that field to both the invoice_line_ids and line_ids in xml, in order for the field value to be saved.
2) @api.depends
You may use it with the compute method.
This method is triggered during the loading of the related view/form, but not when the invoice state is changed to Paid.
compute method will be triggered when the record is created or when any change to 'container_qty' field. If you have 'store=true', must have the @api-depends to re-update everytime, when there is a change in the 'container_qty' field.
@api.depends('container_qty')
def _compute_balance(self):
3) write method
This works when inherited the model account.invoice.
Triggered every time when the record is changed, after the record is created.
vals will contain the field that has been changed.
Click "Like" at the bottom of this blog, to motivate us to continue sharing more Odoo tips.
@api.multi
def write(self, vals):
res = super(AccountInvoice, self).write(vals)
#update your custom model's field when the Invoice state is paid
state = vals.get("state")
if state == 'paid':
#update your custom model
return res
Comments