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;
 }
asked Mar 24, 2018 at 4:15
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? 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 Commented Jul 28, 2021 at 14:36
  • @Ranganathan have you found any solution 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.

answered Mar 26, 2018 at 6:14
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 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. 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.

answered May 29, 2018 at 10:16
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
}
answered Aug 23, 2018 at 17:20
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.

answered Apr 1, 2018 at 9:34
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

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.