Автоматическое информирование партнеров о состоянии взаиморасчетов — одна из ключевых задач при автоматизации торговых и учетных процессов. Часто разработчики сталкиваются с ситуацией, когда процедура рассылки выполняется без видимых ошибок платформы, но сообщение формируется и отправляется только по одному конкретному контрагенту либо вовсе не доходит до адресатов. Разберем типичные ошибки при построении таких алгоритмов и рассмотрим, как правильно организовать выборку данных и отправку писем.
Проанализируем исходный код запроса, с которым возникла проблема при пакетной рассылке:
ВЫБРАТЬ
РасчетыОстатки.Контрагент,
РасчетыОстатки.Контрагент.ЭлПочта,
СУММА(РасчетыОстатки.БалансОстаток) КАК БалансКонОст
ИЗ
РегистрНакопления.Расчеты.Остатки(
&НаДату,
Контрагент.ЭлПочта <> ""
И Контрагент.Наименование = "!РЕЗЕРВНЫЙ ФОНД") КАК РасчетыОстатки
СГРУППИРОВАТЬ ПО
РасчетыОстатки.Контрагент,
РасчетыОстатки.Контрагент.ЭлПочта
Причиной того, что цикл обрабатывал только одну запись, являлось жесткое условие в параметрах виртуальной таблицы: Контрагент.Наименование = "!РЕЗЕРВНЫЙ ФОНД" (а на следующем этапе отладки — конкретное ФИО). Запрос физически возвращал остаток исключительно по указанному элементу справочника.
Чтобы алгоритм обрабатывал всех партнеров, у которых заполнен адрес электронной почты, необходимо исключить фильтрацию по конкретному наименованию или параметризовать список отбираемых контрагентов.
Разберем по шагам создание надежной процедуры массовой отправки уведомлений по взаиморасчетам.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РасчетыОстатки.Контрагент КАК Контрагент,
| РасчетыОстатки.Контрагент.ЭлПочта КАК ЭлПочта,
| РасчетыОстатки.БалансОстаток КАК БалансКонОст
|ИЗ
| РегистрНакопления.Расчеты.Остатки(&НаДату, Контрагент.ЭлПочта ЕСТЬ НЕ NULL И Контрагент.ЭлПочта <> """") КАК РасчетыОстатки";
Запрос.УстановитьПараметр("НаДату", ТекущаяДата());
Выборка = Запрос.Выполнить().Выбрать();
Обратите внимание: если в регистре измерение Контрагент является единственным или запрос строится только по нему, виртуальная таблица Остатки уже возвращает сгруппированные итоги, поэтому использование конструкции СГРУППИРОВАТЬ ПО и агрегатной функции СУММА() является избыточным.
ВыбНачПериода = ДобавитьМесяц(ТекущаяДата(), -1);
ВыбКонПериода = ТекущаяДата();
Пока Выборка.Следующий() Цикл
ТекущийКонтрагент = Выборка.Контрагент;
ТекущийБаланс = Выборка.БалансКонОст;
// Формирование текста темы сообщения
ПериодСтр = ПредставлениеПериода(ВыбНачПериода, ВыбКонПериода, "L=ru_RU");
ТемаОтправки = "Взаиморасчеты по контрагенту " + СокрЛП(ТекущийКонтрагент.Наименование) + " за период " + ПериодСтр + ". ";
Если ТекущийБаланс < 0 Тогда
ТемаОтправки = ТемаОтправки + "Ваш долг: " + Формат(-ТекущийБаланс, "ЧДЦ=2") + " руб.";
Иначе
ТемаОтправки = ТемаОтправки + "Ваш баланс: " + Формат(ТекущийБаланс, "ЧДЦ=2") + " руб.";
КонецЕсли;
// Переход к формированию и отправке отчета
// ...
КонецЦикла;
При массовой отправке писем стандартным кодом часто возникают скрытые ошибки, приводящие к блокировкам или падению сеанса. Рассмотрим, на что следует обратить внимание:
Попытка ... Исключение ... КонецПопытки с записью ошибки в журнал регистрации:
Попытка
глОтправитьОтчетПоПочте(Таб, ТекущийКонтрагент, ТемаОтправки, 0, ПутьКФайлу, 2);
Сообщить("Успешно отправлено: " + ТекущийКонтрагент);
Исключение
ЗаписьЖурналаРегистрации("Рассылка взаиморасчетов", УровеньЖурналаРегистрации.Ошибка,,,
"Ошибка отправки контрагенту " + ТекущийКонтрагент + ": " + ОписаниеОшибки());
КонецПопытки;
G:\Bases2\Balance.htm) может привести к ошибкам доступа ОС при параллельной работе или быстрой перезаписи файла. Рекомендуется использовать метод ПолучитьИмяВременногоФайла("html") и удалять сгенерированный файл после отправки с помощью процедуры УдалитьФайлы().В (&МассивКонтрагентов) или В ИЕРАРХИИ (&ГруппаКонтрагентов).Приостановить().