При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда необходимо связать данные основной конфигурации с новыми объектами, созданными в расширении. Типичный пример: в основной конфигурации существует регистр сведений, измерение которого имеет тип ЛюбаяСсылка. Мы создаем в расширении новый документ (например, «Ремонт») и пытаемся записать ссылку на него в этот регистр. Однако при выполнении кода поле остается пустым или возникает ошибка. Рассмотрим подробнее, почему это происходит, и проанализируем доступные способы решения этой задачи.
Для начала выясним причину такого поведения платформы. Тип ЛюбаяСсылка в 1С не является «абсолютно всеядным». На этапе компиляции основной конфигурации этот тип жестко ограничивается списком всех ссылочных типов, существующих только в основной конфигурации. Объекты, добавленные в расширениях, не входят в этот предопределенный список автоматически.
Проанализируем ситуацию на уровне базы данных. Когда мы пытаемся записать ссылку из расширения в поле типа ЛюбаяСсылка, система может физически поместить GUID и идентификатор типа в таблицу SQL. Однако при попытке чтения данных через механизм объектной модели 1С, платформа видит, что идентификатор типа документа из расширения не зарегистрирован в составе типа ЛюбаяСсылка основной конфигурации. В результате система возвращает Неопределено или пустую ссылку, так как для ядра основной базы этого типа «не существует».
Самый очевидный путь — это «захватить» регистр сведений в расширение и изменить тип его измерения. Разберем по шагам, как это сделать правильно:
ЛюбаяСсылка).ЛюбаяСсылка выберем составной тип, включив в него как старый тип (если нужно сохранить совместимость), так и наш новый документ из расширения.Важный нюанс: Как только мы меняем ЛюбаяСсылка на конкретный перечень типов в расширении, мы ограничиваем универсальность этого поля. Теперь оно будет принимать только те типы, которые мы указали явно. Рассмотрим пример кода для записи:
// Допустим, мы находимся в модуле документа "Ремонт" в расширении
НаборЗаписей = РегистрыСведений.НашРегистрИзОсновы.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент); // Если регистр подчинен
НоваяЗапись = НаборЗаписей.Добавить();
// Теперь платформа "знает", что этот тип допустим для данного измерения в контексте расширения
НоваяЗапись.ИзмерениеСсылка = Объект.Ссылка;
НаборЗаписей.Записать();
Если нам необходимо хранить ссылки на объекты из множества разных расширений, и мы не хотим постоянно «перетряхивать» составной тип регистра, можно применить более гибкий, но трудоемкий метод. Мы можем хранить не саму ссылку, а её GUID.
Рассмотрим реализацию этого метода. В основной конфигурации в регистре сведений создадим измерение с типом Строка (длиной 36 символов) или УникальныйИдентификатор. Это позволит нам записывать данные из любого места системы без конфликтов типов.
Запись данных будет выглядеть следующим образом:
НоваяЗапись = НаборЗаписей.Добавить();
// Сохраняем ссылку как строку-идентификатор
НоваяЗапись.ИдентификаторОбъекта = Строка(ДокументОбъект.Ссылка.УникальныйИдентификатор());
Для чтения и преобразования обратно в ссылку нам потребуется вспомогательная функция. Проанализируем пример получения ссылки:
Функция ПолучитьСсылкуИзСтроки(ИмяМетаданных, СтрокаGUID) Экспорт
// ИмяМетаданных - например, "Документ.Ремонт"
ГУИД = Новый УникальныйИдентификатор(СтрокаGUID);
Возврат Документы[ИмяМетаданных].ПолучитьСсылку(ГУИД);
КонецФункции
Преимущество: Данные не «исчезнут», даже если расширение будет временно отключено. После повторного подключения расширения ссылки снова станут валидными.
Многие опытные разработчики считают «харамом» (плохой практикой) чрезмерное жонглирование метаданными между расширениями и основной конфигурацией. Если документ «Ремонт» живет только в расширении, логично и данные, связанные с ним, хранить в регистре, который также принадлежит этому расширению.
Посмотрим на преимущества этого подхода:
Выясним причины, по которым использование объектов расширений в измерениях основных регистров может быть опасным:
Подводя итог, выберем оптимальную стратегию в зависимости от задачи:
Если данные нужны только внутри логики расширения — создавайте отдельный регистр сведений внутри этого расширения. Это самый безопасный и «чистый» способ.
Если необходимо, чтобы основная конфигурация видела эти данные — используйте промежуточный справочник-посредник в основной конфигурации или храните идентификаторы в виде строк/UUID. Также можно рассмотреть вариант создания служебного справочника в основе, где один из реквизитов будет хранить GUID объекта из расширения, а сам регистр будет ссылаться на этот справочник.
Помните, что расширение — это гибкий инструмент, но он требует осторожности при работе с типами данных. Всегда проектируйте систему так, чтобы отключение расширения не приводило к фатальному падению всей информационной базы.