-
-
Notifications
You must be signed in to change notification settings - Fork 268
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[16.0][MIG] sale_variant_configurator: Migration to version 16.0
- Loading branch information
1 parent
2b98329
commit 0377d1f
Showing
3 changed files
with
77 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
# Copyright 2014-2016 Oihane Crucelaegui - AvanzOSC | ||
# Copyright 2017 David Vidal <[email protected]> | ||
# 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," | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# © 2014-2016 Oihane Crucelaegui - AvanzOSC | ||
# © 2015-2016 Pedro M. Baeza <[email protected]> | ||
# Copyright 2024 Tecnativa - Carolina Fernandez | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from odoo import api, fields, models | ||
|
@@ -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): | ||
|
@@ -48,35 +49,35 @@ class SaleOrderLine(models.Model): | |
), | ||
] | ||
|
||
@api.model | ||
def create(self, vals): | ||
@api.model_create_multi | ||
def create(self, vals_list): | ||
"""Create product if not exist when the sales order is already | ||
confirmed and a line is added. | ||
""" | ||
if vals.get("order_id") and not vals.get("product_id"): | ||
order = self.env["sale.order"].browse(vals["order_id"]) | ||
if order.state == "sale": | ||
line = self.new(vals) | ||
product = line.create_variant_if_needed() | ||
vals["product_id"] = product.id | ||
for vals in vals_list: | ||
if vals.get("order_id") and not vals.get("product_id"): | ||
order = self.env["sale.order"].browse(vals["order_id"]) | ||
if order.state == "sale": | ||
line = self.new(vals) | ||
product = line.create_variant_if_needed() | ||
vals["product_id"] = product.id | ||
return super().create(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 | ||
|
@@ -102,28 +103,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 | ||
|
@@ -145,8 +144,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, | ||
) | ||
|
@@ -165,10 +173,17 @@ def _onchange_product_attribute_ids_configurator(self): | |
self._update_price_configurator() | ||
return res | ||
|
||
@api.onchange("product_uom", "product_uom_qty") | ||
def product_uom_change(self): | ||
@api.depends("display_type", "product_id", "product_packaging_qty") | ||
def _compute_product_uom_qty(self): | ||
"""Update price for having into account changes due to qty""" | ||
res = super().product_uom_change() | ||
if not self.product_id: | ||
res = super()._compute_product_uom_qty() | ||
if self.product_id: | ||
self._update_price_configurator() | ||
return res | ||
|
||
@api.depends("product_id") | ||
def _compute_product_uom(self): | ||
res = super()._compute_product_uom() | ||
if self.product_id: | ||
self._update_price_configurator() | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters