-
-
Notifications
You must be signed in to change notification settings - Fork 811
Expand file tree
/
Copy pathproduct_template.py
More file actions
67 lines (61 loc) · 2.59 KB
/
product_template.py
File metadata and controls
67 lines (61 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = "product.template"
uom_factor_ids = fields.One2many(
"product.uom.factor",
"product_tmpl_id",
string="UoM Conversion Factors",
)
def write(self, vals):
res = super().write(vals)
if "uom_ids" in vals:
self._sync_uom_factor_ids()
return res
def _sync_uom_factor_ids(self):
Factor = self.env["product.uom.factor"]
for template in self:
base_uom = template.uom_id
cross_uoms = template.uom_ids.filtered(
lambda u, bu=base_uom: not bu._has_common_reference(u)
)
existing = template.uom_factor_ids
# Create missing factors for cross-category UoMs
existing_uom_ids = existing.mapped("uom_id")
for uom in cross_uoms - existing_uom_ids:
Factor.create(
{
"product_tmpl_id": template.id,
"uom_id": uom.id,
}
)
# Delete factors whose UoM was removed from uom_ids
to_delete = existing.filtered(lambda f, cu=cross_uoms: f.uom_id not in cu)
to_delete.unlink()
@api.constrains("uom_factor_ids")
def _check_uom_factor_coverage(self):
"""Ensure variant coverage for each cross-category UoM.
Auto-cleans duplicate catch-all lines and auto-creates missing
catch-alls when not all variants are explicitly covered.
Uses uom_ids (the template's allowed UoMs) as the source of truth
for which UoMs need coverage, not just existing factor lines."""
Factor = self.env["product.uom.factor"]
for template in self:
base_uom = template.uom_id
cross_uoms = template.uom_ids.filtered(
lambda u, bu=base_uom: not bu._has_common_reference(u)
)
for uom in cross_uoms:
siblings = template.uom_factor_ids.filtered(
lambda f, u=uom: f.uom_id == u
)
# Auto-create catch-all if needed
catchalls = siblings.filtered(lambda f: not f.product_ids)
if not catchalls:
covered = siblings.mapped("product_ids")
if covered != template.product_variant_ids:
Factor.create(
{
"product_tmpl_id": template.id,
"uom_id": uom.id,
}
)