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

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

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

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

Почему возникает ошибка «Поле объекта не обнаружено»?

Выясним причину этой классической ошибки. Когда мы открываем конфигуратор, переходим на вкладку «Ввод на основании» в свойствах документа и настраиваем списки «Вводится на основании» и «Является основанием для», мы выполняем декларативную настройку для платформы 1С:Предприятие.

Эта настройка указывает платформе на необходимость:

  1. Вывести кнопку «Создать на основании» в интерфейсе (в меню командной панели формы или списка).
  2. Генерировать событие ОбработкаЗаполнения в модуле объекта нового документа при его интерактивном создании пользователем.

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

Рассмотрим, как правильно настроить реквизиты объекта:

  1. Откроем конфигуратор и перейдем к подчиненному документу (например, Док2).
  2. В ветке «Реквизиты» добавим новый реквизит. Назовем его, например, ДокументОснование (или просто Основание).
  3. В свойстве «Тип» укажем ссылку на документ-источник (например, ДокументСсылка.Док1). Если документ может создаваться на основании нескольких различных типов документов, выберем составной тип данных и отметим галочками все возможные документы-основания.

После добавления реквизита в метаданные ошибка «Поле объекта не обнаружено» при обращении к свойству Док2.ДокументОснование исчезнет.

Теперь проанализируем, как правильно осуществлять программное заполнение таких реквизитов.

Правильный программный ввод на основании

В практической разработке часто требуется программно создать один документ на основании другого (например, из обработки или при проведении другого объекта). Прямая запись реквизитов вроде Док2.ДокументОснование = Док1 в коде внешней обработки — это грубая ошибка, нарушающая стандарты разработки 1С.

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

Посмотрим на пример правильного программного создания документа на основании:


// Получаем ссылку на документ-источник
СсылкаНаДок1 = Документы.Док1.НайтиПоРеквизиту("Номер", "001");

// Создаем новый пустой объект подчиненного документа
НовыйДок = Документы.Док2.СоздатьДокумент();

// Метод Заполнить() инициирует вызов обработчика "ОбработкаЗаполнения" в модуле Док2
НовыйДок.Заполнить(СсылкаНаДок1); 

// Записываем документ в базу данных
НовыйДок.Записать();

При вызове метода Заполнить() управление передается в модуль объекта подчиненного документа (в нашем случае Док2) в предопределенную процедуру ОбработкаЗаполнения. Нам необходимо правильно ее запрограммировать.

Разберем по шагам реализацию обработчика заполнения в модуле объекта:


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

Если нам требуется не просто записать документ в коде, а открыть форму нового, еще не записанного документа на клиенте для интерактивного редактирования пользователем, используем следующий код:


// Формируем параметры открытия формы, передавая основание
ПараметрыФормы = Новый Структура("Основание", СсылкаНаДок1);

// Открываем форму нового документа Док2 на основании Док1
ОткрытьФорму("Документ.Док2.ФормаОбъекта", ПараметрыФормы);

Настройка структуры подчиненности документов

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

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

В типовых конфигурациях за вывод дерева связей отвечает предопределенный критерий отбора (обычно он называется СвязанныеДокументы или СтруктураПодчиненности). Нам необходимо включить наш новый реквизит в состав этого критерия отбора.

Выполним настройку критерия отбора пошагово:

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

После выполнения этих действий стандартный отчет структуры подчиненности начнет автоматически находить связку Док1 -> Док2 при вызове из любого из этих документов.

Особенности работы со структурой подчиненности в БСП (Библиотека стандартных подсистем)

Если мы разрабатываем конфигурацию на базе современных типовых решений (таких как ERP, УТ, КА, УНФ или Бухгалтерия предприятия), в них задействована Библиотека стандартных подсистем (БСП). В этом случае настройки одного лишь критерия отбора в метаданных может оказаться недостаточно для полноценного функционирования интерфейса. Требуется выполнить несколько дополнительных шагов для интеграции новых документов. Для поиска готовых примеров программных вызовов подсистем пригодится справочник по методам БСП с примерами использования.

Шаг 1. Настройка общей команды.
В БСП за вывод кнопки «Связанные документы» на форму отвечает общая команда СвязанныеДокументы. Нам нужно зайти в ее свойства и в поле «Тип параметра команды» добавить типы наших новых документов (ДокументСсылка.Док1 и ДокументСсылка.Док2).

Шаг 2. Подключение команд на форму.
Чтобы кнопка «Связанные документы» автоматически появилась в меню «Ещё» или на командной панели формы нашего нового документа, необходимо инициализировать подсистему БСП при создании формы. В модуле формы управляемого документа пропишем следующий код:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Инициализация стандартных команд БСП (включая связанные документы)
    ПодключаемыеКоманды.ПриСозданииНаСервере(ЭтотОбъект);
    
КонецПроцедуры

Также на клиенте необходимо добавить обработчик выполнения этих команд:


&НаКлиенте
Процедура Подключаемый_ВыполнитьКоманду(Команда)
    ПодключаемыеКомандыКлиент.ВыполнитьКоманду(ЭтотОбъект, Команда, Объект);
КонецПроцедуры

Проверка условий и отмена создания документа на основании

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

Поскольку предопределенный обработчик ОбработкаЗаполнения не содержит стандартного параметра Отказ (в отличие от обработчиков ПередЗаписью или ПриОткрытии), единственный корректный способ прервать создание документа на основании, рекомендованный стандартами разработки фирмы «1С» (V8STD), — это вызов исключения.

Рассмотрим пример реализации такой валидации в модуле объекта:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.Док1") Тогда
        
        // Проверяем, проведен ли документ-источник
        Если Не ДанныеЗаполнения.Проведен Тогда
            ВызватьИсключение "Ошибка создания документа! Документ-основание должен быть обязательно проведен.";
        КонецЕсли;
        
        // Проверяем заполнение важных полей в источнике
        Если Не ЗначениеЗаполнено(ДанныеЗаполнения.Контрагент) Тогда
            ВызватьИсключение "Ошибка создания документа! В документе-основании не заполнен Контрагент.";
        КонецЕсли;
        
        // Если все проверки пройдены, выполняем стандартное заполнение
        ЭтотОбъект.ДокументОснование = ДанныеЗаполнения;
        ЗаполнитьЗначенияСвойств(ЭтотОбъект, ДанныеЗаполнения);
        
    КонецЕсли;
    
КонецПроцедуры

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

Подведем итог. Для успешной реализации механизма ввода на основании нам всегда требуется:

← На главную