Как исправить ошибку «Не удалось найти объект расчетов. Код ошибки = 21» при записи договора в 1С?

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

При переносе данных с помощью Конвертации данных 2.1 (КД 2.1) программисты часто сталкиваются с ситуациями, когда стандартные механизмы загрузки дополняются сложным программным кодом в обработчиках. Одной из наиболее «коварных» ошибок в современных конфигурациях на базе платформы 1С:Предприятие 8.3 (таких как ERP 2.5, Комплексная автоматизация 2 или Управление торговлей 11) является ошибка: «Не удалось найти объект расчетов. Код ошибки = 21».

Эта ошибка обычно возникает в момент вызова метода Записать() для объекта справочника ДоговорыКонтрагентов. Давайте подробно разберем, почему это происходит и как правильно настроить обмен, чтобы избежать подобных исключений.

Анализ исходной ситуации

Рассмотрим ситуацию, описанную пользователем. В обработчике «После загрузки» правила конвертации объектов (ПКО) выполняется программное создание или поиск основного договора для контрагента. Код выглядит следующим образом:


// Получение параметров, переданных из источника
ДатаДоговора = ПараметрыОбъекта.Получить("ДатаДоговора");
СрокДействия = ПараметрыОбъекта.Получить("СрокДействия");
НомерДоговора = ПараметрыОбъекта.Получить("НомерДоговора");
ВалютаВзаиморасчетов = ПараметрыОбъекта.Получить("ВалютаВзаиморасчетов");
Владелец = ПараметрыОбъекта.Получить("Владелец");
ВедениеВзаиморасчетов = ПараметрыОбъекта.Получить("ВедениеВзаиморасчетов");

// Поиск или создание Партнера
КонтрагентНаименование = Владелец.Наименование;
ПартнерСсылка = Справочники.Партнеры.НайтиПоРеквизиту("НаименованиеПолное", КонтрагентНаименование);
Партнер = ПартнерСсылка.ПолучитьОбъект(); 

// Логика создания договора
Если ДоговорПроверка = Справочники.БУХ_ДоговорыКонтрагентов.ПустаяСсылка() Тогда    
    ОсновнойДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
Иначе
    // ... логика поиска существующего договора
КонецЕсли;

// Заполнение реквизитов договора
ОсновнойДоговор.Наименование = Объект.Наименование;
// ... установка типов договора и порядка расчетов
ОсновнойДоговор.Записать(); // Здесь возникает ошибка Код 21

Проанализируем причину сбоя. В современных конфигурациях 1С используется сложная подсистема взаиморасчетов. Когда мы вызываем Записать() для договора, система автоматически пытается создать запись в техническом справочнике «Объекты расчетов» (или связать договор с существующим ключом). Код ошибки 21 сигнализирует о том, что внутренняя функция подсистемы не смогла идентифицировать параметры для формирования этого ключа.

Причина 1: Флаг ОбменДанными.Загрузка

Это самая распространенная причина. Когда объект создается или загружается через стандартные механизмы КД 2.1, платформа автоматически устанавливает свойство ОбменДанными.Загрузка = Истина. Это отключает большинство проверок в модуле объекта и модуле менеджера, позволяя записать «сырые» данные.

Однако, в приведенном выше коде автор создает объект вручную через Справочники.ДоговорыКонтрагентов.СоздатьЭлемент(). Для такого объекта свойство ОбменДанными.Загрузка по умолчанию равно Ложь. Следовательно, при вызове Записать() система запускает полную бизнес-логику, включая механизмы онлайн-взаиморасчетов, которые требуют идеальной заполненности всех связанных аналитик.

Решение: Перед вызовом записи необходимо принудительно установить признак загрузки.


ОсновнойДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
// ... заполнение полей ...
ОсновнойДоговор.ОбменДанными.Загрузка = Истина; 
ОсновнойДоговор.Записать();

