Jump to content

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.
Link to comment
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.

Link to comment
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)
Link to comment
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

Link to comment
Share on other sites

  • 3 weeks later...

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 ?

 

:)

Link to comment
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
Link to comment
Share on other sites

  • 5 months later...

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...

Link to comment
Share on other sites

  • 2 years later...
  • 4 months later...

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é ?

Link to comment
Share on other sites

  • 1 year later...
  • 3 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...