from odoo import api, fields, models, _ from odoo.exceptions import UserError class ProductUomChangeWizard(models.TransientModel): _name = 'product.uom.change.wizard' _description = 'Change Product UOM Wizard' product_tmpl_id = fields.Many2one('product.template', string='Product', required=True, readonly=True) current_uom_id = fields.Many2one('uom.uom', related='product_tmpl_id.uom_id', string='Current UOM', readonly=True) uom_category_id = fields.Many2one('uom.category', related='product_tmpl_id.uom_id.category_id', readonly=True) new_uom_id = fields.Many2one('uom.uom', string='New UOM', required=True) new_uom_po_id = fields.Many2one('uom.uom', string='New Purchase UOM') @api.model def default_get(self, fields): res = super(ProductUomChangeWizard, self).default_get(fields) if self._context.get('active_model') == 'product.template' and self._context.get('active_id'): res['product_tmpl_id'] = self._context['active_id'] elif self._context.get('active_model') == 'product.product' and self._context.get('active_id'): product = self.env['product.product'].browse(self._context['active_id']) res['product_tmpl_id'] = product.product_tmpl_id.id return res def action_change_uom(self): self.ensure_one() if self.new_uom_id.category_id != self.product_tmpl_id.uom_id.category_id: raise UserError(_("New UOM must be in the same category as the current UOM.")) # Update UOM via SQL to bypass the constraint check in product.template write self.env.cr.execute("UPDATE product_template SET uom_id = %s WHERE id = %s", (self.new_uom_id.id, self.product_tmpl_id.id)) # Also update Purchase UOM if specified if self.new_uom_po_id: if self.new_uom_po_id.category_id != self.product_tmpl_id.uom_po_id.category_id: raise UserError(_("New Purchase UOM must be in the same category as the current Purchase UOM.")) self.env.cr.execute("UPDATE product_template SET uom_po_id = %s WHERE id = %s", (self.new_uom_po_id.id, self.product_tmpl_id.id)) # Invalidate cache to ensure the new value is read self.product_tmpl_id.invalidate_recordset(['uom_id', 'uom_po_id']) # Log note in chatter self.product_tmpl_id.message_post(body=f"UOM forcefully changed from {self.current_uom_id.name} to {self.new_uom_id.name} via Wizard.") return {'type': 'ir.actions.act_window_close'}