7

How to pass a attribute code dynamically in extension_attributes.xml or how to save a custom field value in db in checkout page without extension_attributes

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="How_to_pass_code_dynamically_here" type="string" />
        <attribute code="How_to_pass_code_dynamically_here" type="string" />
    </extension_attributes>
</config>

It should contain getters and setters of address attribute. In this case. <attribute_code="example"> setExample(), getExample()

attribute_code are given by admin dynamically in backend

code:

 $attributeCollection = $this->helper->getUserDefinedAttribures();
       if ($attributeCollection->getSize() > 0) 
       {
         foreach ($attributeCollection as $attribute)    
         {
          if ($this->helper->isAttribureForCheckoutRegister($attribute- 
          >getAttributeCode()))
         {

           $customAttributeCode = $attribute->getAttributeCode();
            var_dump($customAttributeCode);

          }
        }
    }

image:

enter image description here

I have created a customer attribute which created dynamically from backend its fine works in customer_account_create and customer_account_edit and I stuck at saving customer attribute field data in after saving address information in the checkout form. After filling shipping address, shipping and press next button method I m getting the following error

message: "Internal Error. Details are available in Magento log file. Report ID: webapi-5d3aa1ebbf82a"

Exception log: 'Report ID: webapi-5d3aa1ebbf82a; Message: Property "TestAge" does not have corresponding setter in class "Magento\Quote\Api\Data\AddressExtensionInterface".' in D:\wamp64\www\m2\magento\vendor\magento\framework\Webapi\ErrorProcessor

and I followed this link

app/code/Cm/CustomerAttribute/etc/frontend/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\Checkout\Block\Onepage">
        <arguments>
            <argument name="layoutProcessors" xsi:type="array">
                <item name="cm__fields_layoutprocessor" xsi:type="object">Cm\CustomerAttribute\Block\Checkout\LayoutProcessor</item>
            </argument>
        </arguments>
    </type>
</config>

app/code/ Cm/CustomerAttribute/Block/Checkout/LayoutProcessor.php

<?php
namespace Cm\CustomerAttribute\Block\Checkout;

class LayoutProcessor
{
    protected $customerSession;
    protected $resultPageFactory;
    public function __construct(\Cm\CustomerAttribute\Helper\Customerattribute $helper,
    \Magento\Customer\Api\CustomerRepositoryInterface $customerRepositoryInterface,
    \Magento\Customer\Model\Session $customerSession)
    {
        $this->helper = $helper;
        $this->customerRepositoryInterface = $customerRepositoryInterface;
        $this->customerSession = $customerSession;
    }
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        $jsLayout
    ) {
        $attributeCollection = $this->helper->getUserDefinedAttribures();

       if ($attributeCollection->getSize() > 0) 
       {
         foreach ($attributeCollection as $attribute)

         {
        if ($this->helper->isAttribureForCheckoutRegister($attribute->getAttributeCode()))
        {
        $frontEndLabel = $attribute->getStoreLabel($this->helper->getStoreId());

        $customAttributeCode = $attribute->getAttributeCode();
      if($this->customerSession->isLoggedIn()) {

        $customerId =$this->customerSession->getCustomer()->getId();
         $customer =$this->customerRepositoryInterface->getById($customerId);
        $customerAttr = $customer->getCustomAttribute($customAttributeCode)->getValue();
        }
        else
        {
          $customerAttr = NULL;
        }
        $fieldRequiredClass = ($attribute->getIsRequired()) ? 'true' : '' ;
        if($fieldRequiredClass == '')
        {
            $fieldRequiredClass = false;
        }
        $fieldFrontendClass = ($attribute->getFrontendClass()) ? $attribute->getFrontendClass() : '';
        $fieldInput =$attribute->getFrontendInput();
        $attributeId = $attribute->getAttributeId();
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        $attributeOptionAll = $objectManager->create(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class)
                                    ->setPositionOrder('asc')
                                    ->setAttributeFilter($attributeId)
                                    ->setStoreFilter()
                                    ->load();
        $opt_val = array();
        $allOptions=array();


        foreach ($attributeOptionAll->getData() as $key => $v) 
        {
          // $allid = $v['attribute_id'];
          $opt_val['value'] = $v['option_id'];
          $opt_val['label'] = $v['value'];
          $allOptions[] = $opt_val;
      }
        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
        ['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $this->addNewField($customAttributeCode,$frontEndLabel, $fieldRequiredClass,  $fieldFrontendClass,$fieldInput,  $allOptions, $customerAttr );

        }
      }
    }
    return $jsLayout;
    }

    private function addNewField($customAttributeCode, $frontEndLabel, $fieldRequiredClass,  $fieldFrontendClass, $fieldInput, $allOptions, $customerAttr  )
    {
        if($fieldInput == 'text')
        {
            $fieldInputType = 'input';
            $fieldAbstract =  'abstract';
        }
        elseif ($fieldInput == 'date') {
           $fieldInputType = 'date'; 
           $fieldAbstract =  'date';
        }
        elseif ($fieldInput == 'select') {
           $fieldInputType = 'select'; 
           $fieldAbstract =  'select';
        }

        elseif ($fieldInput == 'boolean') {
           $fieldInputType = 'select'; 
           $fieldAbstract =  'select';
           $allOptions = [
                 ['value' => '0', 'label' => 'No'],
                 ['value' => '1', 'label' => 'Yes']
               ];

        }
         elseif ($fieldInput == 'textarea') {
           $fieldInputType = 'textarea'; 
           $fieldAbstract =  'textarea';

        }
        $customField = [
            'component' => 'Magento_Ui/js/form/element/'.$fieldAbstract.'',
            'config' => [
                'customScope' => 'shippingAddress.custom_attributes',
                'customEntry' => null,
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/'.$fieldInputType.'',
                'rows' => 5
                // 'tooltip' => [
                //     'description' => 'this is what the field is for',
                // ],
            ],
            'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
            'label' => $frontEndLabel,
            'provider' => 'checkoutProvider',
            'sortOrder' => 1000,
            'validation' => [$fieldFrontendClass => true , 
                'required-entry' => $fieldRequiredClass],
            'options' =>  $allOptions,
            'filterBy' => null,
            'customEntry' => null,
            'visible' => true,
            'value' => $customerAttr
        ];

         return $customField;
    }
}

