Как исправить ошибку «Не удалось записать: Задания к...» при удалении помеченных объектов в РИБ 1С

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

При работе в распределенных информационных базах (РИБ) на базе современных конфигураций 1С (таких как 1С:Управление торговлей 11, 1С:Комплексная автоматизация 2 или 1С:ERP Управление предприятием) администраторы и программисты часто сталкиваются со специфической ошибкой при попытке удалить помеченные объекты. Система прерывает транзакцию и выдает сообщение вида: «Не удалось записать: Задания к формированию записей книги покупок/продаж» или «Не удалось записать: Задания к распределению расчетов с клиентами».

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

---

Почему возникает ошибка: разбираемся в деталях

Для начала проанализируем архитектурную логику, заложенную разработчиками фирмы «1С» в механизмы распределенных баз. Регистры сведений, на которые ругается система при удалении документов, — это так называемые регистры заданий. К ним относятся:

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

Чтобы исключить случайный запуск или формирование этих заданий на периферии, разработчики жестко заблокировали возможность записи в эти регистры на стороне подчиненных узлов. В модулях набора записей этих регистров в обработчике ПередЗаписью прописан следующий код:


Если ПланыОбмена.ГлавныйУзел() <> Неопределено Тогда
    Отказ = Истина;
    Возврат;
КонецЕсли;

Если текущая база является подчиненным узлом (то есть метод ПланыОбмена.ГлавныйУзел() возвращает ссылку на главный узел, а не значение Неопределено), то любая попытка записи в регистр вызывает отказ и отмену транзакции.

---

Почему система пытается писать в пустые регистры при удалении?

Часто при анализе этой ошибки через консоль запросов выясняется, что указанные регистры сведений абсолютно пустые и не содержат никаких записей, связанных с удаляемым документом. Возникает логичный вопрос: почему же система пытается туда что-то записать?

Дело в особенностях работы платформы при удалении объектов и механизмов очистки движений Библиотеки Стандартных Подсистем (БСП):

  1. Когда мы запускаем обработку удаления помеченных объектов, платформа вызывает метод УдалитьОбъекты().
  2. Система ищет все ссылки на удаляемый объект (например, на документ Расходный кассовый ордер) во всех таблицах базы данных.
  3. Даже если физических записей в регистре сведений по данному документу нет, алгоритм стандартной очистки движений все равно инициализирует процедуру удаления. Для этого создается пустой набор записей с отбором по регистратору (или по ключевым полям) и для него вызывается метод Записать().
  4. Запись пустого набора записей — это все равно полноценная операция записи, которая активирует системное событие ПередЗаписью в модуле набора записей соответствующего регистра.
  5. Срабатывает проверка на наличие главного узла, переменная Отказ устанавливается в значение Истина, и транзакция удаления аварийно завершается.

Рассмотрим четыре практических способа решения этой проблемы: от простых административных обходов до программных правок.

---

Способ 1. Временное отключение связи с главным узлом (рекомендуемый административный метод)

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

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

  1. Запустите базу данных в режиме «1С:Предприятие» с правами администратора.
  2. Откройте внешнюю обработку или воспользуйтесь групповой обработкой данных (консолью кода) для выполнения следующего кода, отключающего связь с главным узлом:

// Отключаем признак подчиненного узла РИБ
ПланыОбмена.УстановитьГлавныйУзел(Неопределено);
  1. После выполнения этого кода база начнет считать себя главной. Теперь запустите стандартную обработку «Удаление помеченных объектов». Запись пустых наборов данных в регистры сведений пройдет успешно, так как проверка на главный узел больше не будет возвращать Отказ = Истина.
  2. После успешного завершения удаления помеченных объектов обязательно восстановите связь с главным узлом, выполнив код:

// Восстанавливаем связь с главным узлом. 
// СсылкаНаУзел - это ссылка на элемент плана обмена, соответствующий головной базе.
СсылкаНаУзел = ПланыОбмена.НайтиПоКоду("КодГлавногоУзла"); // Укажите реальный код вашего узла
Если ЗначениеЗаполнено(СсылкаНаУзел) Тогда
    ПланыОбмена.УстановитьГлавныйУзел(СсылкаНаУзел);
КонецЕсли;

Важно: во время отключенного состояния узла не рекомендуется вводить новые документы во избежание рассинхронизации кодов и номеров документов.

---

Способ 2. Использование расширения конфигурации (программируемый и безопасный метод)

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

Мы можем перехватить событие ПередЗаписью в проблемных регистрах сведений с помощью аннотации &Вместо или &Перед. Наша задача — разрешить запись набора, если он пустой (то есть происходит попытка очистки движений при удалении).

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


&Вместо("ПередЗаписью")
Процедура Ист_ПередЗаписью(Отказ, Замещение)
    
    // Если набор записей пустой, то разрешаем запись даже в подчиненном узле РИБ
    Если ЭтотОбъект.Количество() = 0 Тогда
        Возврат; 
    КонецЕсли;
    
    // Если в наборе есть записи, то выполняем стандартную проверку конфигурации
    ПродолжитьВызов(Отказ, Замещение);
    
КонецПроцедуры

При таком подходе основная конфигурация остается на полной поддержке, а проблема с удалением объектов в периферийных базах исчезает навсегда.

---

Способ 3. Методологически верное удаление через синхронизацию РИБ

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

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

---

Способ 4. Корректировка кода в основной конфигурации (костыль)

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

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


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

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

---

Резюме

Мы подробно разобрали природу ошибки «Не удалось записать...» при очистке регистров заданий в РИБ. Для разового решения проблемы оптимально использовать Способ 1 (временное отключение связи с главным узлом), а для системного и автоматизированного решения в активно развивающихся базах лучше всего применить Способ 2 с созданием расширения конфигурации.

← На главную