1

I am migrating code from Magento1 to Magento2 and need to create a group of sales rules programatically. I need to do this because it's based on the price of the item, plus $1 if they purchase two (buy one at full price, get a second for $1).

I was previously able to accomplish this using this code. I am wondering how one would go about it under Magento2?

        $discount = ($price - (($price + 1) / 2));
        $shoppingCartPriceRule = Mage::getModel('salesrule/rule');

        $shoppingCartPriceRule->setName('Add a second for $1 - ' . $sku)
        ->setDescription('Buy one item at regular price, and receive a second item for just $1.00 more!')
        ->setFromDate('2000-01-01')
        ->setToDate(NULL)
        ->setUsesPerCustomer('0')
        ->setCustomerGroupIds(array('0','1','2','3',))
        ->setIsActive('1')
        ->setStopRulesProcessing('0')
        ->setIsAdvanced('1')
        ->setProductIds(NULL)
        ->setSortOrder('1')
        ->setSimpleAction('by_fixed')
        ->setDiscountAmount($discount)
        ->setDiscountQty(NULL)
        ->setDiscountStep('0')
        ->setSimpleFreeShipping('0')
        ->setApplyToShipping('0')
        ->setTimesUsed('0')
        ->setIsRss('0')
        ->setWebsiteIds(array('1',))
        ->setCouponType('1')
        ->setCouponCode(NULL)
        ->setUsesPerCoupon(NULL);   

        // Add Sku Condition
        $skuCond = Mage::getModel('salesrule/rule_condition_product')
               ->setType('salesrule/rule_condition_product')
               ->setAttribute('sku')
               ->setOperator('==')
               ->setValue($sku);
        $shoppingCartPriceRule->getActions()->addCondition($skuCond);               

        // Add Qty Condition
        $qtyCond = Mage::getModel('salesrule/rule_condition_product')
               ->setType('salesrule/rule_condition_product')
               ->setAttribute('quote_item_qty')
               ->setOperator('()')
               ->setValue('2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96');
        $shoppingCartPriceRule->getActions()->addCondition($qtyCond);                 

Thank you!

7

If you have object manager then you can go with following example code

$price = 100;
$sku = '24-WG085';
$discount = ($price - (($price + 1) / 2));
$shoppingCartPriceRule = $this->_objectManager->create('Magento\SalesRule\Model\Rule');

$shoppingCartPriceRule->setName('Add a second for $1 - ' . $sku)
    ->setDescription('Buy one item at regular price, and receive a second item for just $1.00 more!')
    ->setFromDate('2000-01-01')
    ->setToDate(NULL)
    ->setUsesPerCustomer('0')
    ->setCustomerGroupIds(array('0','1','2','3',))
    ->setIsActive('1')
    ->setStopRulesProcessing('0')
    ->setIsAdvanced('1')
    ->setProductIds(NULL)
    ->setSortOrder('1')
    ->setSimpleAction('by_fixed')
    ->setDiscountAmount($discount)
    ->setDiscountQty(NULL)
    ->setDiscountStep('0')
    ->setSimpleFreeShipping('0')
    ->setApplyToShipping('0')
    ->setTimesUsed('0')
    ->setIsRss('0')
    ->setWebsiteIds(array('1',))
    ->setCouponType('1')
    ->setCouponCode(NULL)
    ->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
$shoppingCartPriceRule->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);
$shoppingCartPriceRule->getActions()->addCondition($actions);

// Add Qty Condition
$qtyCond = $this->_objectManager->create('Magento\SalesRule\Model\Rule\Condition\Product')
    ->setType('Magento\SalesRule\Model\Rule\Condition\Product')
    ->setAttribute('quote_item_qty')
    ->setOperator('()')
    ->setValue('2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96');
$shoppingCartPriceRule->getActions()->addCondition($qtyCond);

$shoppingCartPriceRule->save();

Otherwise create a object manager using DI

/**
 * @var \Magento\Framework\ObjectManagerInterface
 */
protected $_objectManager;

