4

I have added the drop-down custom field on checkout page with custom values.

enter image description here

InstallSchema.php

$connection->addColumn(
                $installer->getTable('quote_address'),
                'mob_type',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table ::TYPE_TEXT,
                    'nullable' => true,
                    'default' => NULL,
                    'length' => 255,
                    'comment' => 'Mob Type'
                ]
            );
        $connection->addColumn(
                $installer->getTable('sales_order_address'),
                'mob_type',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table ::TYPE_TEXT,
                    'nullable' => true,
                    'default' => NULL,
                    'length' => 255,
                    'comment' => 'Mob Type'
                ]
            );
        $installer->endSetup();

Plugin

use Magento\Checkout\Block\Checkout\LayoutProcessor;

class MobPlugin
{
    public function afterProcess(LayoutProcessor $subject, $jsLayout) {
        $customAttributeCode = 'mob_type';
        $customField = [
            'component' => 'Magento_Ui/js/form/element/select',
            'config' => [
                'customScope' => 'shippingAddress.custom_attributes',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/select',
                'id' => 'drop-down',
            ],
            'dataScope' => 'shippingAddress.custom_attributes.mob_type',
            'label' => 'Mob Type',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => ['required-entry' => true],
            'sortOrder' => 150,
            'id' => 'drop-down',
            'options' => [
                [
                    'value' => 'local',
                    'label' => 'Local',
                ],
                [
                    'value' => 'vip',
                    'label' => 'VIP',
                ]
            ]
        ];

        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField;

        return $jsLayout;
    }
}

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="save_custom_field" type="Namespace\CustomModule\Plugin\Checkout\SaveAddressInformation" />
    </type>

</config>

SaveAddressInformation.php

class SaveAddressInformation
{
    protected $quoteRepository;
    public function __construct(
        \Magento\Quote\Model\QuoteRepository $quoteRepository
    ) {
        $this->quoteRepository = $quoteRepository;
    }
    /**
     * @param \Magento\Checkout\Model\ShippingInformationManagement $subject
     * @param $cartId
     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
     */
    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    ) {
        $shippingAddress = $addressInformation->getShippingAddress();
    $shippingAddressExtensionAttributes = $shippingAddress->getExtensionAttributes();
    if ($shippingAddressExtensionAttributes) {
        $customField = $shippingAddressExtensionAttributes->getMobType();
        $shippingAddress->setMobType($customField);
    }

    }
}

But once click on shipping rate of radio button Magento call guest or user API to carrier model, In carrier model all request information passed but my custom attribute values not getting.

-module-offline-shipping\Model\Carrier\Flaterate.php

private function getShippingPrice(RateRequest $request, $freeBoxes)
    {
       echo $request->getMobType(); exit; // empty result
        $shippingPrice = false;

        $configPrice = $this->getConfigData('price');
        if ($this->getConfigData('type') === 'O') {
            // per order
            $shippingPrice = $this->itemPriceCalculator->getShippingPricePerOrder($request, $configPrice, $freeBoxes);
        } elseif ($this->getConfigData('type') === 'I') {
            // per item
            $shippingPrice = $this->itemPriceCalculator->getShippingPricePerItem($request, $configPrice, $freeBoxes);
        }

        $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice);

        if ($shippingPrice !== false && (
                $request->getFreeShipping() === true || $request->getPackageQty() == $freeBoxes
            )
        ) {
            $shippingPrice = '0.00';
        }
        return $shippingPrice;
    }
5
  • Do you mean, when you click "Next" button you lose your custom attribute on shipping address ? Do you have set-shipping-information-mixin.js in your module?
    – krybbio
    Commented Apr 1, 2018 at 3:31
  • yes. I did it. but I am not getting me value on request object. Commented Apr 1, 2018 at 5:44
  • Did you found solution for this? Commented May 13, 2021 at 14:01
  • @Magento2Devloper Have you found any solution
    – Pawankumar
    Commented Jul 28, 2021 at 14:36
  • @Ranganathan have you found any solution
    – Pawankumar
    Commented Aug 6, 2021 at 2:16

4 Answers 4

1

When you click on a specific shipping rate, all fields are not passed to the api call. It only passes the fields specified in the shipping rate validation rules JS.

You can find the file for FlatRate here:

vendor/magento/module-offline-shipping/view/frontend/web/js/shipping-rate-validation-rules/flatrate.js

Override that file and add your field there, that should send it to the shipping rates api call.

10
  • but how can i pass custom attribute in require? Commented Mar 26, 2018 at 6:33
  • What do you mean? You need to override the js file and add it to the getRules() function
    – hungersoft
    Commented Mar 26, 2018 at 6:35
  • I understand but how can I set it? like as getRules: function () { return { 'postcode': { 'required': true }, 'custom_attributes': { 'required': true } }; } Commented Mar 26, 2018 at 6:39
  • No, you need to use the attribute code mob_type.
    – hungersoft
    Commented Mar 26, 2018 at 6:43
  • did but only four values passed in the address. Commented Mar 26, 2018 at 6:50
1