app/code/Cm/CustomerAttribute/view/frontend/requirejs-config.js

 var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-billing-address': {
                'Cm_CustomerAttribute/js/action/set-billing-address-mixin': true
            },
            'Magento_Checkout/js/action/set-shipping-information': {
                'Cm_CustomerAttribute/js/action/set-shipping-information-mixin': true
            },
            'Magento_Checkout/js/action/create-shipping-address': {
                'Cm_CustomerAttribute/js/action/create-shipping-address-mixin': true
            },
            'Magento_Checkout/js/action/place-order': {
                'Cm_CustomerAttribute/js/action/set-billing-address-mixin': true
            },
            'Magento_Checkout/js/action/create-billing-address': {
                'Cm_CustomerAttribute/js/action/set-billing-address-mixin': true
            }
        }
    }
};

app/code/Cm/CustomerAttribute/view/frontend/web/js/action/create-shipping-address-mixin.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, messageContainer) {

            if (messageContainer.custom_attributes != undefined) {
                $.each(messageContainer.custom_attributes , function( key, value ) {
                    messageContainer['custom_attributes'][key] = {'attribute_code':key,'value':value};
                });
            }

            return originalAction(messageContainer);
        });
    };
});

app/code/Cm/CustomerAttribute/view/frontend/web/js/action/set-billing-address-mixin.js

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

    return function (setBillingAddressAction) {
        return wrapper.wrap(setBillingAddressAction, function (originalAction, messageContainer) {

            var billingAddress = quote.billingAddress();

            if(billingAddress != undefined) {

                if (billingAddress['extension_attributes'] === undefined) {
                    billingAddress['extension_attributes'] = {};
                }

                if (billingAddress.customAttributes != undefined) {
                    $.each(billingAddress.customAttributes, function (key, value) {

                        if($.isPlainObject(value)){
                            value = value['value'];
                        }

                        billingAddress['extension_attributes'][key] = value;
                    });
                }

            }

            return originalAction(messageContainer);
        });
    };
});

app/code/Cm/CustomerAttribute/view/frontend/web/js/action/set-shipping-information-mixin.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, messageContainer) {

            var shippingAddress = quote.shippingAddress();

            if (shippingAddress['extension_attributes'] === undefined) {
                shippingAddress['extension_attributes'] = {};
            }

            if (shippingAddress.customAttributes != undefined) {
                $.each(shippingAddress.customAttributes , function( key, value ) {

                    if($.isPlainObject(value)){
                        value = value['value'];
                    }

                    shippingAddress['customAttributes'][key] = value;
                    shippingAddress['extension_attributes'][key] = value;

                });
            }

            return originalAction(messageContainer);
        });
    };
});

app/code/Cm/CustomerAttribute/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\Checkout\Model\ShippingInformationManagement">
         <plugin name="Cm_CustomerAttribute::ShippingInformationManagement" 
 type="Cm\CustomerAttribute\Plugin\Checkout\Model\ShippingInformationManagement" sortOrder="1"/>
          </type>
      </config>

app/code/Cm/CustomerAttribute/Plugin/Checkout/Model/ShippingInformationManagement.php

   <?php
    namespace Cm\CustomerAttribute\Plugin\Checkout\Model;

  class ShippingInformationManagement
{
    /**
     * @param \Magento\Checkout\Model\ShippingInformationManagement $subject
     * @param $cartId
     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
     */
     protected $helper;
     protected $quoteRepository;
     public function __construct(

    \Bootsgrid\CustomerAttribute\Helper\Customerattribute $helper,
     \Magento\Quote\Model\QuoteRepository $quoteRepository
    ) {

        $this->helper = $helper;
         $this->quoteRepository = $quoteRepository;
    }


    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    ) {
       $extensionAttributes = $addressInformation->getShippingAddress();
       $custAttributes = $extensionAttributes->getExtensionAttributes();
       if($custAttributes )
       {
         $quote = $this->quoteRepository->getActive($cartId);


        $customField = $custAttributes->getTestTextarea();
        $cus = $custAttributes->getTestAge();
        $quote->setTestAge($cus);
        $quote->setTestTextarea($customField);



      }
        // error_log(print_r($custAttributes,1));
    }
}

How to save the customer_field dynamically in sales_order and quote order in magento 2

image:

enter image description here When using extension_attributes.xml file its saved into db but i want to pass a attribute_code dynamically in the xml file

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="test_age" type="string" /> \* how to pass "test_age" dynamically *\
        <attribute code="test_textarea" type="string" />
    </extension_attributes>
</config>

enter image description here

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.