Причина 2: Незаполненные обязательные реквизиты (Организация)

Разберем ситуацию глубже. Даже если мы установим Загрузка = Ложь, запись должна проходить, если все данные корректны. Ошибка 21 часто возникает, когда для формирования объекта расчетов не хватает ключевого поля — Организации.

В коде автора мы видим заполнение контрагента, партнера и валюты, но отсутствует явное указание организации. В ERP и УТ 11 договор жестко привязан к организации. Если подсистема расчетов видит пустую организацию, она не может инициализировать расчетный ключ. Выясним, почему это критично: объект расчетов — это «точка сборки» всех движений по регистрам. Нет организации — нет учета.

Решение: Убедитесь, что реквизит ОсновнойДоговор.Организация заполнен корректной ссылкой до момента вызова Записать().

Причина 3: Порядок ведения взаиморасчетов

В коде есть условие на заполнение реквизита ПорядокРасчетов:


Если ВедениеВзаиморасчетов = 1 Тогда
    ОсновнойДоговор.ПорядокРасчетов = Перечисления.ПорядокРасчетов.ПоДоговорамКонтрагентов;
Иначе
    ОсновнойДоговор.ПорядокРасчетов = Перечисления.ПорядокРасчетов.ПоНакладным;
КонецЕсли;

Если выбран порядок «По договорам», то сам договор становится объектом расчетов. В этом случае требования системы к его корректности возрастают в разы. Ошибка 21 в данном контексте означает, что система попыталась зарегистрировать этот договор в реестре объектов расчетов, но произошел внутренний отказ (например, из-за несоответствия типа договора и типа партнера).

Разберем по шагам правильный алгоритм программного создания договора

Чтобы избежать ошибок при программном создании объектов в обработчиках КД 2.1, рекомендуем придерживаться следующей последовательности действий:

  1. Проверка существования: Всегда проверяйте, не был ли объект создан ранее, чтобы избежать дублирования.
  2. Заполнение Партнера и Контрагента: Помните, что в ERP/УТ 11 это разные сущности. Сначала должен быть записан Партнер, затем Контрагент (Владелец), и только потом Договор.
  3. Установка Организации: Это критически важный реквизит для финансового блока.
  4. Использование флага Загрузка: Если ваша задача — просто перенести данные «как есть», всегда используйте ОбменДанными.Загрузка = Истина. Это сэкономит время и избавит от лишних проверок.
  5. Обновление ключей (если необходимо): Если вы все же записываете объект с Загрузка = Ложь, после записи может потребоваться вызов серверных процедур для обновления иерархии или аналитики (например, модули ВзаиморасчетыСервер).

Пример исправленного кода

Проанализируем, как должен выглядеть фрагмент кода, чтобы ошибка 21 гарантированно исчезла:


// Создаем новый договор
НовыйДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();

// Заполняем основные данные
НовыйДоговор.Наименование = "Основной договор";
НовыйДоговор.Организация  = Справочники.Организации.НайтиПоНаименованию("Наша Организация");
НовыйДоговор.Контрагент   = Владелец;
НовыйДоговор.Партнер      = ПартнерСсылка;
НовыйДоговор.Дата         = ТекущаяДата();

// Устанавливаем режим загрузки, чтобы обойти проверку "Объекта расчетов"
НовыйДоговор.ОбменДанными.Загрузка = Истина;

Попытка
    НовыйДоговор.Записать();
    // Передаем ссылку обратно в основной объект загрузки
    Объект.Владелец = НовыйДоговор.Ссылка;
Исключение
    Сообщить("Не удалось записать договор: " + ОписаниеОшибки());
КонецПопытки;

Резюме

Ошибка с кодом 21 — это защитный механизм конфигураций, использующих сложную финансовую архитектуру. Она возникает тогда, когда бизнес-логика системы не может сопоставить договор с правилами ведения взаиморасчетов. Рассмотрим основные выводы:

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

← На главную