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

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

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

Вариант 1. Использование события ПриИзменении в форме документа

Самый прямой и понятный способ для начинающего разработчика — это перехват события изменения реквизита в табличной части формы. Рассмотрим этот механизм. Когда пользователь выбирает элемент из справочника, срабатывает обработчик на стороне клиента, который обращается к серверу для получения данных о статусе.

Проанализируем программный код, который необходимо разместить в модуле формы документа:


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

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

Разберем подробнее, что здесь происходит. Процедура СписокОборудованияОборудованиеПриИзменении вызывается в тот момент, когда выбор в поле завершен. Мы используем метод ПоказатьПредупреждение() вместо устаревшего Сообщить(), так как это блокирует внимание пользователя и гарантирует, что уведомление будет замечено. Обратите внимание на использование директивы &НаСервереБезКонтекста — это позволяет функции работать быстрее, не передавая всю форму с клиента на сервер.

Вариант 2. Оптимизация производительности: избавляемся от «точки»

Выясним причину, почему обращение СсылкаНаОборудование.Статус может быть не самым лучшим решением. В 1С обращение «через точку» к реквизитам ссылочного типа заставляет систему считывать из базы данных весь объект целиком. Если в справочнике Оборудование много тяжелых реквизитов или присоединенных файлов, это создаст лишнюю нагрузку.

Посмотрим на пример более профессионального подхода с использованием метода ЗначениеРеквизитаОбъекта:


&НаСервереБезКонтекста
Функция ОборудованиеВРемонте(СсылкаНаОборудование)
    
    Статус = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаОборудование, "Статус");
    Возврат Статус = Перечисления.СтатусыОборудования.Ремонт;
    
КонецФункции

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


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

Вариант 3. Архитектурный подход: использование регистров сведений

Как справедливо заметили участники обсуждения, хранение текущего статуса непосредственно в справочнике Оборудование — это архитектурная ловушка. Справочник должен содержать статичные данные (серийный номер, модель, производитель). Статус же — это динамическая характеристика, которая меняется во времени.

Рассмотрим преимущества использования периодического регистра сведений (например, СостоянияОборудования):

  1. История изменений: Вы всегда сможете построить отчет и узнать, когда именно оборудование поступило в ремонт и как долго оно там находилось.
  2. Срез последних: Платформа позволяет мгновенно получить текущий статус на любую дату с помощью виртуальной таблицы СрезПоследних.
  3. Масштабируемость: Если завтра потребуется добавить информацию о том, какой мастер выполняет ремонт, вам не придется менять структуру справочника — достаточно добавить ресурс в регистр.

В этом случае проверка в коде будет обращаться к регистру сведений. Это делает систему более гибкой и надежной.

Вариант 4. Предотвращение ошибки вместо оповещения (UX-дизайн)

Проанализируем ситуацию с точки зрения удобства пользователя. Оповещение после выбора — это хорошо, но еще лучше — ограничить список выбора так, чтобы оборудование в ремонте просто не отображалось или было недоступно для выбора.

Для этого мы можем настроить Параметры выбора для реквизита Оборудование в табличной части документа:

  1. Откройте свойства реквизита в конфигураторе.
  2. Найдите пункт Параметры выбора.
  3. Установите отбор: Отбор.Статус(НеРавно)Перечисления.СтатусыОборудования.Ремонт.

Теперь пользователь при нажатии на кнопку выбора увидит только то оборудование, которое физически доступно для ремонта. Это избавляет от лишних кликов и необходимости закрывать окна с предупреждениями.

Вариант 5. Обеспечение целостности данных на уровне объекта

Важно помнить, что проверка в форме документа (о которой мы говорили выше) защищает только от ошибок при ручном вводе. Если данные будут загружаться программно (например, через обработку обмена данными), проверка в форме не сработает.

Рассмотрим, как гарантировать проверку на уровне модуля объекта документа. Пропишем код в процедуре ПередЗаписью:


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

Используя объект СообщениеПользователю, мы не просто выводим текст, но и привязываем его к конкретной ячейке табличной части, где допущена ошибка. Установка параметра Отказ = Истина гарантирует, что некорректные данные никогда не попадут в базу данных.

Итоги и рекомендации

Подводя итог нашему анализу, можно выделить следующие рекомендации для качественной разработки данного функционала:

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

← На главную