Magento 2: el descuento depende del método de pago no funciona


13

Voy a Magento 2 Admin> Marketing> Promociones> Reglas de precios de carrito y creo una nueva Regla: Pago por transferencia bancaria:

Información de regla de tabulación:

  • Nombre de la regla: pago por transferencia bancaria
  • Estado: Activo
  • Sitios web: sitio web principal
  • Grupos de clientes: seleccionar todo
  • Cupón: sin cupón
  • Usos por cliente: 0
  • De: en blanco
  • Para: en blanco
  • Prioridad: 0
  • Público en RSS: No

Pestaña de condiciones:

  • Si TODAS estas condiciones son VERDADERAS:
    • El método de pago es el pago por transferencia bancaria

Pestaña Acciones:

  • Aplicar: porcentaje del descuento del precio del producto
  • Cantidad de descuento: 2
  • El descuento por cantidad máxima se aplica a: 0
  • Descuento Cantidad Paso (Comprar X): 0
  • Aplicar a la cantidad de envío: No
  • Descartar reglas posteriores: No
  • Envío gratis: no
  • Aplique la regla solo a los artículos del carrito que cumplan las siguientes condiciones (deje en blanco para todos los artículos): nada

Luego habilito el método de Pago por transferencia bancaria, vaya a la página de pago, haga clic en Pago por transferencia bancaria, pero el Precio porcentual de descuento no aparece en el Resumen del pedido.

ingrese la descripción de la imagen aquí

Por favor dame un consejo. Cómo hacer un descuento en el método de pago en Magento 2. Para Magento 1, funciona bien.

Muchas gracias


¿Puedes publicar tu regla aquí?
Khoa TruongDinh

Publiqué mi regla. ¿Puedes comprobar por mí por favor?
Nguyễn Hồng Quang

¿Intenta agregar la fecha activada de la regla?
Khoa TruongDinh

Intento agregar la Fecha de inicio de la regla pero aún no sucede nada en el Resumen del pedido cuando hago clic en la opción de Pago por transferencia bancaria
Nguyễn Hồng Quang

Respuestas:


11

Esta regla no funciona porque Magento 2 no guarda el método de pago para cotizar cuando selecciona uno. Y tampoco recarga los totales al seleccionar un método de pago. Y desafortunadamente, debe escribir un módulo personalizado para resolver el problema.

El nuevo módulo solo necesita 4 archivos para ser creado:

  1. app / code / Namespace / ModuleName / etc / frontend / routes.xml

    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
        <router id="standard">
            <route id="namespace_modulename" frontName="namespace_modulename">
                <module name="Namespace_ModuleName"/>
            </route>
        </router>
    </config>
    

    Esto definirá un nuevo controlador para nuestro módulo.

  2. app / code / Namespace / ModuleName / Controller / Checkout / ApplyPaymentMethod.php

    <?php
    
    namespace Namespace\ModuleName\Controller\Checkout;
    
    class ApplyPaymentMethod extends \Magento\Framework\App\Action\Action
    {
        /**
         * @var \Magento\Framework\Controller\Result\ForwardFactory
         */
        protected $resultForwardFactory;
    
        /**
         * @var \Magento\Framework\View\LayoutFactory
         */
        protected $layoutFactory;
    
        /**
         * @var \Magento\Checkout\Model\Cart
         */
        protected $cart;
    
        /**
         * @param \Magento\Framework\App\Action\Context $context
         * @param \Magento\Framework\View\LayoutFactory $layoutFactory
         * @param \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory
         */
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
            \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory,
            \Magento\Framework\View\LayoutFactory $layoutFactory,
            \Magento\Checkout\Model\Cart $cart
        ) {
            $this->resultForwardFactory = $resultForwardFactory;
            $this->layoutFactory = $layoutFactory;
            $this->cart = $cart;
    
            parent::__construct($context);
        }
    
        /**
         * @return \Magento\Framework\Controller\ResultInterface
         */
        public function execute()
        {
            $pMethod = $this->getRequest()->getParam('payment_method');
    
            $quote = $this->cart->getQuote();
    
            $quote->getPayment()->setMethod($pMethod['method']);
    
            $quote->setTotalsCollectedFlag(false);
            $quote->collectTotals();
            $quote->save();
        }
    }
    

    Este archivo crea una acción del controlador para guardar el método de pago seleccionado para cotizar

  3. app / code / Namespace / ModuleName / view / frontend / requirejs-config.js

    var config = {
        map: {
            '*': {
                'Magento_Checkout/js/action/select-payment-method':
                    'Namespace_ModuleName/js/action/select-payment-method'
            }
        }
    };

    Este archivo permite anular el Magento_Checkout/js/action/select-payment-methodarchivo

  4. app / code / Namespace / ModuleName / view / frontend / web / js / action / select-payment-method.js

    define(
        [
            'Magento_Checkout/js/model/quote',
            'Magento_Checkout/js/model/full-screen-loader',
            'jquery',
            'Magento_Checkout/js/action/get-totals',
        ],
        function (quote, fullScreenLoader, jQuery, getTotalsAction) {
            'use strict';
            return function (paymentMethod) {
                quote.paymentMethod(paymentMethod);
    
                fullScreenLoader.startLoader();
    
                jQuery.ajax('/namespace_modulename/checkout/applyPaymentMethod', {
                    data: {payment_method: paymentMethod},
                    complete: function () {
                        getTotalsAction([]);
                        fullScreenLoader.stopLoader();
                    }
                });
    
            }
        }
    );

    Envía una solicitud ajax para guardar el método de pago y recargar los totales del carrito.

