Magento 2 - Observer on event 'sales_order_place_after' not working - events

I am working on a magento 2 observer (without success), to execute a cURL request to a system with the orderid after a order is placed.
Currently I just send an email, but that's for testing purpose only
Working on a Plesk server with a fresh Magento 2.3.2 install (no sample data) and added 1 product. So, fresh webshop with 1 product in total.
Currently I have the following code:
/app/code/CompanyName/ModuleName/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="sales_order_place_after">
<observer name="companyname__modulename_observer_afterplaceorder" instance="CompanyName\ModuleName\AfterPlaceOrder" />
</event>
<config>
/app/code/CompanyName/ModuleName/AfterPlaceOrder.php
<?php
namespace CompanyName\ModuleName\Observer;
use Magento\Framework\Event\ObserverInterface;
use Psr\Log\LoggerInterface;
class AfterPlaceOrder implements ObserverInterface {
protected $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function execute(\Magento\Framework\Event\Observer $observer) {
Mage::log("Start execute module");
$headers = array();
$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-type: text/html";
$headers[] = "From: Test SYSTEM";
$headers[] = "X-Mailer: PHP/".phpversion();
mail('testemail#companyname.com', 'Test message', "Order placed", implode("\r\n", $headers));
Mage::log("End of email");
}
}
I've also tried other events like:
- checkout_onepage_controller_success_action
- sales_order_place_after
- sales_order_place_before
- sales_order_save_after
Logs don't seem to work, mail doesn't send and tried die() but nothing works.
It's probably that the event is never fired, but I just can't figure out why.
Can you guys see the error?
P.S. What do you use to debug? Is there a better way then logging?
P.S. I'd also like to now if a observer is the best way for this. Any suggestions?
Thx in advance!

Your /app/code/CompanyName/ModuleName/etc/events.xml is missing the observer folder also the close of the config tag. You could use the event:
checkout_onepage_controller_success_action
<?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="checkout_onepage_controller_success_action">
<observer name="companyname__modulename_observer_afterplaceorder" instance="CompanyName\ModuleName\Observer\AfterPlaceOrder"/>
</event>
</config>
To get the orderid just use:
$orderId = $observer->getEvent()->getOrderIds();

Related

How to perform custom javascript on place order but before redirection to payment gateway in Magento 1.9?

I need to integrate my Magento with some order tracking service.
The service provider asked me to include some code on the last page of the checkout process but before a customer is redirected to the payment gateway. I use one page checkout.
Simplified version of the code is something like this
<script type="text/javascript">
var webOrder = {
"id": shop_id,
"sum": order_value
};
</script>
<script type="text/javascript" src="//serivce_address/before.js"></script>
I do not want this code to execute until customer accepts agreements and clicks place order and the order is accepted. How can I do that?
You can use the event/observer method of Magento to do something after the order is placed. You can use this event
sales_order_place_after
In your module's 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=""sales_order_place_after"">
<observer name=""observername"" instance=""Vendor\Module\Observer\YourClass"" />
</event>
</config>
and in YourClass.php
<?php
namespace NBG\Mailtrigger\Observer;
class YourClass implements \Magento\Framework\Event\ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getEvent()->getOrder();
$orderIncrementId = $order->getIncrementId();
// your logic...
}
}

How to get the custom order attributes in default order Api response in magento 2.3

