How to Prevent Selling the Same Downloadable Product More Than Once in Magento 2

Table of Contents

  1. Introduction
  2. Understanding the Problem
  3. Step-by-Step Guide to Implementation
  4. Testing Your Changes
  5. Conclusion
  6. FAQ

Introduction

Running an online store can be challenging, especially when it involves dealing with downloadable products. Managing the sales of these products, ensuring they are only sold once per user, is crucial to avoid duplications and customer dissatisfaction. If you're using Magento 2 and looking to prevent the same downloadable product from being added to the cart more than once, you've come to the right place.

This blog post will walk you through the steps of modifying your Magento 2 store to achieve this. Whether you're a developer or a store owner, this guide will provide you with actionable insights and detailed instructions. By the end of this post, you'll understand how to tweak your store settings, code adjustments, and the potential challenges you might face along the way.

Understanding the Problem

When dealing with downloadable products in Magento 2, enabling customers to purchase the same item multiple times can lead to unnecessary complications. It's often more seamless to limit each user to one purchase per downloadable product. This not only simplifies managing licenses and downloads but also ensures a cleaner, more organized purchasing experience for your customers.

The default Magento 2 setup, however, doesn’t natively support this functionality. Therefore, some adjustments are necessary. These interventions will also help to remove the quantity field from all facets of the purchasing process, ensuring a straightforward one-time purchase model.

Step-by-Step Guide to Implementation

Modifying the Add to Cart Functionality

To prevent a downloadable product from being added to the cart more than once, you’ll need to intercept the "Add to Cart" action. This can be achieved by creating a custom plugin.

  1. Create the necessary directories:

    First, navigate to your Magento 2 root directory. Then, create the following folder structure if it does not already exist:

    app/code/Vendor/Module/etc/
    app/code/Vendor/Module/Plugin/Magento/Checkout/Cart/
    
  2. Create the di.xml file:

    Inside app/code/Vendor/Module/etc/, create a di.xml file if it does not already exist. This XML file will declare your plugin.

    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <type name="Magento\Checkout\Model\Cart">
            <plugin name="vendor_module_beforeAddToCart" type="Vendor\Module\Plugin\Magento\Checkout\Cart\BeforeAddToCart"/>
        </type>
    </config>
    
  3. Create the BeforeAddToCart.php file:

    Inside app/code/Vendor/Module/Plugin/Magento/Checkout/Cart/, create a BeforeAddToCart.php file. This file will contain the logic to intercept the add to cart action and ensure the product cannot be added multiple times.

    <?php
    
    namespace Vendor\Module\Plugin\Magento\Checkout\Cart;
    
    class BeforeAddToCart
    {
        /**
         * @param \Magento\Checkout\Model\Cart $subject
         * @param \Magento\Catalog\Model\Product $product
         * @param int $quantity
         * @param array $requestInfo
         * @return array
         * @throws \Magento\Framework\Exception\LocalizedException
         */
        public function beforeAddProduct(\Magento\Checkout\Model\Cart $subject, $product, $requestInfo = null)
        {
            if ($product->getTypeId() === 'downloadable' && $subject->getQuote()->hasProductId($product->getId())) {
                throw new \Magento\Framework\Exception\LocalizedException(
                    __('You cannot add the same downloadable product more than once.')
                );
            }
            return [$product, $requestInfo];
        }
    }
    

Removing the Quantity Field

To fully ensure downloadable products can only be purchased once per user, you must remove the quantity input field from various parts of the cart.

  1. Override the Cart Templates:

    You’ll need to override cart/item/default.phtml and cart/item/renderer/actions.phtml to remove the quantity field for downloadable products.

    File Path: app/design/frontend/Vendor/theme/Magento_Checkout/templates/cart/item/default.phtml

    <?php
        /** @var \Magento\Quote\Model\Quote\Item\AbstractItem $_item */
        $_item = $_product;
        if ($_item->getProduct()->getTypeId() !== 'downloadable') : ?>
            <!-- Quantity Field -->
            <div class="product-item-details" data-role="product-item-details">
                <div class="details-qty qty">
                    <label class="label" for="cart-<?= /* @escapeNotVerified */ $_item->getId(); ?>-qty"><?= __('Quantity') ?></label>
                    <input id="cart-<?= /* @escapeNotVerified */ $_item->getId(); ?>-qty" value="<?= /* @escapeNotVerified */ $_item->getQty() ?>" type="number" />
                </div>
            </div>
        <?php endif; ?>
    

    File Path: app/design/frontend/Vendor/theme/Magento_Checkout/templates/cart/item/renderer/actions.phtml

    <?php if ($_item->getProduct()->getTypeId() !== 'downloadable') : ?>
        <!-- Change and Remove Action -->
        <li class="item actions">
            <div class="action edit">
                <a class="action-edit" title="Edit item">Edit</a>
            </div>
            <div class="action delete">
                <a class="action-delete" title="Remove item">Remove</a>
            </div>
        </li>
    <?php endif; ?>
    

Handling Edge Cases

When running an e-commerce site, you always have to prepare for edge cases. Here are a few scenarios you should consider:

  1. Customer Splits Across Multiple Accounts: Ensure that the restriction applies by verifying the unique purchase history within customer accounts. If your product license allows multiple downloads within the same user account, ensure this logic is respected.

  2. Multiple User Roles: Administrators might need the ability to add products in bulk for internal purposes. Consider implementing role-based exceptions if necessary.

Testing Your Changes

Before deploying your changes to a production environment, thoroughly test in a development setting to ensure that everything functions as expected. Create various test scenarios, including a mixture of guest and registered users, to validate that the downloadable product can only be added once per user.

Conclusion

By following the steps outlined in this post, you should be able to effectively prevent the same downloadable product from being added to the cart more than once in Magento 2. This modification enhances user experience, ensures clarity in licensing, and maintains the integrity of your downloadable products. Implementing these changes will streamline your sales process and help in managing your store more efficiently.

FAQ

Can this functionality be applied to other product types?

Yes, while this guide specifically covers downloadable products, you can adapt the logic to other product types as well. Make adjustments to the conditionals in the BeforeAddToCart.php plugin file.

Will these changes affect existing orders?

No, these changes should not affect existing orders. They are only applied to the add-to-cart process moving forward. However, thoroughly test your implementation to ensure no unwanted side effects occur.

How do I revert these changes if needed?

You can easily revert these changes by removing the custom plugin and restoring the original default.phtml and actions.phtml files. Always ensure you have backups before making system modifications.

What happens if a user tries to add a product twice via a direct URL?

The plugin implementation will throw an exception if a user attempts to add the same downloadable product twice, ensuring the product is not duplicated regardless of how the add-to-cart request is initiated.