Remove allowed_uom_ids field, its computation, and common reference validation for new UOM and purchase UOM selections.

This commit is contained in:
Suherdy Yacob 2026-03-02 08:35:03 +07:00
parent e7da6c16ca
commit be208591f6
2 changed files with 2 additions and 51 deletions

View File

@ -7,53 +7,9 @@ class ProductUomChangeWizard(models.TransientModel):
product_tmpl_id = fields.Many2one('product.template', string='Product', required=True, readonly=True) 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) current_uom_id = fields.Many2one('uom.uom', related='product_tmpl_id.uom_id', string='Current UOM', readonly=True)
allowed_uom_ids = fields.Many2many('uom.uom', string='Allowed UOMs', compute='_compute_allowed_uom_ids')
new_uom_id = fields.Many2one('uom.uom', string='New UOM', required=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') new_uom_po_id = fields.Many2one('uom.uom', string='New Purchase UOM')
@api.depends('product_tmpl_id.uom_id')
def _compute_allowed_uom_ids(self):
for record in self:
if record.product_tmpl_id.uom_id:
# Find all UOMs that share the same root reference as the current UOM
# uom.uom model now uses _has_common_reference logic, but simpler to search by root category if possible.
# Since category_id is gone, we can group by root UoM if that concept exists, or rely on _has_common_reference.
# However, for a domain, we need a list of IDs.
# We can iterate all UOMs and check _has_common_reference, OR traverse up to the root and back down.
# Looking at uom_uom.py: _order = 'sequence, relative_uom_id, id'.
# fields: relative_uom_id (Reference Unit), related_uom_ids (Related UoMs).
# To get all in "category", we need to find the root.
# Let's traverse up to find the root.
uom = record.product_tmpl_id.uom_id
while uom.relative_uom_id:
uom = uom.relative_uom_id
# uom is now the root. Now find all descendants.
# A recursive search or using parent_path would be ideal if available/indexed.
# uom.uom has parent_path.
# parent_path structure: "root_id/child_id/..."
# So all UOMs in same category start with same root_id in parent_path.
root_id = uom.id
domain = [('parent_path', '=like', f'{root_id}/%')]
# Also include the root itself if it doesn't match the like pattern (which it usually doesn't as it is just "id/")
# Wait, parent_path is updated by standard valid Parent/Child implementation.
# Actually, simpler: search for uoms where root is the same.
# But we don't have a stored 'root_id'.
# Let's use the fact that we have the root uom 'uom'.
# We can search for all uoms that have this root as ancestor?
# Actually, standard Odoo usually just does `uom.search([])` and filters in python if the set is small,
# but UOMs can be many.
# Let's look at uom_uom.py again.
# It has `_has_common_reference`.
# A safer approach for now: Get all UOMs and filter. UOM table is usually small < 100.
all_uoms = self.env['uom.uom'].search([])
allowed = all_uoms.filtered(lambda u: u._has_common_reference(record.product_tmpl_id.uom_id))
record.allowed_uom_ids = allowed
else:
record.allowed_uom_ids = False
@api.model @api.model
def default_get(self, fields): def default_get(self, fields):
res = super(ProductUomChangeWizard, self).default_get(fields) res = super(ProductUomChangeWizard, self).default_get(fields)
@ -66,16 +22,12 @@ class ProductUomChangeWizard(models.TransientModel):
def action_change_uom(self): def action_change_uom(self):
self.ensure_one() self.ensure_one()
if not self.new_uom_id._has_common_reference(self.product_tmpl_id.uom_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 # 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)) 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 # Also update Purchase UOM if specified
if self.new_uom_po_id and 'uom_po_id' in self.product_tmpl_id._fields: if self.new_uom_po_id and 'uom_po_id' in self.product_tmpl_id._fields:
if self.product_tmpl_id.uom_po_id and not self.new_uom_po_id._has_common_reference(self.product_tmpl_id.uom_po_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)) 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 # Invalidate cache to ensure the new value is read

View File

@ -8,9 +8,8 @@
<group> <group>
<field name="product_tmpl_id"/> <field name="product_tmpl_id"/>
<field name="current_uom_id"/> <field name="current_uom_id"/>
<field name="allowed_uom_ids" invisible="1"/> <field name="new_uom_id" domain="[('id', '!=', current_uom_id)]"/>
<field name="new_uom_id" domain="[('id', 'in', allowed_uom_ids), ('id', '!=', current_uom_id)]"/> <field name="new_uom_po_id"/>
<field name="new_uom_po_id" domain="[('id', 'in', allowed_uom_ids)]"/>
</group> </group>
<footer> <footer>
<button name="action_change_uom" string="Change UOM" type="object" class="btn-primary" data-hotkey="q"/> <button name="action_change_uom" string="Change UOM" type="object" class="btn-primary" data-hotkey="q"/>