I have created a new custom order attribute named delivery_date and shown the same in sales order grid but i am not getting the custom attribute in my order Api response.
The error I am getting is Fatal error: Uncaught Error: Call to undefined method Magento\Sales\Api\Data\OrderExtension::setTipAndTrickAttribute()
Please help.
app/code/Amos/CustomOrder/etc/di.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<virtualType name="Magento\Sales\Model\ResourceModel\Order\Grid" type="Magento\Sales\Model\ResourceModel\Grid">
<arguments>
<argument name="columns" xsi:type="array">
<item name="delivery_date" xsi:type="string">sales_order.delivery_date</item>
<item name="no_of_days" xsi:type="string">sales_order.no_of_days</item>
<item name="no_of_crew" xsi:type="string">sales_order.no_of_crew</item>
</argument>
</arguments>
</virtualType>
</config>
app/code/Amos/CustomOrder/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="sales_order_load_after">
<observer name="sales_order_load_delivery_date" instance="Magestore\TipAndTrick\Observer\Sales\OrderLoadAfter" />
</event>
</config>
Amos/CustomOrder/etc/extension_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
<attribute code="delivery_date" type="string" />
</extension_attributes>
</config>
Amos/CustomOrder/Observer/Sales/OrderLoadAfter.php
<?php
namespace Amos\CustomOrder\Observer\Sales;
use Magento\Framework\Event\ObserverInterface;
class OrderLoadAfter implements ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getOrder();
$extensionAttributes = $order->getExtensionAttributes();
if ($extensionAttributes === null) {
$extensionAttributes = $this->getOrderExtensionDependency();
}
$attr = $order->getData('delivery_date');
$extensionAttributes->setTipAndTrickAttribute($attr);
$order->setExtensionAttributes($extensionAttributes);
}
private function getOrderExtensionDependency()
{
$orderExtension = \Magento\Framework\App\ObjectManager::getInstance()->get(
'\Magento\Sales\Api\Data\OrderExtension'
);
return $orderExtension;
}
}
To answer your question about the error you're using the wrong magic function. Your magic functions for that attribute is setDeliveryDate().
You also need to make sure your events.xml has the right class for the observer.
<observer name="sales_order_load_delivery_date" instance="Magestore\TipAndTrick\Observer\Sales\OrderLoadAfter" />
While your observer class is: Amos\CustomOrder\Observer\Sales\OrderLoadAfter
When you are using example material try not to forget to change the class, namespace and functions names among other things when you need to. You may also need an order repository plugin to actually get it into the API response.
<type name="Magento\Sales\Api\OrderRepositoryInterface">
<plugin name="your_name_here_extension_attribute"
type="<Vendor>\<Module>\Plugin\OrderRepositoryPlugin" />
</type>
Yes agree with above answer, you will need to write order repository plugin with get and getlist methods to get it into the API response.
Below are the code snippet
public function afterGet(OrderRepositoryInterface $subject, OrderInterface $order)
{
$this->addDeliveryDate($order);
return $order;
}
public function afterGetList(OrderRepositoryInterface $subject, OrderSearchResultInterface $searchResult)
{
$orders = $searchResult->getItems();
foreach ($orders as $order) {
$this->addDeliveryDate($order);
}
return $searchResult;
}
private function addDeliveryDate($order)
{
$adddeliveryDate = $order->getData(self::DELIVERY_DATE);
$extensionAttributes = $order->getExtensionAttributes() ?: $this->extensionFactory->create();
$extensionAttributes->setDeliveryDate($adddeliveryDate);
$order->setExtensionAttributes($extensionAttributes);
return $order;
}

Migrating Shipping Extension for Magento 1.9 to Magento 2.2

