Magento: отправляйте новый заказ по электронной почте только с cronjobs

11

Как я могу отправить новый заказ по электронной почте, используя:

$order->sendNewOrderEmail();

только из cronjob, используемого в Моем пользовательском модуле.

Спасибо за помощь.

Bizboss
источник

Ответы:

8

Я бы отключил System > Configuration > Sales Email > Order > Enabled

это гарантирует, что во время нормального выполнения оно не отправляется

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

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

Тогда в свой пользовательский модуль включите что-то вроде

    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();
    }

Основная идея заключается в переопределении отключенного значения конфигурации во время выполнения. Код не проверен, но должен дать вам отправную точку. Далее рекомендуется чтение из блога Алана: http://alanstorm.com/magento_loading_config_variables http://alanstorm.com/magento_config_a_critique_and_caching

Одна из проблем, с которой вы можете столкнуться - это кэшированное значение для вышеупомянутого.

Второй вариант будет дублировать код из sendNewOrderEmail ().

Кристоф в Фуман
источник
Genius. Чистый, настоящий, гениальный.
Philwinkle
1
лесть поможет вам повсюду ;-)
Кристоф на Fooman
3

Суть такого (радикального) изменения заключается в следующем:

  • Перепишите sendNewOrderEmail, чтобы он действовал как очередь и условно отправлял / не отправлял в зависимости от режима очереди (см. Некоторый псевдокод ниже)
  • Основываясь на режиме очереди модели заказа на продажу, мы отправляем электронное письмо из очереди, загружая заказ из задания cron и вручную отправляя электронное письмо.

Пример кода для модели заказа клиента переписать:

Следующий код будет зависеть от наличия вызываемой таблицы, yourmodule_sales_email_queueи я буду ссылаться на некоторые столбцы с помощью магических методов получения. Я не собираюсь предоставлять схему, так как это не полностью функциональный код и своего рода подтверждение концепции; не рабочий модуль.

Добавьте это в ваш файл 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>

Приложение / код / ​​местные / YourCompany / YourModule / Модель / 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');
    }


}

Оттуда вам нужно определить модель ресурса, коллекцию и работника cron.

Определение cron в etc / config.xml будет выглядеть примерно так:

<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>

Который вызывает метод из класса YourCompany_YourModule_Model_Observer. Мы загрузим последние 24 часа электронных писем из очереди, загрузим соответствующий заказ и установим флаг, чтобы позволить ему отправлять электронные письма. Затем мы вызовем метод отправки электронной почты:

<?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();
        }

    }
}

Отказ от ответственности:

Обратите внимание, что приведенный выше код не проверен и не будет работать сам по себе. Он ожидает, что существует множество функциональных возможностей (например, коллекций). Я также написал это на высшем уровне, и могут быть несоответствия , поскольку я передумал, как бы я справился с этим один или два раза с момента начала ответа.

Это должно дать вам толчок и подумать о том, как вы этого добьетесь. Я готов ответить на любые ваши вопросы. Я также готов внести свой вклад на Github в версию этого типа модуля с открытым исходным кодом.

Удачи!

philwinkle
источник
Это слишком сильно по сравнению с решением @ fooman, и мне нравится его лучше, чем мое :)
philwinkle