← Назад к вопросам

Проверка отрицательных остатков с уведомлением

2.0 Middle🔥 191 комментариев
#Регистры#Стандарты разработки

Условие

Создайте регламентное задание, которое каждый день в 21:00 проверяет наличие отрицательных остатков товаров и отправляет уведомление на почту или в Telegram.

Требования:

  • Проверка остатков по всем складам
  • Формирование списка товаров с отрицательными остатками
  • Отправка email или сообщения в Telegram ответственному
  • Логирование результатов проверки

Формат уведомления

Обнаружены отрицательные остатки:

Склад: Основной
- Товар 1: -5 шт.
- Товар 2: -10 шт.

Дата проверки: 01.01.2024 21:00

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

Регламентное задание для проверки отрицательных остатков

Рассмотрим архитектуру автоматической проверки остатков товаров с уведомлением через email и Telegram.

Создание регламентного задания

Конфигурация регламентного задания:

// В конфигураторе создаём:
// Объекты метаданных → Регламентные задания → ПроверкаОтрицательныхОстатков

РегламентноеЗадание ПроверкаОтрицательныхОстатков
  Название: "Проверка отрицательных остатков"
  Использование: "Используется"
  Расписание: "Каждый день в 21:00"
  ProcedureName: "МодульОбщегоНазначения.ПроверитьОтрицательныеОстатки"
КонецРегламентногоЗадания

Реализация процедуры проверки

Общий модуль МодульОбщегоНазначения:

// Основная процедура для регламентного задания
Процедура ПроверитьОтрицательныеОстатки(ПараметрыЗадания) Экспорт
    
    ПопыткаПроверки = Новый ТекущаяДата();
    ТекстОшибок = "";
    
    Попытка
        // Получаем список отрицательных остатков
        ОтрицательныеОстатки = ПолучитьОтрицательныеОстатки();
        
        Если ОтрицательныеОстатки.Количество() > 0 Тогда
            // Формируем текст уведомления
            ТекстУведомления = СформироватьТекстУведомления(ОтрицательныеОстатки);
            
            // Отправляем на почту
            ОтправитьEmail(ТекстУведомления);
            
            // Отправляем в Telegram
            ОтправитьTelegram(ТекстУведомления);
            
            ЗаписатьВЖурнал("Проверка остатков", "Обнаружены отрицательные остатки. Количество: " + ОтрицательныеОстатки.Количество());
        Иначе
            ЗаписатьВЖурнал("Проверка остатков", "Отрицательные остатки не обнаружены");
        КонецЕсли;
    
    Исключение
        ТекстОшибок = ОписаниеОшибки();
        ЗаписатьВЖурнал("Проверка остатков", "Ошибка: " + ТекстОшибок, УровеньЖурналаРегистрации.Ошибка);
        ВызватьОшибку("Ошибка при проверке остатков: " + ТекстОшибок);
    КонецПопытки;
    
КонецПроцедуры

Запрос отрицательных остатков

// Функция для получения остатков с отрицательными значениями
Функция ПолучитьОтрицательныеОстатки()
    
    РезультатТаблица = Новый ТаблицаЗначений();
    РезультатТаблица.Колонки.Добавить("Склад", Новый ОписаниеТипов("Строка"));
    РезультатТаблица.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
    РезультатТаблица.Колонки.Добавить("Остаток", Новый ОписаниеТипов("Число"));
    
    // SQL запрос к регистру накопления
    Запрос = Новый Запрос();
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    Остатки.Склад.Наименование КАК СкладНаименование,
    |    Остатки.Номенклатура.Наименование КАК НоменклатураНаименование,
    |    СУММА(Остатки.КоличествоОстаток) КАК Остаток
    |ИЗ
    |    РегистрНакопления.ОстаткиТоваров.Остатки(,) КАК Остатки
    |ГДЕ
    |    СУММА(Остатки.КоличествоОстаток) < 0
    |СГРУППИРОВАТЬ ПО
    |    Остатки.Склад,
    |    Остатки.Номенклатура";
    
    РезультатЗапроса = Запрос.Выполнить();
    ВыборкаДанных = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДанных.Следующий() Цикл
        НоваяСтрока = РезультатТаблица.Добавить();
        НоваяСтрока.Склад = ВыборкаДанных.СкладНаименование;
        НоваяСтрока.Номенклатура = ВыборкаДанных.НоменклатураНаименование;
        НоваяСтрока.Остаток = ВыборкаДанных.Остаток;
    КонецЦикла;
    
    Возврат РезультатТаблица;
    
КонецФункции

Формирование текста уведомления

