from odoo import models, api from odoo.tools import float_round class AccountMoveLine(models.Model): _inherit = 'account.move.line' def _get_hr_expense_base_class(self): """ Returns the hr_expense class in the MRO to jump over it. """ mro = type(self).mro() return next((c for c in mro if 'hr_expense' in c.__module__), None) @api.model_create_multi def create(self, vals_list): for vals in vals_list: if vals.get('expense_id') and vals.get('price_unit'): # Force rounding on expense-related lines to prevent noise from 10-decimal precision currency = self.env['res.currency'].browse(vals.get('currency_id')) or self.env.company.currency_id vals['price_unit'] = float_round(vals['price_unit'], precision_digits=currency.decimal_places or 2) return super().create(vals_list) def write(self, vals): # 1. Rounding Logic if 'price_unit' in vals: for line in self: if line.expense_id: currency = line.currency_id or self.env.company.currency_id vals['price_unit'] = float_round(vals['price_unit'], precision_digits=currency.decimal_places or 2) # 2. Surgical Jumper to bypass hr_expense's account.move.line lock hr_expense_class = self._get_hr_expense_base_class() if hr_expense_class and self._context.get('skip_expense_lock'): return super(hr_expense_class, self).write(vals) return super().write(vals) def unlink(self): # Surgical Jumper to bypass hr_expense's account.move.line lock hr_expense_class = self._get_hr_expense_base_class() if hr_expense_class and self._context.get('skip_expense_lock'): return super(hr_expense_class, self).unlink() return super().unlink()