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