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