Почему возникает ошибка «Метод объекта не обнаружен (ПолучитьОбъект)» при работе с задачами и как ее решить?

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

При разработке в конфигурации 1С:Документооборот (особенно версии 1.2 и выше) программисты часто сталкиваются с ситуацией, когда код, написанный и отлаженный в тестовой базе, внезапно перестает работать в промышленной среде. Типичный пример — ошибка Метод объекта не обнаружен (ПолучитьОбъект) при попытке программного обращения к задаче. На первый взгляд кажется, что проблема в типе клиента (тонкий или толстый), но причина обычно кроется гораздо глубже — в механике работы бизнес-процессов и фоновых заданий.

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

Разбор причины: почему метод ПолучитьОбъект() не срабатывает?

Проанализируем стандартную ситуацию. Код выполняется в серверном контексте (директива &НаСервере), переменная содержит ссылку на задачу (тип ЗадачаСсылка.ЗадачаИсполнителя), но при вызове МояЗадачаСсылка.ПолучитьОбъект() система выдает ошибку. Рассмотрим основные причины:

  1. Пустая ссылка: Это самая частая причина. Если ваш программный код (например, запрос) не нашел подходящую задачу, он возвращает ПустаяСсылка. У пустой ссылки метод ПолучитьОбъект() в определенных контекстах или при определенных условиях получения данных может вести себя некорректно, либо ошибка возникает на следующем шаге при обращении к свойствам объекта.
  2. Гонка данных и фоновые задания: В 1С:Документооборот создание последующих задач бизнес-процесса часто происходит в фоновом режиме. Когда пользователь нажимает кнопку "Исполнено" в одной задаче, транзакция завершается, и управление возвращается в интерфейс. Однако следующая задача (например, "Проверить") может создаваться фоновым заданием с задержкой в несколько секунд. Если ваш код пытается найти новую задачу сразу после выполнения предыдущей, запрос вернет пустоту.
  3. Несоответствие типов: Несмотря на то что отладчик может показывать тип "ЗадачаСсылка", в результате ошибки в логике (например, при передаче параметров между клиентом и сервером) в переменную может попасть значение Неопределено или системное представление битой ссылки.

Корректное получение ссылки на задачу через запрос

Рассмотрим, как правильно реализовать функцию получения задачи бизнес-процесса, чтобы избежать неопределенности. Часто разработчики используют циклы Пока Выборка.Следующий(), что может привести к возврату неверного значения, если выборка пуста. Перепишем функцию более надежно:


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

Теперь, при вызове метода ПолучитьОбъект(), мы обязательно должны добавить проверку на пустую ссылку, чтобы избежать аварийного завершения программы:


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

Работа с данными формы: РеквизитФормыВЗначение и обратно

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

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


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

Копирование дополнительных реквизитов (БСП)

В 1С:Документооборот дополнительные реквизиты хранятся в табличной части ДополнительныеРеквизиты. Простая запись объекта не всегда приводит к обновлению визуальных элементов на форме, если используется механизм БСП (Библиотека стандартных подсистем). Проанализируем, как это работает.

Если при вызове стандартных процедур вы получаете ошибку Поле объекта не обнаружено (Свойства_ОписаниеДополнительныхРеквизитов), это означает, что форма еще не инициализировала динамические реквизиты для доп. свойств. Это происходит в методе ПриСозданииНаСервере.

Для гарантированного копирования данных между задачами "сбоку" (когда форма приемника еще не открыта или это делается регламентным заданием), используйте прямой перебор табличной части:


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

Рекомендации по архитектуре решения

Чтобы избежать ошибок "объект не обнаружен" и проблем с задержкой фоновых заданий, придерживайтесь следующих правил:

  1. Событийная модель: Старайтесь не искать "будущую" задачу из "текущей". Лучше поместить код заполнения реквизитов в саму задачу-приемник на событие ПриСозданииНаСервере. В этом случае задача уже гарантированно существует.
  2. Модуль бизнес-процесса: Самый надежный способ — прописать логику в модуле самого Бизнес-процесса в обработчике точки маршрута ПередСозданиемЗадач. В этот момент система передает вам массив формируемых задач, и вы можете заполнить их свойства до того, как они будут записаны в базу и станут доступны пользователям.
  3. Проверка модифицированности: Если вы меняете данные формы через ЗначениеВРеквизитФормы, не забывайте устанавливать ЭтаФорма.Модифицированность = Истина;, чтобы пользователь видел изменения и система предложила сохранить их при закрытии.
  4. Использование ОповеститьОбИзменении: Если вы программно изменили задачу в базе данных из другой формы, вызовите ОповеститьОбИзменении(СсылкаНаЗадачу), чтобы открытые динамические списки у пользователей обновили информацию.

Таким образом, корень проблемы чаще всего заключается в асинхронности процессов в Документообороте. Всегда проверяйте возвращаемые значения запросов и учитывайте, что между завершением одной задачи и физическим появлением следующей в базе данных может пройти время, необходимое для отработки фонового процесса.

← На главную