Magento 2: Alterar preço do produto no Controller não funciona no momento!

9

Tentei alterar o preço dos meus produtos assim:

Controller.php:

[EDITAR]

   <?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) Com o novo código, o preço muda, mas o subtotal não! Como você pode ver aqui: insira a descrição da imagem aqui

Desde já, obrigado!

Felix Schönherr
fonte
Oi, você pode elaborar? qual controlador você usa e qual é a sua tarefa? Deseja alterar o preço quando um cliente adiciona um produto ao carrinho?
Sony
Olá Sony, não, eu quero alterar o preço, se um botão for clicado, não se um produto estiver sendo adicionado ao carrinho. Por enquanto, eu só quero alterar o preço de todos os produtos para 100 $ para teste. Vou atualizar a minha pergunta para mostrar-lhe mais algum código
Felix Schönherr
Desculpe, tenho medo de não entender o que você está tentando. Quando olho o seu código, você deseja alterar os preços dos itens que estão na sua cesta. Na verdade, você está chamando o quotede checkoutSession. Eu estou um pouco confuso.
Sony
Sim, quero alterar os preços dos itens na minha cesta. Tentei algumas outras coisas também para conseguir isso e o último que tentei é o código atual entre aspas.
Felix Schönherr
A alteração de preço não funcionará usando o controlador que você precisa para usar o plugin ou o observador.
Aasim Goriya

Respostas:

5

Entendi, acho que você está no caminho certo, mas acho que você precisa salvar a cotação. Se você der uma olhada nesta classe: \Magento\Checkout\Controller\Cart\Add você pode ver na Linha 114:

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

            $this->cart->save();

Eu mudo o preço do evento chamado no final do addProduct()método, e o Magento salva o carrinho no final. Portanto, no seu caso, você deve salvar a cotação no seu controlador.

Sony
fonte
Ok, o preço mudou agora (veja a minha pergunta atualizada), mas o subtotal não muda, alguma idéia?
Felix Schönherr
Além disso, se você clicar em check-out, o preço será o mesmo novamente
Felix Schönherr
Eu acho que você precisa dar uma olhada no modelo de cotação, especialmente no método collectTotals (). Você deve definir o sinalizador $ this-> setTotalsCollectedFlag (false) que pede ao Magento para calcular novamente.
Sony
Infelizmente isso não funcionou para mim :(
Felix Schönherr
Tentei de várias maneiras diferentes e nunca funcionou.
Felix Schönherr
3

Fiz um trecho que permite alterar o preço. Na verdade, ele altera o preço depois de adicionar o produto à sua cesta. Em outras palavras, ele altera os preços de seus itens em sua cotação. https://gist.github.com/0-Sony/d9d2ea792b5533bfeaff28827e6f207a

Espero que ajude.

Sony
fonte
Desculpe, mas não ajuda, não posso usar um observador, preciso usar meu controlador
Felix Schönherr
3

Você deseja atualizar o total da linha e não o subtotal, use o método $item->setRowTotal()ou $item->setBaseRowTotal(). Além disso, pode ser útil adicionar $item->save()antes do final do loop.

Subtotal é o subtotal do pedido / carrinho.

coderGeek
fonte
Infelizmente isso não mudou nada. Mas obrigado pela sua resposta
Felix Schönherr
3

@ Felix, você precisa definir setSubtotal()uma cotação. Definir o subtotal fora de for loop .

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

como isso

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

Nota: Código testado

Arunprabakaran M
fonte
Pode funcionar para você, mas não para mim.
Felix Schönherr
Você tentou isso ($ subtotal = $ carrinho-> GetQuote () -> setSubtotal ($ subtotalprice);) fora deste loop
Arunprabakaran M
Sim, eu fiz isso exatamente como você disse
Felix Schönherr
setSubtotal não está funcionando. corrigir? outros métodos set funcionando bem como setprice? corrigir?
Arunprabakaran M
Sim correto ....
Felix Schönherr
3

Para atualizar o preço do carrinho, você deve usar o carrinho de modelo em vez da sessão de checkout. Carregue o item do carrinho e atualize-o.

<?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();
?>
Ketan Borada
fonte
Na verdade, ele não está funcionando, desculpe
Felix Schönherr
É o meu código de trabalho, eu estou criando Citações por preço personalizado por API.It deve Work.may ser qualquer módulo de conflitos seu lado
Ketan Borada
0

Experimente o código abaixo:

você precisa modificar a process()função para sua exigência.

fornecedor / 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;
    }

NOTA: Não modifique os arquivos principais do magento. Crie um plugin para isso.

Eu espero que isso ajude...!!!

Balwant Singh
fonte
Mas se eu criar um plugin para esta e outra extensão, que é executada na mesma loja, também cria um plugin do Validator.php, apenas um estará funcionando. verdade?
Felix Schönherr
@felix: Não, você só precisa criar um plugin para a função de processo do arquivo validator.php. ele será executado em todas as suas lojas. primeiro, basta fazer alterações no arquivo principal e verificar quando seus requisitos forem cumpridos ou não? Se tudo estiver de acordo com essa modificação, depois de criar o plugin para isso.
Balwant Singh
Ok, tentarei isso amanhã e, em seguida, responderá.
Felix Schönherr
Isso mudou apenas o preço no resumo do carrinho, mas o preço dos produtos permanece o mesmo #
Felix Schönherr