Как расширить тип реквизита ДокументОснование в расширении 1С?

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

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

Выясним причину ошибки: Контроль vs Расширение

Прежде всего, проанализируем поведение платформы. Когда вы заимствуете реквизит (например, ДокументОснование документа СборкаЗапасов) в расширение, по умолчанию платформа устанавливает на него режим строгого соответствия. В более старых версиях платформы (до 8.3.15) расширение типов данных для существующих реквизитов было физически невозможно.

Важно понимать разницу в работе диалогового окна выбора типов:

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

Способ 1. Использование современных возможностей платформы (8.3.15 и выше)

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

  1. Добавим документ СборкаЗапасов и его реквизит ДокументОснование в расширение.
  2. Добавим в расширение документ РасходнаяНакладная (который мы хотим сделать основанием).
  3. Откроем свойства реквизита ДокументОснование в расширении.
  4. В окне выбора типов найдем свойство «Проверять» (или «Контролировать»). Нам необходимо снять этот флаг.
  5. После снятия контроля мы можем добавить новый тип (ДокументСсылка.РасходнаяНакладная) в список.

Обратите внимание: Такое изменение может потребовать реструктуризации таблиц базы данных. При первом обновлении конфигурации базы данных с таким расширением потребуется монопольный доступ, так как 1С физически меняет описание типов в полях таблиц SQL.

Способ 2. Добавление собственного реквизита в расширение

Если версия платформы ниже 8.3.15 или вы не хотите рисковать реструктуризацией основной таблицы документа, проанализируем альтернативный путь — добавление нового реквизита. Это наиболее «безопасный» способ с точки зрения стабильности основной конфигурации.

Разберем по шагам, как это реализовать:

  1. В расширении у документа СборкаЗапасов создадим новый реквизит, например, Доп_ДокументОснование с типом ДокументСсылка.РасходнаяНакладная.
  2. Вынесем этот реквизит на форму документа в расширении.
  3. Настроим логику заполнения.

Рассмотрим пример кода для команды «Создать на основании», которую мы разместим в расширении для документа РасходнаяНакладная. Нам нужно передать данные из накладной в новую сборку запасов:


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

Далее в модуле объекта документа СборкаЗапасов (в расширении) необходимо обработать эти данные в процедуре ОбработкаЗаполнения:


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

Проблема структуры подчиненности при использовании своего реквизита

Одним из главных минусов использования собственного реквизита (Способ 2) является то, что типовой отчет «Структура подчиненности» не увидит эту связь автоматически. Типовой механизм ищет ссылки в стандартном реквизите ДокументОснование или по критериям отбора.

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

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

Проверка на дубли: предотвращаем повторное создание

Часто возникает вопрос: как проверить, не создана ли уже СборкаЗапасов на основании конкретной РасходнойНакладной? Рассмотрим функцию, которую можно вызвать перед открытием формы:


&НаСервере
Функция СборкаУжеСуществует(СсылкаНаНакладную)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |	СборкаЗапасов.Ссылка КАК Ссылка
        |ИЗ
        |	Документ.СборкаЗапасов КАК СборкаЗапасов
        |ГДЕ
        |	СборкаЗапасов.Доп_ДокументОснование = &Основание
        |	И НЕ СборкаЗапасов.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("Основание", СсылкаНаНакладную);
    Результат = Запрос.Выполнить();
    Возврат НЕ Результат.Пустой();
КонецФункции

Резюме

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

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

← На главную