Las partes de PS del código se tomaron de la extensión de la tarifa de pago para Magento 2.


1
Muchas gracias MagestyApps, creé un nuevo Módulo siguiendo sus instrucciones. Sin embargo, al final obtuve este problema jquery.js 192.168.41.59/phoenix_checkout/checkout/applyPaymentMethod 404 (No encontrado). ¿Recibiste este error antes?
Nguyễn Hồng Quang

1
Funciona muy bien Muchas gracias MagestyApps. Esta solución es perfecta.
Nguyễn Hồng Quang

Funciona, me salvaste el tiempo. Gracias :)
Sameer Bhayani

Cosas increíbles, gracias. La regla del precio del carro para los métodos de pago se eliminó por cierto ( github.com/magento/magento2/commit/… ). Agregué la línea "'payment_method' => __ ('Método de pago')," nuevamente, ahora puedo crear reglas de precio de carrito para métodos de pago.
DaFunkyAlex

Esto ayudó mucho. Gracias. +1 :)
Shoaib Munir

3

En Magento 2.2 no pude conseguir que la respuesta de MagestyApps funcionara. Necesitaba agregar algunos archivos adicionales. Porque:

  • La regla del precio del carrito para el método de pago se eliminó del administrador (como lo señala DaFunkyAlex);
  • En Magento 2.2, el descuento no se aplicaba en la cotización, porque el método \Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod::generateFilterText(en realidad recurre a \Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address::generateFilterText), esperaba que los datos payment_methodse establecieran en las direcciones de cotización;
  • Incluso cambiar el controlador de la respuesta de MagestyApps para establecer payment_methoddatos en las direcciones de cotización, no funcionó cuando la cotización se convirtió en un pedido, porque no persiste payment_method;

El siguiente módulo funcionó para mí (gracias a la respuesta de MagestyApps, se basó en eso):

registro.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_SalesRulesPaymentMethod',
    __DIR__
);

etc / module.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_SalesRulesPaymentMethod" setup_version="1.0.0">
        <sequence>
            <module name="Magento_AdvancedSalesRule"/>
            <module name="Magento_Checkout"/>
            <module name="Magento_SalesRules"/>
            <module name="Magento_Quote"/>
        </sequence>
    </module>
</config>

etc / di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod"
                type="Vendor\SalesRulesPaymentMethod\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod"/>
    <type name="Magento\SalesRule\Model\Rule\Condition\Address">
        <plugin name="addPaymentMethodOptionBack" type="Vendor\SalesRulesPaymentMethod\Plugin\AddPaymentMethodOptionBack" />
    </type>
</config>

etc / frontend / routes.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="salesrulespaymentmethod" frontName="salesrulespaymentmethod">
            <module name="Vendor_SalesRulesPaymentMethod"/>
        </route>
    </router>
</config>

Controller / Checkout / ApplyPaymentMethod.php

<?php