I am trying to migrate a custom magento 1.9 extension to magento 2.2. I have done a lot of searching and can't find information on the use case I'm trying to migrate. I originally followed this tutorial for the 1.9 extension. I understand there is a tool to help port extensions, but I am trying to do this manually as I couldn't get that tool to function for me.
The custom shipping extension would run each time the shopping cart was updated to calculate a custom shipping rate. The goal is to recreate this extension in magento 2.2 such that each time the shopping cart is opened or updated it will run and calculate a shipping cost which will then propagate through the checkout process.
Below is an overview of the magento 1.9 extension. Any advice on how to translate this to magento 2.2?
/app/etc/modules/Extensions_Shipper.xml
<?xml version="1.0"?>
<config>
<modules>
<Extensions_Shipper>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Shipping />
</depends>
</Extensions_Shipper>
</modules>
/app/code/local/Extensions/Shipper/etc/config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Extensions_Shipper>
<module>0.0.1</module>
</Extensions_Shipper>
</modules>
<global>
<models>
<extensions_shipper>
<class>Extensions_Shipper_Model</class>
</extensions_shipper>
</models>
</global>
<default>
<carriers>
<extensions_shipper>
<active>1</active>
<model>extensions_shipper/carrier</model>
<title>Shipping Options</title>
<sort_order>10</sort_order>
<sallowspecific>0</sallowspecific>
</extensions_shipper>
</carriers>
</default>
/app/code/local/Extensions/Shipper/Model/Carrier.php
<?php
class Extensions_Shipper_Model_Carrier extends Mage_Shipping_Model_Carrier_Abstract implements Mage_Shipping_Model_Carrier_Interface
{
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
//Are there magento 2.2 equivalence for the following?
$addressInfo = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getData();
$result = Mage::getModel('shipping/rate_result');
$items = Mage::getSingleton('checkout/session')->getQuote()->getAllItems();
$currentItem = Mage::getModel('catalog/product')->load($items[$itemsArray[$i]]->getProduct()->getId());
Mage::getSingleton('core/session')->addNotice('some text');
//$result = some calculations for shipping rate
return $result;
}
public function getAllowedMethods()
{
return array();
}
}
You can create an event observer on the checkout_cart_add_product_complete event to execute the logic to update the shipping costs.
namespace MyCompany\MyModule\Observer;
use Magento\Framework\Event\ObserverInterface;
class MyObserver implements ObserverInterface
{
public function __construct()
{
//Observer initialization code...
//You can use dependency injection to get any class this observer may need.
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
//Observer execution code...
}
}
Subscribe to the event in 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="my_module_event_before">
<observer name="myObserverName" instance="MyCompany\MyModule\Observer\MyObserver" />
</event>
<event name="my_module_event_after">
<observer name="myObserverName" instance="MyCompany\MyModule\Observer\AnotherObserver" />
</event>
</config>
See Magento docs on events and observers: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/events-and-observers.html
For a list of all Magento 2.2 events, see: https://cyrillschumacher.com/magento-2.2-list-of-all-dispatched-events/

SimpleXML (Zend_Config_Xml actually) and foreach : which tag am I iterating?

I'm implementing a little event manager in order to use the Observer pattern. To subscribe my observers to my events, I'm using the following xml file :
<?xml version="1.0" encoding="UTF-8"?>
<configData>
<subscriptions>
<subscription>
<eventName>event_name</eventName>
<class>My_Observer_Class</class>
<function>myFunction</function>
</subscription>
<subscription>
<eventName>other_event_name</eventName>
<class>My_Observer_Otherclass</class>
<function>myOtherFunction</function>
</subscription>
</subscriptions>
</configData>
I'm using a foreach to loop on the subscriptions :
foreach($subscriptions->subscription as $subscription) {
/* using $subscription->eventName etc... */
}
And everything is ok, each $subscription item has it's eventName etc...
But here comes my problem :
<?xml version="1.0" encoding="UTF-8"?>
<configData>
<subscriptions>
<subscription>
<eventName>event_name</eventName>
<class>My_Observer_Class</class>
<function>myFunction</function>
</subscription>
</subscriptions>
</configData>
Here I have only one <subscription> node. And my foreach loops on the subscription children !
To solve this problem, I'd like to know how I can check if the xml file contains several <subscription> tags, or just one...
Any help will be appreciated :)
Edit : Is there a way to use xpath with my Zend_Config_Xml object ?
You can use Xpath.
Please try below code, i have tested it with both of sample XML's you provided.
<?php
$subscriptions = simplexml_load_file('test.xml');
$scTag = $subscriptions->xpath("//subscription");
foreach($scTag as $subscription) {
echo $subscription->eventName;
/* using $subscription->eventName etc... */
}
?>
hope this help !
Just to clarify, this is an issue with Zend_Config_XML which is not present in PHP's native SimpleXML.
Given your second example as $xml, I can run the following and get the word 'subscription' as expected:
$configData = simplexml_load_string($xml);
foreach($configData->subscriptions->subscription as $subscription)
{
echo $subscription->getName();
}

