0

When add a product to the cart, Then an error shows as "Invalid address id". How to solve this issue

  • 1
    check using clera broswer cache and cache flush – Rakesh Jesadiya Oct 6 '17 at 5:16
  • Done. But no changes. Still shows that error. – Rita Jose Oct 6 '17 at 6:12
  • are you login in website, right? – Dhiren Vasoya Oct 6 '17 at 6:13
  • @DhirenVasoya yes, after login & add a product to cart – Rita Jose Oct 6 '17 at 6:16
  • The issue is that, dua to some reason the address which is store for customer is mismatch. do you have database access? – Dhiren Vasoya Oct 6 '17 at 6:21
1

This is core Magento2 issue. And created a module for this solution.

Steps to reproduce the issue.

1.Login

2.Add a product to your basket (remember which product you added)

3.Go to checkout and select a delivery address (do not process a transaction)

4.Remove the product from basket

5.Delete the address you selected from your account

6.add the same product as before to your basket

Then an error shows as "Invalid address id" .

This is related to missing address id in quote_address database table. The reference to address which is removed from customer addressbook is still exists in this table. Magento try to fetch customer address in address repository using customer id and halt.

This module is only helps to avoid the issue in future. For the existing issue, we have to edit the database entry itself.

for eg: if error shows like "invalid address id 185". check the address id with 185 in quote_address table. Then replace the corresponding customer_id against that address_id as "NULL". The the issue resolved and able to add a product to cart. Module creation steps.

in Custom/DefaultAddress/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Custom_DefaultAddress',
 __DIR__
);
?>

in Custom/DefaultAddress/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Custom_DefaultAddress" setup_version="0.0.1"/>
</config>

in Custom/DefaultAddress/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">
  <preference for="Magento\Customer\Controller\Address\Delete" type="Custom\DefaultAddress\Controller\Rewrite\Address\Delete" />
<preference for="Magento\Customer\Controller\Adminhtml\Index\Save" type="Custom\DefaultAddress\Controller\Adminhtml\Rewrite\Index\Save" />

in Custom/DefaultAddress/etc/frontend/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
 <router id="standard">
<route id="dafaultaddress" frontName="dafaultaddress">
<module name="Custom_DefaultAddress" />
</route>
</router>
</config>

in Custom/DefaultAddress/Controller/Adminhtml/Rewrite/Index/Save.php

<?php
namespace Custom\DefaultAddress\Controller\Adminhtml\Rewrite\Index;
use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Controller\RegistryConstants;
use Magento\Customer\Model\EmailNotificationInterface;
use Magento\Customer\Model\Metadata\Form;
use Magento\Framework\Exception\LocalizedException;

