6

I have created a custom shipping method which allows delivery to a local office of the carrier. I have created a select when the shipping method is selected, so the user picks the office. Now I need to store the office ID to quote_address when it is provided.

I have managed to add that field to extension_attributes, so when the checkout form is submitted, this is passed to the back-end (@ http://website/rest/default/V1/guest-carts/e01f063c3b16e082b3546697e321e643/shipping-information:

sendJson

carrier_office in extension_attributes is what I need to save. I already created an install script, which creates a column in quote_address and its there in the database. I just need to save the value to it.

What I've done is first, I set up an extension field in in 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="carrier_office" type="string"/>
    </extension_attributes>
</config>

Then in di.xml I set up a plugin:

<?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="Vendor_Module\Api\OfficeManagementInterface" type="Vendor_Module\Model\OfficeManagement" />
    <preference for="Vendor_Module\Api\Data\OfficeInterface" type="Vendor_Module\Model\Office" />
    <type name="Magento\Quote\Model\ShippingAddressManagement">
        <plugin disabled="false" name="Creatizmo_Speedy_Plugin_Magento_Quote_Model_ShippingAddressManagement" sortOrder="10" type="Vendor_Module\Plugin\Magento\Quote\Model\ShippingAddressManagement"/>
    </type>
</config>

Where of course Vendor_Module is replaced with my module's name.

And then in Plugin/Magento/Quote/Model/ShippingAddressManagement:

namespace Vendor_Module\Plugin\Magento\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
    ) {

        $extAttributes = $address->getExtensionAttributes();

        if (!empty($extAttributes)) {

            try {
                $address->setCarrierOffice($address->getCarrierOffice());
            } catch (\Exception $e) {
                $this->logger->critical($e->getMessage());
            }

        }

    }
}

In the last file I can see the extension attribute with the correct ID (if I dump it), but it's not saved. It seems $address->setCarrierOffice is not doing its thing or maybe it's not the right place for a hook.. I don't know

Any suggestions on what I'm doing wrong or what I should be doing are highly appreciated.

Aasim Goriya
  • 5,444
  • 2
  • 28
  • 53
DreamWave
  • 133
  • 1
  • 1
  • 14
  • Hi i want add custom distance (warehosue to shipping address which i get from google api in scripts/helper class)variable/value to shipping address whenever address change or default address in shipping address. – sangan Jan 04 '18 at 06:55
  • wait, so $address get the attribute, and then you set the attribute back to $address? @@ I'm doing exactly like you but don't understand at all .. @@ – fudu Sep 14 '18 at 07:18

3 Answers3

3

Seem that you're wrong when trying to get the carrier office code

$address->setCarrierOffice($address->getCarrierOffice());

It should be

$address->setCarrierOffice($extAttributes->getCarrierOffice());

The value is from extension attributes.

Khoa TruongDinh
  • 32,054
  • 11
  • 88
  • 155
1

Following a tutorial it used a helper method to transport the fields from extension attributes to another object via the getters and setters.

Within the Plugin e.g. Payment Information Management is the example I had. Their helper method could be used on the payment or shipping extension attributes.

{
    $extAttributes = $address->getExtensionAttributes();
    if (!empty($extAttributes)) {
        $this->helper->transportFieldsFromExtensionAttributesToObject(
            $extAttributes,
            $address,
            'extra_checkout_billing_address_fields'
        );
    }
}

In Helper/Data.php

public function transportFieldsFromExtensionAttributesToObject(
    $fromObject,
    $toObject,
    $fieldset='extra_checkout_billing_address_fields'
)
{
    foreach($this->getExtraCheckoutAddressFields($fieldset) as $extraField) {
        $set = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $extraField)));
        $get = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $extraField)));
        $value = $fromObject->$get();
        try {
            $toObject->$set($value);
        } catch (\Exception $e) {
            $this->logger->critical($e->getMessage());
        }
    }
    return $toObject;
}

Which amounts to the same thing Khoa TruongDinh said. Using the getters and setters to assign the value from the Extension Attributes into the object passed through to the quote/estimates.

$extAttributes = $address->getExtensionAttributes();
if (!empty($extAttributes)) {
    $this->helper->transportFieldsFromExtensionAttributesToObject(
        $extAttributes,
        $address,
        'extra_checkout_shipping_address_fields'
    );
}

The guide I was following was was a website but was more helpful to look at their code in git. https://codeblog.experius.nl/magento-2-add-extra-billing-or-shipping-field-to-the-checkout/

Github repo here: https://github.com/experius/Magento-2-Module-Experius-ExtraCheckoutAddressFields/blob/master/Plugin/Magento/Quote/Model/ShippingAddressManagement.php

However the values are still NULL when I look at them in shipping cost estimate but I may have somewhere else to set it for my use case as I am using a different module for customized shipping/carrier costs...

Liam Mitchell
  • 356
  • 4
  • 14
0

I'm not that familiar with extension attributes and more with custom attributes.

But looking at \Magento\Quote\Api\Data\AddressInterfaceyou might want to use

->setExtensionAttributes(\Magento\Quote\Api\Data\AddressExtensionInterface $extensionAttributes);

You will need to construct the \Magento\Quote\Api\Data\AddressExtensionInterfaceand use that to set your extension attribute itself.

Again , not that familiar so its just a piece of information that i hope will help you out.

CompactCode
  • 2,467
  • 1
  • 20
  • 36