namespace Vendor\SalesRulesPaymentMethod\Controller\Checkout;

use Magento\Checkout\Model\Cart;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\ForwardFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\LayoutFactory;
use Magento\Quote\Model\Quote;

class ApplyPaymentMethod extends Action
{
    /**
     * @var ForwardFactory
     */
    protected $resultForwardFactory;

    /**
     * @var LayoutFactory
     */
    protected $layoutFactory;

    /**
     * @var Cart
     */
    protected $cart;

    /**
     * @param Context $context
     * @param LayoutFactory $layoutFactory
     * @param ForwardFactory $resultForwardFactory
     */
    public function __construct(
        Context $context,
        ForwardFactory $resultForwardFactory,
        LayoutFactory $layoutFactory,
        Cart $cart
    ) {
        $this->resultForwardFactory = $resultForwardFactory;
        $this->layoutFactory = $layoutFactory;
        $this->cart = $cart;

        parent::__construct($context);
    }

    /**
     * @return ResponseInterface|ResultInterface|void
     * @throws \Exception
     */
    public function execute()
    {
        $pMethod = $this->getRequest()->getParam('payment_method');

        /** @var Quote $quote */
        $quote = $this->cart->getQuote();

        $quote->getPayment()->setMethod($pMethod['method']);

        $quote->setTotalsCollectedFlag(false);
        $quote->collectTotals();

        $quote->save();
    }
}

Modelo / Regla / Condición / FilterTextGenerator / Address / PaymentMethod.php

<?php

namespace Vendor\SalesRulesPaymentMethod\Model\Rule\Condition\FilterTextGenerator\Address;

use Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod as BasePaymentMethod;

class PaymentMethod extends BasePaymentMethod
{
    /**
     * @param \Magento\Framework\DataObject $quoteAddress
     * @return string[]
     */
    public function generateFilterText(\Magento\Framework\DataObject $quoteAddress)
    {
        $filterText = [];
        if ($quoteAddress instanceof \Magento\Quote\Model\Quote\Address) {
            $value = $quoteAddress->getQuote()->getPayment()->getMethod();
            if (is_scalar($value)) {
                $filterText[] = $this->getFilterTextPrefix() . $this->attribute . ':' . $value;
            }
        }

        return $filterText;
    }
}

Plugin / AddPaymentMethodOptionBack.php

<?php

namespace Vendor\SalesRulesPaymentMethod\Plugin;

use Magento\SalesRule\Model\Rule\Condition\Address;

class AddPaymentMethodOptionBack
{
    /**
     * @param Address $subject
     * @param $result
     * @return Address
     */
    public function afterLoadAttributeOptions(Address $subject, $result)
    {
        $attributeOption = $subject->getAttributeOption();
        $attributeOption['payment_method'] = __('Payment Method');

        $subject->setAttributeOption($attributeOption);

        return $subject;
    }
}

ver / frontend / requirejs-config.js

var config = {
    map: {
        '*': {
            'Magento_Checkout/js/action/select-payment-method':
                'Vendor_SalesRulesPaymentMethod/js/action/select-payment-method'
        }
    }
};

ver / frontend / web / js / action / select-payment-method.js

define(
    [
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/full-screen-loader',
        'jquery',
        'Magento_Checkout/js/action/get-totals',
    ],
    function (quote, fullScreenLoader, jQuery, getTotalsAction) {
        'use strict';
        return function (paymentMethod) {
            quote.paymentMethod(paymentMethod);

            fullScreenLoader.startLoader();

            jQuery.ajax('/salesrulespaymentmethod/checkout/applyPaymentMethod', {
                data: {payment_method: paymentMethod},
                complete: function () {
                    getTotalsAction([]);
                    fullScreenLoader.stopLoader();
                }
            });

        }
    }
);

Me sale esto cuando se trata de compilar: Fatal error: Class 'Magento\AdvancedSalesRule\Model\Rule\Condition\Address\PaymentMethod' not found in Vendor/SalesRulesPaymentMethod/Model/Rule/Condition/FilterTextGenerator/Address/PaymentMethod.php on line 7. Incluso intenté cambiar AdvancedSalesRule a SalesRule ya que puedo ver que no hay un modelo AdvancedSalesRule en Magento 2.2.2
Alexandros

