0

I created a custom observer in customer_address_save_after event that retrieves customer data and send it via SOAP. So far, so good.

My file Vendor/Module/etc/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="customer_address_save_after">
        <observer name="sap_register" instance="Vendor\Module\Observer\CustomerRegister" />
    </event>
</config>

In addition, i also need a custom button in backend that performs the same action manually. So i created my Vendor\Module\Controller\Adminhtml\Customer\Send.php controller:

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $pageFactory,        
        \Magento\Customer\ApiCustomerRepositoryInterface $customer,        
        \Magento\Customer\Model\Address $address       
    )
    {
        $this->_pageFactory = $pageFactory;
        $this->logger = $logger;
        $this->dir = $dir;
        $this->ioFile = $ioFile;
        $this->customer = $customer;
        $this->address = $address;
        $this->soapCustomer = $soapCustomer;
        $this->helper = $helper;
        return parent::__construct($context);
    }

    /**
     * Index action
     *
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        try {
             // Fecth customer info
            $customerId = $this->getRequest()->getParam('customer_id');
            if (!$customerId) {                
                $this->messageManager->addErrorMessage(__('Customer was not defined'));
                return $resultRedirect->setUrl($this->_redirect->getRefererUrl());
            }

            $customer = $this->customer->getById($customerId);            
            // If customer doesn't have address, can't be processed
            if (!$customer->getDefaultBilling()) {
               $this->messageManager->addErrorMessage(__('Error: Customer doesn\'t have an address'));
                return $resultRedirect->setUrl($this->_redirect->getRefererUrl());
            }

            $this->address->setCustomerId($customerId);
            $this->address->setId($customer->getDefaultShipping());
            $this->address->setIsDefaultBilling(true);
            $this->_eventManager->dispatch(
                'customer_address_save_after',
                ['customer_address' => $this->address]
            );            
        } catch (\Exception $e) {           
            // display error message
            $this->messageManager->addErrorMessage('Error: ' . $e->getMessage());
            // go back to customer edit
            return $resultRedirect->setUrl($this->_redirect->getRefererUrl());
        }

        $resultRedirect->setUrl($this->_redirect->getRefererUrl());
        return $resultRedirect;
    }

My idea is dispatching previous defined event to do all the logic. However, i found that event fires twice and also address data is empty (customer data is ok, only address is not populated), so my custom event fails:

print_r($this->address->getData()); 
Array ( [parent_id] => 52 [customer_id] => 52 [entity_id] => 53 [id] => 53 [is_default_billing] => 1 )
print_r($this->address->getCustomer()->getData()); 
Array ( [entity_id] => 52 [website_id] => 1 [email] => name@domain.com [group_id] => 1 [increment_id] => [store_id] => 1 [created_at] => 2020-04-03 08:55:06 [updated_at] => 2020-04-13 10:46:45 [is_active] => 1 [disable_auto_group_change] => 0 [created_in] => Default Store View [prefix] => [firstname] => XXX [middlename] => [lastname] => XXX [suffix] => [dob] => yyyy-mm-dd [password_hash] => XXX [rp_token] => XXX [rp_token_created_at] => yyyy-mm-dd hh:mm:ss [default_billing] => 53 [default_shipping] => 53 [taxvat] => XXX [confirmation] => [gender] => [failures_num] => 0 [first_failure] => [lock_expires] => [reward_update_notification] => 1 [reward_warning_notification] => 1 [sforce_sync_status] => 0 [sforce_disable_sync] => 0 [sap_number] => XXX [apellido2] => XXX ) )

What am i missing? What's the best way to manually dispatch an event? I already know that i can also save my customer at this point so the event will fire, but IMHO dispatching the event is a best approach.

Best regards, Antonio.

1

$this->address never seems to have been loaded. Probably something like this would work:

$this->address = $this->address->load($customer->getDefaultShipping());
| improve this answer | |
  • It works fine and populates address data, thank you! However, event still fires twice. Any idea why? – Antonio Apr 20 at 7:14
  • 1
    A quote usually has two addresses attached to it (billing and shipping). So anything that saves the quote would trigger two address saves. But it is also possible that the code executes two saves in a given action. – Kristof at Fooman Apr 20 at 21:38

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.