При разработке в среде 1С:Предприятие 8 начинающие программисты часто сталкиваются с вопросом: существует ли в системе автоматическая, «скрытая» связь между документом-источником и новым документом, созданным на его основании? Кажется логичным, что если платформа предоставляет стандартную кнопку «Создать на основании», то она должна где-то сохранять ссылку на родительский объект. Давайте подробно разберем, как на самом деле устроена эта механика, почему стандартного реквизита «Владелец» у документов не существует и как правильно организовать прослеживаемость цепочек документов в своих конфигурациях.
Начнем с прояснения технического устройства платформы. В отличие от справочников, у которых есть стандартное свойство Владелец (реализованное на уровне СУБД как поле OwnerID), у документов в 1С нет встроенного механизма владения. Когда вы нажимаете кнопку «Создать на основании», платформа выполняет лишь транспортную функцию: она открывает форму нового документа и передает в него ссылку на исходный объект. Если в коде нового документа не предусмотрена фиксация этой ссылки, информация об источнике будет безвозвратно утеряна сразу после инициализации объекта.
Рассмотрим ситуацию: вы создали документ «Реализация товаров и услуг» на основании «Заказа клиента». Если в метаданных документа «Реализация» вы сами не добавили реквизит (например, с именем ДокументОснование), то система не будет знать, откуда пришли данные. Таким образом, любая связь между документами — это всегда явная разработка, а не автоматическое поведение ядра платформы.
Для того чтобы документ «запомнил» своего родителя, необходимо использовать стандартный механизм заполнения. Разберем по шагам, как это реализуется в коде модуля объекта. Основным инструментом здесь выступает процедура ОбработкаЗаполнения.
Проанализируем пример кода, который должен присутствовать в документе-приемнике:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Проверяем, что в качестве данных заполнения пришла ссылка на нужный нам тип документа
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказКлиента") Тогда
// 1. Фиксируем связь в специальном реквизите
// Предварительно этот реквизит нужно создать в метаданных
ЭтотОбъект.ДокументОснование = ДанныеЗаполнения;
// 2. Заполняем остальные реквизиты из источника
ЭтотОбъект.Организация = ДанныеЗаполнения.Организация;
ЭтотОбъект.Контрагент = ДанныеЗаполнения.Контрагент;
ЭтотОбъект.Валюта = ДанныеЗаполнения.Валюта;
// 3. Заполняем табличную часть
Для Каждого СтрокаИсточника Из ДанныеЗаполнения.Товары Цикл
НоваяСтрока = ЭтотОбъект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
В данном примере параметр ДанныеЗаполнения — это и есть та самая ссылка на «документ-владелец». Обратите внимание на строку ЭтотОбъект.ДокументОснование = ДанныеЗаполнения. Именно она создает физическую связь в базе данных, которую в дальнейшем можно будет использовать для построения отчетов или структуры подчиненности.
Выясним, как система строит знаменитое дерево «Структура подчиненности», если явного реквизита «Владелец» не существует. Для этого в 1С используется объект метаданных Критерий отбора (часто называемый СвязанныеДокументы в типовых конфигурациях).
Рассмотрим принцип работы критерия отбора:
КритерийОтбора.ДокументОснование у документов «Реализация», «Счет на оплату», «Возврат товаров».Когда пользователь запрашивает структуру подчиненности для конкретного «Заказа», система не ищет «подчиненных» внутри самого заказа. Вместо этого она выполняет быстрый поиск по индексу критерия отбора во всех таблицах, указанных в составе, находя те записи, где в поле ДокументОснование записана ссылка на наш «Заказ».
В современных решениях, таких как ERP, УТ 11 или Бухгалтерия 3.0, механизмы связи значительно усложнены для обеспечения гибкости. Библиотека стандартных подсистем (БСП) включает подсистему «Связи объектов».
Проанализируем основные отличия работы в типовых конфигурациях:
СвязиОбъектов.Основание с типом «Строка». Важно понимать: это текстовое представление для печатных форм. Для программного анализа он бесполезен, так как не является ссылкой.Важно различать эти две операции, так как в обоих случаях вызывается ОбработкаЗаполнения. Рассмотрим, как их дифференцировать:
ДанныеЗаполнения передается ДокументСсылка источника.ДанныеЗаполнения передается сам объект (прототип), из которого создается копия.Посмотрим на пример кода, который предотвращает перенос ссылки на старое основание при копировании документа:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
// Это копирование! Очистим ссылку на основание, чтобы не дублировать связь
ЭтотОбъект.ДокументОснование = Неопределено;
КонецЕсли;
КонецПроцедуры
Если вы столкнулись с ситуацией, когда реквизит связи не был заведен заранее, или вам нужно найти все упоминания документа во всей базе, используйте метод НайтиПоСсылкам. Рассмотрим, как это работает:
Метод принимает массив ссылок и возвращает таблицу значений со всеми местами, где эти ссылки встречаются (включая реквизиты, табличные части и регистры). Однако помните, что это ресурсоемкая операция. Для оперативной работы в пользовательском интерфейсе всегда следует использовать заранее определенные реквизиты и Критерии отбора.
Подводя итог: если вы хотите проверять, «на основании чего создан документ», вы обязаны самостоятельно предусмотреть реквизит для хранения этой ссылки и самостоятельно заполнить его в модуле объекта. Платформа 1С предоставляет только удобные «рельсы» для передачи этой информации, но не сохраняет её автоматически в скрытых полях.