В этой статье разберем достаточно специфическую, но распространенную проблему, с которой можно столкнуться в доработанных конфигурациях 1С. Ситуация следующая: есть два связанных документа. Например, на основании стандартного документа Требование-накладная создан собственный документ Операция, в котором есть реквизит ДокументОснование, ссылающийся на требование-накладную. Когда мы помечаем на удаление оба документа и запускаем стандартную процедуру через меню Администрирование → Обслуживание → Удаление помеченных объектов, происходит странное: зависимый документ Операция успешно удаляется, а при попытке удалить основной документ Требование-накладная система выдает ошибку о наличии битой ссылки и отменяет его удаление.
При этом, если выполнить ту же самую процедуру, но через другой путь — Все функции → Стандартные → Удаление помеченных объектов, — то оба документа удаляются корректно, без каких-либо ошибок. Давайте выясним, в чем причина такого поведения и как решить эту проблему.
Ключ к разгадке кроется в том, что в системе 1С, как оказалось, существует два разных механизма для удаления помеченных объектов, и работают они по-разному.
Обработка в пользовательском режиме (Администрирование → Удаление помеченных объектов). Это основная обработка, предназначенная для пользователей. Она работает в многопользовательском (конкурентном) режиме. Ее алгоритм анализирует и удаляет объекты последовательно. В нашем случае, она сначала удаляет документ Операция. В этот момент ссылка на него из документа Требование-накладная должна быть очищена, но из-за особенностей кэширования или логики транзакций в конкурентном режиме, система все еще "видит" эту связь. Когда очередь доходит до удаления документа Требование-накладная, контроль ссылочной целостности срабатывает некорректно, обнаруживая ссылку на уже несуществующий в базе, но еще "живой" в контексте операции объект. Результат — ошибка "объект не найден" или "битая ссылка".
Обработка в монопольном режиме (Все функции → Стандартные → Удаление помеченных объектов). Этот механизм чаще всего требует монопольного доступа к базе данных. Он блокирует работу других пользователей и выполняет все операции в рамках единой, более строгой и контролируемой транзакции. Платформа получает возможность построить полное дерево зависимостей всех удаляемых объектов и определить правильную последовательность их удаления. Это исключает конфликты и проблемы с контролем ссылочной целостности, поэтому удаление проходит успешно.
Таким образом, основная причина проблемы — различие в алгоритмах работы и условиях выполнения двух стандартных обработок удаления. Пользовательская обработка в конкурентном режиме не всегда корректно обрабатывает сложные цепочки зависимостей, особенно если в них участвуют доработанные объекты.
Рассмотрим несколько подходов к решению этой задачи, от простого обходного пути до более глубокого технического вмешательства.
Это самый простой и надежный способ, который уже подтвердил свою работоспособность. Если вы столкнулись с подобной ошибкой, рекомендуем выполнять удаление объектов через "Все функции".
Пошаговая инструкция:
Этот метод гарантирует корректное удаление связанных объектов без ошибок.
Чтобы не выполнять удаление вручную и не мешать работе пользователей, можно настроить автоматическое удаление помеченных объектов по расписанию, например, ночью. Регламентные задания часто выполняются в фоновом режиме, который по своей природе близок к монопольному, что позволяет избежать большинства проблем конкурентного доступа.
Как настроить:
Этот подход автоматизирует процесс и избавляет пользователей от необходимости запускать удаление вручную.
Если необходимо, чтобы работала именно пользовательская обработка удаления, можно применить программный подход. Суть его в том, чтобы перед запуском стандартного удаления принудительно очистить "проблемные" ссылки в помеченных на удаление объектах.
Для этого можно создать небольшую внешнюю обработку, которая найдет все помеченные на удаление документы Операция и очистит у них реквизит ДокументОснование.
Пример кода для такой обработки:
Процедура ОчиститьСсылки()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Операция.Ссылка
|ИЗ
| Документ.Операция КАК Операция
|ГДЕ
| Операция.ПометкаУдаления = ИСТИНА
| И НЕ Операция.ДокументОснование.ПометкаУдаления"; // Ищем только те, где основание не помечено на удаление
ВыборкаДокументов = Запрос.Выполнить().Выбрать();
Пока ВыборкаДокументов.Следующий() Цикл
// Получаем объект документа
ДокументОбъект = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
// Очищаем ссылку на документ-основание
// Используем пустую ссылку нужного типа, чтобы избежать ошибок типов
ДокументОбъект.ДокументОснование = Документы.ТребованиеНакладная.ПустаяСсылка();
Попытка
// Записываем изменения, обходя проверки
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Очищена ссылка в документе: " + ДокументОбъект.Ссылка);
Исключение
Сообщить("Не удалось записать документ: " + ДокументОбъект.Ссылка + ". " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Сообщить("Обработка завершена.");
КонецПроцедуры
После выполнения такой обработки стандартное удаление через "Администрирование" должно пройти без ошибок, так как "битых" ссылок с точки зрения системы уже не будет.
Если проблема возникает регулярно, стоит провести более глубокий анализ конфигурации. Обратите внимание на следующие моменты:
ПередУдалением) для документов Операция или Требование-накладная. Некорректный код в обработчике такой подписки может приводить к ошибкам.Операция не создает неочевидных связей в регистрах сведений или накопления, которые не очищаются стандартными механизмами.В заключение, проблема с "битыми ссылками" при удалении связанных объектов — это яркий пример того, как внутренние механизмы платформы 1С могут вести себя по-разному в зависимости от контекста их вызова. Понимание этих различий помогает быстро находить эффективные решения.