para magento 2.1.9, ¿debemos omitir las piezas de AdvancedSalesRule?
Doni Wibowo

Obteniendo error al compilar: Error fatal: la clase 'Magento \ AdvancedSalesRule \ Model \ Rule \ Condition \ Address \ PaymentMethod' no se encuentra en Vendor / SalesRulesPaymentMethod / Model / Rule / Condition / FilterTextGenerator / Address / PaymentMethod.php en la línea 7
Magecode

AdvancedSalesRule no está disponible en Magento 2.1.5
Magecode

2

Simplemente verificamos la misma regla y descubrimos que no funciona. Usando las mismas condiciones, no se envía información sobre el método elegido seleccionado y no se registra en ninguna parte hasta que se realiza el pedido y la regla puede no funcionar.

ingrese la descripción de la imagen aquí

La dirección no tiene método de pago hasta la validación y obtiene el método de pago de la cotización de pago que no existe porque no se ha enviado información ( $model->getQuote()->getPayment()->getMethod()devoluciones null).

ingrese la descripción de la imagen aquí

Suponemos que este es un error de Magento. Cuando elige un método de pago, la información debe enviarse por adelantado.


2
Se acepta la respuesta de MagestyApps. Gracias.
Nguyễn Hồng Quang

1

La solución con el módulo personalizado está funcionando.

Solo pensé que sería una información útil para los principiantes de Magento saber que también deben agregar estos archivos para poder agregar y habilitar este módulo:

(copie desde un módulo diferente y cambie los archivos de acuerdo con el nombre y el espacio de nombres de su módulo)

app/code/Namespace/ModuleName/composer.js
app/code/Namespace/ModuleName/registration.php
app/code/Namespace/ModuleName/etc/module.xml

entonces podrías correr bin/magento setup:upgrade


0

Creé los archivos y reemplacé los espacios de nombres y el nombre del módulo, pero creo que mis archivos no se ejecutarán.

Tal vez un error en mis archivos?

registro.php

<?php

use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Jacor_Checkoutpayment',
__DIR__
);

composer.json

{
"name": "jacor/checkoutpayment",
"autoload": {
    "psr-4": {
        "Jacor\\Checkoutpayment\\": ""
    },
    "files": [
        "registration.php"
    ]
}

}

module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Jacor_Checkoutpayment" setup_version="1.0.0" />
</config>

0

en realidad, anular los archivos principales de magento no es una buena idea. En lugar de anular Magento_Checkout/js/action/select-payment-methodmejor crear un mixin para ello. Y puede revenderlo sin crear un nuevo controlador. Vea a continuación (además de la respuesta @magestyapps)

  1. app / code / Namespace / ModuleName / view / frontend / requirejs-config.js

        var config = {
            config: {
                mixins: {
                    'Magento_Checkout/js/action/select-payment-method': {
                        'Namespace_ModuleName/js/checkout/action/select-payment-method-mixin': true
                    },
                }
            }
        };
  2. app / code / Namespace / ModuleName / view / frontend / js / checkout / action / select-payment-method-mixin.js

        define([
        'jquery',
        'mage/utils/wrapper',
        'mage/storage',
        'Magento_Checkout/js/action/get-totals',
        'Magento_Checkout/js/model/full-screen-loader',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/url-builder',
        'Magento_Customer/js/model/customer',
    ], function ($, wrapper, storage, getTotalsAction, fullScreenLoader, quote, urlBuilder, customer) {
        'use strict';
        return function (selectPaymentMethod) {
            return wrapper.wrap(selectPaymentMethod, function (originalAction, paymentMethod) {
                var serviceUrl, payload;
    
                originalAction(paymentMethod);
    
                payload = {
                    method: paymentMethod
                };
                if (customer.isLoggedIn()) {
                    serviceUrl = urlBuilder.createUrl('/carts/mine/selected-payment-method', {});
                } else {
                    serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/selected-payment-method', {
                        cartId: quote.getQuoteId()
                    });
                }
                fullScreenLoader.startLoader();
                storage.put(
                    serviceUrl,
                    JSON.stringify(payload)
                ).success(function () {
                    getTotalsAction([]);
                    fullScreenLoader.stopLoader();
                });
            });
        };
    });

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.