Jump to content
guigs06.pro

Tri par prix, problème pagination

Recommended Posts

Bonjour,

 

J'ai un problème avec le tri par prix (je suis sur la version 1.5.3.1).

En effet, lorsque je veut effectuer un tri par prix dans une catégorie, le tri est bien effectué avec les prix spécifiques pris en compte, mais lorsque je passe sur la deuxième page par exemple, le tri est toujours bon mais le prix du premier produit de la page2 est inférieur au prix du dernier produit de la page1.

 

ex.: page1, premier prix 30€, dernier prix 200€.  page2 : premier prix 55€, dernier prix 330€.

 

Est-ce un bug déjà relevé ? Est-ce qu'il y a un correctif à appliquer ?

 

J'ai regarder la classe "category.php", voici le code de la requête si ça peut aider :

$sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, product_attribute_shop.`id_product_attribute`, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, pl.`description`, pl.`description_short`, pl.`available_now`,
					pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, image_shop.`id_image`,
					il.`legend`, m.`name` AS manufacturer_name, cl.`name` AS category_default,
					DATEDIFF(product_shop.`date_add`, DATE_SUB(NOW(),
					INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).'
						DAY)) > 0 AS new, product_shop.price AS orderprice
				FROM `'._DB_PREFIX_.'category_product` cp
				LEFT JOIN `'._DB_PREFIX_.'product` p
					ON p.`id_product` = cp.`id_product`
				'.Shop::addSqlAssociation('product', 'p').'
				LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa
				ON (p.`id_product` = pa.`id_product`)
				'.Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1').'
				'.Product::sqlStock('p', 'product_attribute_shop', false, $context->shop).'
				LEFT JOIN `'._DB_PREFIX_.'category_lang` cl
					ON (product_shop.`id_category_default` = cl.`id_category`
					AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')
				LEFT JOIN `'._DB_PREFIX_.'product_lang` pl
					ON (p.`id_product` = pl.`id_product`
					AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').')
				LEFT JOIN `'._DB_PREFIX_.'image` i
					ON (i.`id_product` = p.`id_product`)'.
				Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
				LEFT JOIN `'._DB_PREFIX_.'image_lang` il
					ON (image_shop.`id_image` = il.`id_image`
					AND il.`id_lang` = '.(int)$id_lang.')
				LEFT JOIN `'._DB_PREFIX_.'manufacturer` m
					ON m.`id_manufacturer` = p.`id_manufacturer`
				WHERE product_shop.`id_shop` = '.(int)$context->shop->id.'
				AND (pa.id_product_attribute IS NULL OR product_attribute_shop.id_shop='.(int)$context->shop->id.') 
				AND (i.id_image IS NULL OR image_shop.id_shop='.(int)$context->shop->id.')
					AND cp.`id_category` = '.(int)$this->id
					.($active ? ' AND product_shop.`active` = 1' : '')
					.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')
					.($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : ''); 
 
Merci à vous, bonne journée.

Share this post


Link to post
Share on other sites

Bonjour,

 

Je vous conseille dans un premier temps de régler un "tri par défaut" dans le back-office:

 

PRÉFÉRENCE -> PRODUIT -> PAGINATION

Tri par défaut = Prix du produit

Ordre par défaut = croissant

 

Bien à vous,

Math

Share this post


Link to post
Share on other sites

Bonjour,

 

Merci pour le conseil mais le problème est toujours là.. :/

 

Deuxième page produit le moins cher 5€, produit le plus cher 43.90€

Troisième page produit le moins cher 26.80 €, produit le plus cher 65€

Et pourtant les prix spécifique sont bien pris en compte... :s

 

Guillaume.

Share this post


Link to post
Share on other sites

Hello,

 

Je me suis fait la même réflexion il y a 2-3 jours et ce "bug" a en effet déjà été signalé en... 2011 :blink:

 

http://forge.prestashop.com/browse/PSCFV-6820?jql=text%20~%20%22sort%20specific%20prices%22

 

D'après les devs cela fonctionne ainsi pour des raisons de performances, le bug est donc considéré comme une suggestion d'amélioration et non un bug.

 

Sincèrement, y a une kyrielle de "bugs" dans Prestashop de ce type que je ne parviens toujours pas à m'expliquer.

 

J'ai mis le nez dans Prestashop il y a 3 ans et toutes ces incohérences m'ont découragé d'aller plus loin. Là je me remets dedans depuis quelques jours et je constate qu'après tout ce temps PS en est toujours au même point... j'ai d'ailleurs du mal à comprendre comment il peut y avoir autant d'utilisateurs alors que dès qu'on sort un peu des sentiers battus dans sa config, y a une série de bugs et d'incohérences qui se mettent en oeuvre... mais apparemment beaucoup s'en moquent... ou font avec :blink:

 

Bref, ce petit constat mis à part, tout ça pour dire que oui, ce fonctionnement est "normal" :lol:

 

Les produits sont en fait d'abord triés sur leur prix de base, la pagination est ensuite appliquée et puis seulement les prix spécifiques sont triés. Useless.

 

Mais je sens que ça va m'irriter aussi ce tri désordonné, donc j'irai quand-même jeter un oeil dans le code un peu plus tard ;)

