2

In case of virtual products, we do not need a shipping step so customer directly goes for payment step during checkout.

I have a simple product and a custom field delivery_type in quote table. delivery_type field's value is updated on the cart page by selecting what is the delivery type (home/store).

If the value of delivery_type is store shipping step is not required and the customer should see only payment step similar to virtual products at checkout. Can anyone guide me on how I should go about customizing it?

I tried changing the value of field is_virtual to 1 in quote and quote_item table manually but it does not make any difference. I have logged window.checkoutConfig.quoteData.is_virtual which still shows 0.

  • 1
    vendor\magento\module-checkout\view\frontend\web\js\model\quote.js have method name isVirtual: function () { return !!Number(quoteData['is_virtual']);} need to be extend this function hopefully its will be work for you – Arshad Muhammad Aug 10 '18 at 7:34
  • Just to test I changed return value of isVirtual function to true. Is shows message No Payment method available. – amitshree Aug 10 '18 at 7:47
3
+50

Please have a look at this class

Magento\Quote\Model\Quote

in this class you have this method isVirtual() [image attached]

if the return result is true, Magento will skip the Shipping Step.

You can override this method or create a "after plugin" (recommended) to change the return value as you want

https://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html

enter image description here

| improve this answer | |
  • Thanks a lot.. for this post, it really helped me to achieve my requirement. – Amy Dec 20 '19 at 13:35
  • If a different type of product is available in the cart then add to cart is not working afterIsVirtual(). – Vinod Kumar Sep 23 at 11:00
0

Found generic way to skip shipping, not just for virtual products, in my case I have table driven shipping rate according to zip code (distance), and shipping screen is redundant. The idea is waiting for the shipping screen to load and then approve and continue automatically.

  1. Create requirejs-config.js file in
    app/code/[Vendor]/[Modulename]/view/
    folder and add below code see why.
var config = {
   paths: {
      'Magento_Checkout/js/view/shipping': '[Vendor]_[Modulename]/js/view/shipping'
   }
};
  1. Copy Shipping.js from magento source folder:
    vendor/magento/module-checkout/view/frontend/web/js/view to your module in the following folder:
    app/code/[Vendor]/[Modulename]/view/frontend/web/js/view

  2. Revising the Shipping.js to include the following code:

define([
    'jquery',
    'underscore',
    'Magento_Ui/js/form/form',
    'ko',
    'Magento_Customer/js/model/customer',
    'Magento_Customer/js/model/address-list',
    'Magento_Checkout/js/model/address-converter',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/action/create-shipping-address',
    'Magento_Checkout/js/action/select-shipping-address',
    'Magento_Checkout/js/model/shipping-rates-validator',
    'Magento_Checkout/js/model/shipping-address/form-popup-state',
    'Magento_Checkout/js/model/shipping-service',
    'Magento_Checkout/js/action/select-shipping-method',
    'Magento_Checkout/js/model/shipping-rate-registry',
    'Magento_Checkout/js/action/set-shipping-information',
    'Magento_Checkout/js/model/step-navigator',
    'Magento_Ui/js/modal/modal',
    'Magento_Checkout/js/model/checkout-data-resolver',
    'Magento_Checkout/js/checkout-data',
    'uiRegistry',
    'mage/translate',
    'Magento_Checkout/js/model/shipping-rate-service'
], function (
    $,
    _,
    Component,
    ko,
    customer,
    addressList,
    addressConverter,
    quote,
    createShippingAddress,
    selectShippingAddress,
    shippingRatesValidator,
    formPopUpState,
    shippingService,
    selectShippingMethodAction,
    rateRegistry,
    setShippingInformationAction,
    stepNavigator,
    modal,
    checkoutDataResolver,
    checkoutData,
    registry,
    $t
) {
    'use strict';

    var popUp = null;

    // ### 1st revision start
    var timer = setInterval(function() {
        // Wait until all page was loaded, using Next button div id
        var nextVar = $( "#shipping-method-buttons-container");
        if (nextVar.length > 0) {
            clearInterval(timer);
            // Make sure 'Next' button is visible
            var nextBtn = $("button", nextVar);
            if (nextBtn.is(":visible")) {
                __self.setShippingInformation();
            }

        }
    }, 100);

    // ### 1st revision end

    return Component.extend({
        defaults: {
            template: 'Magento_Checkout/shipping',
            shippingFormTemplate: 'Magento_Checkout/shipping-address/form',
            shippingMethodListTemplate: 'Magento_Checkout/shipping-address/shipping-method-list',
            shippingMethodItemTemplate: 'Magento_Checkout/shipping-address/shipping-method-item'
        },
        visible: ko.observable(!quote.isVirtual()),
        errorValidationMessage: ko.observable(false),
        isCustomerLoggedIn: customer.isLoggedIn,
        isFormPopUpVisible: formPopUpState.isVisible,
        isFormInline: addressList().length === 0,
        isNewAddressAdded: ko.observable(false),
        saveInAddressBook: 1,
        quoteIsVirtual: quote.isVirtual(),

        /**
         * @return {exports}
         */
        initialize: function () {
            var self = this,
                hasNewAddress,
                fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset';

            // ### last revision start
            __self = self;
            // ### last revision end

            this._super();
            ...

Using setInterval is not best practice, but couldn't find a way to trigger setShippingInformation() after the shipping screen fully loaded. Tried $(document).ready as well as $(window).on("load", function) but the document wasn't fully loaded even then, making the call to setShippingInformation() to be ignored.

Hope this helps anyone.

| improve this answer | |
  • what are you doing with this code? how can you skip as like this? – Sarvesh Tiwari Jun 7 at 11:41
  • Uncaught ReferenceError: __self is not defined – Sarvesh Tiwari Jun 7 at 11:54
  • I'm calling the function as if you pressed the Next button, I think you missed the 2nd revision in the code: __self = self; – adir katz Jun 14 at 16:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.