Как правильно отправлять электронные письма при изменении реквизитов документа в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке функционала в 1С часто возникает задача: необходимо отследить изменение определенного реквизита (например, статуса заявки или срочности) и при выполнении условий отправить электронное письмо пользователю. Разберем типичные ошибки начинающих разработчиков при решении этой задачи, проанализируем механизмы передачи данных между событиями объекта и посмотрим, как правильно организовать архитектуру отправки.

Анализ проблемы: почему нельзя менять параметры стандартных обработчиков

Часто программисты пытаются реализовать проверку условия в событии ПриЗаписиНаСервере, а саму отправку письма вынести в ПослеЗаписиНаСервере. Чтобы сообщить второму событию о том, что письмо нужно отправить, разработчик может попытаться добавить свою переменную прямо в объявление процедуры, например так:


&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи, ПроверимУстановленЛиФлагЧтоПисьмоОтправлятьНужно)
    // Попытка передать флаг в параметрах
КонецПроцедуры

Это критическая ошибка. Платформа 1С вызывает обработчики событий со строго заданным набором параметров (сигнатурой). Изменение сигнатуры стандартных процедур приведет к тому, что событие либо не отработает корректно, либо вызовет ошибку выполнения в момент сохранения документа.

Передача состояния через ДополнительныеСвойства

Разберем правильный способ передачи информации (флагов, таблиц значений, структур) между событиями записи одного объекта (из ПередЗаписью в ПриЗаписи или ПослеЗаписи). В платформе для этого существует специальная коллекция — ДополнительныеСвойства.

Это структура, которая доступна через объект и существует только в оперативной памяти во время цикла записи объекта. Она не сохраняется в базу данных и идеально подходит для временных флагов.

Пошаговое решение задачи

Рассмотрим логику работы по шагам. Нам необходимо выполнить три действия:

  1. Проверить, изменился ли реквизит.
  2. Если изменился — установить флаг необходимости отправки письма.
  3. После успешной записи документа проверить флаг и отправить письмо.

Шаг 1. Проверка условия до записи

Сравнивать старое значение (из базы данных) и новое значение (только что введенное пользователем) правильнее всего в событии ПередЗаписьюНаСервере (в модуле формы) или ПередЗаписью (в модуле объекта). В этот момент новые данные еще не зафиксированы в базе, и мы можем обратиться к старым данным через Объект.Ссылка (или ТекущийОбъект.Ссылка), а к новым — напрямую через реквизиты объекта.


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Проверяем, что срочность заполнена и изменилась по сравнению с базой
    Если ЗначениеЗаполнено(ТекущийОбъект.Срочность) 
       И ТекущийОбъект.Срочность <> ТекущийОбъект.Ссылка.Срочность Тогда
        
        // Устанавливаем флаг в ДополнительныеСвойства
        ТекущийОбъект.ДополнительныеСвойства.Вставить("НужноОтправитьПисьмо", Истина);
        
        // Здесь же можно подготовить тему и текст письма
        ТекущийОбъект.ДополнительныеСвойства.Вставить("ТекстПисьма", "Срочность заявки изменена на " + ТекущийОбъект.Срочность);
    КонецЕсли;
КонецПроцедуры

Шаг 2. Отправка письма после записи

В событии ПослеЗаписиНаСервере мы проверяем наличие нашего флага. Если он есть — инициируем отправку. К этому моменту транзакция записи объекта в форме уже завершается (или завершена), и мы можем быть уверены, что данные сохранены.


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    // Проверяем наличие флага
    Если ТекущийОбъект.ДополнительныеСвойства.Свойство("НужноОтправитьПисьмо") Тогда
        // Получаем подготовленный текст
        ТекстПисьма = "";
        ТекущийОбъект.ДополнительныеСвойства.Свойство("ТекстПисьма", ТекстПисьма);
        
        // Вызываем общую процедуру отправки
        СозданиеИОтправкаПисьма(ТекстПисьма);
    КонецЕсли;
КонецПроцедуры

Архитектурная проблема синхронной отправки писем

Выше мы рассмотрели технически верный способ передачи параметров, но вызывать функцию отправки писем напрямую в событии формы или объекта — это не самая хорошая практика с точки зрения архитектуры высоконагруженных систем. Выясним причины:

Рекомендуемый подход (Best Practice)

Посмотрим на более профессиональный способ решения (асинхронная рассылка):

  1. Создаем специальный РегистрСведений (например, «Очередь исходящих писем»).
  2. В событии ПриЗаписи (модуля объекта) мы не отправляем письмо, а лишь добавляем запись в этот регистр с указанием темы, текста и адресата. Это происходит моментально и в рамках общей транзакции документа.
  3. Создаем РегламентноеЗадание, которое запускается на сервере 1С каждую минуту.
  4. Регламентное задание читает невыполненные записи из регистра рассылки, пытается отправить письма и в случае успеха ставит отметку об отправке (или удаляет запись).

Используя механизм ДополнительныеСвойства в связке с фоновой отправкой писем, мы обеспечиваем надежную, быструю и безопасную работу системы, не заставляя пользователей ждать завершения сетевых операций.

← На главную