Edited by Zebx (see edit history)

Share this post


Link to post
Share on other sites

Hello,

 

Voici une modif qui devrait résoudre ce "bug" :

 

Juste après le code de ta requête, vers la ligne 650 (sur PS1.5.6.2).

 

Remplacer ceci :

		if ($random === true)
		{
			$sql .= ' ORDER BY RAND()';
			$sql .= ' LIMIT 0, '.(int)$random_number_products;
		}
		else
			$sql .= ' ORDER BY '.(isset($order_by_prefix) ? $order_by_prefix.'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).'
			LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n;

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
		if ($order_by == 'orderprice')
			Tools::orderbyPrice($result, $order_way);

Par ceci :

		if ($random === true)
		{
			$sql .= ' ORDER BY RAND()';
			$sql .= ' LIMIT 0, '.(int)$random_number_products;
		}
		else
		if ($order_by == 'orderprice'){
			$sql .= ' ORDER BY '.(isset($order_by_prefix) ? $order_by_prefix.'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way);
		} else {
			$sql .= ' ORDER BY '.(isset($order_by_prefix) ? $order_by_prefix.'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).'
			LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n;
		}
		
		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

		if ($order_by == 'orderprice'){
			Tools::orderbyPrice($result, $order_way);
			$result = array_slice($result, (((int)$p - 1) * (int)$n), (int)$n);
		}

Evidemment, ça ne marche que pour la page catégorie... le même type de modif est donc à faire sur toutes les pages de listes de produits qu'on souhaite pouvoir trier correctement par prix.

 

Ce code est à tester un peu plus en profondeur, là j'ai juste fait un test à la va-vite sur un seul produit, mais à priori ça devrait être bon ;)

 

Bien entendu c'est un peu plus lourd que le code d'origine, donc si on a beaucoup de produits à trier faut voir aussi niveau performances comment ça se comporte... (cela dit tous les autres tris ne sont pas affectés, seul le tri par prix devient plus lourd)

 

Enjoy :D

Share this post


Link to post
Share on other sites

Bonjour,

 

Merci d'avoir pris le temps d'essayer de trouver le problème.

Malheureusement cela n'a pas fonctionné.

 

J'ai pourtant bien modifié le code dans classes->Category.php ligne 650 :/

 

Il y a peut-être un autre endroit à modifier ?

 

:)

Share this post


Link to post
Share on other sites

Raaah, Prestashop va finir par me rendre fou :lol:

 

Ma modif marchait nickel, puis là après ton message, je reteste sur mon site en local et je constate... que ça marche plus :blink:

 

Le responsable de ce mic-mac : le module de navigation à facettes ! Que j'ai activé depuis lors...

 

C'est bon que ce module m'avait déjà fait des misères dans le même genre sur des affichages de prix de déclinaisons sinon je crois que j'aurais pu chercher longtemps le fautif ^^

 

Bref, le code à modifier est dans la même idée mais ça se passe maintenant dans modules/blocklayered/blocklayered.php

 

Vers la ligne 1957 (PS 1.5.6.2) :

 

Remplacer :

		if ($this->nbr_products == 0)
			$this->products = array();
		else
		{
			$n = (int)Tools::getValue('n', Configuration::get('PS_PRODUCTS_PER_PAGE'));
			$nb_day_new_product = (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20);

			$this->products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
			SELECT
				p.*,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'
				'.$alias_where.'.id_category_default,
				pl.*,
				MAX(image_shop.`id_image`) id_image,
				il.legend, 
				m.name manufacturer_name,
				MAX(pa.id_product_attribute) id_product_attribute,
				DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB(NOW(), INTERVAL '.(int)$nb_day_new_product.' DAY)) > 0 AS new,
				stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
			FROM `'._DB_PREFIX_.'category_product` cp
			LEFT JOIN '._DB_PREFIX_.'category c ON (c.id_category = cp.id_category)
			LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
			'.Shop::addSqlAssociation('product', 'p').'
			'.Product::sqlStock('p', null, false, Context::getContext()->shop).'
			LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (pl.id_product = p.id_product'.Shop::addSqlRestrictionOnLang('pl').' AND pl.id_lang = '.(int)$cookie->id_lang.')
			LEFT JOIN `'._DB_PREFIX_.'image` i  ON (i.`id_product` = p.`id_product`)'.
			Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
			LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$cookie->id_lang.')
			LEFT JOIN '._DB_PREFIX_.'manufacturer m ON (m.id_manufacturer = p.id_manufacturer)
			LEFT JOIN '._DB_PREFIX_.'product_attribute pa ON (p.id_product = pa.id_product)
			WHERE '.$alias_where.'.`active` = 1 AND '.$alias_where.'.`visibility` IN ("both", "catalog")
			AND '.(Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= '.(int)$parent->nleft.' AND c.nright <= '.(int)$parent->nright : 'c.id_category = '.(int)$id_parent).'
			AND c.active = 1
			AND p.id_product IN ('.implode(',', $product_id_list).')
			GROUP BY product_shop.id_product
			ORDER BY '.Tools::getProductsOrder('by', Tools::getValue('orderby'), true).' '.Tools::getProductsOrder('way', Tools::getValue('orderway')).
			' LIMIT '.(((int)$this->page - 1) * $n.','.$n));
		}

		if (Tools::getProductsOrder('by', Tools::getValue('orderby'), true) == 'p.price')
			Tools::orderbyPrice($this->products, Tools::getProductsOrder('way', Tools::getValue('orderway')));
			
		return $this->products;

