I'm trying to send an SMS notification to the client after creating a shipment.
In M1 I can do that with this event:
<sales_order_shipment_save_after>
But in Magento 2 there is no event triggering after creating the shipment.
you can use sales_order_shipment_save_after event
for this you need to create etc/events.xml file to define your event
<?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_shipment_save_after">
<observer name="emizentechshipment" instance="Emizentech\MyModule\Observer\ProcessShipment" />
</event>
</config>
than you need to create Observer\ProcessShipment.php file
<?php
namespace Emizentech\MyModule\Observer;
use Magento\Framework\Event\ObserverInterface;
class ProcessShipment implements ObserverInterface
{
/**
*
* #param \Magento\Framework\Event\Observer $observer
* #return $this
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
$shipment = $observer->getEvent()->getShipment();
$order = $shipment->getOrder();
// your code for sms here
}
}
Related
upon adding my observer, I got error 500 when I'm trying to complete shipping process. What I want to achieve is, I want to send a review request after the shipment is done.I've started using Magento for about a month ago, that's why I don't know if I made an error on Observer, events.xml or it just doesn't work. I've been doing this for about three days, please help.
Vendor name: Lns
Module Name: ReviewRequest
Review.php
<?php
namespace Lns\ReviewRequest\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class Review implements ObserverInterface
{
protected $transportBuilder;
protected $storeManager;
protected $logger;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
TransportBuilder $transportBuilder,
StoreManagerInterface $storeManager,
LoggerInterface $logger
) {
$this->transportBuilder = $transportBuilder;
$this->storeManager = $storeManager;
$this->logger = $logger;
}
/**
* Below is the method that will fire whenever the event runs!
*
* #param Observer $observer
*/
public function execute(Observer $observer)
{
$store = $this->storeManager->getStore();
$templateParams = ['store' => $store, 'customer' => $customer, 'administrator_name' => $receiverInfo['name']];
$transport = $this->transportBuilder
->setTemplateIdentifier('Entrelabel Add Review')
->setTemplateOptions(['area' => 'frontend', 'store' => $store->getId()])
->addTo($receiverInfo['email'], $receiverInfo['name'])
->setTemplateVars($templateParams)
->setFrom('general')
->getTransport();
try {
// Send an email
$transport->sendMessage();
} catch (\Exception $e) {
// Write a log message whenever get errors
$this->logger->critical($e->getMessage());
}
return var_dump($e);
}
}
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_shipment_save_after">
<observer name="reviewRequest" instance="Lns\ReviewRequest\Observer\Review" />
</event>
</config>
add before class start
use Magento\Framework\Mail\Template\TransportBuilder
use Magento\Store\Model\StoreManagerInterface
and check log files in var folder
I have been trying to setup a basic module in Magento2, it keeps throwing 404 despite doing all the ideal changes. Below is the code related to the module. My vendor name is Chirag and module name is HelloWorld.
/var/www/html/magento2/app/code/Chirag/HelloWorld/etc/module.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. 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/Module/etc/module.xsd">
<module name="Chirag_HelloWorld" schema_version="0.0.1" setup_version="0.0.1">
</module>
</config>
/var/www/html/magento2/app/code/Chirag/HelloWorld/etc/frontend/route.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. 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/App/etc/routes.xsd">
<router id="standard">
<route id="helloworld" frontName="helloworld">
<module name="Chirag_HelloWorld" />
</route>
</router>
</config>
/var/www/html/magento2/app/code/Chirag/HelloWorld/Controller/Index/Index.php
<?php
/**
*
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Chirag\HelloWorld\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{
/**
*
*
* #return void
*/
public function execute()
{
protected $resultPageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
}
public function execute()
{
return $this->resultPageFactory->create();
}
}
}
/var/www/html/magento2/app/code/Chirag/HelloWorld/Block/HelloWorld.php
<?php
namespace Chirag\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
}
/var/www/html/magento2/app/code/Chirag/HelloWorld/view/frontend/layout/helloworld_index_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Chirag\HelloWorld\Block\HelloWorld" name="helloworld" template="helloworld.phtml" />
</referenceContainer>
</body>
</page>
/var/www/html/magento2/app/code/Chirag/HelloWorld/view/frontend/templates/helloworld.phtml
<h1> test hello to Magento 2 !! </h1>
Any kind of help would be really appreciated.
First try to rename route.xml to routes.xml and see if that fixes the issue.
Next try changing your code in the controller, try change company/module names:
<?php
namespace YourCompany\ModuleName\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{
protected $resultPageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
) {
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
}
public function execute()
{
return $this->resultPageFactory->create();
}
}
also in your helloworld_index_index.xml you can try changing the template decoration to:
template="YourCompany_ModuleName::templatename.phtml"
lastly you can try changing the module.xml setup_version declaration to:
setup_version="2.0.0"
I hope this helps!
Below changes led to correct answer for me :
Index controller - magento2/app/code/Chirag/HelloWorld/Controller/Index/Index.php
<?php
/**
*
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Chirag\HelloWorld\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{
/**
* Show Contact Us page
*
* #return void
*/
public function execute()
{
$this->_view->loadLayout();
$this->_view->getLayout()->getBlock('helloworld');
$this->_view->renderLayout();
}
}
Block - magento2/app/code/Chirag/HelloWorld/Block/Question.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Chirag\HelloWorld\Block;
use Magento\Framework\View\Element\Template;
/**
* Main contact form block
*/
class Question extends Template
{
/**
* #param Template\Context $context
* #param array $data
*/
public function __construct(Template\Context $context, array $data = [])
{
parent::__construct($context, $data);
$this->_isScopePrivate = true;
}
}
Layout file - magento2/app/code/Chirag/HelloWorld/view/frontend/layout/helloworld_index_index.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Chirag\HelloWorld\Block\Question" name="helloworld" template="Chirag_HelloWorld::helloworld.phtml">
</block>
</referenceContainer>
</body>
</page>
View template - magento2/app/code/Chirag/HelloWorld/view/frontend/templates/helloworld.phtml
<?php echo 'helloworld view'; ?>
<h1> Hello World </h1>
You need to follow the below steps to resolve:
You have to change route.xml to routes.xml
Run setup upgrade command:
php bin/magento s:up
Go to your_base_link/helloworld/index/index
Enjoin your result
First of all, rename route.xml to routes.xml
app/code/Chirag/HelloWorld/etc/frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="helloworld" frontName="helloworld">
<module name="Chirag_HelloWorld" />
</route>
</router>
</config>
Index Controller - app/code/Chirag/HelloWorld/Controller/Index/Index.php
You can't use __construct inside the execute method and these two should be separated.
<?php
/**
*
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Chirag\HelloWorld\Controller\Index;
use Magento\Framework\App\Action\Action;
class Index extends Action
{
/**
* #var \Magento\Framework\View\Result\PageFactory
*/
protected $resultPageFactory;
/**
* #param \Magento\Framework\App\Action\Context $context
* #param \Magento\Framework\View\Result\PageFactory $resultPageFactory
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
}
/**
* #return mixed
*/
public function execute()
{
return $this->resultPageFactory->create();
}
}
You should use the below format when you are calling the template in layout xml.
eg: Chirag_HelloWorld::helloworld.phtml
app/code/Chirag/HelloWorld/view/frontend/layout/helloworld_index_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Chirag\HelloWorld\Block\HelloWorld" name="helloworld" template="Chirag_HelloWorld::helloworld.phtml" />
</referenceContainer>
</body>
</page>
app/code/Chirag/HelloWorld/Block/HelloWorld.php
<?php
namespace Chirag\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
public function getHelloWorldText()
{
return __('Hello World');
}
}
app/code/Chirag/HelloWorld/view/frontend/templates/helloworld.phtml
<?= /* #noEscape */ $block->getHelloWorldText() ?>
Once you done run the below commands to apply the changes.
bin/magento setup:upgrade
bin/magento setup:static-content:deploy -f
bin/magento c:f
Use -f as a parameter if you are in developer mode.
Use bin/magento deploy:mode:show to check the mode.
Happy Coding!!
I need to redirect pages that contain no products to the first child category URL containing products (if the child category exists)
Since I need to do this only if the category contains no products, I'm not able to do this via .htaccess
Does anyone have any ideas on how this can be achieved in Magento?
I'm not having much luck hunting through Google.
Haven't checked it. You should put it in your view.phtml.
$currentCategory = Mage::getModel('catalog/layer')->getCurrentCategory()->getId();
$productCheck = Mage::getModel('catalog/category')->load($currentCategory)
->getProductCollection();
if (count($productCheck) < 1) {
echo '<script type="text/javascript">
window.location = "' . Mage::getUrl('somewhere') . '"
</script>';
}
You can use an observer. You could edit/create a local catalog module and try this:
1) Define observer on your config.xml:
<?xml version="1.0"?>
<config>
<!--(...)-->
<global>
<!--(...)-->
<events>
<catalog_controller_category_init_after>
<observers>
<yourcompany_catalog>
<type>singleton</type>
<class>yourcompany_catalog/observer</class>
<method>categoryRedirect</method>
</yourcompany_catalog>
</observers>
</catalog_controller_category_init_after>
</events>
<!--(...)-->
</global>
<!--(...)-->
</config>
2) Your observer method can be something like this:
<?php
class GraspingMagento_SocialShare_Model_Observer
{
/**
* #param Varien_Event_Observer $observer
* #return void
*/
public function categoryRedirect(Varien_Event_Observer $observer)
{
/** #var Mage_Catalog_Model_Category $category */
$category = $observer->getData('category');
if ($category->getProductCollection()->count() > 0) {
// Category has products, no need to redirect
return;
}
/** #var Mage_Catalog_Model_Resource_Category_Collection $childrenCategories */
$childrenCategories = $category->getChildrenCategories();
/** #var Mage_Catalog_CategoryController $controller */
$controller = $observer->getControllerAction();
foreach ($childrenCategories as $childCategory) {
/** #var Mage_Catalog_Model_Category $childCategory */
if ($childCategory->getProductCollection()->count() > 0) {
$controller->getResponse()->setRedirect($childCategory->getData('request_path'));
break;
}
}
}
}
This will verify that your current category has no products. If it doesn't, it will try to find a direct child that has products, and redirect to it.
I would like to add a custom promotion condition to Magento 1.7. It should be possible to apply a promotion based on a custom attribute in the shipping address of the customer. Its actually quite basic: if the attribute is filled, the promotion should apply, not more.
It should appear as a seperate condition point of the Cart Attributes like "Shipping Postcode" or "Shipping Region"
What would help as well: How are the standard Cart Promotion conditions are implemented or where to look for more information on this topic.
I searched the internet for quite a while now, and I'm really stuck. Your help is highly appreciated!
Thx a lot
Ok, I found a more or less working solution I want to share here, in case sombody else is needing this:
I created a module, that is introducing a new Condition into the promotions. The missing peace in order to achieve this was to do it via an observer.
First the config <path to module>\etc\config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<HauteNature_FamilienkarteHessen>
<version>1.0.0</version>
</HauteNature_FamilienkarteHessen>
</modules>
<admin>
<fieldsets>
<customer_dataflow>
<building>
<billing>1</billing>
<shipping>1</shipping>
</building>
</customer_dataflow>
</fieldsets>
</admin>
<global>
<models>
<familienkartehessen>
<class>HauteNature_FamilienkarteHessen_Model</class>
</familienkartehessen>
</models>
<helpers>
<familienkartehessen>
<class>HauteNature_FamilienkarteHessen_Helper</class>
</familienkartehessen>
</helpers>
<events>
<salesrule_rule_condition_combine>
<observers>
<add_condition_to_sales_rule>
<class>familienkartehessen/observer</class>
<method>addConditionToSalesRule</method>
</add_condition_to_sales_rule>
</observers>
</salesrule_rule_condition_combine>
</events>
<resources>
<familienkartehessen_setup>
<setup>
<module>HauteNature_FamilienkarteHessen</module>
<class>Mage_Eav_Model_Entity_Setup</class>
</setup>
<connection>
<use>core_setup</use>
</connection>
</familienkartehessen_setup>
</resources>
<fieldsets>
<sales_copy_order_billing_address>
<familiycarthessen><to_order>*</to_order></familiycarthessen>
</sales_copy_order_billing_address>
<sales_copy_order_shipping_address>
<familiycarthessen><to_order>*</to_order></familiycarthessen>
</sales_copy_order_shipping_address>
<sales_convert_quote_address>
<familiycarthessen><to_order_address>*</to_order_address><to_customer_address>*</to_customer_address></familiycarthessen>
</sales_convert_quote_address>
<sales_convert_order_address>
<familiycarthessen><to_quote_address>*</to_quote_address></familiycarthessen>
</sales_convert_order_address>
<customer_address>
<familiycarthessen><to_quote_address>*</to_quote_address></familiycarthessen>
</customer_address>
<checkout_onepage_billing>
<familiycarthessen><to_customer>*</to_customer></familiycarthessen>
</checkout_onepage_billing>
</fieldsets>
</global>
</config>
I think this part is hoocking it to the magento Interface:
<salesrule_rule_condition_combine>
<observers>
<add_condition_to_sales_rule>
<class>familienkartehessen/observer</class>
<method>addConditionToSalesRule</method>
</add_condition_to_sales_rule>
</observers>
</salesrule_rule_condition_combine>
Second the observer, quite simple, just adding the menu point to the UI and linking it to the condition: <path to module>\Model\Observer.php:
class HauteNature_FamilienkarteHessen_Model_Observer extends Mage_Core_Model_Abstract {
/**
* Event: salesrule_rule_condition_combine
*
* #param $observer
*/
public function addConditionToSalesRule($observer) {
$additional = $observer->getAdditional();
$conditions = (array) $additional->getConditions();
$conditions = array_merge_recursive($conditions, array(
array('label'=>Mage::helper('familienkartehessen')->__('Familienkarte Hessen'), 'value'=>'familienkartehessen/condition_familienkarte'),
));
$additional->setConditions($conditions);
$observer->setAdditional($additional);
return $observer;
}
}
And finally the custom Condition Class that actually does the work <path to module>\Model\Condition/Familienkarte.php:
class HauteNature_FamilienkarteHessen_Model_Condition_Familienkarte extends Mage_Rule_Model_Condition_Abstract {
/**
* #TODO for whatever this it, check it and afterwards document it!
*
* #return Hackathon_DiscountForATweet_Model_Condition_Tweet
*/
public function loadAttributeOptions() {
$attributes = array(
'fkhContent' => Mage::helper('familienkartehessen')->__('Familienkarte Hessen')
);
$this->setAttributeOption($attributes);
return $this;
}
/**
* #TODO for whatever this it, check it and afterwards document it!
*
* #return mixed
*/
public function getAttributeElement() {
$element = parent::getAttributeElement();
$element->setShowAsText(true);
return $element;
}
/**
* #TODO for whatever this it, check it and afterwards document it!
*
* #return string
*/
public function getInputType() {
switch ($this->getAttribute()) {
case 'fkhContent':
return 'boolean';
}
return 'string';
}
/**
* #TODO for whatever this it, check it and afterwards document it!
* #return string
*/
public function getValueElementType() {
return 'text';
}
/**
* Validate FamiliencarteHessen Rule Condition
*
* #param Varien_Object $object
*
* #return bool
*/
public function validate(Varien_Object $object) {
/* here should be something meaningful */
$address = $object;
if (!$address instanceof Mage_Sales_Model_Quote_Address) {
if ($object->getQuote()->isVirtual()) {
$address = $object->getQuote()->getBillingAddress();
}
else {
$address = $object->getQuote()->getShippingAddress();
}
}
return $this->validateAttribute(trim($address->getFamiliycarthessen()));
}
}
If anyone of you has comments on this code, I would be greatfull to hear them.
Best wishes
Andreas
When duplicating a product in the backend in magento the new product status is Disabled by default. That confuses the store admins who expect the product to show on the frontend.
How can I make the product status Enabled by default?
THanks
In your custom module you need to:
in config.xml file:
<config>
<adminhtml>
<events>
<catalog_model_product_duplicate>
<observers>
<custom_catalog_product_duplicate>
<class>custom_module/observer</class>
<method>catalogModelProductDuplicate</method>
</custom_catalog_product_duplicate>
</observers>
</catalog_model_product_duplicate>
</events>
</adminhtml>
</config>
Create an observer class with method like this:
class Custom_Module_Model_Observer
{
/**
* Prepare product for duplicate action.
*
* #param Varien_Event_Observer $observer
* #return object
*/
public function catalogModelProductDuplicate(Varien_Event_Observer $observer)
{
$newProduct = $observer->getEvent()->getNewProduct();
$newProduct->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
return $this;
}
}