class Save extends \Magento\Customer\Controller\Adminhtml\Index\Save
{
  private $emailNotification;

/**
 * Reformat customer account data to be compatible with customer service interface
 *
 * @return array
 */
protected function _extractCustomerData()
{
    $customerData = [];
    if ($this->getRequest()->getPost('customer')) {
        $additionalAttributes = [
            CustomerInterface::DEFAULT_BILLING,
            CustomerInterface::DEFAULT_SHIPPING,
            'confirmation',
            'sendemail_store_id',
            'extension_attributes',
        ];

        $customerData = $this->_extractData(
            $this->getRequest(),
            'adminhtml_customer',
            CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
            $additionalAttributes,
            'customer'
        );
    }

    if (isset($customerData['disable_auto_group_change'])) {
        $customerData['disable_auto_group_change'] = (int) filter_var(
            $customerData['disable_auto_group_change'],
            FILTER_VALIDATE_BOOLEAN
        );
    }

    return $customerData;
}

/**
 * Perform customer data filtration based on form code and form object
 *
 * @param \Magento\Framework\App\RequestInterface $request
 * @param string $formCode The code of EAV form to take the list of attributes from
 * @param string $entityType entity type for the form
 * @param string[] $additionalAttributes The list of attribute codes to skip filtration for
 * @param string $scope scope of the request
 * @param \Magento\Customer\Model\Metadata\Form $metadataForm to use for extraction
 * @return array Filtered customer data
 * @SuppressWarnings(PHPMD.NPathComplexity)
 */
protected function _extractData(
    \Magento\Framework\App\RequestInterface $request,
    $formCode,
    $entityType,
    $additionalAttributes = [],
    $scope = null,
    \Magento\Customer\Model\Metadata\Form $metadataForm = null
) {
    $metadataForm = $metadataForm ? $metadataForm : $this->getMetadataForm($entityType, $formCode, $scope);
    $formData = $metadataForm->extractData($request, $scope);

    // Initialize additional attributes
    /** @var \Magento\Framework\DataObject $object */
    $object = $this->_objectFactory->create(['data' => $request->getPostValue()]);
    $requestData = $object->getData($scope);
    foreach ($additionalAttributes as $attributeCode) {
        $formData[$attributeCode] = isset($requestData[$attributeCode]) ? $requestData[$attributeCode] : false;
    }

    $result = $metadataForm->compactData($formData);

    // Re-initialize additional attributes
    $formData = array_replace($formData, $result);

    // Unset unused attributes
    $formAttributes = $metadataForm->getAttributes();
    foreach ($formAttributes as $attribute) {
        /** @var \Magento\Customer\Api\Data\AttributeMetadataInterface $attribute */
        $attributeCode = $attribute->getAttributeCode();
        if ($attribute->getFrontendInput() != 'boolean'
            && $formData[$attributeCode] === false
        ) {
            unset($formData[$attributeCode]);
        }
    }

    if (empty($formData['extension_attributes'])) {
        unset($formData['extension_attributes']);
    }

    return $formData;
}

/**
 * Saves default_billing and default_shipping flags for customer address
 *
 * @param array $addressIdList
 * @param array $extractedCustomerData
 * @return array
 */
protected function saveDefaultFlags(array $addressIdList, array & $extractedCustomerData)
{
    $result = [];
    $extractedCustomerData[CustomerInterface::DEFAULT_BILLING] = null;
    $extractedCustomerData[CustomerInterface::DEFAULT_SHIPPING] = null;
    foreach ($addressIdList as $addressId) {
        $scope = sprintf('address/%s', $addressId);
        $addressData = $this->_extractData(
            $this->getRequest(),
            'adminhtml_customer_address',
            AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
            ['default_billing', 'default_shipping'],
            $scope
        );

        if (is_numeric($addressId)) {
            $addressData['id'] = $addressId;
        }
        // Set default billing and shipping flags to customer
        if (!empty($addressData['default_billing']) && $addressData['default_billing'] === 'true') {
            $extractedCustomerData[CustomerInterface::DEFAULT_BILLING] = $addressId;
            $addressData['default_billing'] = true;
        } else {
            $addressData['default_billing'] = false;
        }
        if (!empty($addressData['default_shipping']) && $addressData['default_shipping'] === 'true') {
            $extractedCustomerData[CustomerInterface::DEFAULT_SHIPPING] = $addressId;
            $addressData['default_shipping'] = true;
        } else {
            $addressData['default_shipping'] = false;
        }
        $result[] = $addressData;
    }
    return $result;
}

/**
 * Reformat customer addresses data to be compatible with customer service interface
 *
 * @param array $extractedCustomerData
 * @return array
 */
protected function _extractCustomerAddressData(array & $extractedCustomerData)
{
    $addresses = $this->getRequest()->getPost('address');
    $result = [];
    if (is_array($addresses)) {
        if (isset($addresses['_template_'])) {
            unset($addresses['_template_']);
        }

        $addressIdList = array_keys($addresses);
        $result = $this->saveDefaultFlags($addressIdList, $extractedCustomerData);
    }

    return $result;
}

/**
 * Save customer action
 *
 * @return \Magento\Backend\Model\View\Result\Redirect
 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
 * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
 * @SuppressWarnings(PHPMD.NPathComplexity)
 */
public function execute()
{
    $returnToEdit = false;
    $originalRequestData = $this->getRequest()->getPostValue();

    $customerId = $this->getCurrentCustomerId();

    if ($originalRequestData) {
        try {
            // optional fields might be set in request for future processing by observers in other modules
            $customerData = $this->_extractCustomerData();
            $addressesData = $this->_extractCustomerAddressData($customerData);

            if ($customerId) {
                $currentCustomer = $this->_customerRepository->getById($customerId);
                $customerData = array_merge(
                    $this->customerMapper->toFlatArray($currentCustomer),
                    $customerData
                );
                $customerData['id'] = $customerId;
            }

            /** @var CustomerInterface $customer */
            $customer = $this->customerDataFactory->create();
            $this->dataObjectHelper->populateWithArray(
                $customer,
                $customerData,
                '\Magento\Customer\Api\Data\CustomerInterface'
            );
            $addresses = [];
            foreach ($addressesData as $addressData) {
                $region = isset($addressData['region']) ? $addressData['region'] : null;
                $regionId = isset($addressData['region_id']) ? $addressData['region_id'] : null;
                $addressData['region'] = [
                    'region' => $region,
                    'region_id' => $regionId,
                ];
                $addressDataObject = $this->addressDataFactory->create();
                $this->dataObjectHelper->populateWithArray(
                    $addressDataObject,
                    $addressData,
                    '\Magento\Customer\Api\Data\AddressInterface'
                );
                $addresses[] = $addressDataObject;
            }

            $this->_eventManager->dispatch(
                'adminhtml_customer_prepare_save',
                ['customer' => $customer, 'request' => $this->getRequest()]
            );
            $customer->setAddresses($addresses);
            if (isset($customerData['sendemail_store_id'])) {
                $customer->setStoreId($customerData['sendemail_store_id']);
            }

            // Save customer
            if ($customerId) {
                $this->_customerRepository->save($customer);
                $this->getEmailNotification()->credentialsChanged($customer, $currentCustomer->getEmail());
            } else {
                $customer = $this->customerAccountManagement->createAccount($customer);
                $customerId = $customer->getId();
            }
            $this->_resources = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\App\ResourceConnection');
            $connection= $this->_resources->getConnection();
            $customer_addressquote_table = $this->_resources->getTableName('quote_address');
            $sql_customeraddressquote = "SELECT customer_address_id FROM ".$customer_addressquote_table." WHERE customer_id = ".$customerId." ";
            $connection->query($sql_customeraddressquote);
            $result_customeraddress_id = $connection->fetchAll($sql_customeraddressquote);
            if(!empty($result_customeraddress_id)){
                foreach( $result_customeraddress_id as $result_customeraddress) {
                    foreach($result_customeraddress as $result_customeraddress_entity){
                        if($result_customeraddress_entity != ''){
                            $customeraddress_table = $this->_resources->getTableName('customer_address_entity');
                            $sql_customeraddress = "SELECT * FROM ".$customeraddress_table." WHERE entity_id = ".$result_customeraddress_entity." ";
                            $connection->query($sql_customeraddress);
                            $resultaddress = $connection->fetchAll($sql_customeraddress);
                            if(empty($resultaddress)){

                                $themeTable = $this->_resources->getTableName('quote_address');
                                $sql = "Update " . $themeTable . " Set customer_address_id = null where customer_address_id = ".$result_customeraddress_entity."";
                                $connection->query($sql);
                            }
                        }
                   }
                }
            }

            $isSubscribed = null;
            if ($this->_authorization->isAllowed(null)) {
                $isSubscribed = $this->getRequest()->getPost('subscription');
            }
            if ($isSubscribed !== null) {
                if ($isSubscribed !== 'false') {
                    $this->_subscriberFactory->create()->subscribeCustomerById($customerId);
                } else {
                    $this->_subscriberFactory->create()->unsubscribeCustomerById($customerId);
                }
            }

            // After save
            $this->_eventManager->dispatch(
                'adminhtml_customer_save_after',
                ['customer' => $customer, 'request' => $this->getRequest()]
            );
            $this->_getSession()->unsCustomerFormData();
            // Done Saving customer, finish save action
            $this->_coreRegistry->register(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId);
            $this->messageManager->addSuccess(__('You saved the customer.'));
            $returnToEdit = (bool)$this->getRequest()->getParam('back', false);
        } catch (\Magento\Framework\Validator\Exception $exception) {
            $messages = $exception->getMessages();
            if (empty($messages)) {
                $messages = $exception->getMessage();
            }
            $this->_addSessionErrorMessages($messages);
            $this->_getSession()->setCustomerFormData($originalRequestData);
            $returnToEdit = true;
        } catch (LocalizedException $exception) {
            $this->_addSessionErrorMessages($exception->getMessage());
            $this->_getSession()->setCustomerFormData($originalRequestData);
            $returnToEdit = true;
        } catch (\Exception $exception) {
            $this->messageManager->addException($exception, __('Something went wrong while saving the customer.'));
            $this->_getSession()->setCustomerFormData($originalRequestData);
            $returnToEdit = true;
        }
    }
    $resultRedirect = $this->resultRedirectFactory->create();
    if ($returnToEdit) {
        if ($customerId) {
            $resultRedirect->setPath(
                'customer/*/edit',
                ['id' => $customerId, '_current' => true]
            );
        } else {
            $resultRedirect->setPath(
                'customer/*/new',
                ['_current' => true]
            );
        }
    } else {
        $resultRedirect->setPath('customer/index');
    }
    return $resultRedirect;
}

/**
 * Get email notification
 *
 * @return EmailNotificationInterface
 * @deprecated
 */
private function getEmailNotification()
{
    if (!($this->emailNotification instanceof EmailNotificationInterface)) {
        return \Magento\Framework\App\ObjectManager::getInstance()->get(
            EmailNotificationInterface::class
        );
    } else {
        return $this->emailNotification;
    }
}

/**
 * Get metadata form
 *
 * @param string $entityType
 * @param string $formCode
 * @param string $scope
 * @return Form
 */
private function getMetadataForm($entityType, $formCode, $scope)
{
    $attributeValues = [];

    if ($entityType == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) {
        $customerId = $this->getCurrentCustomerId();
        if ($customerId) {
            $customer = $this->_customerRepository->getById($customerId);
            $attributeValues = $this->customerMapper->toFlatArray($customer);
        }
    }

    if ($entityType == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) {
        $scopeData = explode('/', $scope);
        if (isset($scopeData[1]) && is_numeric($scopeData[1])) {
            $customerAddress = $this->addressRepository->getById($scopeData[1]);
            $attributeValues = $this->addressMapper->toFlatArray($customerAddress);
        }
    }

    $metadataForm = $this->_formFactory->create(
        $entityType,
        $formCode,
        $attributeValues,
        false,
        Form::DONT_IGNORE_INVISIBLE
    );

    return $metadataForm;
}

/**
 * Retrieve current customer ID
 *
 * @return int
 */
private function getCurrentCustomerId()
{
    $originalRequestData = $this->getRequest()->getPostValue(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER);

    $customerId = isset($originalRequestData['entity_id'])
        ? $originalRequestData['entity_id']
        : null;

    return $customerId;
}
}

