[FIX] website_sale: fix website_sequence

There was multiple issues with `website_sequence` field, mostly coming from
commits during the last few years (eg 43c544f8a8) that tried to change the
`website_sequence` order to be the same as `sequence` but changing only part of
the code.
Other commits tried to restore that again by changing only some parts.

This commit does:
1. Originally, the `website_sequence` was supposed to be the opposite of
   `sequence` field, the greater the first.
   This commit ensure this is not the case anymore and it is used as the
   regular `sequence` field.
2. `website_sequence` demo data was set between 4 and 1000, no need to use so
   big differences. Plus, having a website_sequence set to 4 means the next
   product would already have negative value.
3. Add `website_sequence` field in tree view in place of `sequence` for website
   product view, and in debug mode on form view.

task-1960777

closes odoo/odoo#32593

Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
Romain Derie
2019-04-16 13:19:32 +00:00
parent 728348f378
commit d2ed857608
9 changed files with 159 additions and 36 deletions
@@ -12,6 +12,7 @@ Publish your members/association directory publicly.
'depends': ['website_partner', 'website_google_map', 'association', 'website_sale'],
'data': [
'data/membership_data.xml',
'views/product_template_views.xml',
'views/website_membership_templates.xml',
'security/ir.model.access.csv',
'security/website_membership.xml',
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_template_view_form" model="ir.ui.view">
<field name="name">product.template.view.form.inherit.website_membership</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="membership.membership_products_form"/>
<field name="arch" type="xml">
<field name="active" position="after">
<field name="website_sequence" groups="base.group_no_one"/>
</field>
</field>
</record>
<record id="product_template_view_tree" model="ir.ui.view">
<field name="name">product.template.view.tree.inherit.website_membership</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="membership.membership_products_tree"/>
<field name="arch" type="xml">
<field name="name" position="before">
<field name="website_sequence" widget="handle"/>
</field>
</field>
</record>
</odoo>
+1 -1
View File
@@ -157,7 +157,7 @@ class WebsiteSale(http.Controller):
def _get_search_order(self, post):
# OrderBy will be parsed in orm and so no direct sql injection
# id is added to be sure that order is a unique sort key
order = post.get('order') or 'website_sequence desc'
order = post.get('order') or 'website_sequence ASC'
return 'is_published desc, %s, id desc' % order
def _get_search_domain(self, search, category, attrib_values, search_in_description=True):
+3 -5
View File
@@ -58,15 +58,13 @@
<field name="website_published" eval="True"/>
<field name="website_size_x">2</field>
<field name="website_size_y">2</field>
<field name="website_sequence">1000</field>
<field name="website_sequence">9950</field>
<field name="website_style_ids" eval="[(6,0,[ref('website_sale.image_full')])]"/>
</record>
<record id="product.product_product_6" model="product.product">
<field name="website_published" eval="True"/>
<field name="website_sequence">4</field>
<field name="website_style_ids" eval="[(6,0,[ref('website_sale.image_full')])]"/>
<field name="website_sequence">4</field>
<field name="website_sequence">10010</field>
<field name="website_style_ids" eval="[(6,0,[ref('website_sale.image_full')])]"/>
</record>
@@ -639,7 +637,7 @@
<field name="name">Warranty</field>
<field name="default_code">SERV_125889</field>
<field name="list_price">20.0</field>
<field name="website_sequence">100</field>
<field name="website_sequence">9980</field>
<field name="website_published" eval="True"/>
<field name="type">service</field>
<field name="uom_id" ref="uom.product_uom_unit"/>
+24 -11
View File
@@ -3,7 +3,6 @@
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError, UserError
from odoo.addons import decimal_precision as dp
from odoo.addons.website.models import ir_http
from odoo.tools.translate import html_translate
from odoo.osv import expression
@@ -204,7 +203,7 @@ class ProductTemplate(models.Model):
'(upsell strategy).Those product show up on the product page.')
accessory_product_ids = fields.Many2many('product.product', 'product_accessory_rel', 'src_id', 'dest_id',
string='Accessory Products', help='Accessories show up when the customer'
'reviews the cart before payment (cross-sell strategy).')
'reviews the cart before payment (cross-sell strategy).')
website_size_x = fields.Integer('Size X', default=1)
website_size_y = fields.Integer('Size Y', default=1)
website_style_ids = fields.Many2many('product.style', string='Styles')
@@ -345,27 +344,41 @@ class ProductTemplate(models.Model):
return website and website.company_id or res
def _default_website_sequence(self):
self._cr.execute("SELECT MIN(website_sequence) FROM %s" % self._table)
min_sequence = self._cr.fetchone()[0]
return min_sequence and min_sequence - 1 or 10
''' We want new product to be the last (highest seq).
Every product should ideally have an unique sequence.
Default sequence (10000) should only be used for DB first product.
As we don't resequence the whole tree (as `sequence` does), this field
might have negative value.
'''
self._cr.execute("SELECT MAX(website_sequence) FROM %s" % self._table)
max_sequence = self._cr.fetchone()[0]
if max_sequence is None:
return 10000
return max_sequence + 5
def set_sequence_top(self):
self.website_sequence = self.sudo().search([], order='website_sequence desc', limit=1).website_sequence + 1
min_sequence = self.sudo().search([], order='website_sequence ASC', limit=1)
self.website_sequence = min_sequence.website_sequence - 5
def set_sequence_bottom(self):
self.website_sequence = self.sudo().search([], order='website_sequence', limit=1).website_sequence - 1
max_sequence = self.sudo().search([], order='website_sequence DESC', limit=1)
self.website_sequence = max_sequence.website_sequence + 5
def set_sequence_up(self):
previous_product_tmpl = self.sudo().search(
[('website_sequence', '>', self.website_sequence), ('website_published', '=', self.website_published)],
order='website_sequence', limit=1)
previous_product_tmpl = self.sudo().search([
('website_sequence', '<', self.website_sequence),
('website_published', '=', self.website_published),
], order='website_sequence DESC', limit=1)
if previous_product_tmpl:
previous_product_tmpl.website_sequence, self.website_sequence = self.website_sequence, previous_product_tmpl.website_sequence
else:
self.set_sequence_top()
def set_sequence_down(self):
next_prodcut_tmpl = self.search([('website_sequence', '<', self.website_sequence), ('website_published', '=', self.website_published)], order='website_sequence desc', limit=1)
next_prodcut_tmpl = self.search([
('website_sequence', '>', self.website_sequence),
('website_published', '=', self.website_published),
], order='website_sequence ASC', limit=1)
if next_prodcut_tmpl:
next_prodcut_tmpl.website_sequence, self.website_sequence = self.website_sequence, next_prodcut_tmpl.website_sequence
else:
+1
View File
@@ -5,3 +5,4 @@ from . import test_website_sale_mail
from . import test_website_sale_pricelist
from . import test_website_sale_product_attribute_value_config
from . import test_website_sale_image
from . import test_website_sequence
@@ -0,0 +1,70 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo.tests
@odoo.tests.common.tagged('post_install', '-at_install')
class TestWebsiteSequence(odoo.tests.TransactionCase):
def setUp(self):
super(TestWebsiteSequence, self).setUp()
ProductTemplate = self.env['product.template']
product_templates = ProductTemplate.search([])
# if stock is installed we can't archive since there is orderpoints
if hasattr(self.env['product.product'], 'orderpoint_ids'):
product_templates.mapped('product_variant_ids.orderpoint_ids').write({'active': False})
product_templates.write({'active': False})
self.p1, self.p2, self.p3, self.p4 = ProductTemplate.create([{
'name': 'First Product',
'website_sequence': 100,
}, {
'name': 'Second Product',
'website_sequence': 180,
}, {
'name': 'Third Product',
'website_sequence': 225,
}, {
'name': 'Last Product',
'website_sequence': 250,
}])
self._check_correct_order(self.p1 + self.p2 + self.p3 + self.p4)
def _search_website_sequence_order(self, order='ASC'):
'''Helper method to limit the search only to the setUp products'''
return self.env['product.template'].search([
], order='website_sequence %s' % (order))
def _check_correct_order(self, products):
product_ids = self._search_website_sequence_order().ids
self.assertEqual(product_ids, products.ids, "Wrong sequence order")
def test_01_website_sequence(self):
# 100:1, 180:2, 225:3, 250:4
self.p2.set_sequence_down()
# 100:1, 180:3, 225:2, 250:4
self._check_correct_order(self.p1 + self.p3 + self.p2 + self.p4)
self.p4.set_sequence_up()
# 100:1, 180:3, 225:4, 250:2
self._check_correct_order(self.p1 + self.p3 + self.p4 + self.p2)
self.p2.set_sequence_top()
# 95:2, 100:1, 180:3, 225:4
self._check_correct_order(self.p2 + self.p1 + self.p3 + self.p4)
self.p1.set_sequence_bottom()
# 95:2, 180:3, 225:4, 230:1
self._check_correct_order(self.p2 + self.p3 + self.p4 + self.p1)
current_sequences = self._search_website_sequence_order().mapped('website_sequence')
self.assertEqual(current_sequences, [95, 180, 225, 230], "Wrong sequence order (2)")
self.p2.website_sequence = 1
self.p3.set_sequence_top()
# -4:3, 1:2, 225:4, 230:1
self.assertEqual(self.p3.website_sequence, -4, "`website_sequence` should go below 0")
new_product = self.env['product.template'].create({
'name': 'Last Newly Created Product',
})
self.assertEqual(self._search_website_sequence_order()[-1], new_product, "new product should be last")
+34 -18
View File
@@ -12,22 +12,6 @@
</field>
</record>
<record id="product_template_action_website" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="res_model">product.template</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form,activity</field>
<field name="search_view_id" ref="product_template_search_view_website"/>
<field name="context">{'search_default_published': 1, 'default_website_published': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new product
</p><p>
A product can be either a physical product or a service that you sell to your customers.
</p>
</field>
</record>
<record model="ir.ui.view" id="product_pricelist_view">
<field name="name">product.pricelist.website.form</field>
<field name="model">product.pricelist</field>
@@ -50,8 +34,9 @@
</field>
</record>
<record model="ir.ui.view" id="product_template_website_tree_view">
<field name="name">product.template.website.tree</field>
<!-- We want website_id to be shown outside of website module like other models -->
<record model="ir.ui.view" id="product_template_view_tree">
<field name="name">product.template.view.tree.inherit.website_sale</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_tree_view"/>
<field name="arch" type="xml">
@@ -61,6 +46,36 @@
</field>
</record>
<!-- only website module template view should use the website_sequence -->
<record model="ir.ui.view" id="product_template_view_tree_website_sale">
<field name="name">product.template.view.tree.website_sale</field>
<field name="mode">primary</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="website_sale.product_template_view_tree"/>
<field name="arch" type="xml">
<field name="sequence" position="replace">
<field name="website_sequence" widget="handle"/>
</field>
</field>
</record>
<record id="product_template_action_website" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="res_model">product.template</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form,activity</field>
<field name="view_id" ref="product_template_view_tree_website_sale"/>
<field name="search_view_id" ref="product_template_search_view_website"/>
<field name="context">{'search_default_published': 1, 'default_website_published': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new product
</p><p>
A product can be either a physical product or a service that you sell to your customers.
</p>
</field>
</record>
<record model="ir.ui.view" id="product_template_form_view_invoice_policy">
<field name="name">product.template.invoice.policy</field>
<field name="model">product.template</field>
@@ -96,6 +111,7 @@
<group string="Shop">
<field name="website_url" invisible="1"/>
<field name="website_id" options="{'no_create': True}" groups="website.group_multi_website"/>
<field name="website_sequence" groups="base.group_no_one"/>
<field name="public_categ_ids" widget="many2many_tags" string="Categories"/>
<field name="alternative_product_ids" widget="many2many_tags"/>
<field name="accessory_product_ids" widget="many2many_tags"/>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="sale_product_configurator.product_product_1_product_template" model="product.template">
<field name="website_sequence">100</field>
<field name="website_sequence">9980</field>
<field name="website_published" eval="True"/>
</record>
<record id="product.product_product_4_product_template" model="product.template">