我们都知道,Magento以一种直接的方式处理产品库存。数据库中只有一个“warehouse”,一个库存,一个“number”负责最终决定权 - 库存的数量。其他大部分功能依赖于全局库存。如果我们从产品管理中检查Advanced inventory配置,我们会注意到所有选项都是全局的:Out of stock thresholdMinimum and maximum qty allowed in Shopping Cartbackordersnotifications等

虽然这是完全正常的——具有全局库存,需要大多数功能与其相关,也需要全局设置,但可能会出现这样的情况,即我们需要一些功能来处理不同的范围(例如网站或商店视图范围)。这样的例子就是延期交货,一个简单的功能,来允许客户购买没有库存的产品。 这会使数量进一步减少为负值,例如-5。

我们是否可以将此功能扩展到全球范围之外,并将其用于网站级别?事实证明我们可以,而且变化不大。

为了研究这一点,我们需要将更多的商品添加到购物车中。通过这样做,我们最终(省略了几个简短的步骤)vendor/magento/module-catalog-inventory/Model/StockStateProvider.php

/**
     * Check quantity
     *
     * @param StockItemInterface $stockItem
     * @param int|float $qty
     * @exception \Magento\Framework\Exception\LocalizedException
     * @return bool
     */
    public function checkQty(StockItemInterface $stockItem, $qty)
    {
        if (!$this->qtyCheckApplicable) {
            return true;
        }
        if (!$stockItem->getManageStock()) {
            return true;
        }
        if ($stockItem->getQty() - $stockItem->getMinQty() - $qty < 0) {
            switch ($stockItem->getBackorders()) {
                case \Magento\CatalogInventory\Model\Stock::BACKORDERS_YES_NONOTIFY:
                case \Magento\CatalogInventory\Model\Stock::BACKORDERS_YES_NOTIFY:
                    break;
                default:
                    return false;
            }
        }
        return true;
    }

这样做是检查qty我们是否想要购买。如果不是,它会对延期交货功能进行检查,从而进一步引导我们vendor/magento/module-catalog-inventory/Model/Configuration.php,用于从数据库(core_config_data)中检索延期交货信息。

/**
     * Retrieve backorders status
     *
     * @param null|string|bool|int|\Magento\Store\Model\Store $store
     * @return int
     */
    public function getBackorders($store = null)
    {
        return (int) $this->scopeConfig->getValue(
            self::XML_PATH_BACKORDERS,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
            $store
        );
    }

要注意的有趣的事情是在获取配置细节时传递的$Stand变量。因此,Magento正在寻找数据库中延期交货设置的范围值,但由于没有,因此返回全局范围的值。如果我们将此配置的范围从全局更改为网站会怎么样?我们试试吧。

  1. 制作一个简单的Magento 2模块
  2. 创建一个文件 app\code\Your_Vendor\Your_Module\etc\adminhtml\system.xml

内容如下:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="cataloginventory" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
            <group id="item_options" translate="label comment" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <field id="backorders" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
                    <label>Backorders</label>
                    <source_model>Magento\CatalogInventory\Model\Source\Backorders</source_model>
                    <backend_model>Magento\CatalogInventory\Model\Config\Backend\Backorders</backend_model>
                    <comment>Changing can take some time due to processing whole catalog.</comment>
                </field>
            </group>
        </section>
    </system>
</config>

 

我们刚刚复制了位于ven./magento/module-catalog-./etc/adminhtml/system.xml的核心配置,并将showInWebsite从0更新为1。现在我们有一个网站上的备份订单的配置。

我们刚刚复制位于vendor/magento/module-catalog-inventory/etc/adminhtml/system.xml的核心配置,并将showInWebsite从0更新为1,现在我们有一个网站级别的延期交货配置。

这里的更改产生了一些影响:

  1. 显然,我们可以在网站级别设置后台功能
  2. 由于仍然只有1个库存,我们需要确保打开缺省的订单范围,因为cataloginventory_stockstatus indexer使用该范围来正确设置状态
  3. 如果启用了默认配置(如第2点所示),则所有产品在前端都是“可用”,这并非我们所希望的(“Add to cart”按钮将随处可见)

值得庆幸的是,Magento提供了一些方便的事件,我们可以监听以“修复”那些没有启用bacorder的库存状态。

vendor/magento/module-catalog/Model/Product.php中isSalable()方法,从前端调用(在决定是否应显示“add-to-cart”按钮时)。据调度catalog_product_is_salable_beforecatalog_product_is_salable_after,我们可以使用,和显示产品为“不实用”,如果他们。

我们可以使用catalog_product_is_salable_before和catalog_product_is_salable_after事件,将未启用延期交货的功能的店铺里的产品显示为“不可销售的”

/**
     * Check is product available for sale
     *
     * @return bool
     */
    public function isSalable()
    {
        // ...
 
        <strong>$this->_eventManager->dispatch('catalog_product_is_salable_before', ['product' => $this]);</strong>
 
        $salable = $this->isAvailable();
 
        $object = new \Magento\Framework\DataObject(['product' => $this, 'is_salable' => $salable]);
 
        <strong>$this->_eventManager->dispatch(
            'catalog_product_is_salable_after',
            ['product' => $this, 'salable' => $object]
        );</strong>
 
        // ...
    }

 

我们可以创建一个自定义观察器,该观察器将监听这些事件之一,并在qty <= 0或者店铺未启用延期交货时将product设置为不可销售($product->setIsSalable(false)

就是这样 - 在配置上的一个小更改,以及一个自定义的观察器,就能确保所有数据都正确显示,使我们能够在网站范围内拥有延期交货功能。