in Custom/DefaultAddress/Controller/Rewrite/Address/Delete.php

<?php
namespace Custom\DefaultAddress\Controller\Rewrite\Address;
class Delete extends \Magento\Customer\Controller\Address\Delete
{

    public function execute()
    {
        $addressId = $this->getRequest()->getParam('id', false);

        $address = $this->_addressRepository->getById($addressId);
        if ($addressId && $this->_formKeyValidator->validate($this->getRequest())) {
            try {
                $address = $this->_addressRepository->getById($addressId);
                if ($address->getCustomerId() === $this->_getSession()->getCustomerId()) {
                    $this->_addressRepository->deleteById($addressId);
                    $this->messageManager->addSuccess(__('You deleted the address.'));
                    $customer_id =   $address->getCustomerId();
                    $this->_resources = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\App\ResourceConnection');
                    $connection= $this->_resources->getConnection();

                    $customer_addressquote_table = $this->_resources->getTableName('quote_address');
                    $sql_customeraddressquote = "SELECT * FROM ".$customer_addressquote_table." WHERE customer_address_id = ".$addressId." ";
                    $connection->query($sql_customeraddressquote);
                    $result_customeraddress_id = $connection->fetchAll($sql_customeraddressquote);
                    if(!empty($result_customeraddress_id)){
                        $customer_address_table = $this->_resources->getTableName('quote_address');
                        $sql_customeraddress = "SELECT customer_address_id FROM ".$customer_address_table." WHERE customer_address_id = ".$addressId." ";

                        $connection->query($sql_customeraddress);
                        $result_customeraddress_id = $connection->fetchAll($sql_customeraddress);

                        foreach( $result_customeraddress_id as $result_customeraddress) {
                            foreach($result_customeraddress as $result_customeraddress_entity){
                                $themeTable = $this->_resources->getTableName('quote_address');
                                $sql = "Update " . $themeTable . " Set customer_address_id = null where customer_address_id = ".$result_customeraddress_entity."";
                                $connection->query($sql);
                           }

                        }
                    }
                } else {
                    $this->messageManager->addError(__('We can\'t delete the address right now.'));
                }
            } catch (\Exception $other) {
                $this->messageManager->addException($other, __('We can\'t delete the address right now.'));
            }
        }
        return $this->resultRedirectFactory->create()->setPath('*/*/index');
    }
}
  • Great! I was facing the issue and I resolved it using your solution! thank you, you saved my time! – Bhavin Shah May 14 '18 at 11:13
  • Hi, I still got the error after using this solution. – Rajan Soni May 30 '18 at 11:05
0

When, I Use this extention get below error.

Exception #0 (Exception): Warning: Declaration of Custom\DefaultAddress\Controller\Adminhtml\Rewrite\Index\Save::_extractData(Magento\Framework\App\RequestInterface $request, $formCode, $entityType,

0

Seems to be a known issue: https://github.com/magento/magento2/issues/7570

Don't run this in production, but a quick fix if you just need it working locally is to run the following SQL:

DELETE FROM quote_address;

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.