Skip to content

[FIX] sale_order_type_invoice_policy_invoice_link: replace process-wide monkey patch with model inheritance - #992

Open
gal-adhoc wants to merge 1 commit into
ingadhoc:18.0from
adhoc-dev:18.0-h-124767-gal
Open

[FIX] sale_order_type_invoice_policy_invoice_link: replace process-wide monkey patch with model inheritance#992
gal-adhoc wants to merge 1 commit into
ingadhoc:18.0from
adhoc-dev:18.0-h-124767-gal

Conversation

@gal-adhoc

@gal-adhoc gal-adhoc commented Aug 7, 2026

Copy link
Copy Markdown

Problem

models/stock_move.py patched stock_picking_invoice_link's StockMove.write at import time:

from odoo.addons.stock_picking_invoice_link.models.stock_move import StockMove
def new_write(self, vals): ...
StockMove.write = new_write

That mutates the class object for the whole Odoo process, and nothing ever undoes it. Uninstalling this module removes its models from the registry but does not un-import the Python module nor restore the original write. The patched body reads sale_line_id.order_id.type_id.invoice_policy, a field contributed by sale_order_type_invoice_policy, so once that field is gone every picking validation crashes until the worker is restarted.

Reproduced on a production database:

  1. Install sale_order_type_invoice_policysale_order_type_invoice_policy_invoice_link auto-installs and the patch is applied to the class.
  2. Uninstall it ~45 seconds later. The registry reloads without sale.order.type.invoice_policy, but the patched write is still in place.
  3. Validate any delivery, the next day, on the same worker:
File ".../stock/models/stock_move.py", line 2111, in _action_done
    moves_todo.write({'state': 'done', 'date': fields.Datetime.now()})
File ".../sale_order_type_invoice_policy_invoice_link/models/stock_move.py", line 16, in new_write
    invoice_policy = stock_move.sudo().sale_line_id.order_id.type_id.invoice_policy
AttributeError: 'sale.order.type' object has no attribute 'invoice_policy'

23 consecutive failures over ~50 minutes, from a module that was not installed on that database.

Fix

Use a regular _inherit = "stock.move" override. The code then lives in the registry instead of in the class object, so it is present exactly when the module is installed and gone as soon as it is uninstalled. That removes the whole class of failure rather than guarding against this one symptom.

Also drops the duplicated You can not modify an invoiced stock move check: the monkey patch had to reimplement it because it was replacing stock_picking_invoice_link.write. With normal inheritance that check runs through super() again.

Business logic is unchanged — invoice lines are still linked when the sale order type policy is order, or when it is by_product and the product policy is order.

Test plan

  • With sale_order_type_invoice_policy and this module installed: create a sale.order.type with invoice_policy = 'order', confirm a SO with that type, invoice it, validate the delivery, and check stock.move.invoice_line_ids is populated. Same behaviour as before.
  • Install both modules, uninstall them, then validate a delivery without restarting the worker: no longer raises AttributeError. This is the regression that motivated the change.
  • Modifying product_uom_qty on a done move that has linked invoice lines still raises the UserError.

Ref: https://www.adhoc.inc/odoo/helpdesk.ticket/124767

…de monkey patch with model inheritance

The module patched stock_picking_invoice_link's StockMove.write at import
time, which mutates the class for the whole Odoo process instead of for the
databases where this module is installed. On a database that has
stock_picking_invoice_link installed but not sale_order_type_invoice_policy,
the patched write still ran and crashed on picking validation with
AttributeError: 'sale.order.type' object has no attribute 'invoice_policy'.

Use a regular _inherit = "stock.move" override instead, so the code can only
run in the registries where the module is actually installed. The duplicated
"You can not modify an invoiced stock move" check is dropped: it now runs
through super() from stock_picking_invoice_link, which the monkey patch was
replacing. Business logic is unchanged.
@roboadhoc

Copy link
Copy Markdown
Collaborator

Pull request status dashboard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants