craftcms / commerce

Fully integrated ecommerce for Craft CMS.
https://craftcms.com/commerce
Other
215 stars 169 forks source link

[5.x]: Updating the stock programmatically no longer possible #3558

Closed youwebmax closed 2 days ago

youwebmax commented 4 days ago

What happened?

Description

It is mentioned in the changelog that the attribute $stock is no longer available on craft\commerce\elements\Variant.

Removed craft\commerce\elements\Variant::$stock. craft\commerce\base\Purchasable::getStock() can be used instead. (https://github.com/craftcms/commerce/blob/5.x/CHANGELOG.md)

The alternative getStock() is of no use to us, since we need to set the stock. With a regular cronjob we fetch the stock in our custom Craft CMS plugin from an external inventory system and replace the stock in Craft Commerce with the updated value.

Steps to reproduce

  1. $variant->stock = 25;

Expected behavior

The stock of the variant is updated.

Since there is now a multi store inventory management in Craft Commerce I understand it might not be possible to use the simple $stock property anymore. Is there any other way to update the stock in our custom Craft CMS plugin?

Actual behavior

Setting the stock is not possible: Setting read-only property: craft\\commerce\\elements\\Variant::stock

Craft CMS version

5.2.4.1

Craft Commerce version

5.0.11.1

PHP version

8.2.20

Operating system and version

Linux 6.4.16-linuxkit

Database type and version

MariaDB 10.5.9

Image driver and version

Imagick 3.7.0 (ImageMagick 6.9.10-23)

Installed plugins and versions

No response

linear[bot] commented 4 days ago

PT-1903 [5.x]: Updating the stock programmatically no longer possible

lukeholder commented 2 days ago

To update the inventory for a variant, the variant needs to be saved so that the inventory item is created for it. You can then update the inventory into a specific location like this:

        use craft\commerce\collections\UpdateInventoryLevelCollection;
        use craft\commerce\models\inventory\UpdateInventoryLevel;

        $commercePlugin = Commerce::getInstance();
        $variants = []; // get your variants

        $updateInventoryLevels = UpdateInventoryLevelCollection::make();
        foreach ($variants as $variant) {
            if ($inventoryItem = $commercePlugin->getInventory()->getInventoryItemByPurchasable($variant)) {
                /** In this example we are only updating stock in the first inventory location for this variant */
                /** @var InventoryLevel $firstInventoryLevel */
                $firstInventoryLevel = $commercePlugin->getInventory()->getInventoryLevelsForPurchasable($variant)->first();
                if ($firstInventoryLevel && $firstInventoryLevel->getInventoryLocation()) {
                    $stock = 1; // stock amount
                    $updateInventoryLevels->push(new UpdateInventoryLevel([
                            'type' => \craft\commerce\enums\InventoryTransactionType::AVAILABLE->value,
                            'updateAction' => \craft\commerce\enums\InventoryUpdateQuantityType::SET,
                            'inventoryItem' => $inventoryItem,
                            'inventoryLocation' => $firstInventoryLevel->getInventoryLocation(),
                            'quantity' => $stock,
                            'note' => '',
                        ])
                    );
                }
            }
        }

        if ($updateInventoryLevels->count() > 0) {
            commercePlugin->getInventory()->executeUpdateInventoryLevels($updateInventoryLevels);
        }