Magento 2: ¡Cambiar el precio del producto en el controlador no funciona en este momento!

9

Traté de cambiar el precio de mis productos de esta manera:

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

(EDITAR) Con el nuevo código, el precio cambia, ¡pero el subtotal no! Como puedes ver aquí: ingrese la descripción de la imagen aquí

¡Gracias por adelantado!

Felix Schönherr
fuente
Hola, ¿puedes dar más detalles? ¿Qué controlador utiliza y cuál es su tarea? ¿Desea cambiar el precio cuando un cliente agrega un producto al carrito?
Sony
Hola Sony, no, quiero cambiar el precio, si se hace clic en un botón, no si se agrega un producto al carrito. Por ahora solo quiero cambiar el precio de todos los productos a 100 $ para la prueba. Actualizaré mi pregunta para mostrarle un poco más de código
Felix Schönherr
Lo siento, me temo que no entiendo lo que estás intentando. Cuando miro su código, desea cambiar los precios de los artículos que están en su cesta. De hecho, estás llamando quotedesde checkoutSession. Estoy un poco confundido.
Sony
Sí, quiero cambiar los precios de los artículos en mi cesta. También probé otras cosas para lograr esto y el último que probé es el código actual con cita.
Felix Schönherr
El cambio de precio no funcionará con el controlador que necesita para usar el complemento u observador para eso.
Aasim Goriya

Respuestas:

5

Lo entiendo, creo que estás en el camino correcto, pero creo que tienes que guardar la cotización. Si echa un vistazo a esta clase: \Magento\Checkout\Controller\Cart\Add puede ver en la línea 114:

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

            $this->cart->save();

Cambio el precio del evento que se llama al final del addProduct()método, y Magento guarda el carrito al final. Entonces, en su caso, debe guardar la cotización en su controlador.

Sony
fuente
Ok, el precio ha cambiado ahora (mira mi pregunta actualizada), pero el subtotal no cambiará, ¿alguna idea?
Felix Schönherr
Además, si hace clic en finalizar la compra, el precio vuelve a ser el mismo
Felix Schönherr
Creo que debe echar un vistazo al Modelo de cotización, especialmente al método collectTotals (). Debe establecer la bandera $ this-> setTotalsCollectedFlag (false) que le pide a Magento que vuelva a calcular.
Sony
Lamentablemente, esto no funcionó para mí :(
Felix Schönherr
Lo probé de muchas maneras diferentes y nunca funcionó.
Felix Schönherr
3

Hice un fragmento que le permite cambiar el precio. En realidad, cambia el precio después de agregar el producto a su cesta. En otras palabras, cambia los precios de sus artículos en su presupuesto. https://gist.github.com/0-Sony/d9d2ea792b5533bfeaff28827e6f207a

Espero eso ayude.

Sony
fuente
Lo siento, no ayuda, no puedo usar un observador, necesito usar mi controlador
Felix Schönherr
3

Desea actualizar el total de la fila y no el subtotal, utilice el método $item->setRowTotal()o $item->setBaseRowTotal(). Además, podría ser útil agregar $item->save()antes del final del ciclo.

Subtotal es el subtotal del pedido / carrito.

codificador
fuente
Lamentablemente esto no cambió nada. Pero gracias por su respuesta
Felix Schönherr
3

@ felix, debes establecer setSubtotal()una cotización. Establecer subtotal fuera de f or loop.

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

Me gusta esto

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 probado

Arunprabakaran M
fuente
May trabajó para ti, pero no para mí.
Felix Schönherr
¿Intentó esto ($ subTotal = $ cart-> getQuote () -> setSubtotal ($ subtotalprice);) fuera de este bucle for
Arunprabakaran M
sí, hice exactamente lo que dijiste
Felix Schönherr
setSubtotal solo no funciona. ¿correcto? otros métodos establecidos funcionan bien como setprice? ¿correcto?
Arunprabakaran M
Sí correcto ....
Felix Schönherr
3

Para el precio del carrito Upadate, debe usar el modelo de carrito en lugar de la sesión de pago. Cargue el artículo del carrito y actualícelo.

<?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
fuente
En realidad no funciona, lo siento
Felix Schönherr
Es mi código de trabajo, estoy creando una cotización por precio personalizado por API. Debe funcionar. Puede que cualquier módulo entre en conflicto con usted
Ketan Borada
0

Pruebe el siguiente código:

necesita modificar la process()función para su requerimiento.

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

NOTA: No modifique los archivos principales de magento. Crea un complemento para esto.

Espero que ayude ... !!!

Balwant Singh
fuente
Pero si creo un complemento para esta y otra extensión, que se ejecuta en la misma tienda, también crea un complemento de Validator.php, solo uno funcionará. ¿cierto?
Felix Schönherr
@felix: No, solo necesita crear un complemento para la función de proceso del archivo validator.php. se ejecutará para todas sus tiendas. Primero, ¿simplemente realiza un cambio en el archivo principal y verifica una vez que se cumple su requisito o no? Si todos están de acuerdo con esta modificación, luego de crear un complemento para esto.
Balwant Singh
Ok, intentaré esto mañana y luego te daré una respuesta.
Felix Schönherr
Esto solo cambió el precio en el resumen del carrito, pero el precio de los productos sigue siendo el mismo
Felix Schönherr