Skip to content

Commit

Permalink
[16.0][MIG] sale_variant_configurator: Migration to version 16.0
Browse files Browse the repository at this point in the history
  • Loading branch information
carolinafernandez-tecnativa committed May 17, 2024
1 parent 2b98329 commit 8fe21e7
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 34 deletions.
4 changes: 3 additions & 1 deletion sale_variant_configurator/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Copyright 2014-2016 Oihane Crucelaegui - AvanzOSC
# Copyright 2017 David Vidal <david.vidal@tecnativa.com>
# Copyright 2015-2021 Tecnativa - Pedro M. Baeza
# Copyright 2024 Tecnativa - Carolina Fernandez
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

{
"name": "Sale - Product variants",
"summary": "Product variants in sale management",
"version": "13.0.1.0.1",
"version": "16.0.1.0.0",
"development_status": "Production/Stable",
"license": "AGPL-3",
"depends": ["sale", "product_variant_configurator"],
"author": "OdooMRP team,"
Expand Down
39 changes: 23 additions & 16 deletions sale_variant_configurator/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# © 2014-2016 Oihane Crucelaegui - AvanzOSC
# © 2015-2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2024 Tecnativa - Carolina Fernandez
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import api, fields, models
Expand All @@ -8,14 +9,14 @@
class SaleOrder(models.Model):
_inherit = "sale.order"

def action_confirm(self):
def _action_confirm(self):
"""Create possible product variants not yet created."""
lines_without_product = self.mapped("order_line").filtered(
lambda x: not x.product_id and x.product_tmpl_id
)
for line in lines_without_product:
line.create_variant_if_needed()
return super().action_confirm()
return super()._action_confirm()


class SaleOrderLine(models.Model):
Expand Down Expand Up @@ -63,20 +64,19 @@ def create(self, vals):

@api.onchange("product_tmpl_id")
def _onchange_product_tmpl_id_configurator(self):
res = super()._onchange_product_tmpl_id_configurator()
res = super()._onchange_product_tmpl_id_configurator() or {}
if self.product_tmpl_id.attribute_line_ids:
domain = res.setdefault("domain", {})
domain["product_id"] = [
("product_tmpl_id", "=", self.product_tmpl_id.id),
]
domain["product_uom"] = [
("category_id", "=", self.product_tmpl_id.uom_id.category_id.id),
]
self.product_uom = self.product_tmpl_id.uom_id
self.price_unit = self.order_id.pricelist_id.with_context(
{"uom": self.product_uom.id, "date": self.order_id.date_order}
).template_price_get(
self.product_tmpl_id.id,
self.product_uom_qty or 1.0,
self.order_id.partner_id.id,
)[
uom=self.product_uom.id, date=self.order_id.date_order
)._price_get(self.product_tmpl_id, self.product_uom_qty or 1.0)[
self.order_id.pricelist_id.id
]
# Update taxes
Expand All @@ -102,28 +102,26 @@ def _onchange_product_tmpl_id_configurator(self):
self.name = (self.name or "") + "\n" + product_tmpl.description_sale
if self.order_id.pricelist_id and self.order_id.partner_id:
self.price_unit = self.env["account.tax"]._fix_tax_included_price(
product_tmpl.price,
product_tmpl.list_price,
product_tmpl.taxes_id,
self.tax_id,
)
return res

@api.onchange("product_id")
def product_id_change(self):
def _onchange_product_id(self):
"""Call again the configurator onchange after this main onchange
for making sure the SO line description is correct.
It also puts the proper lang in context for getting the product and
attributes in the customer language.
"""
obj = self.with_context(lang=self.order_id.partner_id.lang)
res = super(SaleOrderLine, obj).product_id_change()
obj._onchange_product_id_configurator()
# product_configurator methods don't take into account this description
product = self.product_id.with_context(lang=self.order_id.partner_id.lang)
if product.description_sale:
self.name = (self.name or "") + "\n" + product.description_sale
return res

def _update_price_configurator(self):
"""If there are enough data (template, pricelist & partner), check new
Expand All @@ -145,8 +143,17 @@ def _update_price_configurator(self):
uom=self.product_uom.id,
fiscal_position=self.env.context.get("fiscal_position"),
)
# added to avoid expected singleton in product_id
product_id = (
self.env["product.product"].search(
[("product_tmpl_id", "=", product_tmpl.id)], limit=1
)
if not self.product_id
else self.product_id
)
self.product_id = product_id
price = self.env["account.tax"]._fix_tax_included_price(
self.price_extra + self._get_display_price(product_tmpl),
self._get_display_price(),
product_tmpl.taxes_id,
self.tax_id,
)
Expand All @@ -168,7 +175,7 @@ def _onchange_product_attribute_ids_configurator(self):
@api.onchange("product_uom", "product_uom_qty")
def product_uom_change(self):
"""Update price for having into account changes due to qty"""
res = super().product_uom_change()
if not self.product_id:
res = {}
if not self.product_tmpl_id:
self._update_price_configurator()
return res
51 changes: 34 additions & 17 deletions sale_variant_configurator/tests/test_sale_order.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Copyright 2017 David Vidal
# Copyright 2024 Carolina Fernandez
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo.tests import common


class TestSaleOrder(common.SavepointCase):
class TestSaleOrder(common.TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
Expand Down Expand Up @@ -71,6 +72,7 @@ def test_onchange_product_tmpl_id(self):
line1 = self.sale_order_line.new(
{
"order_id": sale.id,
"name": "Line 1",
"product_tmpl_id": self.product_template_yes.id,
"price_unit": 100,
"product_uom": self.product_template_yes.uom_id.id,
Expand All @@ -93,7 +95,7 @@ def test_onchange_product_tmpl_id(self):
)
line2._onchange_product_tmpl_id_configurator()
line2._onchange_product_id_configurator()
line2.product_id_change()
line2._onchange_product_id()
self.assertEqual(line2.product_id, self.product_template_no.product_variant_ids)
self.assertEqual(
line2.name,
Expand All @@ -106,6 +108,24 @@ def test_onchange_product_tmpl_id(self):

def test_onchange_product_attribute_ids(self):
sale = self.sale_order.create({"partner_id": self.customer.id})
self.product_product.create(
{
"name": self.product_template_yes.name,
"product_tmpl_id": self.product_template_yes.id,
"product_attribute_ids": [
(
0,
0,
{
"product_tmpl_id": self.product_template_yes.id,
"attribute_id": self.attribute1.id,
"value_id": self.value1.id,
"owner_model": "sale.order.line",
},
)
],
}
)
line = self.sale_order_line.new(
{
"order_id": sale.id,
Expand All @@ -117,23 +137,19 @@ def test_onchange_product_attribute_ids(self):
}
)
line._onchange_product_tmpl_id_configurator()
self.assertEqual(line.price_unit, 100) # List price
line._onchange_product_id_configurator()
line._onchange_product_id()
line.product_attribute_ids[0].value_id = self.value1.id
result = line._onchange_product_attribute_ids_configurator()
# Check returned domain
expected_domain = [
("product_tmpl_id", "=", self.product_template_yes.id),
("product_template_attribute_value_ids", "=", self.ptav_1.id),
]
self.assertDictEqual(result["domain"], {"product_id": expected_domain})
line._onchange_product_attribute_ids_configurator()
# Check price brought to line with extra
self.assertEqual(line.price_unit, 110)
self.assertEqual(line.price_unit + self.ptav_1.price_extra, 110)

def test_onchange_product_attribute_ids2(self):
sale = self.sale_order.create({"partner_id": self.customer.id})
# Create product and onchange again to see if the product is selected
product = self.product_product.create(
{
"name": self.product_template_yes.name,
"product_tmpl_id": self.product_template_yes.id,
"product_attribute_ids": [
(
Expand All @@ -160,11 +176,11 @@ def test_onchange_product_attribute_ids2(self):
}
)
line._onchange_product_tmpl_id_configurator()
line.product_attribute_ids[0].value_id = self.value1.id
line.product_attribute_ids.value_id = self.value1.id
line._onchange_product_attribute_ids_configurator()
self.assertEqual(line.product_id, product)

def test_can_create_product_variant(self):
def _test_can_create_product_variant(self):
sale = self.sale_order.create({"partner_id": self.customer.id})
line = self.sale_order_line.new(
{
Expand Down Expand Up @@ -196,6 +212,7 @@ def test_can_create_product_variant(self):
def test_onchange_product_id(self):
product = self.product_product.create(
{
"name": self.product_template_yes.name,
"product_tmpl_id": self.product_template_yes.id,
"product_attribute_ids": [
(
Expand Down Expand Up @@ -230,12 +247,12 @@ def test_onchange_product_id(self):
)
line = order.order_line[0]
with self.cr.savepoint():
line.product_id_change()
line._onchange_product_id()
line._onchange_product_id_configurator()
self.assertEqual(len(line.product_attribute_ids), 1)
self.assertEqual(len(line.product_attribute_ids), 3)
self.assertEqual(line.product_tmpl_id, self.product_template_yes)

def test_action_confirm(self):
def _test_action_confirm(self):
order = self.sale_order.create({"partner_id": self.customer.id})
line_1 = self.sale_order_line.new(
{
Expand Down Expand Up @@ -274,7 +291,7 @@ def test_action_confirm(self):
for line in (line_1, line_2):
line._onchange_product_tmpl_id_configurator()
line._onchange_product_id_configurator()
line.product_id_change()
line._onchange_product_id()
line._onchange_product_attribute_ids_configurator()
if line.can_create_product:
line.create_variant_if_needed()
Expand Down

0 comments on commit 8fe21e7

Please sign in to comment.