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