0

I want to give an offer on these SKUS "sku-111-11-11,sku-222-22-22,sku-333-33-33,sku-444-44-44,sku-555-55-55,sku-666-66-66".

case 1: If customer add any 2, 4, 6 items from above skus then customer will get 50% discount.
case 2: If customer add any one sku with qty 2 then they will get 50% discount.
case 3: If customer add three skus from above skus then customer will get 50% off only on 2 items.(This one is the main where I am getting stuck right now)

So technically we want to give 1 - 1 sku free for above mentioned skus, how can I do this using cart price rule.

1 Answer 1

0

Default magento you have to manually add product and it will give you additional item with price zero,To achive you can create a customization for your requirment. You can the refer the files below.

Vendor/Module/etc/adminhtml/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\SalesRule\Model\Rule\Metadata\ValueProvider">
<plugin name="salesrule-plugin" type="Vendor\Module\Plugin\Rule\Metadata\CustomValueProvider" sortOrder="1"/>
</type>
</config>

Vendor/Module/Plugin/Rule/Metadata/CustomValueProvider.php

<?php
namespace Vendor\Module\Plugin\Rule\Metadata;

class CustomValueProvider
{
    public function afterGetMetadataValues(
        \Magento\SalesRule\Model\Rule\Metadata\ValueProvider $subject,
        $result
    ) {
        $applyOptions = [
            'label' => __('Free Gift'),
            'value' => [
                [
                    'label' => 'Buy x get x free',
                    'value' => 'buy-x-get-x-free',
                ]
                
            ],
        ];
        
        array_push($result['actions']['children']['simple_action']['arguments']['data']['config']['options'], $applyOptions); 
        return $result;
    }
}

Vendor/Module/etc/db_schema.xml

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="salesrule">
<column xsi:type="varchar" name="gift_skus" nullable="false" length="255" comment="Gift Sku"/>
<column xsi:type="int" name="giftsku_qty" unsigned="true" nullable="false" identity="false" default="0" comment="Gifts Qty Allowed"/>
</table>
</schema>

Vendor/Module/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory">
<arguments>
<argument name="discountRules" xsi:type="array">
<item name="buy-x-get-x-free" xsi:type="string">\Vendor\Module\Model\Rule\Action\Discount\BuyXGetX</item>
</argument>
</arguments>
</type>
</config>

Vendor/Module/view/adminhtml/ui_component/sales_rule_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="actions" sortOrder="30">
    <field name="custom_step_nqty" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">sales_rule</item>
                    <item name="sortOrder" xsi:type="number">4</item>
                </item>
            </argument>
            <settings>
                <validation>
                    <rule name="required-entry" xsi:type="boolean">true</rule>
                    <rule name="validate-number" xsi:type="boolean">true</rule>
                    <rule name="validate-zero-or-greater" xsi:type="boolean">true</rule>
                </validation>
                <dataType>text</dataType>
                <label translate="true">Discount Qty (Buy Y)</label>
                <dataScope>custom_step_nqty</dataScope>
            </settings>
        </field>
        <field name="gift_skus" formElement="textarea">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">sales_rule</item>
                    <item name="notice" xsi:type="string" translate="true">Enter products separated by comma. </item>
                </item>
            </argument>
            <settings>
                <dataType>number</dataType>
                <label translate="true">Promo SKU</label>
                <dataScope>promo_skus</dataScope>
            </settings>
        </field>
    </fieldset>
</form>

Vendor/Module/Model/Rule/Action/Discount/BuyXGetX.php

    <?php
    namespace Vendor\Module\Model\Rule\Action\Discount;
    
    use Magento\SalesRule\Model\Rule\Action\Discount\AbstractDiscount;
    use Magento\SalesRule\Model\Rule\Action\Discount\DataFactory;
    use Magento\Framework\Pricing\PriceCurrencyInterface;
    use Magento\SalesRule\Model\Validator;
    use Magento\Checkout\Model\Cart;
    use Magento\Catalog\Model\Product;
    use Magento\Checkout\Model\Session;
    use Magento\Quote\Model\Quote\ItemFactory;
    use Magento\Framework\Serialize\Serializer\Json;
    use Magento\Framework\App\ObjectManager;
    use Psr\Log\LoggerInterface;
    
    class BuyXGetX extends AbstractDiscount
    {
        /**
         * @var \Magento\SalesRule\Model\Rule\Action\Discount\DataFactory
         */
        protected $discountFactory;
    
        /**
         * @var \Magento\SalesRule\Model\Validator
         */
        protected $validator;
    
        /**
         * @var \Magento\Framework\Pricing\PriceCurrencyInterface
         */
        protected $priceCurrency;
    
        /**
         * @var \Magento\Checkout\Model\Cart
         */
        protected $cart;
    
        /**
         * @var \Magento\Catalog\Model\Product
         */
        protected $product;
    
        /**
         * @var \Magento\Checkout\Model\Session
         */
        protected $session;
    
        /**
         * @var  ItemFactory
         */
        protected $itemFactory;
        /**
         * @var  Json
         */
        protected $serializer;
        
        /**
         * @var LoggerInterface
         */
        protected $logger;
    
        
        public function __construct(
            Validator $validator,
            DataFactory $discountDataFactory,
            PriceCurrencyInterface $priceCurrency,
            Cart $cart,
            Product $product,
            Session $session,
            ItemFactory $itemFactory,
            Json $serializer = null,
            LoggerInterface $logger
        ) {
            $this->validator = $validator;
            $this->discountFactory = $discountDataFactory;
            $this->priceCurrency = $priceCurrency;
            $this->cart = $cart;
            $this->product = $product;
            $this->session = $session;
            $this->itemFactory = $itemFactory;
            $this->serializer = $serializer ?: ObjectManager::getInstance()->get(\Magento\Framework\Serialize\Serializer\Json::class); 
            $this->logger = $logger;
        }
    
        
        public function calculate($rule, $item, $qty)
        {
            $discountData = $this->discountFactory->create();
            $this->applyFreeGiftDiscount($item, $rule, $qty);
            
            return $discountData;
        }
    
        
        protected function applyFreeGiftDiscount($item, $rule, $qty)
        {     
        try {   
// add your logic here for simple product below is sample
            $quote = $item->getQuote();
                $productId = $item->getProductId();
                $ruleId =$rule->getId();
                $additionalOptions = []; // if you have any item custom option
                $product = $this->product->load($productId);
                $product->addCustomOption('additional_options', $this->serializer->serialize($additionalOptions));
                $product->setPrice(0);
                $product->setOriginalPrice(0);
                $product->setCustomPrice(0);
                $product->setOriginalCustomPrice(0);
                $buyRequest = new \Magento\Framework\DataObject([
                    'qty' => $qty,
                    'price' => '0',
                    'final_price' => '0'
                ]);
                $quote->addProduct($product, $buyRequest);
                
                } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
                 $this->logger->critical($e->getMessage());
            }  
        }   
    }

Also there is a blog available that might help : https://webkul.com/blog/how-to-create-a-custom-cart-rule-for-buy-x-get-next-y-with-percent-discount-in-magento-2/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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