Автоматическая отправка уведомлений по электронной почте — важнейший элемент современных корпоративных систем на базе 1С. В интеграционных решениях, таких как 1С:ERP Управление предприятием совместно с финансовой системой БИТ.ФИНАНС, за отправку писем отвечает мощная подсистема оповещений. Однако разработчики часто сталкиваются с ситуацией, когда для новых документов оповещения упорно отказываются регистрироваться и отправляться в момент проведения. Проанализируем эту проблему, детально разберем механизм работы подсистемы БИТ.ФИНАНС, выявим архитектурные ошибки в коде и найдем надежное решение.
Для того чтобы понять, почему оповещение не уходит на почту, разберем по шагам, как устроена подсистема отправки писем в БИТ.ФИНАНС. Этот механизм работает по асинхронной трехступенчатой схеме:
Регистрация событий для оповещений (техническое имя в системе — бит_фн_РегистрацияСобытийОповещений). Запись создается со статусом «Зарегистрировано».бит_фн_Оповещения, проверяет дополнительные пользовательские условия, формирует списки получателей и текст письма по шаблону. Подготовленные данные переносятся в регистр сведений Оповещения.Оповещения, подключается к почтовому серверу через системную учетную запись и производит физическую отправку писем адресатам.Если на первом этапе запись в регистр бит_фн_РегистрацияСобытийОповещений не попадает, то вся дальнейшая цепочка прерывается. Именно это и происходит у автора обсуждаемой темы.
Посмотрим на пример исходного кода, который автор добавил в модуль объекта документа для перехвата проведения:
Процедура СТ_ОбработкаПроведения(Отказ, РежимПроведения)
Если Отказ Тогда
Возврат;
КонецЕсли;
Если НЕ Отказ Тогда
Если Статус = Перечисления.СТ_СтатусыАктовИспытаний.НеРаспределен Тогда
Документы.СТ_АктИспытаний.СТ_РегистрацияОповещений(ДополнительныеСвойства, ЭтотОбъект);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
И процедура регистрации в модуле менеджера документа:
Процедура СТ_РегистрацияОповещений(ДополнительныеСвойства, ДокументОбъект) Экспорт
бит_фн_ОповещенияСервер.ЗарегистрироватьПоВидуСобытияДляОповещения(
ПредопределенноеЗначение("Перечисление.СТ_СобытияОповещений.СТ_АктИспытаний_НеРаспределен"),
ДокументОбъект.Ссылка
);
КонецПроцедуры
Проанализируем ситуацию и выделим несколько критических уязвимостей данного решения, из-за которых новые документы не регистрируют события.
Обратите внимание на вызов метода бит_фн_ОповещенияСервер.ЗарегистрироватьПоВидуСобытияДляОповещения. Вторым параметром туда передается ДокументОбъект.Ссылка. На этапе проведения нового документа транзакция записи в базу данных еще не завершена. Ссылка на документ уже сформирована в оперативной памяти платформы, но физической записи в таблицах СУБД для внешних сеансов или определенных видов запросов может еще не существовать (или данные находятся в промежуточном состоянии).
Внутри процедуры регистрации БИТ.ФИНАНС выполняется следующий запрос к справочнику настроек оповещений:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| бит_фн_Оповещения.Ссылка КАК Оповещение,
| бит_фн_Оповещения.ВидСобытия КАК ВидСобытия,
| бит_фн_Оповещения.Виза КАК Виза,
| бит_фн_Оповещения.ПользовательскоеУсловие КАК ПользовательскоеУсловие
|ИЗ
| Справочник.бит_фн_Оповещения КАК бит_фн_Оповещения
|ГДЕ
| бит_фн_Оповещения.СТ_СобытиеОповещения = &СобытиеОповещения
| И НЕ бит_фн_Оповещения.ПометкаУдаления"
);
После выборки настроек система БИТ.ФИНАНС выполняет проверку пользовательских условий:
СтруктураКонтекст = Новый Структура("ТекущийОбъект", ОбъектОповещения);
// ...
Если ЗначениеЗаполнено(Выборка.ПользовательскоеУсловие)
И Не бит_уп_Сервер.ПроверитьПользовательскоеУсловие(Выборка.ПользовательскоеУсловие, СтруктураКонтекст) Тогда
Продолжить;
КонецЕсли;
Поскольку в ОбъектОповещения была передана Ссылка, функция ПроверитьПользовательскоеУсловие при вычислении формул (например, при проверке реквизитов документа вроде Организации, Суммы или Статуса) будет обращаться к базе данных через эту ссылку. Так как транзакция проведения нового документа еще не зафиксирована окончательно, СУБД вернет либо пустые значения полей, либо старые данные (если документ ранее уже существовал, но перезаписывается). В результате пользовательское условие вернет Ложь, срабатывает оператор Продолжить, и запись в регистр сведений просто игнорируется.
Автор указывает, что проблема возникает, когда статус документа равен "НеОпределен". При этом в коде СТ_ОбработкаПроведения стоит жесткое условие:
Если Статус = Перечисления.СТ_СтатусыАктовИспытаний.НеРаспределен Тогда
Если в момент проведения нового документа его статус еще не успел заполниться значением "НеРаспределен" и равен пустому значению (или значению "НеОпределен"), то условие Если... Тогда просто не выполняется, и вызов процедуры регистрации оповещения даже не инициируется. Необходимо четко отслеживать жизненный цикл изменения статусов в документе.
Любая ошибка или принудительная отмена проведения (когда переменная Отказ принимает значение Истина) после вызова вашей процедуры регистрации приведет к полному откату транзакции СУБД. Запись в регистре сведений бит_фн_РегистрацияСобытийОповещений, созданная внутри транзакции проведения, также будет безвозвратно удалена. Поэтому регистрация событий внутри процедуры ОбработкаПроведения всегда сопряжена с риском ложных срабатываний или потерь данных при ошибках проведения других механизмов ERP.
В ходе обсуждения на форуме прозвучал вопрос о том, почему в отладчике все поля видны, а поле Виза остается пустым. Разберем этот момент подробнее. В архитектуре БИТ.ФИНАНС измерение Виза в регистрах оповещений заполняется исключительно тогда, когда событие связано с процессами визирования и согласования (например, при установке конкретной визы, направлении на согласование и т.д.). Для обычных кастомных событий (таких как изменение статуса или проведение произвольного документа) отсутствие заполненной визы — это абсолютно штатное поведение системы, не влияющее на отправку писем.
Рассмотрим, как правильно модифицировать код и настройки системы, чтобы оповещения гарантированно регистрировались и уходили адресатам.
Для того чтобы подсистема проверки условий БИТ.ФИНАНС могла анализировать реквизиты нового (еще не записанного в БД) документа непосредственно из оперативной памяти, необходимо передавать в процедуру регистрации сам объект документа, а не его ссылку. Модернизируем процедуру в модуле менеджера следующим образом:
Процедура СТ_РегистрацияОповещений(ДополнительныеСвойства, ДокументОбъект) Экспорт
// Передаем сам ДокументОбъект вместо ДокументОбъект.Ссылка
бит_фн_ОповещенияСервер.ЗарегистрироватьПоВидуСобытияДляОповещения(
ПредопределенноеЗначение("Перечисление.СТ_СобытияОповещений.СТ_АктИспытаний_НеРаспределен"),
ДокументОбъект
);
КонецПроцедуры
Теперь внутри метода ЗарегистрироватьПоВидуСобытияДляОповещения переменная ОбъектОповещения будет содержать полноценный объект типа ДокументОбъект.СТ_АктИспытаний. В этом случае проверка условий будет производиться корректно по актуальным данным из памяти сеанса.
Проанализируем логику установки статусов. Если новый документ при проведении должен автоматически получать статус "НеРаспределен", убедимся, что этот статус присваивается реквизиту до момента вызова регистрации оповещений. Перепишем логику в модуле объекта:
Процедура СТ_ОбработкаПроведения(Отказ, РежимПроведения)
Если Отказ Тогда
Возврат;
КонецЕсли;
// Если статус не определен для нового документа, принудительно устанавливаем его
Если Не ЗначениеЗаполнено(Статус) Или Статус = Перечисления.СТ_СтатусыАктовИспытаний.НеОпределен Тогда
Статус = Перечисления.СТ_СтатусыАктовИспытаний.НеРаспределен;
КонецЕсли;
// Теперь инициируем регистрацию события
Если Статус = Перечисления.СТ_СтатусыАктовИспытаний.НеРаспределен Тогда
Документы.СТ_АктИспытаний.СТ_РегистрацияОповещений(ДополнительныеСвойства, ЭтотОбъект);
КонецЕсли;
КонецПроцедуры
Чтобы избежать проблем с транзакционными блокировками и откатами проведения, хорошей практикой является вынос регистрации оповещений в событие модуля объекта ПриЗаписи или использование дополнительных свойств для отложенной обработки. Рассмотрим пример реализации через дополнительные свойства:
// В модуле объекта документа
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Основная логика проведения...
// Если проведение успешно, помечаем необходимость отправки оповещения
Если Не Отказ Тогда
ДополнительныеСвойства.Вставить("СТ_ТребуетсяОповещение_НеРаспределен", Истина);
КонецЕсли;
КонецПроцедуры
Процедура ПриЗаписи(Отказ)
Если Отказ Тогда
Возврат;
КонецЕсли;
// Проверяем флаг, установленный при успешном проведении
Если ДополнительныеСвойства.Свойство("СТ_ТребуетсяОповещение_НеРаспределен")
И ДополнительныеСвойства.СТ_ТребуетсяОповещение_НеРаспределен Тогда
Документы.СТ_АктИспытаний.СТ_РегистрацияОповещений(ДополнительныеСвойства, ЭтотОбъект);
КонецЕсли;
КонецПроцедуры
Даже при идеальном коде оповещения не зарегистрируются, если отключена глобальная функциональность в настройках конфигурации. Проверим следующие параметры:
Использовать механизм оповещений.бит_фн_Оповещения найдем нашу настройку по событию СТ_АктИспытаний_НеРаспределен, проверим, что у нее установлен статус Действует.После того как код заработает и записи начнут появляться в регистре бит_фн_РегистрацияСобытийОповещений, проконтролируем запуск регламентных заданий. В файловых базах или тестовых контурах они часто выключены по умолчанию. Проверим работу заданий через консоль регламентных заданий 1С:
Обработка событий регистрации оповещений (должна запускаться каждые 1-5 минут).Отправка оповещений (должна запускаться с аналогичной или чуть меньшей частотой).Применение этого комплексного подхода гарантирует стабильную, отказоустойчивую регистрацию и отправку писем при проведении любых документов в связке 1С:ERP и БИТ.ФИНАНС.