Custom observer not being triggered

I am trying to write an observer for magento that will be triggered when an order has been marked as shipped and has been given a tracking number.
When I go in through the admin and place an order, invoice and then go to ship the function I need to call is never actually called, and I do not understand why.
I have go through a couple of of pages on the magento website to see what I might be doing wrong, but I just cant figure it out (http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/customizing_magento_using_event-observer_method & http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-2-the-magento-config).
Please note that I do see the module within the admin Advanced area and it is enabled.
If anyone could look over the code I have attached and let me know where my issue is, it would be much appreciated.
Here is my Observer class which is located in app/code/local/WR/TrackingEmail/Model/Observer.php
class WR_TrackingEmail_Model_Observer
{
public function sendTrackEmail($observer)
{
$track = $observer->getEvent()->getTrack();
$shipment = $track->getShipment(true);
$shipment->sendEmail();
}
}
Here is my config.xml for the module
<config>
<global>
<modules>
<wr_trackingemail>
<version>0.1.1</version>
</wr_trackingemail>
</modules>
<events>
<sales_order_shipment_track_save_after>
<observers>
<Wr_trackingemail_model_observer>
<type>singleton</type>
<class>WR_TrackingEmail_Model_Observer</class>
<method>sendTrackEmail</method>
</Wr_trackingemail_model_observer>
</observers>
</sales_order_shipment_track_save_after>
</events>
</global>
</config>
Here is my app/etc/modules/WR_TrackingEmail.xml
<config>
<modules>
<WR_TrackingEmail>
<active>true</active>
<codePool>local</codePool>
</WR_TrackingEmail>
</modules>
</config>
Your statement "Custom observer not being triggered" leaves a lot of room for interpretation. Here's what you'll want to check.
Your observer appears to be setup correctly (although the modules tag belongs outside the global tag, but that doesn't appear to matter for this case). You can test your setup by running the following code yourself from a blank controller action (or other bootstrapped, event loaded, Magento script)
Mage::dispatchEvent('sales_order_shipment_track_save_after');
and then replacing your sendTrackEmail with this
public function sendTrackEmail($observer)
{
exit(__METHOD__);
}
If execution halts with the text
WR_TrackingEmail_Model_Observer::sendTrackEmail
you'll know your event is configured correctly.
If your event IS configured correctly, the next step is to ensure that the event is actually being fired when you perform the steps above. You can log these events in app/Mage.php by adding this temporary logging code
public static function dispatchEvent($name, array $data = array())
{
//brain dead logging
file_put_contents('/tmp/events.log',"$name\n",FILE_APPEND);
Varien_Profiler::start('DISPATCH EVENT:'.$name);
$result = self::app()->dispatchEvent($name, $data);
#$result = self::registry('events')->dispatch($name, $data);
Varien_Profiler::stop('DISPATCH EVENT:'.$name);
return $result;
}
Also, there's a good chance that leaving your exit in above will still result in execution halting if your event is being fired.
If you've determined your observer is configured correctly, AND your event is being fired, then the problem isn't an event being triggered, but your observer code not doing what you think its doing. Re-add your code but keep your exit in place
class WR_TrackingEmail_Model_Observer
{
public function sendTrackEmail($observer)
{
$track = $observer->getEvent()->getTrack();
$shipment = $track->getShipment(true);
$shipment->sendEmail();
exit(__METHOD__);
}
}
This will allow you to reload the browser over and over again to test your observer code. Good luck!
Have you registered your module under app/etc/modules/ in a .xml file?
<?xml version="1.0"?>
<config>
<modules>
<Wr_Trackingemail>
<active>true</active>
<codePool>local</codePool>
</Wr_Trackingemail>
</modules>
</config>

Resources