Magento 2: изменение цены продукта в контроллере в данный момент не работает!

9

Я пытался изменить цену своих продуктов следующим образом:

controller.php:

[РЕДАКТИРОВАТЬ]

   <?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;
        }
    }
}

(РЕДАКТИРОВАТЬ) С новым кодом цена меняется, но промежуточный итог нет! Как вы можете видеть здесь: введите описание изображения здесь

Заранее спасибо!

Феликс Шенхерр
источник
Привет, можешь уточнить? какой контроллер вы используете, и какова ваша задача? Хотите изменить цену, когда покупатель добавляет товар в корзину?
Sony
Здравствуйте Sony, нет, я хочу изменить цену, если кнопка нажата, а не если продукт добавляется в корзину. Сейчас я просто хочу изменить цену всех продуктов на 100 $ для тестирования. Я
Феликс
Извините, я боюсь не понять, что вы пытаетесь. Когда я смотрю на ваш код, вы хотите изменить цены товаров, которые находятся в вашей корзине. Действительно вы зовете quoteиз checkoutSession. Я немного смущен.
Sony
Да, я хочу изменить цены товаров в моей корзине. Я попробовал и другие вещи, чтобы добиться этого, и последний, который я попробовал, это текущий код с кавычками.
Феликс
Изменение цены не будет работать с контроллером, для которого вам нужно использовать плагин или наблюдатель.
Аасим Гория

Ответы:

5

Я понял, я думаю, что вы на правильном пути, но я думаю, что вы должны сохранить цитату. Если вы посмотрите на этот класс: \Magento\Checkout\Controller\Cart\Add вы можете увидеть в строке 114:

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

            $this->cart->save();

Я изменяю цену с события, которое вызывается в конце addProduct()метода, а Magento сохраняет корзину в конце. Так что в вашем случае вы должны сохранить цитату в вашем контроллере.

Sony
источник
Хорошо, цена изменилась сейчас (посмотрите на мой обновленный Вопрос), но промежуточный итог не изменится, есть идеи?
Феликс
Также, если вы затем нажмете на кнопку «
Феликс
Я думаю, что вы должны взглянуть на модель цитирования, особенно на метод collectTotals (). Вы должны установить флаг $ this-> setTotalsCollectedFlag (false), который попросит Magento вычислить снова.
Sony
К сожалению, у меня это не сработало :(
Феликс
Пробовал по-разному, и он никогда не работал.
Феликс
3

Я сделал фрагмент, который позволяет изменить цену. На самом деле, это меняет цену после добавления товара в корзину. Другими словами, это меняет цены ваших товаров в вашей цитате. https://gist.github.com/0-Sony/d9d2ea792b5533bfeaff28827e6f207a

Надеюсь, поможет.

Sony
источник
Извините, это не помогает, я не могу использовать наблюдателя, мне нужно использовать мой контроллер
Феликс
3

Вы хотите обновить общее количество строк, а не промежуточный итог, используйте метод $item->setRowTotal()или $item->setBaseRowTotal(). Кроме того, это может помочь добавить $item->save()до конца цикла.

Промежуточный итог - промежуточный итог заказа / корзины.

coderGeek
источник
К сожалению, это ничего не изменило. Но спасибо за ваш ответ
Феликс
3

@ felix, нужно выставить setSubtotal()цитату. Установите Промежуточный итог за пределами f or loop.

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

нравится

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();

Примечание: код протестирован

Арунпрабакаран М
источник
Может работать для вас, но не для меня.
Феликс
Вы пробовали это ($ subTotal = $ cart-> getQuote () -> setSubtotal ($ subtotalprice);) вне цикла for
Arunprabakaran M
да, я сделал это именно так, как вы сказали
Феликс
setSubtotal только не работает. правильный? другие методы набора работают нормально, как setprice? правильный?
Arunprabakaran M
Да, правильно ....
Феликс
3

В качестве цены корзины Upadate вы должны использовать модель корзины вместо сеанса оформления заказа. Загрузите товар из корзины и обновите его.

<?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();
?>
Кетан Борада
источник
На самом деле это не работает, извините
Феликс
Это мой рабочий код, я создаю цитату по пользовательской цене через API. Должно быть, Work.may, если любой модуль вступает в конфликт с вашей стороны
Ketan Borada
0

Попробуйте код ниже:

вам нужно изменить process()функцию по вашему требованию.

продавец / Magento / модуль-продажа властвуй / Модель / 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;
    }

ПРИМЕЧАНИЕ. Не изменяйте файлы ядра magento. Создать плагин для этого.

Надеюсь, это поможет...!!!

Balwant Singh
источник
Но если я создаю плагин для этого и еще одного расширения, которое работает в том же магазине, также создает плагин Validator.php, будет работать только один. правда?
Феликс
@felix: Нет, вам просто нужно создать плагин для функции процесса файла validator.php. он будет работать для всех ваших магазинов. Сначала вы вносите изменения в основной файл и проверяете, когда ваше требование выполнено или нет? Если с этой модификацией все в порядке, то после создания плагина для этого.
Балвант Сингх
Хорошо, попробую завтра, а потом дам ответ.
Феликс
Это только изменило цену в сводке корзины, но цены на товары остались прежними
Феликс