cancel
Showing results for 
Search instead for 
Did you mean: 

Magento 2: Creating cart rules programatically using ObjectManager, Factories or Interfaces.

Magento 2: Creating cart rules programatically using ObjectManager, Factories or Interfaces.

Over the last few days I have felt an increasing level of frustration as I troubleshoot the attempted development of a new module.

The module has a custom console command which is supposed to generate a cart rule for a 5% discount, applied to the SKU provided as an argument to the command.

I have made a few posts in the magento stackexchange about this and was told,  part-way through developing my first solution, that factories are no longer the protocol and that I must use interfaces. So, I re-wrote the command to use interfaces.

I was receiving all kinds of weird and wonderful errors from the server, before I discovered that interfaces do not properly support cart-rule creation yet. So, I then attempted to solve the problem with object manager. Now I can't work out whether or not the code is working because I receive the 'Area code not set' error whenever I attempt to run magento commands with the module installed.

I have attempted every permutation of setting the area code that I have been able to find online nut I still receive the error. Although, as far as all examples I've found of working imply, I should not even need to set the area code on my command.

Code I have so far is as follows:

<?php
/**
 * Copyright (c) 2018 Joshua Flood. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace [Vendor_name]\[Module_name]\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

use Magento\Framework\App\Action\Context;
use Magento\Framework\ObjectManagerInterface;

use Magento\SalesRule\Api\RuleRepositoryInterface;
use Magento\SalesRule\Api\Data\ConditionInterface;

/**
 * Class WeeklyDiscountCommand
 */
class WeeklyDiscountCommand extends Command
{
    /**
     * SKU argument
     */
    const SKU_ARGUMENT = 'sku';
    /**
     * @var \Magento\Framework\App\State
     */
    protected $appState;
    /**
     * @var Context
     */
    protected $context;
    /**
     * @var ObjectManagerInterface
     */
    protected $_objectManager;
    /**
     * @var RuleRepositoryInterface
     */
    protected $ruleRepository;
    /**
     * @var ConditionInterface
     */
    protected $condition;

    public function __construct(
        \Magento\Framework\App\State $appState,
        Context $context,
        ObjectManagerInterface $_objectManager,
        RuleRepositoryInterface $ruleRepository,
        ConditionInterface $condition
    ) {
        $appState->setAreaCode('admin');
        parent::__construct($context);
        $this->_objectManager = $_objectManager;
        $this->ruleRepository = $ruleRepository;
        $this->condition = $condition;
    }


    public function createRule($sku)
    {
        $discount = '5';
        $salesRule = $this->objectManager->create('Magento\SalesRule\Model\Rule');

        $salesRule->setName('JoshuaFlood_DiscountGenerator')
            ->setDescription('Do not delete! Current product sku - ' .$sku)
            ->setFromDate(NULL)
            ->setToDate(NULL)
            ->setUsesPerCustomer('0')
            ->setCustomerGroupIds(array('0','1','2','3',))
            ->setIsActive('1')
            ->setStopRulesProcessing('0')
            ->setIsAdvanced('1')
            ->setProductIds(NULL)
            ->setSortOrder('1')
            ->setSimpleAction('by_percent')
            ->setDiscountAmount($discount)
            ->setDiscountQty(NULL)
            ->setDiscountStep('0')
            ->setSimpleFreeShipping('0')
            ->setApplyToShipping('0')
            ->setTimesUsed('0')
            ->setIsRss('0')
            ->setWebsiteIds(array('1',))
            ->setCouponType('1')
            ->setCouponCode('WEEKLY5')
            ->setUsesPerCoupon(NULL);

        $item_found = $this->objectManager->create('Magento\SalesRule\Model\Rule\Condition\Product\Found')
            ->setType('Magento\SalesRule\Model\Rule\Condition\Product\Found')
            ->setValue(1) // 1 == FOUND
            ->setAggregator('all'); // match ALL conditions
        $salesRule->getConditions()->addCondition($item_found);
        $conditions = $this->objectManager->create('Magento\SalesRule\Model\Rule\Condition\Product')
            ->setType('Magento\SalesRule\Model\Rule\Condition\Product')
            ->setAttribute('sku')
            ->setOperator('==')
            ->setValue($sku);
        $item_found->addCondition($conditions);

        $actions = $this->objectManager->create('Magento\SalesRule\Model\Rule\Condition\Product')
            ->setType('Magento\SalesRule\Model\Rule\Condition\Product')
            ->setAttribute('sku')
            ->setOperator('==')
            ->setValue($sku);
        $salesRule->getActions()->addCondition($actions);

        $salesRule->save();
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('discountgenerator:weeklydiscount')
            ->setDescription('Re-assign weekly discount to SKU provided in argument.')
            ->setDefinition([
                new InputArgument(
                    self:Smiley FrustratedKU_ARGUMENT,
                    InputArgument::REQUIRED,
                    'SKU'
                ),

            ]);

        parent::configure();
    }
    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $sku = $input->getArgument(self:Smiley FrustratedKU_ARGUMENT);
        if (is_null($sku)) {
            throw new \InvalidArgumentException('Argument ' . self:Smiley FrustratedKU_ARGUMENT . ' is missing.');
        }

        try{
            $this->createRule($sku);
        } catch(Exception $e) {
            echo 'Failed to create rule: ',  $e->getMessage(), "\n";
        }

        $output->writeln('<info>Weekly discount created for product: ' . $sku . '!</info>');
    }
}