Прикрепляем в письмо менеджеру Excel файл с данными заказа

Обратился ко мне заказчик по доработкам minishop2, чтобы в письма менеджеру добавлять файд Excel с данными заказа. Изначально подумал про счет какой-то, или накладную. Оказалось обычная таблица с четырьмя колонками: код товара, название, цена и кол-во. Сроки как всегда поджимают — сделать надо было еще вчера.
Собственно вот так выглядил шаблон, который нужно было заполнить:


В голове два решения: сделать быстро и сделать по-феншую.
Озвучиваю клиенту два решения сроки и стоимость:
1. Залезть в код компонента для формирования письма для клиента, и добавить туда формирование файла XLS и прикрепление письма (если у вас уже были изменения по minishop2 и не планируется его обновление, но он проще в плане реализации);
2. Отвязать стандартное действие отправки писем, написать плагин, который повесить на событие смены статуса, и в котором реализовать тот же функционал, что и был + добавить формирование и прикрепление файла.
Клиент выбрал первый(. Но попросил сделать с минимальными изменениями, чтобы после обновления, все быстро восстановить. Вынес что возможно в отдельные функции.

Код все равно покажу, может кому-то пригодиться собирать Excel файл и данный материал поможет.
Правился файл /core/components/minishop2/model/minishop2/minishop2.class.php
Изменялся метод changeOrderStatus
Это было
if ($status->get('email_manager')) {
    $subject = $this->pdoTools->getChunk('@INLINE ' . $status->get('subject_manager'), $pls);
    $tpl = '';
    if ($chunk = $this->modx->getObject('modChunk', $status->get('body_manager'))) {
        $tpl = $chunk->get('name');
    }
    $body = $this->modx->runSnippet('msGetOrder', array_merge($pls, array('tpl' => $tpl)));
    $emails = array_map('trim', explode(',',
            $this->modx->getOption('ms2_email_manager', null, $this->modx->getOption('emailsender')))
    );
    if (!empty($subject)) {
        foreach ($emails as $email) {
            if (preg_match('#.*?@.*#', $email)) {
                $this->sendEmail($email, $subject, $body);
            }
        }
    }
}
так стало
if ($status->get('email_manager')) {
    $subject = $this->pdoTools->getChunk('@INLINE ' . $status->get('subject_manager'), $pls);
    $tpl = '';
    if ($chunk = $this->modx->getObject('modChunk', $status->get('body_manager'))) {
        $tpl = $chunk->get('name');
    }
    $body = $this->modx->runSnippet('msGetOrder', array_merge($pls, array('tpl' => $tpl)));
    $emails = array_map('trim', explode(',',
            $this->modx->getOption('ms2_email_manager', null, $this->modx->getOption('emailsender')))
    );
    $attach = $this->getOrdersXls($order->get('id'));
    if (!empty($subject)) {
        foreach ($emails as $email) {
            if (preg_match('#.*?@.*#', $email)) {
                $this->sendEmailEx($email, $subject, $body, $attach);
            }
        }
        @unlink($attach);
    }
}
На картинке нагляднее, что поменялось

и соответственно новые функции в класс добавляем
/**
     * Function for sending email and attach XLS
     *
     * @param string $email
     * @param string $subject
     * @param string $body
     * @param string $attach
     *
     * @return void
     */
    public function sendEmailEx($email, $subject, $body = '', $attach = '')
    {
        $this->modx->getParser()->processElementTags('', $body, true, false, '[[', ']]', array(), 10);
        $this->modx->getParser()->processElementTags('', $body, true, true, '[[', ']]', array(), 10);

        /** @var modPHPMailer $mail */
        $mail = $this->modx->getService('mail', 'mail.modPHPMailer');
        $mail->setHTML(true);

        $mail->address('to', trim($email));
        $mail->set(modMail::MAIL_SUBJECT, trim($subject));
        $mail->set(modMail::MAIL_BODY, $body);
        $mail->set(modMail::MAIL_FROM, $this->modx->getOption('emailsender'));
        $mail->set(modMail::MAIL_FROM_NAME, $this->modx->getOption('site_name'));
        if (!empty($attach) && is_readable($attach)) {
            $mail->attach($attach);    
        }
        if (!$mail->send()) {
            $this->modx->log(modX::LOG_LEVEL_ERROR,
                'An error occurred while trying to send the email: ' . $mail->mailer->ErrorInfo
            );
        }
        $mail->reset();
    }
и для получения данных в файле XLS
private function getOrdersXls ($order_id) {
        $msOrder = $this->modx->getObject('msOrder', $order_id);
        $msProducts = $msOrder->getMany('Products');

        $aData = array();
        foreach ($msProducts as $product) {
            $msProductData = $this->modx->getObject('msProductData', $product->get('product_id'));
            $tmp = array();
            $tmp['code'] = $msProductData->get('article');
            $tmp['name'] = $product->get('name');
            $tmp['price'] = $product->get('price');
            $tmp['count'] = $product->get('count');
            $aData[] = $tmp;
        }

        require_once MODX_CORE_PATH . 'components/orderattach/PHPExcel/Classes/PHPExcel/IOFactory.php';

        $objReader = PHPExcel_IOFactory::createReader('Excel5');
        $objPHPExcel = $objReader->load(MODX_CORE_PATH . 'components/orderattach/order_attach.xls');
        $iter = 1;
        $baseRow = 1;
        foreach($aData as $r => $dataRow) {
            $row = $baseRow + $iter;
            $objPHPExcel->setActiveSheetIndex(0)->insertNewRowBefore($row+1,1);
            $objPHPExcel->setActiveSheetIndex(0)
                                ->setCellValue('A'.$row, $dataRow['code'])
                                ->setCellValue('B'.$row, $dataRow['name'])
                                ->setCellValue('C'.$row, $dataRow['price'])
                                ->setCellValue('D'.$row, $dataRow['count']);
            $iter++;
        }

        $filename = MODX_CORE_PATH . 'cache/order' . str_replace('/','_',$msOrder->get('num')).'.xls';
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
        $objWriter->save($filename);
        return $filename;
    }

Для формирования файлы Excel с данными заказа minishop2 использую библиотеку PHPExcel
После сборки файла сохраняю его в папку с кешем. После отправки письма удаляю.
В комментариях отпишите, если знаете иное решение данного задания.

Нет комментариев