В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача оперативного информирования пользователя о состоянии выбираемых объектов. Рассмотрим классическую ситуацию: у нас есть справочник Оборудование с реквизитом Статус и документ Ремонт. Нам необходимо сделать так, чтобы при добавлении оборудования в табличную часть документа система мгновенно проверяла его текущее состояние и, если оно уже находится в ремонте, выводила предупреждение. Разберем по шагам, как это реализовать максимально эффективно и архитектурно правильно.
Самый прямой и понятный способ для начинающего разработчика — это перехват события изменения реквизита в табличной части формы. Рассмотрим этот механизм. Когда пользователь выбирает элемент из справочника, срабатывает обработчик на стороне клиента, который обращается к серверу для получения данных о статусе.
Проанализируем программный код, который необходимо разместить в модуле формы документа:
&НаКлиенте
Процедура СписокОборудованияОборудованиеПриИзменении(Элемент)
// Получаем текущую строку табличной части
СтрокаТЧ = Элементы.СписокОборудования.ТекущиеДанные;
Если СтрокаТЧ = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем статус на сервере
Если ОборудованиеВРемонте(СтрокаТЧ.Оборудование) Тогда
ТекстСообщения = "Внимание! Оборудование '" + СтрокаТЧ.Оборудование + "' уже находится в статусе 'Ремонт'!";
ПоказатьПредупреждение(, ТекстСообщения);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ОборудованиеВРемонте(СсылкаНаОборудование)
// Проверяем, заполнена ли ссылка
Если СсылкаНаОборудование.Пустая() Тогда
Возврат Ложь;
КонецЕсли;
// Получаем статус напрямую из справочника (упрощенный вариант)
Возврат СсылкаНаОборудование.Статус = Перечисления.СтатусыОборудования.Ремонт;
КонецФункции
Разберем подробнее, что здесь происходит. Процедура СписокОборудованияОборудованиеПриИзменении вызывается в тот момент, когда выбор в поле завершен. Мы используем метод ПоказатьПредупреждение() вместо устаревшего Сообщить(), так как это блокирует внимание пользователя и гарантирует, что уведомление будет замечено. Обратите внимание на использование директивы &НаСервереБезКонтекста — это позволяет функции работать быстрее, не передавая всю форму с клиента на сервер.
Выясним причину, почему обращение СсылкаНаОборудование.Статус может быть не самым лучшим решением. В 1С обращение «через точку» к реквизитам ссылочного типа заставляет систему считывать из базы данных весь объект целиком. Если в справочнике Оборудование много тяжелых реквизитов или присоединенных файлов, это создаст лишнюю нагрузку.
Посмотрим на пример более профессионального подхода с использованием метода ЗначениеРеквизитаОбъекта:
&НаСервереБезКонтекста
Функция ОборудованиеВРемонте(СсылкаНаОборудование)
Статус = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаОборудование, "Статус");
Возврат Статус = Перечисления.СтатусыОборудования.Ремонт;
КонецФункции
Если в вашей конфигурации нет библиотеки стандартных подсистем (БСП), можно использовать обычный запрос. Это самый быстрый способ получения данных из базы:
&НаСервереБезКонтекста
Функция ОборудованиеВРемонте(СсылкаНаОборудование)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Оборудование.Статус КАК Статус
|ИЗ
| Справочник.Оборудование КАК Оборудование
|ГДЕ
| Оборудование.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаОборудование);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Статус = Перечисления.СтатусыОборудования.Ремонт;
КонецЕсли;
Возврат Ложь;
КонецФункции
Как справедливо заметили участники обсуждения, хранение текущего статуса непосредственно в справочнике Оборудование — это архитектурная ловушка. Справочник должен содержать статичные данные (серийный номер, модель, производитель). Статус же — это динамическая характеристика, которая меняется во времени.
Рассмотрим преимущества использования периодического регистра сведений (например, СостоянияОборудования):
СрезПоследних.В этом случае проверка в коде будет обращаться к регистру сведений. Это делает систему более гибкой и надежной.
Проанализируем ситуацию с точки зрения удобства пользователя. Оповещение после выбора — это хорошо, но еще лучше — ограничить список выбора так, чтобы оборудование в ремонте просто не отображалось или было недоступно для выбора.
Для этого мы можем настроить Параметры выбора для реквизита Оборудование в табличной части документа:
Отбор.Статус(НеРавно)Перечисления.СтатусыОборудования.Ремонт.Теперь пользователь при нажатии на кнопку выбора увидит только то оборудование, которое физически доступно для ремонта. Это избавляет от лишних кликов и необходимости закрывать окна с предупреждениями.
Важно помнить, что проверка в форме документа (о которой мы говорили выше) защищает только от ошибок при ручном вводе. Если данные будут загружаться программно (например, через обработку обмена данными), проверка в форме не сработает.
Рассмотрим, как гарантировать проверку на уровне модуля объекта документа. Пропишем код в процедуре ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Для Каждого СтрокаТЧ Из СписокОборудования Цикл
Если ОборудованиеВРемонте(СтрокаТЧ.Оборудование) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Оборудование " + СтрокаТЧ.Оборудование + " уже в ремонте. Запись невозможна.";
Сообщение.Поле = "СписокОборудования[" + СписокОборудования.Индекс(СтрокаТЧ) + "].Оборудование";
Сообщение.Сообщить();
Отказ = Истина; // Блокируем запись документа
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Используя объект СообщениеПользователю, мы не просто выводим текст, но и привязываем его к конкретной ячейке табличной части, где допущена ошибка. Установка параметра Отказ = Истина гарантирует, что некорректные данные никогда не попадут в базу данных.
Подводя итог нашему анализу, можно выделить следующие рекомендации для качественной разработки данного функционала:
ПриИзменении на клиенте с вызовом внеконтекстной серверной функции.ПоказатьОповещениеПользователя() (всплывающее окно в углу) или ПоказатьПредупреждение() (модальное окно), если действие критично.ПередЗаписью), чтобы защитить базу от программных ошибок.Применяя эти подходы в комплексе, вы создадите надежную и удобную систему, которая минимизирует количество ошибок при вводе данных и будет легко поддаваться дальнейшему развитию.