Par le code suivant :

		if ($this->nbr_products == 0)
			$this->products = array();
		else
		{
			$n = (int)Tools::getValue('n', Configuration::get('PS_PRODUCTS_PER_PAGE'));
			$nb_day_new_product = (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20);

// Zebx fix START
// Affichage en catégorie du prix de la déclinaison par défaut + tri par prix compatible multipages
			
			$sql='SELECT
				p.*,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'
				'.$alias_where.'.id_category_default,
				pl.*,
				MAX(image_shop.`id_image`) id_image,
				il.legend, 
				m.name manufacturer_name,
				MAX(pa.id_product_attribute) id_product_attribute,
				DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB(NOW(), INTERVAL '.(int)$nb_day_new_product.' DAY)) > 0 AS new,
				stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
			FROM `'._DB_PREFIX_.'category_product` cp
			LEFT JOIN '._DB_PREFIX_.'category c ON (c.id_category = cp.id_category)
			LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
			'.Shop::addSqlAssociation('product', 'p').'
			'.Product::sqlStock('p', null, false, Context::getContext()->shop).'
			LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (pl.id_product = p.id_product'.Shop::addSqlRestrictionOnLang('pl').' AND pl.id_lang = '.(int)$cookie->id_lang.')
			LEFT JOIN `'._DB_PREFIX_.'image` i  ON (i.`id_product` = p.`id_product`)'.
			Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
			LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$cookie->id_lang.')
			LEFT JOIN '._DB_PREFIX_.'manufacturer m ON (m.id_manufacturer = p.id_manufacturer)
			LEFT JOIN '._DB_PREFIX_.'product_attribute pa ON (p.id_product = pa.id_product)
			WHERE '.$alias_where.'.`active` = 1 AND '.$alias_where.'.`visibility` IN ("both", "catalog")
			AND '.(Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= '.(int)$parent->nleft.' AND c.nright <= '.(int)$parent->nright : 'c.id_category = '.(int)$id_parent).'
			AND c.active = 1
			AND p.id_product IN ('.implode(',', $product_id_list).')
			AND (pa.default_on = 1 OR ISNULL(pa.default_on))
			GROUP BY product_shop.id_product
			ORDER BY '.Tools::getProductsOrder('by', Tools::getValue('orderby'), true).' '.Tools::getProductsOrder('way', Tools::getValue('orderway'));
			
			if (!(Tools::getProductsOrder('by', Tools::getValue('orderby'), true) == 'p.price'))
				$sql .= ' LIMIT '.(((int)$this->page - 1) * $n.','.$n);
			
			$this->products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

		}

		if (Tools::getProductsOrder('by', Tools::getValue('orderby'), true) == 'p.price') {
			Tools::orderbyPrice($this->products, Tools::getProductsOrder('way', Tools::getValue('orderway')));
			$this->products = array_slice($this->products, (((int)$this->page - 1) * $n), $n);
		}

