Как программно создать документ на основании и включить его в структуру подчиненности в 1С

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

При разработке обработок массового ввода документов разработчики часто сталкиваются с задачей создания подчиненных документов (например, накладных реализации на основании счетов или заказов покупателей). Нередко возникает вопрос: как правильно перенести данные и гарантировать, что созданный документ появится в дереве структуры подчиненности (связанных документах)? Разберем этот процесс подробно.

Как формируется структура подчиненности в 1С

Распространенным заблуждением является представление о том, что при создании документа на основании платформа выполняет некую специальную регистрацию и физически «включает» документ в подчиненность. В действительности этот механизм устроен иначе:

  1. Динамический поиск связей: Дерево структуры подчиненности не хранится в виде отдельной постоянной таблицы. Оно строится «на лету» в момент открытия соответствующей формы или отчета.
  2. Критерии отбора: В большинстве конфигураций 1С для поиска связанных объектов используется объект метаданных КритерийОтбора (обычно с именем СтруктураПодчиненности или СвязанныеДокументы).
  3. Реквизиты связывания: Критерий отбора проверяет метаданные и находит все документы, в которых есть реквизиты, ссылающиеся на текущий документ. Ссылка может находиться в реквизите шапки (например, Сделка, ДокументОснование, СчетНаОплату) или в реквизитах табличных частей (например, колонка ЗаказПокупателя в табличной части Товары).
  4. Механизмы БСП: В современных конфигурациях на базе Библиотеки стандартных подсистем дополнительно могут использоваться процедуры в модулях менеджеров для поиска связей по регистрам учета.

Таким образом, чтобы документ появился в структуре подчиненности, достаточно, чтобы в его реквизитах было корректно сохранено значение ссылки на документ-основание.

Почему ручное копирование реквизитов — не лучший подход

Рассмотрим типовой пример ручного переноса полей, который часто пишут начинающие разработчики:


// Ручное заполнение реквизитов шапки и табличных частей
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = Основание.Организация;
НовыйДокумент.Контрагент = Основание.Контрагент;
НовыйДокумент.ДоговорКонтрагента = Основание.ДоговорКонтрагента;
НовыйДокумент.Склад = Основание.Склад;

Для Каждого ТекСтрока Из Основание.Товары Цикл
    НоваяСтрока = НовыйДокумент.Товары.Добавить();
    НоваяСтрока.Номенклатура = ТекСтрока.Номенклатура;
    НоваяСтрока.Количество = ТекСтрока.Количество;
    НоваяСтрока.Цена = ТекСтрока.Цена;
    НоваяСтрока.Сумма = ТекСтрока.Сумма;
КонецЦикла;

Такой подход имеет существенные недостатки:

  1. Риск пропустить ссылку на основание: Если забыть явно заполнить реквизит привязки к документу-основанию, связь в структуре подчиненности не отобразится.
  2. Отсутствие инициализации служебных реквизитов: При ручном заполнении не отрабатывает типовая логика конфигурации (установка счетов учета расчетов, счетов учета номенклатуры, налоговых параметров, флагов взаиморасчетов). В результате при попытке проведения такого документа могут возникать ошибки.
  3. Трудности поддержки: При изменении состава реквизитов конфигурации код ручного копирования придется переписывать.

Использование штатного метода Заполнить()

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

Посмотрим на пример правильной реализации:


// Программное создание и инициализация по основанию
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Заполнить(Основание);

// При необходимости можно скорректировать отдельные поля
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Комментарий = "Создано автоматически по обработке";

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

Преимущества метода Заполнить():

  1. Автоматическая привязка: Внутри типового обработчика ОбработкаЗаполнения уже заложено заполнение всех реквизитов оснований, благодаря чему документ гарантированно попадет в структуру подчиненности.
  2. Корректная инициализация: Заполняются все обязательные реквизиты, договоры, соглашения, валюты, условия цен и счета учета по умолчанию.
  3. Соблюдение бизнес-логики: Используются алгоритмы, заложенные разработчиками конфигурации именно для ввода на основании.

Рекомендации для пакетного создания документов

Если вам требуется обработать массив документов (например, более 100 заказов), учтите следующие практические моменты:

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