Как программно очистить структуру подчиненности документа в 1С:Бухгалтерии 3.0?

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

При работе в конфигурации «Бухгалтерия предприятия 3.0» периодически возникает необходимость разорвать связи между документами — то есть очистить дерево подчиненности. Разберем, как устроена структура подчиненности в платформе 1С:Предприятие 8, почему она не хранится в отдельной таблице базы данных и какими способами можно программно или интерактивно удалить лишние связи.

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

Выясним главную особенность этого механизма: в 1С нет отдельного регистра или таблицы, где записывается древовидная структура подчиненности. Механизм связей строится динамически с использованием метаданного КритерийОтбора.СвязанныеДокументы.

Связи между документами бывают двух типов:

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

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

Шаг 1. Очистка реквизитов-оснований у самого документа

Рассмотрим ситуацию, когда наш документ ссылается на другой объект в качестве основания. Для удаления этой связи необходимо очистить соответствующий реквизит шапки или табличную часть.

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


// Получаем объект документа для редактирования
ОбъектДокумента = ДокументСсылка.ПолучитьОбъект();

// Если основание указано в табличной части
ОбъектДокумента.ДокументыОснования.Очистить();

// Если основание указано в реквизите шапки
ОбъектДокумента.ДокументОснование = Неопределено;

// Записываем изменения
ОбъектДокумента.Записать();

Обратите внимание: присваивать реквизиту шапки значение Неопределено корректнее, чем пустую строку "", так как реквизиты документов имеют ссылочный тип данных.

Шаг 2. Поиск и очистка подчиненных документов

Теперь проанализируем обратную задачу: когда нужно очистить ссылки у всех нижестоящих документов, которые были выписаны на основании нашего объекта. Для этого воспользуемся критерием отбора КритерийОтбора.СвязанныеДокументы.

С помощью специального запроса мы можем найти все объекты базы данных, входящие в состав критерия отбора для нашего документа:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СвязанныеДокументы.Ссылка КАК Ссылка
    |ИЗ
    |	КритерийОтбора.СвязанныеДокументы(&ЦелевойДокумент) КАК СвязанныеДокументы";

Запрос.УстановитьПараметр("ЦелевойДокумент", ИскомыйДокумент);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    ПодчиненныйОбъект = Выборка.Ссылка.ПолучитьОбъект();
    
    // Проверяем и очищаем реквизит шапки
    Если Метаданные.Документы[ПодчиненныйОбъект.Метаданные().Имя].Реквизиты.Найти("ДокументОснование") <> Неопределено Тогда
        Если ПодчиненныйОбъект.ДокументОснование = ИскомыйДокумент Тогда
            ПодчиненныйОбъект.ДокументОснование = Неопределено;
        КонецЕсли;
    КонецЕсли;
    
    // Проверяем и очищаем табличную часть ДокументыОснования (при наличии)
    Если Метаданные.Документы[ПодчиненныйОбъект.Метаданные().Имя].ТабличныеЧасти.Найти("ДокументыОснования") <> Неопределено Тогда
        ИндексыДляУдаления = Новый Массив;
        Для Каждого СтрокаТЧ Из ПодчиненныйОбъект.ДокументыОснования Цикл
            Если СтрокаТЧ.ДокументОснование = ИскомыйДокумент Тогда
                ИндексыДляУдаления.Добавить(СтрокаТЧ);
            КонецЕсли;
        КонецДля;
        Для Каждого СтрокаДляУдаления Из ИндексыДляУдаления Цикл
            ПодчиненныйОбъект.ДокументыОснования.Удалить(СтрокаДляУдаления);
        КонецДля;
    КонецЕсли;

    // Записываем подчиненный документ, отключив проверки БСП
    ПодчиненныйОбъект.ОбменДанными.Загрузка = Истина;
    ПодчиненныйОбъект.Записать();
КонецЦикла;

Установка флага ОбменДанными.Загрузка = Истина позволяет избежать срабатывания дополнительных проверок при записи объекта (например, проверки заполнения обязательных полей в управляемых формах и БСП).

Альтернативный вариант: Интерактивная групповая обработка

Если задача носит разовый характер и писать код в обработке не требуется, разберем более простой вариант без программирования. Для этого можно применить встроенную типовую обработку Групповое изменение реквизитов:

  1. Перейдем в раздел Администрирование — Обслуживание — Корректировка данных — Групповое изменение реквизитов.
  2. Выберем тип документа, у которого требуется отвязать подчиненность.
  3. Настроим отбор по нужному документу или группе документов.
  4. В списке доступных реквизитов найдем поле Документ основание (или аналогичное поле связи).
  5. Установим флажок очистки реквизита (оставив значение пустым) и выполним изменение.

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

← На главную