Jump to content

Quantité par déclinaison différents entre le back-office et le front-office


Recommended Posts

Bonjour à tous,

 

Je tombe sur un problème étrange, qui ne m'avais jamais dérangé jusque là et qui pourtant est présent sur tous mes sites Prestashop 1.6.

Contexte :

  • Préférence Produit > Refuser les commandes en cas de rupture de stock
  • Création de plusieurs attributs (peu importe, ici exemple Date pour des cours de cuisine)
  • Association des attributs à mon produit, et gestion des quantités manuelle.

Je définis ma déclinaison par défaut à la date la plus proche, j'ai donc ici 3 décli, avec le 25 octobre par défaut pour que mon produit propose cette date en premier, cf capture d'écran.

Ensuite je me dirige dans les quantités, la ligne en bleue est différente mais je ne m'en inquiète pas plus que ça, je définis mes quantité en prenant soin de mettre une déclinaison à 0 quantité pour mon test. Ici 13 novembre.

Je me dirige vers l'aperçu du produit, et que n'est pas ma surprise, le produit sans quantité est le 20 décembre, rien à voir avec mon backoffice.

Pour corriger le problème, je suis obligé de sélectionner en attribut par défaut le produit qui est en bleu dans l'onglet quantité, donc 20 décembre comme vu sur ma capture d'écran. Si je procède ainsi, alors seulement les quantités sont correctement alignées.

Et je peux reproduire ce bug sur TOUS mes sites.

Est-ce que je fais quelque chose dans le mauvais ordre ?

J'ai essayé de créer mes déclinaisons une par une ou via le générateur, j'ai le même problème. J'ai aussi essayé de changer l'ordre des attributs dans l'onglet Attributs et valeurs, mais ça ne corrige rien et surtout l'ordre est celui que je souhaite.

Je suis paumé !

Je vais me créer un Presta vierge 1.6 pour le triturer, mais si quelqu'un a déjà eu le problème je suis preneur d'une solution ou d'un tuto, merci !

Capture d’écran 2024-09-23 154319.jpg

Capture d’écran 2024-09-23 154439.jpg

Capture d’écran 2024-09-23 154551.jpg

Link to comment
Share on other sites

il y a une heure, Nemesis tech a dit :

Bonjour,

Normalement, il faut sélectionner un attribut par défault. Si cela ne fonctionne pas après avoir vidé le cache de PrestaShop & autre, alors, il y a sûrement un problème au niveau du thème.

 

Non, le thème ne fait qu'afficher les données envoyées par le contrôleur. Si le thème avait un souci les données ne seraient jamais correctes.

Link to comment
Share on other sites

Merci de vos réponses

On 9/23/2024 at 5:42 PM, Eolia said:

Pas de cache serveur derrière type varnish, speedcache, litespeed ou cloudflare ?

Non aucun cache d'installé, j'ai testé sur un hébergement OVH, un hébergement O2switch et en local sans différence.

J'ai essayé sur un site installé à l'instant ce matin en local, récupéré sur le site de Prestashop version 1.6.1.19 donc site vierge.

Produit par défaut, sans rien changer sauf la quantité et le problème est exactement le même (cf capture).

Version PHP 7.1.33, il s'agit donc bien d'un problème sur tous les presta je pense.

C'est assez improbable que je n'ai jamais vu le problème avec la masse de sites 1.6 que j'ai installé pour des clients, en général mes clients autorisent la commande hors stock mais là comme il s'agit de cours de cuisine limités, les stocks sont importants. C'est une première pour moi et là ça me dépasse.

Capture d’écran 2024-09-25 090223.jpg

Link to comment
Share on other sites

Je n'arrive pas à reproduire votre bug.

La seule différence avec vous c'est que mes sites 1.6 sont restés en PHP 5.6 vu que les versions 1.6 et même la 1.6.1.24 n'ont jamais été complètement compatibles PHP 7.

Link to comment
Share on other sites

Alors je ne peux rien tester en 5.6 tout du moins pas sur wamp. Je ne peux pas ouvrir phpmyadmin avec cette version de PHP.

