0

Currently Magento is using the special price if it is lower than the applied catalog price rule. If the catalog price rule makes the product cheaper than the special price, then the catalog price rule defines the shop price.

I am looking for an elegant way to make catalog price rules be applied to the special price (additionally). Maybe there is some store config for it? Maybe there is some neat observer way?


EDIT
I thought about editing the rule.php inside vendor/magento/module-catalog-rule/Model/RessourceModel to check the already placed special price (there is a solution like that for magento 1.8) but im kinda stuck there

public function getRulePrices(\DateTimeInterface $date, $websiteId, $customerGroupId, $productIds)
{
    $connection = $this->getConnection();
    $select = $connection->select()
        ->from($this->getTable('catalogrule_product_price'), ['product_id', 'rule_price'])
        ->where('rule_date = ?', $date->format('Y-m-d'))
        ->where('website_id = ?', $websiteId)
        ->where('customer_group_id = ?', $customerGroupId)
        ->where('product_id IN(?)', $productIds);

    return $connection->fetchPairs($select);
}


public function getRulesFromProduct($date, $websiteId, $customerGroupId, $productId)
{
    $connection = $this->getConnection();
    if (is_string($date)) {
        $date = strtotime($date);
    }
    $select = $connection->select()
        ->from($this->getTable('catalogrule_product'))
        ->where('website_id = ?', $websiteId)
        ->where('customer_group_id = ?', $customerGroupId)
        ->where('product_id = ?', $productId)
        ->where('from_time = 0 or from_time < ?', $date)
        ->where('to_time = 0 or to_time > ?', $date);

    return $connection->fetchAll($select);
}
  • No there is no any store config to apply catalog price rule over special price. – Ranjit Shinde Oct 25 '18 at 13:20
  • You may need to use third party extension to achieve this. Not in default Version – Priyank Oct 25 '18 at 13:26
  • Please take a look at the updated question, maybe its possible that way. Otherwise, do you guys know a 3rd party extension? – Marcel H. Oct 25 '18 at 13:31
1

I do not know if this is the best solution - but it works for me (I just needed special prices for customer groups without quantities):

Write a plugin with a before method for https://github.com/magento/magento2/blob/2.3.0/app/code/Magento/CatalogRule/Model/Indexer/ProductPriceCalculator.php#L34

public function beforeCalculate(
    \Magento\CatalogRule\Model\Indexer\ProductPriceCalculator $subject,
    $ruleData,
    $productData = null
  )
  {
    if (isset($ruleData['product_id']) && isset($ruleData['customer_group_id'])) {
      try {
        $specialPrice = $this->getSpecialPrice($ruleData['product_id'], $ruleData['customer_group_id']);
        if ($specialPrice <= 0) {
          return [
            $ruleData,
            $productData,
          ];
        }

        if ($productData !== null && isset($productData['rule_price'])) {
          $productData['rule_price'] = $specialPrice;
        } else {
          $ruleData['default_price'] = $specialPrice;
        }
      } catch (\Exception $noSuchEntityException) {
        // Do nothing
      }
    }

    return [
      $ruleData,
      $productData,
    ];
  }

getSpecialPrice() is a modified version of https://magento.stackexchange.com/a/176738/77389

private function getSpecialPrice($productId, $customerGroupId)
  {
    $product = $this->_productRepository->getById($productId, ['edit_mode' => true]);

    $priceKey = 'website_price';
    $value = $this->_config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE);
    if ($value == 0) {
      $priceKey = 'price';
    }

    $cgi = ($customerGroupId === 'all'
      ? $this->_groupManagement->getAllCustomersGroup()->getId()
      : $customerGroupId);

    $prices = [];
    foreach ($product->getData('tier_price') as $price) {
      if ((is_numeric($customerGroupId) && intval($price['cust_group']) === intval($customerGroupId))
        || ($customerGroupId === 'all' && $price['all_groups'])
      ) {
        /** @var \Magento\Catalog\Api\Data\ProductTierPriceInterface $tierPrice */
        $tierPrice = $this->_priceFactory->create();
        $tierPrice->setValue($price[$priceKey])
          ->setQty($price['price_qty'])
          ->setCustomerGroupId($cgi);
//        $prices[] = $tierPrice->getValue();
        return $tierPrice->getValue();
      }
    }
//    echo '<pre>';print_r($prices);
    return 0;
  }

I have not yet figured out how to get special pricing for quantities - I'm not sure, but I think if you need special pricing with quantities, this solution will not work for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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