de onde vem o is_salable?

27

Nota: Se você estiver editando produtos por código PHP, indexe-os novamente no administrador depois, economize suas horas tentando descobrir por que eles não aparecem como eu abaixo ...

Estou circulando em círculos, tentando descobrir como is_salableestá definido um produto e, assim, descobrir por que meus produtos estão sendo exibidos agora.

Existe apenas um lugar no código que o define:

$salable = $this->isAvailable();

mas não consigo isAvailableentender como e de onde isso ocorre, como quando sigo isso parece voltar ao normal ....

/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();
}

seguindo $ this-> isAvailable () a partir daqui, algumas linhas:

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

isso chama 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;
}

que chama o pai: /app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php's isSalable:

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;
}

que apenas uma chamada tem / recebe dados no valor is_saleable?!? Eu rastreei isso certo? De onde vem esse valor?

Emiti um grep recursivo em minha instalação para is_salable, certamente isso deve mostrar todas as linhas em que está definido, mas não vejo nenhuma imediatamente:

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');

ENCONTRADO:

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);

Era setIsSalable que eu não pensava / sabia procurar, em vez de apenas setIsSalable .

Hayden Thring
fonte

Respostas:

18

isAvailable() se parece com isso:

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

Isso significa que o resultado do método depende do tipo de produto.
Cada tipo de produto possui um isSalable()método:

  • Mage_Catalog_Model_Product_Type_Grouped::isSalable() - para produtos agrupados
  • Mage_Catalog_Model_Product_Type_Configurable::isSalable() - para produtos configuráveis
  • Mage_Catalog_Model_Product_Type_Abstract::isSalable()- para o restante dos tipos de produtos, pois todos os tipos de produtos se estendem Mage_Catalog_Model_Product_Type_Abstract.
    Eu acho que a ligação $this->getTypeInstance(true)te confunde. O método getTypeInstance()não retorna uma instância do modelo do produto, mas uma instância de um tipo de produto.

[EDIT]
Para um produto simples, isso é chamado Mage_Catalog_Model_Product_Type_Grouped::isSalable(). Este método verifica se o produto está ativado. Caso contrário, falseé retornado. Se estiver ativado, verifica se possui uma propriedade is_salableque pode ser definida por um de seus observadores.
Se não tiver essa propriedade, ele verifica se a instância do tipo de produto $this->isComposite(). Se for, então não é vendável.
Para produtos configuráveis, verifica se as condições acima são atendidas e se existe um produto simples associado ao produto configurável vendável (Novamente com as condições acima).
O mesmo é feito para o produto agrupado, mas de uma maneira diferente.

Em conclusão is_salable, não precisa existir. Mas, caso você tenha um observador que defina essa propriedade, ela será levada em consideração ao verificar se o produto pode ser vendido.
Aqui está um exemplo do núcleo: O método Mage_CatalogInventory_Model_Stock_Status::assignProduct()cals $product->setIsSalable()
Mesmo vale Mage_CatalogInventory_Model_Stock_Status::addStockStatusToProducts.
O último é chamado pelo evento catalog_product_collection_load_after.

Marius
fonte
muito obrigado por sua ajuda novamente, eu tinha rastreado isAvailable para isSalable e isSalable de Configurable.php, que apenas chama isSalable de Abstract.php, mas tudo o que faz é verificar 'is_salable', mas não encontro nenhuma configuração dele ?? vou adicionar minha trilha de código acima.
Hayden Thring
adicionado à minha pergunta
Hayden Thring
2
Sim existe. Eu mencionei isso na minha resposta catalog_product_collection_load_after. Mas este é apenas um exemplo. Há também cataloginventory/observer::addInventoryDataque chama assignProductque define is_salable. Poderia haver outros, mas eu não procurei por todos.
Marius
11
Não tenho um método confiável para fazer isso. Talvez obtenha todos os eventos iniciados catalog_product_e depure os métodos chamados pelos observadores nesses eventos. e veja se alguém chama setIsSalableousetData('is_salable')
Marius
11
O XmlConnect permite conectar seu aplicativo móvel ao seu site. Ignore isto.
Marius
2

if for Salable retorna false, Reindexing também pode ter problema de reindexar os dados

Hassan Ali Shahzad
fonte
0

Se após a reindexação e a depuração não puder ser finalizada e o produto configurável ainda estiver fora de estoque, verifique se todos os simples têm o status definido como Ativado, em TODAS as visualizações da loja. Eu perdi duas horas me perguntando por que um configurável estava fora de estoque, não importa o que eu fiz, até verificar todas as visualizações da loja e descobrir que algum corpo havia desativado o status.

David Tay
fonte