d'où vient is_salable?

27

Remarque: Si vous avez modifié des produits par du code PHP, ré-indexez-les ensuite dans l'administrateur, économisez vos heures en essayant de comprendre pourquoi ils ne s'affichent pas comme moi ci-dessous ...

Je tourne en rond en essayant de comprendre comment is_salableest défini pour un produit, et donc pourquoi mes produits s'affichent maintenant.

Il n'y a qu'un seul endroit dans le code que je peux trouver qui le définit:

$salable = $this->isAvailable();

mais je ne peux pas trouver comment ni où cela va isAvailablevenir , car quand je le suis, il semble que ça tourne en rond ...

/app/code/core/Mage/Catalog/Model/Product.php

    public function isSalable()
    {
        Mage::dispatchEvent('catalog_product_is_salable_before', array(
            'product'   => $this
        ));

        $salable = $this->isAvailable();

    $object = new Varien_Object(array(
        'product'    => $this,
        'is_salable' => $salable
    ));
    Mage::dispatchEvent('catalog_product_is_salable_after', array(
        'product'   => $this,
        'salable'   => $object
    ));
    return $object->getIsSalable();
}

suivant $ this-> isAvailable () à partir d'ici, il va quelques lignes:

**public function isAvailable()
{ 
    return $this->getTypeInstance(true)->isSalable($this);
}**

cela appelle ensuite app / code / core / Mage / Catalog / Model / Product / Type / Configurable.php's isSalable

public function isSalable($product = null)
{
    $salable = parent::isSalable($product);

    if ($salable !== false) {
        $salable = false;
        if (!is_null($product)) {
            $this->setStoreFilter($product->getStoreId(), $product);
        }
        foreach ($this->getUsedProducts(null, $product) as $child) {
            if ($child->isSalable()) {
                $salable = true;
                break;
            }
        }
    }

    return $salable;
}

qui appelle le parent: isappel de /app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php:

public function isSalable($product = null)
{
    $salable = $this->getProduct($product)->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_ENABLED;
    if ($salable && $this->getProduct($product)->hasData('is_salable')) {
        $salable = $this->getProduct($product)->getData('is_salable');
    }
    elseif ($salable && $this->isComposite()) {
        $salable = null;
    }

    return (boolean) (int) $salable;
}

qui fait juste un appel has / get data sur la valeur is_saleable?!? Ai-je suivi cela correctement? D'où vient cette valeur?

J'ai émis un grep récursif sur mon installation pour is_salable, cela devrait sûrement montrer toutes les lignes où il est défini mais je n'en vois pas tout de suite:

