Magento 2: Das Ändern des Produktpreises in Controller funktioniert derzeit nicht!

9

Ich habe versucht, den Preis meiner Produkte folgendermaßen zu ändern:

Controller.php:

[BEARBEITEN]

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

(BEARBEITEN) Mit dem neuen Code ändert sich der Preis, die Zwischensumme jedoch nicht! Wie Sie hier sehen können: Geben Sie hier die Bildbeschreibung ein

Danke im Voraus!

Felix Schönherr
quelle
Hallo, kannst du das näher erläutern? Welchen Controller verwenden Sie und was ist Ihre Aufgabe? Möchten Sie den Preis ändern, wenn ein Kunde ein Produkt in den Warenkorb legt?
Sony
Hallo Sony, nein, ich möchte den Preis ändern, wenn auf eine Schaltfläche geklickt wird, nicht, wenn ein Produkt in den Warenkorb gelegt wird. Im Moment möchte ich nur den Preis aller Produkte zum Testen auf 100 $ ändern. Ich werde meine Frage aktualisieren, um Ihnen etwas mehr Code zu zeigen
Felix Schönherr
Entschuldigung, ich habe Angst, nicht zu verstehen, was Sie versuchen. Wenn ich mir Ihren Code ansehe, möchten Sie die Preise der Artikel in Ihrem Warenkorb ändern. In der Tat rufen Sie die quotevon der checkoutSession. Ich bin etwas verwirrt.
Sony
Ja, ich möchte die Preise der Artikel in meinem Warenkorb ändern. Ich habe auch einige andere Dinge ausprobiert, um dies zu erreichen, und das letzte, das ich ausprobiert habe, ist der aktuelle Code mit Anführungszeichen.
Felix Schönherr
Die Preisänderung funktioniert nicht mit dem Controller, für den Sie ein Plugin oder einen Observer benötigen.
Aasim Goriya

Antworten:

5

Ich verstehe, ich denke, Sie sind auf dem richtigen Weg, aber ich denke, Sie müssen das Zitat speichern. Wenn Sie sich diese Klasse ansehen: \Magento\Checkout\Controller\Cart\Add Sie können in Zeile 114 sehen:

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

            $this->cart->save();

Ich ändere den Preis von dem Ereignis, das am Ende der addProduct()Methode aufgerufen wird, und Magento speichert den Wagen am Ende. In Ihrem Fall müssen Sie das Angebot also in Ihrem Controller speichern.

Sony
quelle
Ok, der Preis wird jetzt geändert (siehe meine aktualisierte Frage), aber die Zwischensumme ändert sich nicht, irgendwelche Ideen?
Felix Schönherr
Auch wenn Sie dann auf Kasse klicken, ist der Preis wieder der gleiche
Felix Schönherr
Ich denke, Sie müssen sich das Quote-Modell ansehen, insbesondere die Methode collectTotals (). Sie müssen das Flag $ this-> setTotalsCollectedFlag (false) setzen, das Magento zur erneuten Berechnung auffordert.
Sony
Leider hat das bei mir nicht funktioniert :(
Felix Schönherr
Versuchte es auf viele verschiedene Arten und es hat nie funktioniert.
Felix Schönherr
3

Ich habe einen Ausschnitt gemacht, mit dem Sie den Preis ändern können. Tatsächlich ändert sich der Preis, nachdem Sie das Produkt in Ihren Warenkorb gelegt haben. Mit anderen Worten, es ändert die Preise Ihrer Artikel in Ihrem Angebot. https://gist.github.com/0-Sony/d9d2ea792b5533bfeaff28827e6f207a

Ich hoffe es hilft.

Sony
quelle
Sorry, es hilft nicht, ich kann keinen Beobachter benutzen, ich muss meinen Controller benutzen
Felix Schönherr
3

Sie möchten die Zeilensumme und nicht die Zwischensumme aktualisieren, verwenden Sie die Methode $item->setRowTotal()oder $item->setBaseRowTotal(). Es kann auch hilfreich sein, $item->save()vor dem Ende der Schleife hinzuzufügen .

Zwischensumme ist die Zwischensumme für Bestellung / Warenkorb.

coderGeek
quelle
Leider hat sich daran nichts geändert. Aber danke für deine Antwort
Felix Schönherr
3

@ felix, du musst setSubtotal()ein Angebot machen. Zwischensumme außerhalb f setzen or loop.

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

so was

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

Hinweis: Code getestet

Arunprabakaran M.
quelle
May hat für dich gearbeitet, aber nicht für mich.
Felix Schönherr
Haben Sie dies versucht ($ subTotal = $ cart-> getQuote () -> setSubtotal ($ subtotalprice);) außerhalb dieser for-Schleife
Arunprabakaran M
Ja, ich habe genau das getan, was du gesagt hast
Felix Schönherr
setSubtotal funktioniert nur nicht. richtig? andere Set-Methoden funktionieren gut wie Setprice? richtig?
Arunprabakaran M
Ja richtig ....
Felix Schönherr
3

Für den Upadate-Warenkorbpreis müssen Sie anstelle der Checkout-Sitzung den Modellwagen verwenden. Laden Sie den Artikel aus dem Warenkorb und aktualisieren Sie ihn.

<?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
quelle
Eigentlich funktioniert es nicht, sorry
Felix Schönherr
Es ist mein Arbeitscode, ich erstelle ein Angebot nach benutzerdefiniertem Preis per API. Es muss funktionieren. Möglicherweise sind alle Modulkonflikte auf Ihrer Seite
Ketan Borada
0

Versuchen Sie den folgenden Code:

Sie müssen die process()Funktion für Ihre Anforderung ändern .

Hersteller / Magento / Modul-Verkaufsregel / Modell / 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;
    }

HINWEIS: Ändern Sie keine Magento-Kerndateien. Plugin dafür erstellen.

Ich hoffe es wird helfen ... !!!

Balwant Singh
quelle
Wenn ich jedoch ein Plugin für diese und eine andere Erweiterung erstelle, die im selben Store ausgeführt wird, wird auch ein Plugin der Datei Validator.php erstellt, von dem nur eines funktioniert. wahr?
Felix Schönherr
@felix: Nein, Sie müssen nur ein Plugin für die Prozessfunktion der Datei validator.php erstellen. Es wird für alle Stores ausgeführt. Nehmen Sie zunächst eine Änderung in der Kerndatei vor und überprüfen Sie, ob Ihre Anforderung erfüllt ist oder nicht. Wenn alle mit dieser Änderung einverstanden sind, nachdem Sie das Plugin dafür erstellt haben.
Balwant Singh
Ok, werde es morgen versuchen und dir dann eine Antwort geben.
Felix Schönherr
Dies änderte nur den Preis in der Zusammenfassung des Warenkorbs, aber der Preis der Produkte bleibt einfach gleich
Felix Schönherr