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