Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docsource/modules180-190.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,7 @@ Module coverage 18.0 -> 19.0
+---------------------------------------------------+----------------------+-------------------------------------------------+
| sale_loyalty_delivery | |No DB layout changes. |
+---------------------------------------------------+----------------------+-------------------------------------------------+
| sale_management | | |
| sale_management |Done | |
+---------------------------------------------------+----------------------+-------------------------------------------------+
| sale_margin | | |
+---------------------------------------------------+----------------------+-------------------------------------------------+
Expand Down
104 changes: 104 additions & 0 deletions openupgrade_scripts/scripts/sale_management/19.0.1.0/post-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Copyright 2026 Hunki Enterprises BV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from openupgradelib import openupgrade


def sale_order_line_options(env):
"""
Model sale.order.option has been replaced by optional lines on sale orders
"""
SaleOrderLine = env["sale.order.line"]
link_column = openupgrade.get_legacy_name("option_id")
env.cr.execute(
f"ALTER TABLE sale_order_line ADD COLUMN IF NOT EXISTS {link_column} int "
)
env.cr.execute(
"""
SELECT
id, order_id, name, product_id, quantity, price_unit, sequence, uom_id, discount
FROM
sale_order_option
"""
)
for (
option_id,
order_id,
name,
product_id,
quantity,
price_unit,
sequence,
uom_id,
discount,
) in env.cr.fetchall():
line = SaleOrderLine.create(
{
"is_optional": True,
"order_id": order_id,
"name": name,
"product_id": product_id,
"product_uom_qty": quantity,
"price_unit": price_unit,
"sequence": sequence,
"product_uom_id": uom_id,
"discount": discount,
}
)
env.cr.execute(
f"""
UPDATE sale_order_line
SET {link_column}={option_id}
WHERE id={line.id}
"""
)


def sale_order_template_options(env):
"""
Model sale.order.template.option has been replaced by optional lines
"""
SaleOrderTemplateLine = env["sale.order.template.line"]
link_column = openupgrade.get_legacy_name("option_id")
env.cr.execute(
"ALTER TABLE sale_order_template_line "
f"ADD COLUMN IF NOT EXISTS {link_column} int "
)
env.cr.execute(
"""
SELECT
id, sale_order_template_id, name, product_id, quantity, uom_id
FROM
sale_order_template_option
"""
)
for (
option_id,
template_id,
name,
product_id,
quantity,
uom_id,
) in env.cr.fetchall():
line = SaleOrderTemplateLine.create(
{
"is_optional": True,
"sale_order_template_id": template_id,
"name": name,
"product_id": product_id,
"product_uom_qty": quantity,
"product_uom_id": uom_id,
}
)
env.cr.execute(
f"""
UPDATE sale_order_template_line
SET {link_column}={option_id}
WHERE id={line.id}
"""
)


@openupgrade.migrate()
def migrate(env, version):
sale_order_line_options(env)
sale_order_template_options(env)
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---Models in module 'sale_management'---
obsolete model sale.order.option
obsolete model sale.order.template.option

# DONE: moved to sale.order.line/sale.order.template.line

---Fields in module 'sale_management'---
sale_management / sale.order / sale_order_option_ids (one2many): DEL relation: sale.order.option
sale_management / sale.order.line / is_optional (boolean) : NEW hasdefault: default
sale_management / sale.order.line / sale_order_option_ids (one2many): DEL relation: sale.order.option
sale_management / sale.order.option / discount (float) : DEL
sale_management / sale.order.option / line_id (many2one) : DEL relation: sale.order.line
sale_management / sale.order.option / name (text) : DEL required
sale_management / sale.order.option / order_id (many2one) : DEL relation: sale.order
sale_management / sale.order.option / price_unit (float) : DEL required
sale_management / sale.order.option / product_id (many2one) : DEL relation: product.product, required
sale_management / sale.order.option / quantity (float) : DEL required
sale_management / sale.order.option / sequence (integer) : DEL
sale_management / sale.order.option / uom_id (many2one) : DEL relation: uom.uom, required
sale_management / sale.order.template / sale_order_template_option_ids (one2many): DEL relation: sale.order.template.option
sale_management / sale.order.template.line / display_type (selection) : selection_keys added: [line_subsection] (most likely nothing to do)
sale_management / sale.order.template.line / is_optional (boolean) : NEW hasdefault: default
sale_management / sale.order.template.option / company_id (many2one) : DEL relation: res.company
sale_management / sale.order.template.option / name (text) : DEL required
sale_management / sale.order.template.option / product_id (many2one) : DEL relation: product.product, required
sale_management / sale.order.template.option / quantity (float) : DEL required
sale_management / sale.order.template.option / sale_order_template_id (many2one): DEL relation: sale.order.template, required
sale_management / sale.order.template.option / uom_id (many2one) : DEL relation: uom.uom, required

# DONE: create optional lines / template lines from former options

---XML records in module 'sale_management'---
DEL ir.model.access: sale_management.access_sale_order_option
DEL ir.model.access: sale_management.access_sale_order_option_invoice
DEL ir.model.access: sale_management.access_sale_order_option_readonly
DEL ir.model.access: sale_management.access_sale_order_template_option
DEL ir.model.access: sale_management.access_sale_order_template_option_manager
NEW ir.ui.view: sale_management.sale_order_portal_optional_product_quantity
DEL ir.ui.view: sale_management.report_saleorder_document_inherit_sale_management

# NOTHING TO DO
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
env = locals().get("env")

# create template with options
template = env["sale.order.template"].create(
{
"name": "Sale order template",
"sale_order_template_line_ids": [],
"sale_order_template_option_ids": [
(
0,
0,
{
"name": "some option",
"product_id": env.ref("product.product_product_1").id,
"uom_id": env.ref("uom.product_uom_unit").id,
"quantity": 42,
},
),
(
0,
0,
{
"name": "another option",
"product_id": env.ref("product.product_product_2").id,
"uom_id": env.ref("uom.product_uom_unit").id,
"quantity": 4242,
},
),
],
}
)
order = env["sale.order"].create(
{
"partner_id": env.user.partner_id.id,
"sale_order_template_id": template.id,
}
)
order._onchange_sale_order_template_id()

env.cr.commit()
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from odoo.tests import TransactionCase

from odoo.addons.openupgrade_framework import openupgrade_test


@openupgrade_test
class TestSaleManagementMigration(TransactionCase):
def test_sale_order_template_migration(self):
template = self.env["sale.order.template"].search(
[("name", "=", "Sale order template")],
)
order = self.env["sale.order"].search(
[("sale_order_template_id", "=", template.id)]
)
self.assertItemsEqual(
order.order_line.mapped("name"), ("some option", "another option")
)
self.assertItemsEqual(order.order_line.mapped("is_optional"), (True, True))
self.assertItemsEqual(
template.sale_order_template_line_ids.mapped("is_optional"), (True, True)
)