Почему не удаляется документ «Приобретение товаров и услуг» методом Удалить() в 1С:УТ 11 и как это исправить?

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

В современных типовых конфигурациях 1С, таких как «Управление торговлей, ред. 11», «ERP Управление предприятием» или «Комплексная автоматизация», механизмы контроля ссылочной целостности и бизнес-логики глубоко интегрированы на уровне платформы и конфигурации. Обычный вызов метода Удалить() для объектной сущности документа часто приводит к системным ошибкам или блокировкам. Это связано с тем, что система пытается выполнить каскад проверок в модулях объекта, подписках на события и связанных регистрах.

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

Выясняем причину: почему блокируется удаление документа?

Когда мы программно вызываем метод Удалить() для объекта документа, платформа выполняет целый комплекс неявных действий:

  1. Инициируется транзакция удаления.
  2. Срабатывают подписки на события ПередУдалением и ПриЗаписи (для очистки движений).
  3. Выполняется код в модуле самого документа (процедуры перед удалением).
  4. Проверяется ссылочная целостность: если на документ ссылаются другие объекты (например, документ УстановкаЦенНоменклатуры, регистры сведений РеестрДокументов, СвязанныеДокументы), СУБД или логика конфигурации блокируют операцию.

Рассмотрим подробнее основные преграды и способы их обхода.

Способ 1. Использование механизма «ОбменДанными.Загрузка = Истина»

Самый простой и в то же время радикальный способ обойти большинство программных проверок и подписок на события при программном удалении — это использование свойства ОбменДанными.Загрузка. Установка этого флага в значение Истина сообщает системе, что объект записывается или удаляется в режиме переноса данных, поэтому выполнять стандартные проверки бизнес-логики и заполнения реквизитов не требуется.

Важный нюанс: просто вызвать метод Удалить() у ссылки нельзя, так как проверки все равно сработают. Нам необходимо сначала получить объект документа, установить свойство и только затем выполнить удаление. Разберем этот процесс на примере кода:


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

Если ДокОбъект <> Неопределено Тогда
    // Отключаем выполнение подписок на события и проверок бизнес-логики
    ДокОбъект.ОбменДанными.Загрузка = Истина;
    
    Попытка
        ДокОбъект.Удалить();
        Сообщить("Документ успешно удален из базы данных.");
    Исключение
        // Обрабатываем исключение, если возникла ошибка на уровне СУБД
        Сообщить("Не удалось удалить документ. Ошибка: " + ОписаниеОшибки());
    КонецПопытки;
КонецЕсли;

Этот метод решает проблему в 90% случаев, когда удалению мешают внутренние подписки конфигурации (например, ПроверитьВозможностьУдаленияДокумента).

Способ 2. Очистка связей со сторонними документами (на примере «Установки цен»)

Часто документ ПриобретениеТоваровУслуг является основанием для автоматического формирования цен через документ УстановкаЦенНоменклатуры. В системе существует жесткая логическая связь. Если мы попытаемся удалить приобретение, на которое ссылается установка цен, система выдаст ошибку ссылочной целостности.

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

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


// Шаг 1. Находим связанные документы УстановкаЦенНоменклатуры
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	СвязанныеДокументы.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.УстановкаЦенНоменклатуры КАК СвязанныеДокументы
    |ГДЕ
    |	СвязанныеДокументы.ДокументОснование = &ДокументОснование";

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

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

После того как все внешние связи разорваны, можно повторно вызвать метод Удалить() для документа приобретения.

Способ 3. Очистка записей в независимых регистрах сведений

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

Рекомендуется перед непосредственным удалением документа принудительно очистить его движения и записи в этих реестрах. Посмотрим на практический пример очистки записей регистра сведений по регистратору:


// Очищаем записи в регистре сведений "Реестр документов"
НаборЗаписейРеестра = РегистрыСведений.РеестрДокументов.СоздатьНаборЗаписей();
НаборЗаписейРеестра.Отбор.Регистратор.Установить(СсылкаНаПриобретение);

Попытка
    НаборЗаписейРеестра.Записать(); // Запись пустого набора удаляет движения
    Сообщить("Движения в реестре документов успешно очищены.");
Исключение
    Сообщить("Ошибка очистки реестра документов: " + ОписаниеОшибки());
КонецПопытки;

Аналогичным образом рекомендуется поступить со всеми регистрами накопления, в которые документ делает движения при проведении. Хотя при удалении система пытается делать это автоматически, явная предварительная очистка снижает нагрузку на СУБД и предотвращает взаимоблокировки.

Способ 4. Использование Дополнительных Свойств объекта

В коде модулей конфигураций ERP/УТ 11 разработчики фирмы «1С» закладывают специальные флаги-параметры в коллекцию ДополнительныеСвойства объекта. Эти флаги позволяют управлять поведением процедур ПередЗаписью, ПриЗаписи и ПередУдалением.

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


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

// Передаем системные флаги для обхода проверок
ОбъектДляУдаления.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаРедактирования", Истина);
ОбъектДляУдаления.ДополнительныеСвойства.Вставить("УдалениеОбъекта", Истина);
ОбъектДляУдаления.ДополнительныеСвойства.Вставить("ОтключитьКонтрольОстатков", Истина);

Попытка
    ОбъектДляУдаления.Удалить();
Исключение
    Сообщить("Удаление не выполнено: " + ОписаниеОшибки());
КонецПопытки;

Использование коллекции ДополнительныеСвойства позволяет тонко управлять логикой удаления без полного отключения подписок на события (в отличие от свойства ОбменДанными.Загрузка).

Резюме и правила хорошего тона при программном удалении

Необходимо помнить, что непосредственное физическое удаление документов (методом Удалить()) в работающей базе данных — это крайняя мера, способная нарушить ссылочную целостность и породить множество "битых" ссылок (объектов вида <Объект не найден...>).

Рекомендуем придерживаться следующего безопасного алгоритма:

  1. Сначала программно помечайте документ на удаление с помощью метода УстановитьПометкуУдаления(Истина). При этом система автоматически пометит на удаление связанные движения и проверит логические связи в интерактивном режиме.
  2. Для окончательного удаления используйте стандартную обработку «Удаление помеченных объектов». Она выполняет комплексный контроль ссылочной целостности на уровне всей базы данных и гарантирует, что вы не удалите документ, критически важный для других цепочек учета.
← На главную