11

How can I send The new order Emails using:

$order->sendNewOrderEmail();

only from a cronjob used in My custom Module.

Thanks for help.

8

I would disable System > Configuration > Sales Email > Order > Enabled

this makes sure that during normal execution it is not send

public function sendNewOrderEmail()
{
    $storeId = $this->getStore()->getId();

    if (!Mage::helper('sales')->canSendNewOrderEmail($storeId)) {
        return $this;
    }

Then in your custom module include something like

    Mage::getConfig()->setNode(
        'default/'.Mage_Sales_Model_Order::XML_PATH_EMAIL_ENABLED, true
    );
    foreach(Mage::app()->getStores() as $storeCode=>$store){
        Mage::getConfig()->setNode(
            "stores/{$storeCode}/".Mage_Sales_Model_Order::XML_PATH_EMAIL_ENABLED, true
        );
    }
    $collection = Mage::getModel('sales/order')->getCollection()->addAttributeToFilter('email_sent', 0);
    foreach ($collection as $order){
        $order->sendNewOrderEmail();
    }

The main idea being to override the disabled configuration value at runtime. The code is not tested but should give you a starting point. Further recommended reading from Alan's blog: http://alanstorm.com/magento_loading_config_variables http://alanstorm.com/magento_config_a_critique_and_caching

One issue that you might encounter is a cached value for the above.

Second option would be to duplicate the code from sendNewOrderEmail().

| improve this answer | |
  • Genius. Pure, unadulterated, genius. – philwinkle Oct 24 '13 at 19:09
  • 1
    flattery will get you everywhere ;-) – Kristof at Fooman Oct 24 '13 at 21:30
3

The essence of making this kind of (radical) change is the following:

  • Rewrite sendNewOrderEmail to act as a queue and conditionally send/not send based on the queue mode (see some pseudo-code below)
  • Based on the queue mode of the sales order model, we send the email from the queue by loading the order from the cron job and manually sending the email.

Some sample code for the sales order model rewrite:

The following code will depend on the presence of a table called yourmodule_sales_email_queue and I'll be referencing some columns with magic getters. I'm not going to provide a schema as this isn't fully-functional code and is sort of proof of concept; not a working module.

Add this to your module's etc/config.xml:

<global>
    <model>
        <emailqueue>
            <class>YourCompany_YourModule_Model</class>
            <resourceModel>emailqueue_resource</resourceModel>
        </emailqueue>
        <emailqueue_resource>
            <class>YourCompany_YourModule_Model_Resource</class>
            <entities>
                <queue>
                    <table>yourmodule_sales_email_queue</table>
                </queue>
            </entities>
        </emailqueue_resource>
        <sales>
            <rewrite>
                <order>YourCompany_YourModule_Model_Order</order>
            </rewrite>
        </sales>
    </model>
</global>

app/code/local/YourCompany/YourModule/Model/Order.php

<?php

class YourCompany_YourModule_Model_Order extends Mage_Sales_Model_Order
{
    protected $_isQueueMode = false;

    public function sendNewOrderEmail()
    {       
        //send order email if our custom queue mode is set
        if($this->_isQueueMode){
            parent::sendNewOrderEmail();
            return;
        }

        //not running from queue, let's shove stuff into the queue
        $this->getEmailQueue()->load($this)->save();
    }


    public function getEmailQueue()
    {
        if(!isset($this->queue)){
            $this->queue = $this->_getEmailQueue();
        }
        return $this->queue;
    }

    protected function _getEmailQueue()
    {
        return Mage::getResourceModel('emailqueue/queue');
    }


}

From there you need to define a resource model, a collection, and a cron worker.

The cron definition in etc/config.xml would look something like this:

<crontab>
    <jobs>
        <emailqueue_send_order_emails>
            <schedule>
                <cron_expr>0 0 * * *</cron_expr>
            </schedule>
            <run>
                <model>emailqueue/observer::sendEmailsFromQueue</model>
            </run>
        </emailqueue_send_order_emails>
    </jobs>
</crontab>

Which invokes a method from the class YourCompany_YourModule_Model_Observer. We'll load the last 24 hours of emails from the queue, load up the associated order, and set the flag to allow it to send emails. Then we'll invoke the email send method:

<?php

class YourCompany_YourModule_Model_Observer
{
    public function sendEmailsFromQueue($observer)
    {
        //load queue and define the run window
        $queue = Mage::getModel('emailqueue/queue')->getCollection()->getSelect()
                ->where('created_at',array('lt'=>Zend_Db_Expr('NOW()')))
                ->where('created_at',array('gt'=>Zend_Db_Expr('NOW() - INTERVAL 24 HOUR')));

        foreach($queue as $worker){
            //logic to send the email e.g.:
            $order = Mage::getModel('sales/order')->loadByIncrementId($worker->getOrderIncrementId());
            $order->_isQueueMode = true;
            $order->sendNewOrderEmail();
        }

    }
}

Disclaimer:

Note that the above code is not tested and will not work on its' own. It expects a lot of functionality (like collections) to exist. I also wrote it top-of-mind and there may be inconsistencies, as I've changed my mind on how I would handle this once or twice since starting this answer.

This is meant to get you kick-started and thinking about how you would accomplish this. I'm willing to answer any questions you might have. I'm also willing to contribute on Github to an open-source version of this type of module.

Best of luck!

| improve this answer | |
  • This is overengineered compared to @fooman's solution and I like his better than mine :) – philwinkle Oct 24 '13 at 19:09

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.