Magento 2: Create a cart price rule with conditions programmatically (for coupons)
Pregunta
I want to generate a coupon, when a new user registrates on the website. For that, I use this module, which works very well:
https://github.com/php-cuong/magento2-newsletter-coupon-code
In this module the coupon code is generated when the user subscribes to the newsletter. The code for the generation can be found under magento2-newsletter-coupon-code/Model/Subscriber.php and it looks like this:
protected function generateCouponCode()
{
try {
$couponData = [];
$couponData['name'] = '$5 Gift Voucher Newsletter Subscription ('.$this->getEmail().')';
$couponData['is_active'] = '1';
$couponData['simple_action'] = 'by_fixed';
$couponData['discount_amount'] = '5';
$couponData['from_date'] = date('Y-m-d');
$couponData['to_date'] = '2019-12-31 23:59:59';
$couponData['uses_per_coupon'] = '1';
$couponData['coupon_type'] = '2';
$couponData['customer_group_ids'] = $this->getCustomerGroupIds();
$couponData['website_ids'] = $this->getWebsiteIds();
/** @var \Magento\SalesRule\Model\Rule $rule */
$rule = $this->_getSalesRule();
$couponCode = $rule->getCouponCodeGenerator()->setLength(4)->setAlphabet(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
)->generateCode().'SUBNEW';
$couponData['coupon_code'] = $couponCode;
$rule->loadPost($couponData);
$rule->save();
return $couponCode;
} catch (\Exception $e) {
return null;
}
}
Now I know from this post ( Magento 2: Programmatically create & apply shopping cart rule ) that in order to add a condition for the generated coupon, I have to add
"conditions_serialized" => '',
"actions_serialized" => ''
So I added them and it looks like this, but it doesn't work for some reason:
protected function generateCouponCode()
{
try {
$couponData = [];
$couponData['name'] = '2€ Newsletter Anmeldung ('.$this->getEmail().')';
$couponData['is_active'] = '1';
$couponData['simple_action'] = 'by_fixed';
$couponData['discount_amount'] = '2';
$couponData['from_date'] = date('Y-m-d');
$couponData['to_date'] = '2029-12-31 23:59:59';
$couponData['uses_per_coupon'] = '1';
$couponData['coupon_type'] = '2';
$couponData['customer_group_ids'] = $this->getCustomerGroupIds();
$couponData['website_ids'] = $this->getWebsiteIds();
/** @var \Magento\SalesRule\Model\Rule $rule */
$rule = $this->_getSalesRule();
$couponCode = $rule->getCouponCodeGenerator()->setLength(12)->setAlphabet(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
)->generateCode().'NEWABO';
$couponData['coupon_code'] = $couponCode;
$couponData['conditions_serialized'] = '{"type":"Magento\\SalesRule\\Model\\Rule\\Condition\\Combine","attribute":null,"operator":null,"value":"1","is_value_processed":null,"aggregator":"all","conditions":[{"type":"Magento\\SalesRule\\Model\\Rule\\Condition\\Address","attribute":"base_subtotal","operator":">=","value":"50","is_value_processed":false}]}';
$couponData['actions_serialized'] = '{"type":"Magento\\SalesRule\\Model\\Rule\\Condition\\Product\\Combine","attribute":null,"operator":null,"value":"1","is_value_processed":null,"aggregator":"all"}';
$rule->loadPost($couponData);
$rule->save();
return $couponCode;
} catch (\Exception $e) {
return null;
}
}
I got the string for the conditions_serialized and the actions_serialized by creating the a coupon in the admin backend and then looking for it in the database in the colum of the salesrule table:
With this setup, I still get an error message, when I try to register as a new user. Does anyone have an idea what I did wrong?
Thanks for your help and your time!
No hay solución correcta
Otros consejos
In my opinion, this module is ~okay~ but not ideal. Firstly, because it will create a brand new sales rule every time someone subscribes to your newsletter - this means it will create more work for you if you ever want to clean up your sales rules.
A better solution would be to change this function entirely so that it loads a rule you have already created in the admin panel. That way, you can define the desired conditions in the rule beforehand, then when someone subscribes, the function will generate a coupon code against the existing rule.
You'll need to add to your construct these dependencies:
\Magento\SalesRule\Api\RuleRepositoryInterface $ruleRepository, \Magento\SalesRule\Model\CouponGenerator $couponGenerator,
e.g.
/**
* Generate single coupon code
*
* @return string
*/
protected function generateCouponCode()
{
$ruleId = 1; //enter your rule Id here
$rule = $this->_ruleRepository->getById($ruleId);
$data = [
'rule_id' => $rule->getRuleId(),
'qty' => '1',
'length' => '8', //change to your requirements
'format' => 'alphanum', //options alphanum, num, alpha
'prefix' => 'NEWSUB',
'suffix' => '',
'dash' => '4',
];
$couponCode = $this->_couponGenerator->generateCodes($data)[0];
return $couponCode;
}
Optionally, you can actually enter these default parameters in admin panel as well - in Stores > Configuration > Customers > Promotions. If you want to set there, you should add to your construct:
\Magento\SalesRule\Helper\Coupon $couponHelper
And use these functions instead to retrieve that data:
$data = [ 'rule_id' => $rule->getRuleId(), 'qty' => '1', 'length' => $this->couponHelper->getDefaultLength(), 'format' => $this->couponHelper->getDefaultFormat(), 'prefix' => $this->couponHelper->getDefaultPrefix(), 'suffix' => $this->couponHelper->getDefaultSuffix(), 'dash' => $this->couponHelper->getDefaultDashInterval(), ];