Sur OVH je suis passé en 5.6 pour mon site qui affiche cet problème, et je n'ai aucun changement sur le comportement.

Pour arriver à reproduire l'erreur, il me suffit de définir une déclinaison par défaut différente de la déclinaison qui est en bleu dans l'onglet Quantités (toujours la dernière déclinaison semble-t-il).

Ensuite, la déclinaison qui affiche la rupture de stock est toujours en décalé par rapport au backoffice.

Par contre si je définis la déclinaison par défaut sur la même valeur que la déclinaison sur fond bleu dans l'onglet Quantité, je n'ai plus de problème. Sauf que bien évidemment ça ne m'arrange pas du tout car la déclinaison côté Quantité n'est pas celle que je souhaite.

Capture d’écran 2024-09-26 151706.jpg

Link to comment
Share on other sites

Quand je crée des déclis c'est toujours la 1ère qui est en bleu que ce soit dans l'onglet déclinaison et l'onglet quantité.

Le code est d'ailleurs clair à ce sujet:

image.thumb.png.c27ad6dac750f8f552cbf6f5c3018888.png

on commence par assigner $default_on à 1.

On l'applique à la 1ère décli et on l'assigne à 0

Toutes les suivantes seront donc à 0.

 

  • Like 1
Link to comment
Share on other sites

17 hours ago, Nemesis tech said:

@Shonen avec un PrestaShop clean, de test, est-ce que vous arrivez à reproduire le problème ? Ou tout fonctionne correctement ?

Prestashop clean comme mentionné plus haut, et le problème persiste même avec les produits par défauts (non créés par moi même).

@Eolia J'ai pourtant le même code source que vous.

image.png.0d36a988eff11daf4fe9a1bfcbec69c7.png

Dans l'onglet Déclinaisons c'est bien Couleur Orange, Taille S qui est en bleu, ce qui correspond bien à ma base de données.

image.thumb.png.4bbcddb895257c93a42e4cd1b56933b5.png

image.png.9db69e96fbb91e3dcb825fdd25eda0d2.png

image.png.4afd4238c70d3008d5e4a41c6d70e313.png

Et pourtant onglet Quantités c'est toujours le dernier qui est en bleu.

image.thumb.png.60272f8a76009fbe6e4ba86944bca3e7.png

 

Pourtant dans mon quantities.tpl je vois bien qu'il appelle le bon bout de code...

image.thumb.png.a244e8ca4f46f43add91b8f92d476f98.png

 

Ca n'arrive vraiment qu'à moi ? Mais alors pourquoi sur tous mes Prestashop, peut importe la configuration ?

Cela peut-il venir du fait que dans mon DOM et dans ma base, l'ordre dans lequel sont appelés les quantités est un peu étrange ? On commence par le qty_2 et on termine par le qty_1, alors que qty_1 devrait logiquement être Taille S couleur Orange dans mon cas puisque c'est id_product_attribute = 1.

image.png.2e13f81c1b59bb4b6825dd8799587a14.png

 

Le var_dump de la variable $attributes : celui-ci n'est pas bon puisque chaque id_product_attribute est décalé. Le problème doit venir de là mais je ne sais pas comment vérifier.