//Zebx fix END
		
		return $this->products;

Par la même occasion ce code corrige donc aussi le module pour que ce soit bien le prix de la déclinaison par défaut qui s'affiche dans les résultats (et non le prix de la dernière déclinaison qui est généralement la plus chère)

 

J'espère que cette fois-ci c'est la bonne ;)

Edited by Zebx (see edit history)
  • Like 2

Share this post


Link to post
Share on other sites

Bonjour,

 

Je vous conseille dans un premier temps de régler un "tri par défaut" dans le back-office:

 

PRÉFÉRENCE -> PRODUIT -> PAGINATION

Tri par défaut = Prix du produit

Ordre par défaut = croissant

 

Bien à vous,

Math

Oui mais c'est un pis aller, c'est pas forcement ce que l'on veut.

Souvent les problèmes de tri sur le prix est dû à un souci dans la navigation à facettes si le module correspondant a été activé.

Par exemple si on a un filtre général s'appliquant à toutes les catégories (avec des filtres sur prix et fournisseurs), ne pas oublier d'ajouter les nouvelles catégories ou sous catégories créées postérieurement au filtre, ça peut être aussi un souci d'indéxation des prix auquel cas il faut lancer l'indéxation des prix manquant et/ou réindéxation des prix etc...

Share this post


Link to post
Share on other sites

Hello, 

 

Je déterre ce topic, car comme tout le monde j'ai le même souci, j'aimerais savoir si il serait possible de faire fonctionner cette astuce sur une version 1.6.1.x ?

 

Merci d'avance, 

Share this post


Link to post
Share on other sites

Bonjour, 

 

Je re déterre ce topic.

 

J'ai le même soucis sur ma boutique et ne trouve pas de solution...

 

Ma version: 1.6.1.7

Share this post


Link to post
Share on other sites

Bonjour, 

 

Je re déterre ce topic.

 

J'ai le même soucis sur ma boutique et ne trouve pas de solution...

 

Ma version: 1.6.1.7

 

 

Bonjour,

 

Même problème sur ma version 1.6.1.9

 

Avez-vous trouvé une solutions de votre côté ?

Share this post


Link to post
Share on other sites

Bonjour,

 

Même problème sur ma version 1.6.1.9

 

Avez-vous trouvé une solutions de votre côté ?

 

Non, toujours pas... 

Share this post


Link to post
Share on other sites

Bonjour,

Je déterre ce topic également car j'ai le même problème sur un PS 1.6.1.23. Avez-vous trouvez une solution ?

NB J'ai l'impression que les produits avec des déclinaisons créaient ce problème

Edited by rricci34 (see edit history)

Share this post


Link to post
Share on other sites

Bonjour, pour info j'ai trouvé une solution via ce topic si ça peut en aider certain... :

 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More