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!


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.


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

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.


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


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

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 ... !!!


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.