Skip to main content

Drupal Commerce 2.x and sale price

Drupal Commerce 2.x and sale price

One of the requirements in one of our recent Drupal Commerce 2.x project was that each product should have a sale price field. By default, Commerce 2.x doesn't support this, but adding it is so easy. In this post I will share with you how I implemented this feature. Like anything else in programming there are many different approaches, but to me this seems like the most straightforward.

First thing that you need to know is that each product variation type comes with a Price field. You cannot delete this field, you can only change some settings related to the form and entity display. But you can add a second Price field to the product variation. Using field of type Price makes the most sense, and I recommend you to avoid using regular text/number fields for this.

So, to cut the story short, you need to add a new field to your product variation. Use a field of type Price and call it Saleprice (machine name should be: field_saleprice).

Sale price field

This field should not be required - it should be optional. It doesn't have to have a value because product can but doesn't need to have a saleprice. If a shop administrator enters a price in this field then that should be the product's price, and if this field is empty or if the value is zero then product's price should be equal to the value in the default Price field.

In Drupal Commerce 2.x there is something called Price resolver. Let's just say that this is a class where you can write some code that will change the product's price in some way. For this to work you need to change one thing in the Drupal Commerce 2.x web interface. You must go to your product variation settings and change the Price field format to Calculated price. You also probably need to hide the Saleprice field here, since you don't want it to be displayed.

Sale price display

 

After you done all this, you can write your own Price Resolver class. The logic is simple. Read value from the saleprice field and check if it is empty, equal to zero or if it has some positive value. In the case that the value is positive (higher then zero) then set the product price to be equal to this saleprice value. Look at the code bellow to see how easy is to accomplish this. And that code looks so damn simple and beautiful.

commerce_product_saleprice/commerce_product_saleprice.info.yml

name: Commerce Product Saleprice
type: module
description: 'Commerce Product Saleprice.'
package: Commerce
core: 8.x
dependencies:
  - commerce

commerce_product_saleprice/commerce_product_saleprice.services.yml

services:
  commerce_product_saleprice.saleprice_resolver:
    class: Drupal\commerce_product_saleprice\Resolvers\SalepriceResolver
    arguments: ['@request_stack']
    tags:
      - { name: commerce_price.price_resolver, priority: 600 }

commerce_product_saleprice/src/Resolvers/SalepriceResolver.php

<?php

namespace Drupal\commerce_product_saleprice\Resolvers;

use Drupal\commerce\Context;
use Drupal\commerce\PurchasableEntityInterface;
use Drupal\commerce_price\Price;
use Drupal\commerce_price\Resolver\PriceResolverInterface;

/**
 * Class SalepriceResolver
 *
 * @package Drupal\commerce_product_saleprice\Resolvers
 */
class SalepriceResolver implements PriceResolverInterface {

  /**
   * {@inheritdoc}
   */
  public function resolve(PurchasableEntityInterface $entity, $quantity, Context $context) {
    // Make sure that product variation has a field called Saleprice.
    if (!$entity->hasField('field_saleprice')) {
      return;
    }

    if ($entity->get('field_saleprice')->isEmpty()) {
      return;
    }

    /** @var \Drupal\commerce_price\Price $sale_price */
    $sale_price = $entity->get('field_saleprice')->first()->toPrice();
    $sale_price_number = $sale_price->getNumber();
    $sale_price_currency_code = $sale_price->getCurrencyCode();

    if (!$sale_price_number || $sale_price_number == 0) {
      return;
    }

    return new Price($sale_price_number, $sale_price_currency_code);
  }

}

You can also visit my github page and download this code if you don't want to write it.

Share