Skip to content

Commit 5703c07

Browse files
committed
[MIG] uom
1 parent fa57e22 commit 5703c07

7 files changed

Lines changed: 353 additions & 1 deletion

File tree

docsource/modules180-190.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ Module coverage 18.0 -> 19.0
11101110
+---------------------------------------------------+----------------------+-------------------------------------------------+
11111111
| transifex | |No DB layout changes. |
11121112
+---------------------------------------------------+----------------------+-------------------------------------------------+
1113-
| uom | | |
1113+
| uom |Done | |
11141114
+---------------------------------------------------+----------------------+-------------------------------------------------+
11151115
| utm | | |
11161116
+---------------------------------------------------+----------------------+-------------------------------------------------+
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?xml version='1.0' encoding='utf-8'?>
2+
<odoo>
3+
<record id="product_uom_cm" model="uom.uom">
4+
<field name="relative_factor" eval="10"/>
5+
<field name="relative_uom_id" ref="uom.product_uom_millimeter"/>
6+
</record>
7+
<record id="product_uom_cubic_foot" model="uom.uom">
8+
<field name="relative_factor" eval="1728"/>
9+
<field name="relative_uom_id" ref="uom.product_uom_cubic_inch"/>
10+
</record>
11+
<record id="product_uom_cubic_inch" model="uom.uom">
12+
<field name="relative_factor" eval="0.0163871"/>
13+
<field name="relative_uom_id" ref="uom.product_uom_litre"/>
14+
</record>
15+
<record id="product_uom_cubic_meter" model="uom.uom">
16+
<field name="relative_factor">1000</field>
17+
<field name="relative_uom_id" ref="uom.product_uom_litre"/>
18+
</record>
19+
<record id="product_uom_day" model="uom.uom">
20+
<field name="relative_factor" eval="8.0"/>
21+
<field name="relative_uom_id" ref="uom.product_uom_hour"/>
22+
</record>
23+
<record id="product_uom_dozen" model="uom.uom">
24+
<field name="relative_factor" eval="12"/>
25+
<field name="relative_uom_id" ref="uom.product_uom_unit"/>
26+
</record>
27+
<record id="product_uom_floz" model="uom.uom">
28+
<field name="relative_factor" eval="0.0295735"/>
29+
<field name="relative_uom_id" ref="uom.product_uom_litre"/>
30+
</record>
31+
<record id="product_uom_foot" model="uom.uom">
32+
<field name="relative_factor" eval="12"/>
33+
<field name="relative_uom_id" ref="uom.product_uom_inch"/>
34+
</record>
35+
<record id="product_uom_gal" model="uom.uom">
36+
<field name="relative_factor" eval="4"/>
37+
<field name="relative_uom_id" ref="uom.product_uom_qt"/>
38+
</record>
39+
<record id="product_uom_gram" model="uom.uom">
40+
<field name="relative_factor" eval="1"/>
41+
</record>
42+
<record id="product_uom_hour" model="uom.uom">
43+
<field name="relative_factor" eval="1"/>
44+
</record>
45+
<record id="product_uom_inch" model="uom.uom">
46+
<field name="relative_factor" eval="2.54"/>
47+
<field name="relative_uom_id" ref="uom.product_uom_cm"/>
48+
</record>
49+
<record id="product_uom_kgm" model="uom.uom">
50+
<field name="relative_factor" eval="1000"/>
51+
<field name="relative_uom_id" ref="uom.product_uom_gram"/>
52+
</record>
53+
<record id="product_uom_km" model="uom.uom">
54+
<field name="relative_factor" eval="1000"/>
55+
<field name="relative_uom_id" ref="uom.product_uom_meter"/>
56+
</record>
57+
<record id="product_uom_kwh" model="uom.uom">
58+
<field name="relative_factor" eval="1.0"/>
59+
</record>
60+
<record id="product_uom_lb" model="uom.uom">
61+
<field name="relative_factor" eval="16"/>
62+
<field name="relative_uom_id" ref="uom.product_uom_oz"/>
63+
</record>
64+
<record id="product_uom_litre" model="uom.uom">
65+
<field name="relative_factor">1000</field>
66+
<field name="relative_uom_id" ref="uom.product_uom_milliliter"/>
67+
</record>
68+
<record id="product_uom_meter" model="uom.uom">
69+
<field name="relative_factor" eval="100.0"/>
70+
<field name="relative_uom_id" ref="uom.product_uom_cm"/>
71+
</record>
72+
<record id="product_uom_mile" model="uom.uom">
73+
<field name="relative_factor" eval="1760"/>
74+
<field name="relative_uom_id" ref="uom.product_uom_yard"/>
75+
</record>
76+
<record id="product_uom_millimeter" model="uom.uom">
77+
<field name="relative_factor" eval="1"/>
78+
</record>
79+
<record id="product_uom_minute" model="uom.uom">
80+
<field name="relative_factor" eval="0.0166667"/>
81+
<field name="relative_uom_id" ref="uom.product_uom_hour"/>
82+
</record>
83+
<record id="product_uom_oz" model="uom.uom">
84+
<field name="relative_factor" eval="28.3495"/>
85+
<field name="relative_uom_id" ref="uom.product_uom_gram"/>
86+
</record>
87+
<record id="product_uom_qt" model="uom.uom">
88+
<field name="relative_factor" eval="32"/>
89+
<field name="relative_uom_id" ref="uom.product_uom_floz"/>
90+
</record>
91+
<record id="product_uom_ton" model="uom.uom">
92+
<field name="name">Ton</field>
93+
<field name="relative_factor" eval="1000"/>
94+
<field name="relative_uom_id" ref="uom.product_uom_kgm"/>
95+
</record>
96+
<record id="product_uom_unit" model="uom.uom">
97+
<field name="relative_factor" eval="1.0"/>
98+
</record>
99+
<record id="product_uom_yard" model="uom.uom">
100+
<field name="relative_factor" eval="3"/>
101+
<field name="relative_uom_id" ref="uom.product_uom_foot"/>
102+
</record>
103+
</odoo>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright 2025 Hunki Enterprises BV
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from openupgradelib import openupgrade
5+
6+
7+
def _uom_relative_uom_id_relative_factor(env):
8+
"""
9+
UOM categories have been obsoleted, UOMs are a tree now with the reference
10+
unit as root and relative_factor giving the ratio to the UOM linked in
11+
relative_uom_id
12+
"""
13+
14+
def has_xmlid(uom):
15+
return env["ir.model.data"].search_count(
16+
[
17+
("model", "=", "uom.uom"),
18+
("res_id", "=", uom.id),
19+
("module", "!=", "__export__"),
20+
]
21+
)
22+
23+
env.cr.execute(
24+
f"""
25+
SELECT
26+
array_agg(id),
27+
array_agg({openupgrade.get_legacy_name("factor")}),
28+
array_agg({openupgrade.get_legacy_name("uom_type")})
29+
FROM
30+
uom_uom
31+
WHERE {openupgrade.get_legacy_name("category_id")} IS NOT NULL
32+
GROUP BY {openupgrade.get_legacy_name("category_id")}
33+
"""
34+
)
35+
for ids, factors, uom_types in env.cr.fetchall():
36+
uoms = env["uom.uom"].browse(ids)
37+
uom2factor = dict(zip(uoms, factors, strict=False))
38+
uom2type = dict(zip(uoms, uom_types, strict=False))
39+
40+
old_reference = uoms.filtered(
41+
lambda x, uom2type=uom2type: uom2type[x] == "reference"
42+
)
43+
44+
for uom in uoms - old_reference:
45+
if has_xmlid(uom):
46+
# uoms with xmlid will be updated by the migration of the module
47+
# providing them
48+
continue
49+
50+
relative_factor = (
51+
uom2factor[uom] if uom2type[uom] == "bigger" else (1 / uom2factor[uom])
52+
)
53+
54+
uom.write(
55+
{
56+
"relative_uom_id": old_reference,
57+
"relative_factor": relative_factor,
58+
}
59+
)
60+
61+
62+
@openupgrade.migrate()
63+
def migrate(env, version):
64+
openupgrade.load_data(env, "uom", "19.0.1.0/noupdate_changes_work.xml")
65+
_uom_relative_uom_id_relative_factor(env)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2025 Hunki Enterprises BV
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from openupgradelib import openupgrade
5+
6+
7+
@openupgrade.migrate()
8+
def migrate(env, version):
9+
openupgrade.copy_columns(
10+
env.cr,
11+
{
12+
"uom_uom": [
13+
("category_id", None, None),
14+
("factor", None, None),
15+
("rounding", None, None),
16+
("uom_type", None, None),
17+
]
18+
},
19+
)
20+
openupgrade.rename_xmlids(
21+
env.cr,
22+
[
23+
("product.decimal_product_uom", "uom.decimal_product_uom"),
24+
("uom.uom_square_foot", "uom.product_uom_square_foot"),
25+
("uom.uom_square_meter", "uom.product_uom_square_meter"),
26+
],
27+
)
28+
# this would be cleaned up after the migration, but we can't have it during
29+
# migration
30+
openupgrade.delete_sql_constraint_safely(
31+
env, "uom", "uom_uom", "factor_reference_is_one"
32+
)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---Models in module 'uom'---
2+
obsolete model uom.category
3+
---Fields in module 'uom'---
4+
uom / uom.category / name (char) : DEL required
5+
uom / uom.category / reference_uom_id (many2one) : DEL relation: uom.uom, stored: False
6+
uom / uom.category / uom_ids (one2many) : DEL relation: uom.uom
7+
8+
# NOTHING TO DO
9+
10+
uom / uom.uom / _order : _order is now 'sequence, relative_uom_id, id' ('factor DESC, id')
11+
12+
# NOTHING TO DO
13+
14+
uom / uom.uom / category_id (many2one) : DEL relation: uom.category, required
15+
16+
# NOTHING TO DO
17+
18+
uom / uom.uom / factor (float) : now a function
19+
uom / uom.uom / parent_path (char) : NEW
20+
uom / uom.uom / related_uom_ids (one2many) : NEW relation: uom.uom
21+
uom / uom.uom / relative_factor (float) : NEW required, hasdefault: default
22+
uom / uom.uom / relative_uom_id (many2one) : NEW relation: uom.uom
23+
24+
# DONE: compute relative_factor, relative_uom_id for custom UOMs in post-migration
25+
26+
uom / uom.uom / rounding (float) : not stored anymore
27+
28+
# DONE: copied to legacy column in pre-migration
29+
30+
uom / uom.uom / rounding (float) : now a function
31+
uom / uom.uom / sequence (integer) : NEW hasdefault: compute
32+
33+
# NOTHING TO DO
34+
35+
uom / uom.uom / uom_type (selection) : DEL required, selection_keys: ['bigger', 'reference', 'smaller']
36+
37+
# DONE: copied to legacy column in pre-migration
38+
39+
---XML records in module 'uom'---
40+
NEW decimal.precision: uom.decimal_product_uom [renamed from product module] (noupdate)
41+
42+
# DONE: renamed in pre-migration
43+
44+
DEL ir.actions.act_window: uom.product_uom_categ_form_action
45+
DEL ir.model.access: uom.access_uom_category_manager
46+
DEL ir.model.access: uom.access_uom_category_user
47+
ir.model.constraint: uom.constraint_uom_uom_factor_gt_zero (changed definition: is now 'CHECK (relative_factor!=0)' ('check(factor!=0)'))
48+
DEL ir.model.constraint: uom.constraint_uom_uom_factor_reference_is_one
49+
DEL ir.model.constraint: uom.constraint_uom_uom_rounding_gt_zero
50+
DEL ir.ui.view: uom.product_uom_categ_form_view
51+
DEL ir.ui.view: uom.product_uom_categ_tree_view
52+
DEL ir.ui.view: uom.uom_categ_view_search
53+
DEL uom.category: uom.product_uom_categ_energy (noupdate)
54+
DEL uom.category: uom.product_uom_categ_kgm (noupdate)
55+
DEL uom.category: uom.product_uom_categ_unit (noupdate)
56+
DEL uom.category: uom.product_uom_categ_vol (noupdate)
57+
DEL uom.category: uom.uom_categ_length (noupdate)
58+
DEL uom.category: uom.uom_categ_surface (noupdate)
59+
DEL uom.category: uom.uom_categ_wtime (noupdate)
60+
NEW uom.uom: uom.product_uom_milliliter (noupdate)
61+
NEW uom.uom: uom.product_uom_pack_6 (noupdate)
62+
63+
# NOTHING TO DO
64+
65+
NEW uom.uom: uom.product_uom_square_foot (noupdate)
66+
NEW uom.uom: uom.product_uom_square_meter (noupdate)
67+
DEL uom.uom: uom.uom_square_foot (noupdate)
68+
DEL uom.uom: uom.uom_square_meter (noupdate)
69+
70+
# DONE: renamed in pre-migration
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
env = locals().get("env")
2+
# decimeter
3+
env["uom.uom"].create(
4+
{
5+
"name": "dm",
6+
"category_id": env.ref("uom.uom_categ_length").id,
7+
"factor": 10,
8+
"uom_type": "smaller",
9+
}
10+
)
11+
# megameter
12+
env["uom.uom"].create(
13+
{
14+
"name": "Mm",
15+
"category_id": env.ref("uom.uom_categ_length").id,
16+
"factor": 1000000,
17+
"uom_type": "bigger",
18+
}
19+
)
20+
# entirely custom uom category
21+
uom_category = env["uom.category"].create(
22+
{
23+
"name": "Electric current",
24+
}
25+
)
26+
env["uom.uom"].create(
27+
{
28+
"name": "A",
29+
"category_id": uom_category.id,
30+
"factor": 1,
31+
"uom_type": "reference",
32+
}
33+
)
34+
env["uom.uom"].create(
35+
{
36+
"name": "mA",
37+
"category_id": uom_category.id,
38+
"factor": 1000,
39+
"uom_type": "smaller",
40+
}
41+
)
42+
env["uom.uom"].create(
43+
{
44+
"name": "MA",
45+
"category_id": uom_category.id,
46+
"factor": 1000000,
47+
"uom_type": "bigger",
48+
}
49+
)
50+
51+
env.cr.commit()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from odoo.tests import TransactionCase
2+
3+
from odoo.addons.openupgrade_framework import openupgrade_test
4+
5+
6+
@openupgrade_test
7+
class TestUomMigration(TransactionCase):
8+
def test_uoms(self):
9+
"""
10+
Test that decimeters and megameters compute correctly
11+
"""
12+
dm = self.env["uom.uom"].search([("name", "=", "dm")])
13+
Mm = self.env["uom.uom"].search([("name", "=", "Mm")])
14+
self.assertEqual(
15+
dm._compute_quantity(1, Mm, round=False),
16+
0.0000001,
17+
)
18+
self.assertEqual(
19+
Mm._compute_quantity(1, dm),
20+
10000000,
21+
)
22+
mA = self.env["uom.uom"].search([("name", "=", "mA")])
23+
MA = self.env["uom.uom"].search([("name", "=", "MA")])
24+
self.assertEqual(
25+
mA._compute_quantity(1, MA, round=False),
26+
0.000000001,
27+
)
28+
self.assertEqual(
29+
MA._compute_quantity(1, mA),
30+
1000000000,
31+
)

0 commit comments

Comments
 (0)