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