public function __construct(
    \Magento\Framework\ObjectManagerInterface $_objectManager
) {
    $this->_objectManager = $_objectManager;
}
  • 1
    You shouldn't use the object manager directly, it's preferrable to use a factory class. – Mir Oct 10 '16 at 12:25
  • @Sohel Rana this is very useful answer. – Sarvesh Tiwari Mar 23 '18 at 14:38
  • @sohel, i got the following error while set the voucher to the particular sku Call to a member function setOperator() on null. then how can i assign this coupon to more than one sku and particular attribute – senthil Mar 11 at 13:18
  • @senthil Sir how can we apply this coupon on the specific products?? Like I want to apply this on product ID 1,2,3 only how can I apply this? – Asad Khan Mar 29 at 14:28
  • Sir I followed your code same it is but it gives me the error Uncaught Error: Call to a member function setOperator() on null how to solve this and what is the problem in the code? – Asad Khan Apr 3 at 11:09
5

Sohel Rana's answer is excellent. To answer Mir's point, here is an example of how DI would be used to bring in the relevant classes in a class context, this is a small tweak to the accepted answer:

protected $ruleFactory;
protected $productRuleFactory;
protected $foundProductRuleFactory;
protected $ruleResource;

public function __construct(
    \Magento\SalesRule\Model\RuleFactory $ruleFactory,
    \Magento\SalesRule\Model\Rule\Condition\ProductFactory $productRuleFactory,
    \Magento\SalesRule\Model\Rule\Condition\Product\FoundFactory $foundProductRuleFactory,
    \Magento\SalesRule\Model\ResourceModel\Rule $ruleResource
) {
    $this->ruleFactory = $ruleFactory;
    $this->productRuleFactory = $productRuleFactory;
    $this->foundProductRuleFactory = $foundProductRuleFactory;
    $this->ruleResource = $ruleResource;
}

public function createRule()
{
    $price = 100;
    $sku = '24-WG085';
    $discount = ($price - (($price + 1) / 2));
    $shoppingCartPriceRule = $this->ruleFactory->create();

    $shoppingCartPriceRule->setName('Add a second for $1 - ' . $sku)
        ->setDescription('Buy one item at regular price, and receive a second item for just $1.00 more!')
        ->setFromDate('2000-01-01')
        ->setToDate(NULL)
        ->setUsesPerCustomer('0')
        ->setCustomerGroupIds(array('0','1','2','3',))
        ->setIsActive('1')
        ->setStopRulesProcessing('0')
        ->setIsAdvanced('1')
        ->setProductIds(NULL)
        ->setSortOrder('1')
        ->setSimpleAction('by_fixed')
        ->setDiscountAmount($discount)
        ->setDiscountQty(NULL)
        ->setDiscountStep('0')
        ->setSimpleFreeShipping('0')
        ->setApplyToShipping('0')
        ->setTimesUsed('0')
        ->setIsRss('0')
        ->setWebsiteIds(array('1',))
        ->setCouponType('1')
        ->setCouponCode(NULL)
        ->setUsesPerCoupon(NULL);

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

    $conditions = $this->productRuleFactory->create()
        ->setType('Magento\SalesRule\Model\Rule\Condition\Product')
        ->setAttribute('sku')
        ->setOperator('==')
        ->setValue($sku);
    $item_found->addCondition($conditions);

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

    // Add Qty Condition
    $qtyCond = $this->productRuleFactory->create()
        ->setType('Magento\SalesRule\Model\Rule\Condition\Product')
        ->setAttribute('quote_item_qty')
        ->setOperator('()')
        ->setValue('2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96');
    $shoppingCartPriceRule->getActions()->addCondition($qtyCond);

    $this->ruleResource->save($shoppingCartPriceRule);
}

The original save statement will work fine, but Magento have depreciated the direct save, so it's more correct to save via the resource model.

  • i am getting "Uncaught Error: Call to a member function setOperator() on null", then how can i set the multiple sku in this code – senthil Mar 11 at 15:20
  • I fixed the issue and the coupon is created, but while apply the coupon to the cart page, it's showing 'The coupon code couldn't be applied. Verify the coupon code and try again' – senthil Mar 14 at 6:41
  • Sir I followed your code same it is but it gives me the error Uncaught Error: Call to a member function setOperator() on null how to solve this and what is the problem in the code? – Asad Khan Apr 3 at 11:08
  • Keep in mind that this answer was correct in 2016 when Magento was at version 2.0, so this is likely a little out of date. – Robert Egginton Apr 12 at 10:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.