cancel
Showing results for 
Search instead for 
Did you mean: 

How to create a new price type?

Highlighted

How to create a new price type?

I am now struggling to create a new price type on Magento 2.2.7. Below are what I have tried so far.

I have created a module Foo_Bar.

And then, first of all, inject the new type into the price pool:

Foo\Bar\etc\di.xml

<virtualType name="Magento\Catalog\Pricing\Price\Pool">
    <arguments>
        <argument name="prices" xsi:type="array">
            <item name="custom_price" xsi:type="string">Foo\Bar\Pricing\Price\CustomPrice</item>
        </argument>
    </arguments>
</virtualType>

Define the price class:

Foo\Bar\Pricing\Price\CustomPrice.php

namespace Foo\Bar\Pricing\Price;

use Magento\Framework\Pricing\Price\AbstractPrice;

class CustomPrice extends AbstractPrice {
    const PRICE_CODE = 'custom_price';

    public function getValue() {
        return '1234'; // for testing purpose
    }
}

I have deleted all files under generated/code, generated/metadata, and I have run all the commands I could think of:

php bin/magento s:d:c
php bin/magento c:c
php bin/magento c:f

Then, for testing purpose, I tried to edit the core block Magento\Catalog\Pricing\Render\FinalPriceBox and added some codes in the function _toHtml() as follows:

echo 'final_price: ' . $this->getPriceType('final_price')->getAmount()->getValue() . '<br/>';
echo 'regular_price: ' . $this->getPriceType('regular_price')->getAmount()->getValue() . '<br/>';
echo 'base_price: ' . $this->getPriceType('base_price')->getAmount()->getValue() . '<br/>';
echo 'tier_price: ' . $this->getPriceType('tier_price')->getAmount()->getValue() . '<br/>';
echo 'special_price: ' . $this->getPriceType('special_price')->getAmount()->getValue() . '<br/>';
// the following line is commented out because it is giving me another irrelevant error about illegal offset
//echo 'custom_option_price: ' . $this->getPriceType('custom_option_price')->getAmount()->getValue() . '<br/>';
echo 'configured_price: ' . $this->getPriceType('configured_price')->getAmount()->getValue() . '<br/>';
echo 'configured_regular_price: ' . $this->getPriceType('configured_regular_price')->getAmount()->getValue() . '<br/>';
echo 'catalog_rule_price: ' . $this->getPriceType('catalog_rule_price')->getAmount()->getValue() . '<br/>';
echo 'msrp_price: ' . $this->getPriceType('msrp_price')->getAmount()->getValue() . '<br/>';
echo 'wishlist_configured_price: ' . $this->getPriceType('wishlist_configured_price')->getAmount()->getValue() . '<br/>';
// the line below would result in an exception
//echo 'custom_price: ' . $this->getPriceType('custom_price')->getAmount()->getValue() . '<br/>';
die();

Basically what I was trying to do is to see if I could retrieve the price type I defined earlier. All the lines except the two I have commented out worked properly. And the last line is giving me an exception like this:

Exception #0 (ReflectionException): Class  does not exist

And part of the related traces:

/vendor/magento/framework/Pricing/Price/Collection.php(138): Magento\Framework\Pricing\Price\Factory->create(Object(Magento\Catalog\Model\Product\Interceptor), NULL, NULL)
/vendor/magento/framework/Pricing/PriceInfo/Base.php(63): Magento\Framework\Pricing\Price\Collection->get('custom_price')
/vendor/magento/framework/Pricing/Render/PriceBox.php(135): Magento\Framework\Pricing\PriceInfo\Base->getPrice('custom_price')
/vendor/magento/module-catalog/Pricing/Render/FinalPriceBox.php(97): Magento\Framework\Pricing\Render\PriceBox->getPriceType('custom_price')
/vendor/magento/framework/View/Element/AbstractBlock.php(667): Magento\Catalog\Pricing\Render\FinalPriceBox->_toHtml()

And from Magento\Framework\Pricing\Price\Factory->create(Object(Magento\Catalog\Model\Product\Interceptor), NULL, NULL), we could find some hints in Magento\Framework\Pricing\Price\Collection:

 

Magento\Framework\Pricing\Price\Collection

public function get($code)
{
    if (!isset($this->priceModels[$code])) {
        $this->priceModels[$code] = $this->priceFactory->create(
            $this->saleableItem,
            $this->pool[$code],
            $this->quantity
        );
    }
    return $this->priceModels[$code];
}

From here we could see that $this->pool[$code] which would be $this->pool['custom_price'] in this case, is NULL. This made me think that my custom price type is still nowhere to be found inside the price pool.

 

What am I missing here?

 

I hope I am clear enough and thanks for any assistance in advance.

3 REPLIES 3
Highlighted

Re: How to create a new price type?

Hello,

 

I'm trying to do the same things! Did you manage to make it work ?

Anyone could help on this topic ?

 

Thank you

Highlighted

Re: How to create a new price type?

Hey,

Did you manage to achieve it the new price type ?

Highlighted

Re: How to create a new price type?

I had the same problem and finally solved it by implementing the new price like the magento-msrp module implements the MSRP price, creating a virtual type for bundle products too:

 

etc/di.xml:

    <virtualType name="Magento\Catalog\Pricing\Price\Pool">
        <arguments>
            <argument name="prices" xsi:type="array">
                <item name="store_price" xsi:type="string">MyVendor\MyModule\Pricing\Price\StorePrice</item>
            </argument>
        </arguments>
    </virtualType>
    <virtualType name="Magento\Bundle\Pricing\Price\Pool">
        <arguments>
            <argument name="prices" xsi:type="array">
                <item name="store_price" xsi:type="string">MyVendor\MyModule\Pricing\Price\StorePrice</item>
            </argument>
        </arguments>
    </virtualType>

 And my price model:

 

<?php

namespace MyVendor\MyModule\Pricing\Price;

use Magento\Catalog\Model\Product;
use Magento\Catalog\Pricing\Price\FinalPrice;
use Magento\Catalog\Pricing\Price\FinalPriceInterface;
use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;

/**
 * Store price model
 */
class StorePrice extends FinalPrice implements FinalPriceInterface
{
    /**
     * Default price type
     */
    const PRICE_CODE = 'store_price';


    /**
     * @param Product $saleableItem
     * @param float $quantity
     * @param CalculatorInterface $calculator
     * @param PriceCurrencyInterface $priceCurrency
     */
    public function __construct(
        Product $saleableItem,
        $quantity,
        CalculatorInterface $calculator,
        PriceCurrencyInterface $priceCurrency
    ) {
        parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency);
    }

    /**
     * Get price value
     *
     * @return float
     */
    public function getValue()
    {
        if ($this->value === null) {
            $price = $this->product->getStorePrice();
            $priceInCurrentCurrency = $this->priceCurrency->convertAndRound($price);
            $this->value = $priceInCurrentCurrency ? (float)$priceInCurrentCurrency : 0;
        }
        return $this->value;
    }
}

My class extends the Magento\Catalog\Pricing\Price\FinalPrice class and implements Magento\Catalog\Pricing\Price\FinalPriceInterface class.

 

Hope this help.