2

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;
    }
  • 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 Apr 1 '18 at 3:31
  • yes. I did it. but I am not getting me value on request object. – Magento2 Devloper Apr 1 '18 at 5:44
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.

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

  • 984 - but this position in how to get address values? – Magento2 Devloper May 29 '18 at 10:32
  • @Magento2Devloper your comment isn't clear. – Ahmed Kooli May 30 '18 at 10:59
  • it's means I am not getting custom filed values in address object and not in request object – Magento2 Devloper May 30 '18 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
}
  • This one solution is not working in magento2.2.x version getting json_decode error. – Magento2 Devloper Feb 5 at 5:40
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.

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

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.