Create coupon code programmatically (in Magento 2.x)

I'm trying to port over tens of thousands of coupons from a custom e-commerce website into Magento 2.0.8 and I'm having a hard time getting it to work. These are simple coupons either fixed $ or % off of the carts subtotal. I have been unable to get it to save from the command line.

I have a command called coupons:migrate that I'm running this code in. This is what I have so far in my createCoupon method that accepts the current coupons row (looping over a CSV file):

protected function createCoupon($coupon) {
        $shoppingCartPriceRule = $this->objectManager->create('Magento\SalesRule\Model\Rule');

        $shoppingCartPriceRule->setName($coupon['name'])
            ->setDescription($coupon['name'])
            ->setFromDate($coupon['start'])
            ->setToDate($coupon['end'])
            ->setUsesPerCustomer($coupon['max_redemptions'])
            ->setCustomerGroupIds(array('0','1','2','3',))
            ->setIsActive('1')
            ->setSimpleAction($coupon['discount_type'])
            ->setDiscountAmount($coupon['discount_amount'])
            ->setDiscountQty(1)
            ->setApplyToShipping($coupon['flag_is_free_shipping'])
            ->setTimesUsed($coupon['redemptions'])
            ->setWebsiteIds(array('1',))
            ->setCouponType('2')
            ->setCouponCode($coupon['code'])
            ->setUsesPerCoupon(NULL);

    return $shoppingCartPriceRule->save();

}

I'm currently getting this error from my database:

[Zend_Db_Statement_Exception]
  SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction, query was: INSERT INTO `magento_reward_salesrule` (`rule_id`,`points_delta`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `points_delta` = VALUES
  (`points_delta`)

  [PDOException]
  SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction

Any help would be greatly appreciated. I'm basically stuck now.

Solutions

You can try below code:

protected $ruleFactory

public function __construct(\Magento\SalesRule\Model\RuleFactory $ruleFactory) {
    $this->rulesFactory = $ruleFactory }


$ruleData = [
            "name" => "Buy 3 tee shirts and get the 4th free",
            "description" => "Buy 3 tee shirts and get the 4th free",
            "from_date" => null,
            "to_date" => null,
            "uses_per_customer" => "0",
            "is_active" => "1",
            "stop_rules_processing" => "0",
            "is_advanced" => "1",
            "product_ids" => null,
            "sort_order" => "0",
            "simple_action" => "buy_x_get_y",
            "discount_amount" => "1.0000",
            "discount_qty" => null,
            "discount_step" => "3",
            "apply_to_shipping" => "0",
            "times_used" => "0",
            "is_rss" => "1",
            "coupon_type" => "NO_COUPON",
            "use_auto_generation" => "0",
            "uses_per_coupon" => "0",
            "simple_free_shipping" => "0",
            "customer_group_ids" => [0, 1, 2, 3],
            "website_ids" => [1],
            "coupon_code" => null,
            "store_labels" => [],
            "conditions_serialized" => '',
            "actions_serialized" => ''
        ];

$ruleModel = $this->ruleFactory->create();
$ruleModel->setData($ruleData);
$ruleModel->save();

Try code below

$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); 
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('adminhtml');  

$coupon['name'] = 'test';
$coupon['desc'] = 'Discount for Test';
$coupon['start'] = date('Y-m-d');
$coupon['end'] = '';
$coupon['max_redemptions'] = 1;
$coupon['discount_type'] = 'by_percent';
$coupon['discount_amount'] = 15;
$coupon['flag_is_free_shipping'] = 'no';
$coupon['redemptions'] = 1;
$coupon['code'] = 'test-1234'; //this code will normally be autogenetated but i am hard coding for testing purposes

$shoppingCartPriceRule = $objectManager->create('Magento\SalesRule\Model\Rule');
$shoppingCartPriceRule->setName($coupon['name'])
    ->setDescription($coupon['desc'])
    ->setFromDate($coupon['start'])
    ->setToDate($coupon['end'])
    ->setUsesPerCustomer($coupon['max_redemptions'])
    ->setCustomerGroupIds(array('0','1','2','3',))
    ->setIsActive(1)
    ->setSimpleAction($coupon['discount_type'])
    ->setDiscountAmount($coupon['discount_amount'])
    ->setDiscountQty(1)
    ->setApplyToShipping($coupon['flag_is_free_shipping'])
    ->setTimesUsed($coupon['redemptions'])
    ->setWebsiteIds(array('1'))
    ->setCouponType(2)
    ->setCouponCode($coupon['code'])
    ->setUsesPerCoupon(NULL);
$shoppingCartPriceRule->save();

I don't try to test your code, however, seem that your code lines need to improve the performance. After saving the object model, we need to unset the data object:

$shoppingCartPriceRule->save()
$shoppingCartPriceRule->unsetData(); 

Similar questions

How to get coupon times used with coupon code using REST Api?
I have no experience with Magento. I was asigned the task to validate a coupon code via magento rest api. I've tried to use /V1/coupons/search GET method. My request url is: However, my java based server receives a 500 status response. I've also tried to make a curl request like this: curl -X GET --header "Authorization: Bearer some-token-string" H...
How to remove particular coupon code if other cart rule without specific coupon is applied on product in magento2?
condition 1: I have 2 cart rule which are directly applied on product if specific conditions are true as given in cart rule. condition 2: there is an another cart rule in which i have added one coupon code "10OFF" for all products. Question is that if for particular product one cart rule is already applied then i want to remove coupon code because ...
how to apply only 1 coupon code when there are multiples coupon codes
I am running magento 1.9 and i have multiple coupon codes on site. how to make that only 1 coupon code apply on cart? any body know how to apply on 1 coupon on cart?
How to apply an existing coupon code programmatically in Magento 2
I try to apply an existing coupon code programmatically in a controller by coupon id. The only thing I found these code lines for Magento 1. Does anyone know how can I do this in magento 2?
Magento 2 get Store Id of a coupon code programmatically
I am using multiple stores, I wanted to get all the coupon code of a particular store. In Magento 2 database, salesrule_website table have stores related information, but their is no model/collection to get the data from this table. Please guide me how to get store information of a coupon code, or I need to create my own model for salesrule_website...
Magento 2: Apply coupon code programmatically
I want to apply coupon code programmatically when the condition is true. If condition false coupon code should be not applied. Please help me.

Also ask

We use cookies to deliver the best possible experience on our website. By continuing to use this site, accepting or closing this box, you consent to our use of cookies. To learn more, visit our privacy policy.