2

i'm doing custom checkout with my module, this module create 2 input in first step (shipping address step) and this first step is working fine, but in the 2nd step, it throw error with status code 500, lets take a look at the description image below :
First step: enter image description here

First step working fine with status code 200 and sending extension attribute. enter image description here

But in the second step, when i click at "Place Order", it return status code 500 with this error message: enter image description here

So here is my code:

C:\xampp\htdocs\magento\app\code\Aht\MagentoCheckoutCustom\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">
    <type name="Magento\Quote\Model\ShippingAddressManagement">
        <plugin name="custom_quote_delivery" type="Aht\MagentoCheckoutCustom\Plugin\Quote\Model\ShippingAddressManagement" sortOrder="1" disabled="false"/>
    </type>
</config>

C:\xampp\htdocs\magento\app\code\Aht\MagentoCheckoutCustom\etc\extension_attributes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\AddressInterface">
        <attribute code="delivery_instruction" type="string"/>
        <attribute code="delivery_type" type="string"/>
    </extension_attributes>
</config>

C:\xampp\htdocs\magento\app\code\Aht\MagentoCheckoutCustom\Plugin\Quote\Model\ShippingAddressManagement.php

<?php
namespace Aht\MagentoCheckoutCustom\Plugin\Quote\Model;

class ShippingAddressManagement
{
    protected $logger;

    public function __construct(
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->logger = $logger;
    }

    public function beforeAssign(
        \Magento\Quote\Model\ShippingAddressManagement $subject,
        $cartId,
        \Magento\Quote\Api\Data\AddressInterface $address
    ) {
//        try {
            $extAttributes = $address->getExtensionAttributes();

            $deliveryInstruction = $extAttributes->getDeliveryInstruction();
            $deliveryType = $extAttributes->getDeliveryType();
            $address->setDeliveryInstruction($deliveryInstruction);
            $address->setDeliveryType($deliveryType);
//        } catch (\Exception $e) {
//            $this->logger->critical($e->getMessage());
//        }
    }
}

C:\xampp\htdocs\magento\app\code\Aht\MagentoCheckoutCustom\Setup\UpgradeSchema.php

<?php
namespace Aht\MagentoCheckoutCustom\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Ddl\Table;

class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->startSetup();

        if (version_compare($context->getVersion(), '1.1.0', '<')) {
            if ($installer->tableExists('quote')) {
                $connection = $installer->getConnection();
                $tableName = $installer->getTable('quote');

                $connection->addColumn(
                        $tableName,
                        'delivery_instruction',
                        [
                            'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                            'nullable' => false,
                            'comment' => 'Delivery Instruction'
                        ]
                    );
                $connection->addColumn(
                        $tableName,
                        'delivery_type',
                        [
                            'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                            'nullable' => false,
                            'comment' => 'Delivery Type'
                        ]
                    );
            }
        }

        $installer->endSetup();
    }
}

C:\xampp\htdocs\magento\app\code\Aht\MagentoCheckoutCustom\view\frontend\requirejs-config.js

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                'Aht_MagentoCheckoutCustom/js/action/set-shipping-information': true
            }
        }
    }
};

C:\xampp\htdocs\magento\app\code\Aht\MagentoCheckoutCustom\view\frontend\web\js\action\set-shipping-information.js

define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper, quote) {
    'use strict';

    return function (setShippingInformationAction) {

        return wrapper.wrap(setShippingInformationAction, function (originalAction) {
            var shippingAddress = quote.shippingAddress();
            if (shippingAddress['extension_attributes'] === undefined) {
                shippingAddress['extension_attributes'] = {};
            }

            shippingAddress['extension_attributes']['delivery_instruction'] = $('[name="delivery_instruction"]').val();
            shippingAddress['extension_attributes']['delivery_type'] = $('[name="delivery_type"]').val();
            // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
            return originalAction();
        });
    };
});

Ok, so i've success created 2 column in "Quote" table named "delivery_instruction" and "delivery_type".
And i've follow a lot of source and topic (devdoc, stackexchange, github) but i thing i saw 2 ways to do this.. the sohelrana09 way on github is using another way as what i did.
Here is sohelrana09 way:
https://github.com/sohelrana09/magento2-module-delivery-date/tree/master/SR/DeliveryDate
And the way i'm following to is from here and the devdoc:
Save a custom attribute from shipping method to quote_address
https://devdocs.magento.com/guides/v2.2/howdoi/checkout/checkout_new_field.html
I've also found another way convert 2 way somehow .. but doesn't have example
Save Custom field in shipping address at Checkout in Magento 2

Okay so i dont know which one is correct, and if both correct, which one is better, Thanks for reading, Have a good day :)

fudu
  • 1,278
  • 2
  • 22
  • 41

1 Answers1

1

That means your code at line:

$extAttributes = $address->getExtensionAttributes(); //return null

please use a plugin to before save instead or add a new observer to the event sales_quote_address_save_before

Example Event observer:

<event name="sales_quote_address_save_before">
    <observer name="namespace_module_addres_save_before" instance="Namespace\Module\Observer\AddressDataBeforeSave" />
</event>


use Magento\Framework\Event\ObserverInterface;

class AddressDataBeforeSave implements ObserverInterface
{
    /**
     *          *
     * @param \Magento\Framework\Event\Observer $observer
     * @return $this
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $quoteAddress = $observer->getEvent()->getQuoteAddress();
        //enter code here
        return $this;
    }
}
HoangHieu
  • 1,348
  • 8
  • 24
  • Oh thanks.. i'll do it and feedback to you later :) – fudu Sep 15 '18 at 10:07
  • Hi .. about ur answer, do you mean i need to follow this source? https://github.com/sohelrana09/magento2-module-delivery-date/tree/master/SR/DeliveryDate because i see it really look like your answer, and if i follow this source, should i remove mine? – fudu Sep 15 '18 at 15:24
  • Right now, i'm not using observer, and i'm override this Magento\Quote\Model\ShippingAddressManagement, but in that source, they use observer and override Magento\Checkout\Model\ShippingInformationManagement instead – fudu Sep 15 '18 at 15:28
  • Dont mater what source did you tried. In your case that mean extAttr doesn't process yet beforeSave to make sure extAttr has processed. – HoangHieu Sep 15 '18 at 15:34
  • Sorry i'm new with this, first time know about observer and plugin .. – fudu Sep 15 '18 at 15:42
  • 1 quick question: how can i know which event should i use with observer? Does it have any devdoc or trick here? – fudu Sep 15 '18 at 15:43
  • Search events observers in magento. Use observer when observer list can support you. – HoangHieu Sep 15 '18 at 15:45
  • did my answer resolve your problem ?? – HoangHieu Sep 16 '18 at 04:00
  • Hi, i dont know what should i put in that AddressDataBeforeSave execute() part, in this module they save extension data to Repository and then they called it with objectManager.https://github.com/sohelrana09/magento2-module-delivery-date/blob/master/SR/DeliveryDate/Observer/SaveDeliveryDateToOrderObserver.php Should i do it too? – fudu Sep 16 '18 at 08:03
  • Did you debug $quoteAddress ?? – HoangHieu Sep 16 '18 at 08:12