C:\wamp64\www\ps6\tools\smarty\sysplugins\smarty_internal_templatebase.php(171) : eval()'d code:213:
array (size=6)
  0 => 
    array (size=18)
      'id_product_attribute' => string '2' (length=1)
      'id_product' => string '1' (length=1)
      'reference' => string '' (length=0)
      'supplier_reference' => string '' (length=0)
      'location' => string '' (length=0)
      'ean13' => string '' (length=0)
      'upc' => string '' (length=0)
      'wholesale_price' => string '0.000000' (length=8)
      'price' => string '0.000000' (length=8)
      'ecotax' => string '0.000000' (length=8)
      'quantity' => int 300
      'weight' => string '0.000000' (length=8)
      'unit_price_impact' => string '0.000000' (length=8)
      'default_on' => null
      'minimal_quantity' => string '1' (length=1)
      'available_date' => string '0000-00-00' (length=10)
      'id_shop' => string '1' (length=1)
      'attribute_designation' => string 'Taille - S, Couleur - Orange' (length=28)
  1 => 
    array (size=18)
      'id_product_attribute' => string '3' (length=1)
      'id_product' => string '1' (length=1)
      'reference' => string '' (length=0)
      'supplier_reference' => string '' (length=0)
      'location' => string '' (length=0)
      'ean13' => string '' (length=0)
      'upc' => string '' (length=0)
      'wholesale_price' => string '0.000000' (length=8)
      'price' => string '0.000000' (length=8)
      'ecotax' => string '0.000000' (length=8)
      'quantity' => int 300
      'weight' => string '0.000000' (length=8)
      'unit_price_impact' => string '0.000000' (length=8)
      'default_on' => null
      'minimal_quantity' => string '1' (length=1)
      'available_date' => string '0000-00-00' (length=10)
      'id_shop' => string '1' (length=1)
      'attribute_designation' => string 'Taille - S, Couleur - Bleu' (length=26)
  2 => 
    array (size=18)
      'id_product_attribute' => string '4' (length=1)
      'id_product' => string '1' (length=1)
      'reference' => string '' (length=0)
      'supplier_reference' => string '' (length=0)
      'location' => string '' (length=0)
      'ean13' => string '' (length=0)
      'upc' => string '' (length=0)
      'wholesale_price' => string '0.000000' (length=8)
      'price' => string '0.000000' (length=8)
      'ecotax' => string '0.000000' (length=8)
      'quantity' => int 0
      'weight' => string '0.000000' (length=8)
      'unit_price_impact' => string '0.000000' (length=8)
      'default_on' => null
      'minimal_quantity' => string '1' (length=1)
      'available_date' => string '0000-00-00' (length=10)
      'id_shop' => string '1' (length=1)
      'attribute_designation' => string 'Taille - M, Couleur - Orange' (length=28)
  3 => 
    array (size=18)
      'id_product_attribute' => string '5' (length=1)
      'id_product' => string '1' (length=1)
      'reference' => string '' (length=0)
      'supplier_reference' => string '' (length=0)
      'location' => string '' (length=0)
      'ean13' => string '' (length=0)
      'upc' => string '' (length=0)
      'wholesale_price' => string '0.000000' (length=8)
      'price' => string '0.000000' (length=8)
      'ecotax' => string '0.000000' (length=8)
      'quantity' => int 300
      'weight' => string '0.000000' (length=8)
      'unit_price_impact' => string '0.000000' (length=8)
      'default_on' => null
      'minimal_quantity' => string '1' (length=1)
      'available_date' => string '0000-00-00' (length=10)
      'id_shop' => string '1' (length=1)
      'attribute_designation' => string 'Taille - M, Couleur - Bleu' (length=26)
  4 => 
    array (size=18)
      'id_product_attribute' => string '6' (length=1)
      'id_product' => string '1' (length=1)
      'reference' => string '' (length=0)
      'supplier_reference' => string '' (length=0)
      'location' => string '' (length=0)
      'ean13' => string '' (length=0)
      'upc' => string '' (length=0)
      'wholesale_price' => string '0.000000' (length=8)
      'price' => string '0.000000' (length=8)
      'ecotax' => string '0.000000' (length=8)
      'quantity' => int 300
      'weight' => string '0.000000' (length=8)
      'unit_price_impact' => string '0.000000' (length=8)
      'default_on' => null
      'minimal_quantity' => string '1' (length=1)
      'available_date' => string '0000-00-00' (length=10)
      'id_shop' => string '1' (length=1)
      'attribute_designation' => string 'Taille - L, Couleur - Orange' (length=28)
  5 => 
    array (size=18)
      'id_product_attribute' => string '1' (length=1)
      'id_product' => string '1' (length=1)
      'reference' => string '' (length=0)
      'supplier_reference' => string '' (length=0)
      'location' => string '' (length=0)
      'ean13' => string '' (length=0)
      'upc' => string '' (length=0)
      'wholesale_price' => string '0.000000' (length=8)
      'price' => string '0.000000' (length=8)
      'ecotax' => string '0.000000' (length=8)
      'quantity' => int 0
      'weight' => string '0.000000' (length=8)
      'unit_price_impact' => string '0.000000' (length=8)
      'default_on' => string '1' (length=1)
      'minimal_quantity' => string '1' (length=1)
      'available_date' => string '0000-00-00' (length=10)
      'id_shop' => string '1' (length=1)
      'attribute_designation' => string 'Taille - L, Couleur - Bleu' (length=26)

 

