Contributors mailing list archives
contributors@odoo-community.org
Browse archives
Re: How to write hook addon properly.
byMy way of explaining this:
All of the python code is "loaded and available" and the classes are instantiated, whether the module is installed or not - Odoo will control, by knowledge of the modules installed, which methods are to be called and in which order.
Lowest level: -invoice_create(..):
Level 1invoice_create(..):super(level1, self).invoice_create()
We can "replace" invoice_create at level 0 by creating a class
New module:new_invoice_create():xxxx
lowest_level.invoice_create = new_module.invoice_create
Problem: Whether the new module is installed or not, Odoo knows that "Lowest level" is installed and should be called, and it will then execute our code in "New module", EVEN IF NEW MODULE IS NOT INSTALLED.Solution: New module needs to somehow be aware if it is installed or not, and if not, it should not try to execute, but should instead call the original lowest level.
We use this method to refactor Odoo methods which are either very long and need some hooks, or very low and we need to respect the inheritance (as Jordi mentioned)
In this example, we override the method completely, and it is always executed at the original level of inheritance, but our hooks will only be called if the module is installed....
We can then even extend the hooks in other modules that depend on this, and always are confident of correct inheritance in both the original method and our new hooks.
Example:
from odoo.addons.mrp.wizard.mrp_product_produce import MrpProductProduce as OriginalMrpProductProduce
class MrpProductProduce(models.TransientModel):
_inherit = "mrp.product.produce"
'''
Code taken from mrp/wizard/mrp_product_produce.py
We make the original point to this, and then make sure the super is calling the correct super!
"
@api.model
def default_get_refactored(self, fields):
# Modified
#=====================================================================================
res = super(OriginalMrpProductProduce, self).default_get(fields)
#=====================================================================================
if self._context and self._context.get('active_id'):
production = self.env['mrp.production'].browse(self._context['active_id'])
serial_finished = (production.product_id.tracking == 'serial')
if serial_finished:
todo_quantity = 1.0
else:
main_product_moves = production.move_finished_ids.filtered(lambda x: x.product_id.id == production.product_id.id)
todo_quantity = production.product_qty - sum(main_product_moves.mapped('quantity_done'))
todo_quantity = todo_quantity if (todo_quantity > 0) else 0
if 'production_id' in fields:
res['production_id'] = production.id
if 'product_id' in fields:
res['product_id'] = production.product_id.id
if 'product_uom_id' in fields:
res['product_uom_id'] = production.product_uom_id.id
if 'serial' in fields:
res['serial'] = bool(serial_finished)
if 'product_qty' in fields:
res['product_qty'] = todo_quantity
if 'produce_line_ids' in fields:
lines = []
for move in production.move_raw_ids.filtered(lambda x: (x.product_id.tracking != 'none') and x.state not in ('done', 'cancel') and x.bom_line_id):
qty_to_consume = float_round(todo_quantity / move.bom_line_id.bom_id.product_qty * move.bom_line_id.product_qty,
precision_rounding=move.product_uom.rounding, rounding_method="UP")
for move_line in move.move_line_ids:
if float_compare(qty_to_consume, 0.0, precision_rounding=move.product_uom.rounding) <= 0:
break
if move_line.lot_produced_id or float_compare(move_line.product_uom_qty, move_line.qty_done, precision_rounding=move.product_uom.rounding) <= 0:
continue
to_consume_in_line = min(qty_to_consume, move_line.product_uom_qty)
lines.append({
'move_id': move.id,
'qty_to_consume': to_consume_in_line,
'qty_done': 0.0,
'lot_id': move_line.lot_id.id,
'product_uom_id': move.product_uom.id,
'product_id': move.product_id.id,
})
# Inserted
#=====================================================================================
# THIS module might not be installed - code is still run as python class has been instantiated.
if hasattr(self, 'default_get_additional_line_vals'):
lines[-1].update(self.default_get_additional_line_vals(fields, lines[-1], production, move, move_line))
#=====================================================================================
qty_to_consume -= to_consume_in_line
if float_compare(qty_to_consume, 0.0, precision_rounding=move.product_uom.rounding) > 0:
if move.product_id.tracking == 'serial':
while float_compare(qty_to_consume, 0.0, precision_rounding=move.product_uom.rounding) > 0:
lines.append({
'move_id': move.id,
'qty_to_consume': 1,
'qty_done': 0.0,
'product_uom_id': move.product_uom.id,
'product_id': move.product_id.id,
})
# Inserted
#=====================================================================================
if hasattr(self, 'default_get_additional_line_vals'):
lines[-1].update(self.default_get_additional_line_vals(fields, lines[-1], production, move, None))
#=====================================================================================
qty_to_consume -= 1
else:
lines.append({
'move_id': move.id,
'qty_to_consume': qty_to_consume,
'qty_done': 0.0,
'product_uom_id': move.product_uom.id,
'product_id': move.product_id.id,
})
# Inserted
#=====================================================================================
if hasattr(self, 'default_get_additional_line_vals'):
lines[-1].update(self.default_get_additional_line_vals(fields, lines[-1], production, move, None))
#=====================================================================================
res['produce_line_ids'] = [(0, 0, x) for x in lines]
# Inserted
#=====================================================================================
if hasattr(self, 'default_get_additional_vals'):
res.update(self.default_get_additional_vals(fields, res, production))
#=====================================================================================
return res
def default_get_additional_vals(self, fields, vals_so_far, production):
return {}
def default_get_additional_line_vals(self, fields, vals_so_far, production, move, move_line):
return {}
# Make original now this version.
OriginalMrpProductProduce.default_get = MrpProductProduce.default_get_refactored
Richard deMeester
Senior Development Analyst
WilldooIT Pty Ltd
E: richard.demeester@willdooit.com
M: +61 403 76 76 76
P: +61 3 9135 1900
A: 10/435 Williamstown Road, Port Melbourne, Vic 3207
Our vision is to provide end to end IT solutions to help our clients achieve their desired objectives and provide growth opportunities for everyone working in the company to reach their full professional potential.
DISCLAIMER | This electronic message together with any attachments is confidential. If you are not the recipient, do not copy, disclose, or use the contents in any way. Please also advise us by e-mail that you have received this message in error and then please destroy this email and any of its attachments. WilldooIT Pty. Ltd. is not responsible for any changes made to this message and/or any attachments after sending by WilldooIT Pty. Ltd. WilldooIT Pty. Ltd. use virus scanning software but exclude all liability for virus or anything similar in this email or attachment.
From: Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
Sent: Thursday, 7 March 2019 2:52 PM
To: Contributors
Subject: How to write hook addon properly.Dear all
I am looking for the right way to write a hook addon when working with OCA modules.
I found the sample from Eficent in https://github.com/OCA/sale-workflow/tree/11.0/sale_order_action_invoice_create_hook
I see that, it is doing things like this in hooks.py
def post_load_hook(): def new_action_invoice_create(self, grouped=False, final=False):
if not hasattr(self, '_get_invoice_group_key'): return self.action_invoice_create_original(grouped=grouped, final=final)
From what I see, since this module is being installed, the new_action_invoice_create() will be used always anyway. I am trying to understand why we would need to do this, instead of directly overwrite method with hook point ?
Thank you for your support.Kitti U._______________________________________________
Mailing-List: https://odoo-community.org/groups/contributors-15
Post to: mailto:contributors@odoo-community.org
Unsubscribe: https://odoo-community.org/groups?unsubscribe
Reference
-
How to write hook addon properly.
byEcosoft Co. Ltd., Kitti Upariphutthiphong-
Re: How to write hook addon properly.
by Richard deMeester <richard.demeester@willdooit.com> - 11/03/2019 23:48:36 - 0 -
Re: How to write hook addon properly.
byEcosoft Co. Ltd., Kitti Upariphutthiphong -
Re: How to write hook addon properly.
byEcosoft Co. Ltd., Kitti Upariphutthiphong -
Re: How to write hook addon properly.
by Richard deMeester <richard.demeester@willdooit.com> - 07/03/2019 23:44:59 - 2 -
Re: How to write hook addon properly.
byEcosoft Co. Ltd., Kitti Upariphutthiphong -
Re: How to write hook addon properly.
byForgeFlow, S.L., Jordi Ballester Alomar
-