Содержание
Мониторинг обмена данными Битрикс
Задача: мониторить состояние обмена сайта на Битрикс с 1С, и при отсутствии обмена отправлять уведомления на почту с темой «Проблема обмена заказами 1С и сайта».
Дорабатываем скрипты обмена
После строчки
- bitrix/components/bitrix/catalog.import.1c/component.php
COption::SetOptionString("sale", "last_export_time_".$curPage, time());
вставить
- bitrix/components/bitrix/catalog.import.1c/component.php
COption::SetOptionString("sale", "monitor/1c-sales/mod=query/time", time());
Добавляем почтовое событие
Создаем новый тип события «MONITOR_REPORT» и добавляем почтовый шаблон следующего вида:
От кого: #DEFAULT_EMAIL_FROM# Кому: #USER_MAIL# Тема: #SUBJECT# Сообщение (тип HTML): #MESSAGE#
Скрипт мониторинга
- cron/monitor-1c.php
if(php_sapi_name() !== 'cli') die('Access denied'); // только по расписанию из CLI $_SERVER["DOCUMENT_ROOT"] = dirname(__DIR__); define("LANGUAGE_ID", "s1"); // ID сайта define("NO_KEEP_STATISTIC", true); define("NOT_CHECK_PERMISSIONS", true); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php"); // Run class MonitorSales1C { private $now, $delay = 10800, // задержка перед повторной отправкой уведомления (секунды) $intervalQuery = 20, // максимальный интервал просрочки обмена (минуты) $intervalSales = 20, // максимальный интервал просрочки подтверждения заказов (минуты) $notifyMails = 'webmaster@site.ru,admin@site.ru', // Email для уведомлений $notifySubj = 'Проблема обмена заказами 1С и сайта', // Тема письма $notifyPS = '<p><em>Это сообщение сформировано автоматически с сайта site.ru</em></p>' // Постскриптум ; public function __construct() { CModule::IncludeModule("iblock"); CModule::IncludeModule("sale"); $this->now = new DateTime(); } public function run() { try { $this->checkQuery(); // проверка обмена заказами $this->checkSales(); // проверка выгрузки подтверждения обработки заказов } catch (Exception $e) { $text = $e->getMessage(); if($this->isDelayLeft()) { $this->setDelay(); $this->notify($text); } echo $text.PHP_EOL; } } private function checkQuery() { $lastTimeStamp = COption::GetOptionString("sale", "monitor/1c-sales/mod=query/time", "0"); // событие, которое проверяем if($lastTimeStamp == "0") return; $diff = $this->calcMaxExceedDate($this->intervalQuery)->getTimestamp() - $lastTimeStamp; if($diff > 0) throw new Exception("Давно не было получения заказов: с ".date('Y-m-d H:i:s', $lastTimeStamp)); } private function checkSales() { $dayAgo = clone $this->now; $dayAgo->modify("-24 hour"); $orderFilter = array( 'CANCELED' => 'N', '>DATE_INSERT' => $dayAgo->format("d.m.Y H:i:s"), // ищем все заказы за день '<DATE_UPDATE' => $this->calcMaxExceedDate($this->intervalSales)->format("d.m.Y H:i:s"), // отбрасываем за последние N минут 'LID' => LANGUAGE_ID ); $ordersList = CSaleOrder::GetList(array("ID" => "DESC"), $orderFilter, false, false, array("ID", "DATE_INSERT")); if($ordersList->SelectedRowsCount() == 0) return; $notImportedOrders = array(); while($order = $ordersList->Fetch()) { $historyFilter = array("ORDER_ID" => $order['ID'], "TYPE" => "ORDER_1C_IMPORT"); $historyList = CSaleOrderChange::GetList(array("ID" => "DESC"), $historyFilter, false, false, array("ID")); if($historyList->SelectedRowsCount() == 0) { $notImportedOrders[] = $order['ID'].' ['.$order['DATE_INSERT'].']'; } } if(count($notImportedOrders) > 0) throw new Exception("Не были импортированы в 1С следующие заказы: <br />".implode('<br />', $notImportedOrders), 1); } private function calcMaxExceedDate($minutes) { $date = new DateTime(); $date->modify("-".(int)$minutes." minute"); // <= максимальное время просрочки return $date; } private function notify($text) { echo 'Send notify...'.PHP_EOL; $arEventFields = array( 'USER_MAIL' => $this->notifyMails, 'SUBJECT' => $this->notifySubj, 'MESSAGE' => '<p><b>'.$text.'</b></p>'.$this->notifyPS ); CEvent::SendImmediate('MONITOR_REPORT', LANGUAGE_ID, $arEventFields, 'N'); } private function isDelayLeft() { $lastTimeStamp = COption::GetOptionString("sale", "monitor/1c-sales/delay", 0); if($lastTimeStamp == 0) return true; $diff = $this->now->getTimestamp() - $lastTimeStamp; return $diff > $this->delay; } private function setDelay() { COption::SetOptionString("sale", "monitor/1c-sales/delay", $this->now->getTimestamp()); } } $MonitorSales1C = new MonitorSales1C(); $MonitorSales1C->run();
Расписание запуска
Скрипт мониторинга состояния выгрузки заказов в 1С следует повесить на расписание по крону, например:
- crontab.txt
# мониторинг обмена заказами: каждые 10 минут, начиная с 8-00 и до 20-00 по рабочим дням */10 8-20 * * 1-5 /usr/bin/php /path-to-site/cron/monitor-1c.php