It's not possible, Magento2 is hard coding the fields needed for collecting shipping methods here : /magento/module-quote/Model/Quote/Address.php line : 984

Magento2 design is not flexible [at all] and is over complicated.

3
  • 984 - but this position in how to get address values? Commented May 29, 2018 at 10:32
  • @Magento2Devloper your comment isn't clear. Commented May 30, 2018 at 10:59
  • it's means I am not getting custom filed values in address object and not in request object Commented May 30, 2018 at 11:20
1

I was having the exact same problem. In the end the only thing that worked for me was to get the POST data and use them to calculate the shipping rate cost. I will really glad to see how it should be done the "magento way"

$formpostdata = json_decode(file_get_contents('php://input'), true);
if (isset($formpostdata['address']['custom_attributes']['mob_type'])) {
    // add here your logic
}
2
  • This one solution is not working in magento2.2.x version getting json_decode error. Commented Feb 5, 2019 at 5:40
  • Hi, this works but were you able to find solution in standard magento way? I am facing the same issue like in this post Commented Oct 11, 2023 at 9:43
0

Flatrate->geShippingPrice() log:

[2018-04-01 09:25:48] main.DEBUG: Flatrate->getShippingPrice::Array
(
    [all_items] => Array
        (
            [0 (Magento\Quote\Model\Quote\Item)] => Array
                (
                    [item_id] => 134
                    [quote_id] => 138
                    [created_at] => 2018-04-01 09:15:02
                    [updated_at] => 0000-00-00 00:00:00
                    [product_id] => 3
                    [store_id] => 1
                    [is_virtual] => 0
                    [sku] => test
                    [name] => test
                    [is_qty_decimal] => 
                    [no_discount] => 0
                    [weight] => 0.0000
                    [qty] => 1
                    [price] => 10
                    [base_price] => 10
                    [discount_percent] => 0.0000
                    [discount_amount] => 0.0000
                    [base_discount_amount] => 0.0000
                    [tax_percent] => 0
                    [tax_amount] => 0
                    [base_tax_amount] => 0
                    [row_total] => 10
                    [base_row_total] => 10
                    [row_total_with_discount] => 0.0000
                    [row_weight] => 0
                    [product_type] => simple
                    [price_incl_tax] => 10
                    [base_price_incl_tax] => 10
                    [row_total_incl_tax] => 10
                    [base_row_total_incl_tax] => 10
                    [discount_tax_compensation_amount] => 0
                    [base_discount_tax_compensation_amount] => 0
                    [free_shipping] => 
                    [qty_options] => Array
                        (
                        )

                    [product (Magento\Catalog\Model\Product\Interceptor)] => Array
                        (
                            [entity_id] => 3
                            [attribute_set_id] => 4
                            [type_id] => simple
                            [sku] => test
                            [has_options] => 0
                            [required_options] => 0
                            [created_at] => 2018-03-12 15:09:32
                            [updated_at] => 2018-03-12 15:13:51
                            [price] => 10.0000
                            [weight] => 0.0000
                            [name] => test
                            [url_key] => test
                            [gift_message_available] => 2
                            [status] => 1
                            [visibility] => 4
                            [tax_class_id] => 2
                            [request_path] => test.html
                            [tier_price] => Array
                                (
                                )

                            [tier_price_changed] => 0
                            [store_id] => 1
                            [customer_group_id] => 0
                        )

                    [tax_class_id] => 2
                    [has_error] => 
                    [converted_price] => 10
                    [base_original_price] => 10.0000
                    [base_calculation_price] => 10
                    [tax_calculation_item_id] => sequence-1
                    [tax_calculation_price] => 10
                    [base_tax_calculation_price] => 10
                    [discount_calculation_price] => 10
                    [base_discount_calculation_price] => 10
                )

        )

    [dest_country_id] => IT
    [dest_region_code] => Stato/Provincia
    [dest_street] => Indirizzo
    [dest_city] => Città
    [dest_postcode] => 00000
    [package_value] => 10
    [package_value_with_discount] => 10
    [package_weight] => 0
    [package_qty] => 1
    [package_physical_value] => 10
    [free_method_weight] => 0
    [store_id] => 1
    [website_id] => 1
    [free_shipping] => 
    [base_currency (Magento\Directory\Model\Currency)] => Array
        (
            [currency_code] => EUR
        )

    [package_currency (Magento\Directory\Model\Currency)] => Array
        (
            [currency_code] => EUR
        )

    [base_subtotal_incl_tax] => 10
    [country_id] => US
    [region_id] => 12
    [postcode] => 90034
)

The only fields from Shipping address are:

[dest_country_id] => IT
[dest_region_code] => Stato/Provincia
[dest_street] => Indirizzo
[dest_city] => Città
[dest_postcode] => 00000

because they're needed to calculate shipping rates. So, unless your field affects shipping costs, you don't need it in $request object.

2
  • But I need custom attribute value if mob_type == local set cost - $5 else $8. Commented Apr 1, 2018 at 11:51
  • That's why I need custom attribute value on request object Commented Apr 1, 2018 at 11:51

Your Answer

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

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