9

I tried to change the Price of my Products like this:

Controller.php:

[EDIT]

   <?php

namespace MassiveArt\ShoppingCart\Controller\Index;

use Magento\Catalog\Model\ProductFactory;
use Magento\Checkout\Model\Cart;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Data\Form\FormKey;

class Index extends Action
{
    /**
     * @var FormKey
     */
    protected $formKey;

    /**
     * @var Session
     */
    protected $checkoutSession;

    /**
     * @var Cart
     */
    protected $cart;

    /**
     * @var ProductFactory
     */
    protected $productFactory;

    /**
     * Constructor.
     *
     * @param Context                         $context
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Customer\Model\Session $customerSession
     * @param JsonFactory                     $resultJsonFactory
     * @param FormKey                         $formKey
     * @param Cart                            $cart
     * @param ProductFactory                  $productFactory
     */
    public function __construct(
        Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Customer\Model\Session $customerSession,
        JsonFactory $resultJsonFactory,
        FormKey $formKey,
        Cart $cart,
        ProductFactory $productFactory
    ) {
        $this->checkoutSession = $checkoutSession;
        $this->customerSession = $customerSession;
        $this->formKey = $formKey;
        $this->resultJsonFactory = $resultJsonFactory;
        $this->cart = $cart;
        $this->productFactory = $productFactory;
        parent::__construct($context);
    }

    public function execute()
    {
        try {

            // Set result data and pass back
            $result = $this->resultJsonFactory->create();


            $allItems = $this->checkoutSession->getQuote()->getAllVisibleItems();
            foreach ($allItems as $item) {
                $item = ( $item->getParentItem() ? $item->getParentItem() : $item );
                $price = 100; //set your price here
                $item->setCustomPrice($price);
                $item->setOriginalCustomPrice($price);
                $item->setSubtotal($price);
                $item->getProduct()->setIsSuperMode(true);
            }
            $this->checkoutSession->setTotalsCollectedFlag(false);
            $this->checkoutSession->getQuote()->save();
            $this->checkoutSession->getQuote()->setTotalsCollectedFlag(false);
            $this->setTotalsCollectedFlag(false);

            $result->setData(['message' => __("Products added succesfully")]);

            return $result;
        } catch (\Exception $e) {
            $result->setData(['error' => __($e->getMessage())]);
            return $result;
        }
    }
}

(EDIT) With the new code the price changes, but the subtotal not! As you can see here: enter image description here

Thanks in advance!

8
  • Hi, can you elaborate? which controller do you use, and what is your task? Do you want to change the price when a customer adds a product to the cart?
    – Sony
    Commented Aug 28, 2019 at 9:49
  • Hello Sony, no i want to change the price, if a button is clicked, not if a product is getting added to cart. For now i just want to change the price of all products to 100$ for testing. I will update my question to show you some more code Commented Aug 28, 2019 at 9:58
  • Sorry, I am afraid to not understand what you are trying. When I look at your code, you look to want to change the prices of items which are in your basket. Indeed you are calling the quote from the checkoutSession . I am a bit confused.
    – Sony
    Commented Aug 28, 2019 at 10:12
  • Yes I want to change the prices of the items in my basket. I tried some other stuff as well to achieve this and the last one I tried is the current code with quote. Commented Aug 28, 2019 at 11:56
  • The price change will not work using the controller you need to use plugin or observer for that. Commented Sep 3, 2019 at 6:11

6 Answers 6

5
+150

I get it, I think you are in the right way, but I think you have to save the quote. If you take a look on this class : \Magento\Checkout\Controller\Cart\Add you can see at Line 114 :

$this->cart->addProduct($product, $params);
            if (!empty($related)) {
                $this->cart->addProductsByIds(explode(',', $related));
            }

            $this->cart->save();

I change the price from the event which is called at the end of the addProduct() method, and Magento saves the cart at the end. So in your case, you have to save the quote in your controller.