grep -r is_salable *
app/code/core/Mage/CatalogInventory/Model/Stock/Status.php:            $object = new Varien_Object(array('is_in_stock' => $product->getData('is_salable')));
app/code/core/Mage/XmlConnect/Block/Wishlist.php:                $itemXmlObj->addChild('is_salable', (int)$item->getProduct()->isSalable());
app/code/core/Mage/XmlConnect/Block/Catalog/Product.php:            $item->addChild('is_salable', (int)$product->isSalable());
app/code/core/Mage/XmlConnect/Block/Cart/Crosssell.php:                $itemXmlObj->addChild('is_salable', 0);
app/code/core/Mage/XmlConnect/Block/Cart/Crosssell.php:                $itemXmlObj->addChild('is_salable', (int)$product->isSalable());
app/code/core/Mage/Catalog/Model/Product.php:        Mage::dispatchEvent('catalog_product_is_salable_before', array(
app/code/core/Mage/Catalog/Model/Product.php:            'is_salable' => $salable
app/code/core/Mage/Catalog/Model/Product.php:        Mage::dispatchEvent('catalog_product_is_salable_after', array(
app/code/core/Mage/Catalog/Model/Product.php:        if ($this->hasData('is_salable')) {
app/code/core/Mage/Catalog/Model/Product.php:            return $this->getData('is_salable');
app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php:        if ($salable && $this->getProduct($product)->hasData('is_salable')) {
app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php:            $salable = $this->getProduct($product)->getData('is_salable');

A TROUVÉ:

grep -r setIsSalable *
app/code/core/Mage/CatalogInventory/Model/Stock/Status.php:        $product->setIsSalable($stockStatus);
app/code/core/Mage/CatalogInventory/Model/Stock/Status.php:                    $product->setIsSalable($status);

C'était setIsSalable que je ne pensais pas / ne savais pas chercher plutôt que setIsSalable .

Hayden Thring
la source

Réponses:

18

isAvailable() ressemble à ça:

public function isAvailable()
{
    return $this->getTypeInstance(true)->isSalable($this)
        || Mage::helper('catalog/product')->getSkipSaleableCheck();
}

Cela signifie que le résultat de la méthode dépend du type de produit.
Chaque type de produit a une isSalable()méthode:

  • Mage_Catalog_Model_Product_Type_Grouped::isSalable() - pour les produits groupés
  • Mage_Catalog_Model_Product_Type_Configurable::isSalable() - pour les produits configurables
  • Mage_Catalog_Model_Product_Type_Abstract::isSalable()- pour le reste des types de produits puisque tous les types de produits s'étendent Mage_Catalog_Model_Product_Type_Abstract.
    Je pense que l'appel $this->getTypeInstance(true)vous embrouille. La méthode getTypeInstance()ne renvoie pas une instance du modèle de produit, mais une instance d'un type de produit.

[EDIT]
Pour un produit simple, cela s'appelle Mage_Catalog_Model_Product_Type_Grouped::isSalable(). Cette méthode vérifie si le produit est activé. Sinon, il falseest renvoyé. S'il est activé, il vérifie s'il possède une propriété is_salablequi peut être définie par l'un de vos observateurs.
S'il ne possède pas une telle propriété, il vérifie si l'instance de type de produit $this->isComposite(). Si c'est le cas, ce n'est pas vendable.
Pour les produits configurables, il vérifie si les conditions ci-dessus sont remplies et s'il existe un produit simple associé au produit configurable qui est vendable (Encore une fois avec les conditions ci-dessus)
La même chose est faite pour le produit groupé mais d'une manière différente.

En conclusion is_salablene doit pas exister. Mais juste au cas où vous avez un observateur qui définit cette propriété, il est pris en considération lors de la vérification si le produit peut être vendu.
Voici un exemple du noyau: La méthode Mage_CatalogInventory_Model_Stock_Status::assignProduct()cals $product->setIsSalable()
va de même Mage_CatalogInventory_Model_Stock_Status::addStockStatusToProducts.
Le dernier est appelé par l'événement catalog_product_collection_load_after.

Marius
la source
merci beaucoup pour votre aide, j'ai retracé isAvailable à isSalable et à Configurable.php's isSalable qui appelle simplement isSalable de Abstract.php mais il ne fait que cocher 'is_salable' mais je ne trouve aucun paramètre de celui-ci ?? j'ajouterai ma piste de code ci-dessus.
Hayden Thring
ajouté à ma question
Hayden Thring
2
Oui il y a. Je l'ai mentionné dans ma réponse catalog_product_collection_load_after. Mais ce n'est qu'un exemple. Il y a aussi cataloginventory/observer::addInventoryDataque les appels assignProductque les ensembles is_salable. Il pourrait y en avoir d'autres mais je ne cherchais pas tout.
Marius
1
Je n'ai pas de méthode fiable pour le faire. Peut-être obtenir tous les événements qui commencent par catalog_product_et déboguer les méthodes appelées par les observateurs sur ces événements. et voyez si on appelle setIsSalableousetData('is_salable')
Marius
1
XmlConnect vous permet de connecter votre application mobile à votre site Web. Ignorez-le.
Marius
2

si est vendable renvoie faux, la réindexation peut également avoir un problème de réindexation des données

Hassan Ali Shahzad
la source
0

Si, après réindexation et débogage, is_salable to no end et que votre produit configurable s'affiche toujours en rupture de stock, assurez-vous que tous les simples ont le statut défini sur Enabled, dans TOUTES les vues du magasin. J'ai juste perdu deux heures à me demander pourquoi un configurable était en rupture de stock, peu importe ce que je faisais, jusqu'à ce que je vérifie toutes les vues du magasin et découvre qu'un organisme a désactivé le statut.

David Tay
la source