From 51ac0092f2fe51a6dfcbbe955c075c75149e0725 Mon Sep 17 00:00:00 2001 From: stcc-odoo <stcc@odoo.com> Date: Mon, 10 Jul 2023 15:18:13 +0000 Subject: [PATCH] [FIX] website_sale: make website_sequence unique Steps to reproduce: - Install website_sale - Go to website shop in the frontend - Login, Edit - Click on 3rd or 4th kanban item - Push down Issue: The item goes to the end of the list instead of moving one element to the right/down. Pushing an element down searches for the next element with a higher `website_sequence` and places the current element right after, by switching their sequence values. Normally the logic works fine, but the problem arises when the `website_sale` module is installed, when records with `website_sequence = NULL` are set to the same default value, namely 10000. Then, when an item with `website_sequence = 10000` is pushed down, it will skip many items, before finding one with a higher `website_sequence`. Solution: When updating records with `website_sequence = NULL`, assign an unique sequence to each one. We can set the `website_sequence` relative to the inverse of the id to ensure that the order on the shopping page remains the same as it was prior to the fix. opw-3318867 closes odoo/odoo#127982 Signed-off-by: Stefan-Calin Crainiciuc (stcc) <stcc@odoo.com> --- addons/website_sale/data/demo.xml | 2 +- addons/website_sale/models/product.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/addons/website_sale/data/demo.xml b/addons/website_sale/data/demo.xml index 568c0f968b85..c55f9e1224bb 100644 --- a/addons/website_sale/data/demo.xml +++ b/addons/website_sale/data/demo.xml @@ -63,7 +63,6 @@ <record id="product.product_product_6" model="product.product"> <field name="is_published" eval="True"/> - <field name="website_sequence">10010</field> </record> <record id="product.product_product_7" model="product.product"> @@ -183,6 +182,7 @@ <field name="public_categ_ids" eval="[(6,0,[ref('public_category_cabinets')])]"/> </record> <record id="product.product_product_11_product_template" model="product.template"> + <field name="website_sequence">9990</field> <field name="public_categ_ids" eval="[(6,0,[ref('public_category_furnitures_chairs')])]"/> </record> <record id="product.product_product_12_product_template" model="product.template"> diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py index fd7430790055..4cfb9878536f 100644 --- a/addons/website_sale/models/product.py +++ b/addons/website_sale/models/product.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import logging from odoo import api, fields, models, tools, _ from odoo.exceptions import ValidationError, UserError @@ -7,6 +8,9 @@ from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.website.models import ir_http from odoo.tools.translate import html_translate from odoo.osv import expression +from psycopg2.extras import execute_values + +_logger = logging.getLogger(__name__) class ProductRibbon(models.Model): @@ -339,6 +343,25 @@ class ProductTemplate(models.Model): website = self.website_id or kwargs.get('website') return website and website.company_id or res + def _init_column(self, column_name): + # to avoid generating a single default website_sequence when installing the module, + # we need to set the default row by row for this column + if column_name == "website_sequence": + _logger.debug("Table '%s': setting default value of new column %s to unique values for each row", self._table, column_name) + self.env.cr.execute("SELECT id FROM %s WHERE website_sequence IS NULL" % self._table) + prod_tmpl_ids = self.env.cr.dictfetchall() + max_seq = self._default_website_sequence() + query = """ + UPDATE {table} + SET website_sequence = p.web_seq + FROM (VALUES %s) AS p(p_id, web_seq) + WHERE id = p.p_id + """.format(table=self._table) + values_args = [(prod_tmpl['id'], max_seq + i * 5) for i, prod_tmpl in enumerate(prod_tmpl_ids)] + execute_values(self.env.cr._obj, query, values_args) + else: + super(ProductTemplate, self)._init_column(column_name) + def _default_website_sequence(self): ''' We want new product to be the last (highest seq). Every product should ideally have an unique sequence. -- GitLab