10
  • Ok, Price gets changed now (look at my updated Question), but the subtotal wont change, any ideas? Commented Aug 28, 2019 at 14:50
  • also if you then click on checkout, the price is the same again Commented Aug 28, 2019 at 14:57
  • I think you have to take a look on the Quote Model, especially at the collectTotals() method. You have to set the flag $this->setTotalsCollectedFlag(false) which ask to Magento to calculate again.
    – Sony
    Commented Aug 28, 2019 at 15:09
  • Unfortunately this did not work for me :( Commented Aug 29, 2019 at 5:41
  • Tried it in a lot of different ways and it never worked. Commented Aug 29, 2019 at 5:42
3

I did a snippet which allows you to change the price. Actually, it changes the price after you add product in your basket. In other words, it changes the prices of your items in your quote. https://gist.github.com/0-Sony/d9d2ea792b5533bfeaff28827e6f207a

Hope it helps.

1
  • Sorry it does not help, i cant use an observer, i need to use my controller Commented Aug 28, 2019 at 13:40
3

You want to update the row total and not the subtotal, use method $item->setRowTotal() or $item->setBaseRowTotal(). Also, it might help to add $item->save() before the end of the loop.

Subtotal is the order/cart subtotal.

1
  • Unfortunately this changed nothing. But thanks for your answer Commented Sep 4, 2019 at 14:18
3

@felix,You need to set setSubtotal() for a quote. Set Subtotal outside for loop.

$subTotal = $cart->getQuote()->setSubtotal($price);
$this->checkoutSession->getQuote()->save();

like this

foreach ($allItems as $item) {
                $item = ( $item->getParentItem() ? $item->getParentItem() : $item );
                $price = 100; //set your price here
                $item->setCustomPrice($price);
                $item->setOriginalCustomPrice($price);
                $item->getProduct()->setIsSuperMode(true);
            }
            $subtotalprice=100;
            $subTotal = $cart->getQuote()->setSubtotal($subtotalprice);
            $this->checkoutSession->setTotalsCollectedFlag(false);
            $this->checkoutSession->getQuote()->save();

Note: Code Tested

5
  • May worked for you, but not for me. Commented Sep 5, 2019 at 11:13
  • Did you try this( $subTotal = $cart->getQuote()->setSubtotal($subtotalprice);) outside this for loop Commented Sep 5, 2019 at 12:51
  • yes, i did this exactly how you said Commented Sep 5, 2019 at 14:02
  • setSubtotal is only not working. correct? other set methods working fine like setprice ? correct? Commented Sep 5, 2019 at 14:03
  • Yes correct.... Commented Sep 5, 2019 at 14:06
3

For Upadate cart price you have to use Model cart instead checkout session. Load item from cart and update it.

<?php 
$items = $this->cart->getQuote()->getAllItems(); //Magento\Checkout\Model\Cart $cart
foreach($items as $item) {

    $item = $this->cart->getQuote()->getItemById($item->getId());
    if (!$item) {
      continue;
    }

    $price = 100;
    $item->setCustomPrice($price);
    $item->setOriginalCustomPrice($price);
    $item->getProduct()->setIsSuperMode(true);
    $item->save();           
}
$this->cart->save();
?>
2
  • Actually it is not working, sorry Commented Sep 5, 2019 at 14:05
  • It's my working code,i'm creating Quote by custom price by API.It must Work.may be any module conflicts your side Commented Sep 6, 2019 at 12:05
0

Try below code:

you need to modify process() function for your requirement.

vendor/magento/module-sales-rule/Model/Validator.php

/**
     * Quote item discount calculation process
     *
     * @param AbstractItem $item
     * @return $this
     */
    public function process(AbstractItem $item)
    {
        $item->setDiscountAmount(0);
        $item->setBaseDiscountAmount(0);
        $item->setDiscountPercent(0);
        $itemPrice = $this->getItemPrice($item);
        if ($itemPrice < 0) {
            return $this;
        }

        $appliedRuleIds = $this->rulesApplier->applyRules(
            $item,
            $this->_getRules($item->getAddress()),
            $this->_skipActionsValidation,
            $this->getCouponCode()
        );
        $this->rulesApplier->setAppliedRuleIds($item, $appliedRuleIds);
        /*Your custom code START here*/
        $item = ( $item->getParentItem() ? $item->getParentItem() : $item );
        $price = 499; //set your price here
        $item->setCustomPrice($price);
        $item->setOriginalCustomPrice($price);
        $item->getProduct()->setIsSuperMode(true);
        //echo "sku: ".$item->getSku()."=== Name: ".$item->getName();die;
        /* Your custom code END here */
        return $this;
    }

NOTE: Don't modify magento core files. Create plugin for this.

I hope it will help...!!!

4
  • But if I create a plugin for this and one other extension, which runs on the same store, also creates a plugin of the Validator.php only one will be working. true? Commented Aug 28, 2019 at 12:50
  • @felix : No, you just need to create plugin for process function of validator.php file. it will run for your all stores.first you just make change in core file and check once your requirement is fulfil or not? If all are okay with this modification then after you create plugin for this. Commented Aug 28, 2019 at 12:54
  • Ok, will try this tomorrow and will then give you a reply. Commented Aug 28, 2019 at 13:39
  • This only changed the Price in the summary of the cart, but the price of the products just stay the same Commented Aug 29, 2019 at 5:53

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.