Link to comment
Share on other sites

les attributs de quantity.tpl arrivent de la fonction initFormQuantities($obj):

$attributes = $obj->getAttributesResume($this->context->language->id);

Pas d'override de Product, pas de foreach par référence où il manquerait un unset() final ?

Cette fonction vous renvoie bien les attributs dans le bon ordre ?

  • Thanks 1
Link to comment
Share on other sites

On 9/27/2024 at 10:32 AM, Eolia said:

les attributs de quantity.tpl arrivent de la fonction initFormQuantities($obj):

$attributes = $obj->getAttributesResume($this->context->language->id);

Pas d'override de Product, pas de foreach par référence où il manquerait un unset() final ?

Cette fonction vous renvoie bien les attributs dans le bon ordre ?

Merci énormément @Eolia pour toutes vos réponses, avec votre aide j'ai pu trouver le problème.

Comme vous disiez, les attributs sont gérés dans la fonction getAttributesResume de la classe Product. La requête SQL en PHP, une fois décryptée donne ceci :

SELECT pa.*, ps_product_attribute_shop.*
				FROM `ps_product_attribute` pa
                LEFT JOIN `ps_product_attribute_shop` ON `ps_product_attribute_shop`.`id_product_attribute` = pa.`id_product_attribute`
				WHERE pa.`id_product` = 1
				GROUP BY pa.`id_product_attribute`

Sauf que le résultat ressemble à ça chez moi (encore une fois, sur un Prestashop VIERGE de toute modification / override) :

image.thumb.png.f3a28869ba1ec5c67514aed1442a5be1.png

Le problème est que ensuite les autres fonctions de Prestashop ajoutent la quantité sur l'index dans l'ordre d'apparition, se basant sur le fait que la première valeur est forcément l'ID 1, ce qui n'est pas le cas chez moi (problème avec ma version de mysql ?).

J'ai donc réalisé un override de ma fonction getAttributesResume pour ajouter ORDER BY, et dorénavant tout fonctionne normalement.

<?php
class Product extends ProductCore
{

    /**
    * Get all available product attributes resume
    *
    * @param int $id_lang Language id
    * @return array Product attributes combinations
    */
    public function getAttributesResume($id_lang, $attribute_value_separator = ' - ', $attribute_separator = ', ')
    {
        if (!Combination::isFeatureActive()) {
            return array();
        }

        /* Ajout du ORDER BY pour corriger mon problème d'attributs */
        $combinations = Db::getInstance()->executeS('SELECT pa.*, product_attribute_shop.*
				FROM `'._DB_PREFIX_.'product_attribute` pa
				'.Shop::addSqlAssociation('product_attribute', 'pa').'
				WHERE pa.`id_product` = '.(int)$this->id.'
				GROUP BY pa.`id_product_attribute`
                ORDER BY pa.`id_product_attribute`');
        /* Fin de la correction */

        if (!$combinations) {
            return false;
        }

        $product_attributes = array();
        foreach ($combinations as $combination) {
            $product_attributes[] = (int)$combination['id_product_attribute'];
        }

        $lang = Db::getInstance()->executeS('SELECT pac.id_product_attribute, GROUP_CONCAT(agl.`name`, \''.pSQL($attribute_value_separator).'\',al.`name` ORDER BY agl.`id_attribute_group` SEPARATOR \''.pSQL($attribute_separator).'\') as attribute_designation
				FROM `'._DB_PREFIX_.'product_attribute_combination` pac
				LEFT JOIN `'._DB_PREFIX_.'attribute` a ON a.`id_attribute` = pac.`id_attribute`
				LEFT JOIN `'._DB_PREFIX_.'attribute_group` ag ON ag.`id_attribute_group` = a.`id_attribute_group`
				LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)$id_lang.')
				LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)$id_lang.')
				WHERE pac.id_product_attribute IN ('.implode(',', $product_attributes).')
				GROUP BY pac.id_product_attribute');

        foreach ($lang as $k => $row) {
            $combinations[$k]['attribute_designation'] = $row['attribute_designation'];
        }

        //Get quantity of each variations
        foreach ($combinations as $key => $row) {
            $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity';

            if (!Cache::isStored($cache_key)) {
                $result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']);
                Cache::store(
                    $cache_key,
                    $result
                );
                $combinations[$key]['quantity'] = $result;
            } else {
                $combinations[$key]['quantity'] = Cache::retrieve($cache_key);
            }
        }

        return $combinations;
    }

 

Donc merci encore à tous pour vos lectures et votre aide, si jamais ce post peut aider quelqu'un d'autre...

Link to comment
Share on other sites

Code de Phenix pour cette fonction:

