[FIX] product: use configurator with deleted attribute

The product configurator can have irrelevant disabled options if the
product selected has some archived variants

Steps to reproduce:
1. Install Sales and Inventory
2. Create a product with two attributes, each with two values (e.g.
   Color: C1, C2 and Weight: W1, W2)
3. Open one of the variant, add some stock then archive it
4. Delete the attribute Weight from the product
5. Create a SO for any customer and add the product
6. The product configurator dialog opens but the C1 color is unavailable

Solution:
Only return the archived combinations for which all of the attribute are
still used in the product

opw-3427753

closes odoo/odoo#132420

X-original-commit: d5cd215dcf1b7e633c86ad734274a65827368ade
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Co-authored-by: Victor Feyens <vfe@odoo.com>
This commit is contained in:
MerlinGuillaume
2023-08-19 12:02:52 +02:00
committed by Victor Feyens
co-authored by Victor Feyens
parent 522c8cd783
commit d5878829cd
2 changed files with 72 additions and 2 deletions
+4 -1
View File
@@ -798,7 +798,10 @@ class ProductTemplate(models.Model):
'archived_combinations': [
product.product_template_attribute_value_ids.ids
for product in archived_products
if product.product_template_attribute_value_ids
if product.product_template_attribute_value_ids and all(
ptav.ptav_active
for ptav in product.product_template_attribute_value_ids
)
],
'parent_exclusions': self._get_parent_attribute_exclusions(parent_combination),
'parent_combination': parent_combination.ids,
@@ -9,8 +9,10 @@ from odoo.addons.sale.tests.common import SaleCommon
@tagged('post_install', '-at_install')
class TestProductConfiguratorData(HttpCase, ProductVariantsCommon, SaleCommon):
def test_dropped_attribute_isnt_shown(self):
def test_dropped_value_isnt_shown(self):
self.assertEqual(len(self.product_template_sofa.product_variant_ids), 3)
# Use variants s.t. they are archived and not deleted when value is removed
self.empty_order.order_line = [
Command.create({
'product_id': product.id
@@ -19,6 +21,7 @@ class TestProductConfiguratorData(HttpCase, ProductVariantsCommon, SaleCommon):
]
self.empty_order.action_confirm()
# Remove attribute value
self.product_template_sofa.attribute_line_ids.value_ids -= self.color_attribute_red
self.assertEqual(len(self.product_template_sofa.product_variant_ids.filtered('active')), 2)
@@ -44,3 +47,67 @@ class TestProductConfiguratorData(HttpCase, ProductVariantsCommon, SaleCommon):
# Make sure the inactive ptav was removed from the loaded attributes
self.assertEqual(len(result['products'][0]['attribute_lines'][0]['attribute_values']), 2)
def test_dropped_attribute(self):
self.product_template_2_attribute_lines = self.env['product.template'].create({
'name': 'Shirt',
'categ_id': self.product_category.id,
'attribute_line_ids': [
Command.create({
'attribute_id': self.size_attribute.id,
'value_ids': [
Command.set([
self.size_attribute_l.id,
self.size_attribute_m.id,
]),
],
}),
Command.create({
'attribute_id': self.color_attribute.id,
'value_ids': [
Command.set([
self.color_attribute_red.id,
self.color_attribute_blue.id,
])
],
}),
],
})
self.assertEqual(len(self.product_template_2_attribute_lines.product_variant_ids), 4)
# Use variants s.t. they are archived and not deleted when value is removed
self.empty_order.order_line = [
Command.create({
'product_id': product.id
})
for product in self.product_template_2_attribute_lines.product_variant_ids
]
self.empty_order.action_confirm()
# Remove attribute
self.product_template_2_attribute_lines.attribute_line_ids[0].unlink()
self.assertEqual(len(self.product_template_2_attribute_lines.product_variant_ids), 2)
self.authenticate('demo', 'demo')
base_url = self.product_template_2_attribute_lines.get_base_url()
response = self.opener.post(
url=base_url + '/sale_product_configurator/get_values',
json={
'params': {
'product_template_id': self.product_template_2_attribute_lines.id,
'quantity': 1.0,
'currency_id': 1,
'so_date': str(self.env.cr.now()),
'product_uom_id': None,
'company_id': None,
'pricelist_id': None,
'ptav_ids': None,
'only_main_product': False,
},
}
)
result = response.json()['result']
# Make sure archived combinations with inactive ptav are not loaded as it's useless to
# exclude combinations that are not even available
self.assertFalse(result['products'][0]['archived_combinations'])