// Функция для форматирования сообщения
Функция СформироватьТекстУведомления(ОтрицательныеОстатки)
    
    Текст = "Обнаружены отрицательные остатки:" + Символы.ПС + Символы.ПС;
    
    // Группируем по складам
    ТекущийСклад = "";
    Для Каждого Строка Из ОтрицательныеОстатки Цикл
        
        Если ТекущийСклад <> Строка.Склад Тогда
            Текст = Текст + "Склад: " + Строка.Склад + Символы.ПС;
            ТекущийСклад = Строка.Склад;
        КонецЕсли;
        
        // Форматируем остаток (количество товара отрицательное)
        Остаток = Число(Строка.Остаток);
        Текст = Текст + "- " + Строка.Номенклатура + ": " + Остаток + " шт." + Символы.ПС;
        
    КонецЦикла;
    
    Текст = Текст + Символы.ПС + "Дата проверки: " + Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy ЧЧ:мм") + Символы.ПС;
    
    Возврат Текст;
    
КонецФункции

Отправка Email

Процедура ОтправитьEmail(ТекстУведомления)
    
    Попытка
        // Получаем почту ответственного лица из параметров
        СоответствиеНастроек = ПолучитьНастройкиУведомлений();
        Email = СоответствиеНастроек.Получить("Email");
        
        Если ЗначениеЗаполнено(Email) Тогда
            ПочтовоеСообщение = Новый ПочтовоеСообщение();
            ПочтовоеСообщение.Отправитель = "noreply@company.ru";
            ПочтовоеСообщение.Тема = "Уведомление: Отрицательные остатки товаров";
            ПочтовоеСообщение.Текст = ТекстУведомления;
            ПочтовоеСообщение.Адресаты.Добавить(Email);
            
            ПочтовоеСообщение.Отправить();
            
            ЗаписатьВЖурнал("Email отправка", "Email отправлено на: " + Email);
        КонецЕсли;
    
    Исключение
        ЗаписатьВЖурнал("Email отправка", "Ошибка отправки Email: " + ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка);
    КонецПопытки;
    
КонецПроцедуры

Отправка в Telegram

Процедура ОтправитьTelegram(ТекстУведомления)
    
    Попытка
        // Получаем параметры Telegram из конфигурации
        СоответствиеНастроек = ПолучитьНастройкиУведомлений();
        APIKey = СоответствиеНастроек.Получить("TelegramAPIKey");
        ChatID = СоответствиеНастроек.Получить("TelegramChatID");
        
        Если ЗначениеЗаполнено(APIKey) И ЗначениеЗаполнено(ChatID) Тогда
            
            // HTTP запрос к Telegram Bot API
            HTTPЗапрос = Новый HTTPЗапрос("sendMessage");
            HTTPЗапрос.УстановитьПараметр("chat_id", ChatID);
            HTTPЗапрос.УстановитьПараметр("text", ТекстУведомления);
            HTTPЗапрос.УстановитьПараметр("parse_mode", "HTML");
            
            URLТелеграм = "https://api.telegram.org/bot" + APIKey + "/";
            HTTPСоединение = Новый HTTPСоединение("api.telegram.org");
            
            Ответ = HTTPСоединение.ОтправитьДляПолучения(HTTPЗапрос);
            
            ЗаписатьВЖурнал("Telegram отправка", "Сообщение отправлено в Telegram");
        КонецЕсли;
    
    Исключение
        ЗаписатьВЖурнал("Telegram отправка", "Ошибка отправки в Telegram: " + ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка);
    КонецПопытки;
    
КонецПроцедуры

Логирование результатов

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

// Функция получения настроек
Функция ПолучитьНастройкиУведомлений()
    
    Настройки = Новый Соответствие();
    
    // Получаем из хранилища настроек (рекомендуется)
    // или из справочника "НастройкиСистемы"
    Настройки.Вставить("Email", ПолучитьОтветственногоЛица());
    Настройки.Вставить("TelegramAPIKey", ПолучитьФункциональнуюОпцию("TelegramAPIKey"));
    Настройки.Вставить("TelegramChatID", ПолучитьФункциональнуюОпцию("TelegramChatID"));
    
    Возврат Настройки;
    
КонецФункции

Расписание задания

В конфигураторе:

  • Тип расписания: Ежедневно
  • Время: 21:00
  • Временная зона: по умолчанию

Архитектурные решения

1. Разделение отправки по каналам:

  • Email — официальное уведомление
  • Telegram — оперативное уведомление
  • Оба работают параллельно

2. Логирование всех операций:

  • Помогает отследить проблемы с отправкой
  • Ведёт историю проверок

3. Обработка ошибок:

  • Ошибка в одном канале не блокирует другой
  • Все события логируются

4. Безопасность:

  • Ключи и пароли хранятся в параметрах конфигурации
  • Не должны быть в исходном коде

Эта реализация обеспечивает надёжное и своевременное уведомление о проблемах с остатками товаров.

Проверка отрицательных остатков с уведомлением | PrepBro