    public function getAttributesResume($id_lang, $attribute_value_separator = ' - ', $attribute_separator = ', ')
    {
        if(!Combination::isFeatureActive()) {
            return array();
        }

        $combinations = Db::getInstance()->executeS('
            SELECT pa.*, product_attribute_shop.*
            FROM `'._DB_PREFIX_.'product_attribute` pa
            '.Shop::addSqlAssociation('product_attribute', 'pa').'
            WHERE pa.`id_product` = '.(int)$this->id.'
            GROUP BY pa.`id_product_attribute`
            ORDER BY pa.`id_product_attribute`
        ');

        if(!$combinations) {
            return array();
        }

        $product_attributes = array();
        foreach($combinations as $combination) {
            $product_attributes[] = (int)$combination['id_product_attribute'];
        }

        $lang = Db::getInstance()->executeS('
            SELECT pac.`id_product_attribute`,
                GROUP_CONCAT(agl.`name`, \''.pSQL($attribute_value_separator).'\',
                al.`name`
                ORDER BY agl.`name`
                SEPARATOR \''.pSQL($attribute_separator).'\') as attribute_designation
            FROM `'._DB_PREFIX_.'product_attribute_combination` pac
            INNER JOIN `'._DB_PREFIX_.'attribute` a
                ON(a.`id_attribute` = pac.`id_attribute`)
            INNER JOIN `'._DB_PREFIX_.'attribute_group` ag
                ON(ag.`id_attribute_group` = a.`id_attribute_group`)
            INNER JOIN `'._DB_PREFIX_.'attribute_lang` al
                ON(a.`id_attribute` = al.`id_attribute`
                AND al.`id_lang` = '.(int)$id_lang.')
            INNER JOIN `'._DB_PREFIX_.'attribute_group_lang` agl
                ON(ag.`id_attribute_group` = agl.`id_attribute_group`
                AND agl.`id_lang` = '.(int)$id_lang.')
            WHERE pac.`id_product_attribute` IN ('.implode(',', $product_attributes).')
            GROUP BY pac.`id_product_attribute`
            ORDER BY pac.`id_product_attribute`
        ');

        foreach($lang as $k => $row) {
            $combinations[$k]['attribute_designation'] = $row['attribute_designation'];
        }

        // Get parcels and quantity of each variations
        foreach($combinations as $key => $row) {
            // Parcels
            $combinations[$key]['parcels'] = array();
            $existing_parcels = StockAvailable::getParcels(
                $row['id_product'],
                $row['id_product_attribute']
            );
            if(count($existing_parcels)) {
                $combinations[$key]['parcels'] = $existing_parcels;
            }

            // Quantity
            $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity';

            if(!Cache::isStored($cache_key)) {
                $result = StockAvailable::getQuantityAvailableByProduct(
                    $row['id_product'],
                    $row['id_product_attribute']
                );
                Cache::store(
                    $cache_key,
                    $result
                );
                $combinations[$key]['quantity'] = $result;
            }
            else {
                $combinations[$key]['quantity'] = Cache::retrieve($cache_key);
            }
        }

        return $combinations;
    }

Il vous manque un deuxième ORDER BY pour info^^

  • Thanks 1
Link to comment
Share on other sites

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