0

I have had an issue for some time in overriding the OrderSender Model in Magento 2 as a result of creating a custom payment module.

First of all i was not able to prevent email from being sent out once an order is made (wether successful or not successful), which was a problem so I decided to create a flow which would override the OrderSender using the advised process by specifying the preference file in the module i.e.

class OrderSender extends \Magento\Sales\Model\Order\Email\Sender\OrderSender{

/**
 * Sends order email to the customer.
 *
 * Email will be sent immediately in two cases:
 *
 * - if asynchronous email sending is disabled in global settings
 * - if $forceSyncMode parameter is set to TRUE
 *
 * Otherwise, email will be sent later during running of
 * corresponding cron job.
 *
 * @param Order $order
 * @param bool $forceSyncMode
 * @return bool
 */
public function send(Order $order, $forceSyncMode = false)
{
    $payment = $order->getPayment()->getMethodInstance()->getCode();

    //allow other module or payment to proceed should in case it is not my payment module is calling for order sender.
    if($payment == 'afronijapay' && !$forceSyncMode){
        return false;
    }

    $order->setSendEmail(true);

    if (!$this->globalConfig->getValue('sales_email/general/async_sending') || $forceSyncMode) {
        if ($this->checkAndSend($order)) {
            $order->setEmailSent(true);
            $this->orderResource->saveAttribute($order, ['send_email', 'email_sent']);
            return true;
        }
    }

    $this->orderResource->saveAttribute($order, 'send_email');

    return false;
}}

as shown above so therefore everything worked fine and i was to send the email upon completing my flow of process then called the following when the payment is successful.

//send new order email
            $this->_checkout_session->setForceOrderMailSentOnSuccess(true);
            $this->_orderSender->send($order, true);

Again, I found this as some proposed solution from several sources including stackoverflow/stackexchange and all.

However, in as much as this works another problem comes to mind i.e. what if someone already is overriding this class from another module and Magento 2 uses that overriden class without mine then the problem may re-occur.

I built another payment module (just a copy of the original) using different namespace and vendor name and my fear came to light as Magento 2 is ignoring one of the classes overriding the OrderSender class and using the other thereby making the problem to start re-occuring.

I will appreciate any suggestions on how to tackle this issue. Thanks.

afro-Nija
  • 185
  • 1
  • 4
  • 17
  • If there is another custom module which has not been created by you but you know the name of that module, then still you can make an order of the modules by adding `` in module.xml – Adeel Jul 02 '18 at 11:12
  • As far as I know, there are two ways to set the sequence of the modules, first to mention the `` in module.xml file and the another way could be modifying the plugin. you can read these [Magento 2 - Component load order](https://devdocs.magento.com/guides/v2.0/extension-dev-guide/build/module-load-order.html) and [Magento 2 - Plugins](https://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html) – Adeel Jul 02 '18 at 11:16
  • @Adeel thanks for ur comment,but I am not sure I understand what you mean,I would like not to change other modules 'module.xml' but mine,I would like the module being used to only use its overriden class not other module overriden class. using sequence in my case was just ensuring the Magento_Sales,Magento_Checkout & Magento_Payment is loaded.if there is another way to stop the order confirmation email programmatically right from the creation of the order and there would not be need of overriding this class thereby not worrying about other modules overriding it, that would be perfect solution. – afro-Nija Jul 02 '18 at 11:40

1 Answers1

3

After so many trials i finally come up with this plan

create an event in your

<Vendor>/<ModuleName>/etc.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="<vendor>_<modulename>_event_email_stopper" instance="<Vendor>\<ModuleName>\Event\EmailStopper\Order\Email" /> </event> </config>

Then create a class named Email.php in the directory \\Event\EmailStopper\Order\ with the following content

 namespace <Vendor>\<ModuleName>\Event\EmailStopper\Order;
class Email implements \Magento\Framework\Event\ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    try{
        $order = $observer->getEvent()->getOrder();
        $this->_current_order = $order;

        $payment = $order->getPayment()->getMethodInstance()->getCode();

        if($payment == 'chukplcspredirect' || $payment == 'chukplcspdirect'){
            $this->stopNewOrderEmail($order);
        }
    }
    catch (\ErrorException $ee){

    }
    catch (\Exception $ex)
    {

    }
    catch (\Error $error){

    }

}

public function stopNewOrderEmail(\Magento\Sales\Model\Order $order){
    $order->setCanSendNewEmailFlag(false);
    $order->setSendEmail(false);
    try{
        $order->save();
    }
    catch (\ErrorException $ee){

    }
    catch (\Exception $ex)
    {

    }
    catch (\Error $error){

    }
}
} 

and when you are done you can easily send email for the order using the code below

$order->setCanSendNewEmailFlag(true);
$order->save();
$this->_checkout_session->setForceOrderMailSentOnSuccess(true);
$this->_orderSender->send($order, true);
afro-Nija
  • 185
  • 1
  • 4
  • 17