При активной разработке, обновлении конфигураций или программном изменении структуры метаданных в среде «1С:Предприятие 8.3» программисты часто сталкиваются с непредвиденным поведением платформы. Одной из таких неочевидных проблем является ошибка: «Не предопределенные объекты не могут иметь предопределенные записи видов субконто» (в англоязычном интерфейсе платформы: «Nonpredefined objects cannot have predefined extra dimension type records»).
Эта ошибка обычно возникает при попытке программно снять признак предопределенности у какого-либо счета в плане счетов (например, присвоив свойству ИмяПредопределенныхДанных пустое значение). В этой статье мы подробно разберем, почему возникает данная ошибка, как на нее влияет режим совместимости платформы и как правильно написать программный код для ее обхода без потери важных аналитических данных в информационной базе.
Начиная с версии платформы «1С:Предприятие 8.3.3», разработчикам стала доступна возможность гибко управлять предопределенными элементами непосредственно в режиме «1С:Предприятие». Мы можем связать обычный пользовательский элемент базы данных с предопределенным именем из конфигуратора или, наоборот, «отвязать» его, сделав непредопределенным. Для этого используется стандартный реквизит ИмяПредопределенныхДанных.
Однако при переходе конфигураций на новые версии платформы и, самое главное, при отключении режима совместимости (или установке режима совместимости с версией 8.3.5 и выше) платформа начинает гораздо строже контролировать логическую целостность данных на уровне СУБД. В типовой конфигурации «Бухгалтерия предприятия 3.0» этот переход как раз и ознаменовал появление описываемой ошибки.
Суть проблемы кроется во взаимосвязи самого счета и строк его табличной части ВидыСубконто. У каждой строки этой табличной части есть скрытый системный признак (свойство) Предопределенное. Логика платформы без режима совместимости работает следующим образом:
ИмяПредопределенныхДанных, платформа проверяет подчиненные записи табличной части ВидыСубконто.Предопределенное = Истина, платформа блокирует запись объекта базы данных и выдает ошибку транзакции.Давайте рассмотрим, как правильно решить эту задачу программно.
Иногда разработчики пытаются решить проблему «в лоб», полностью очищая коллекцию субконто у объекта перед его записью. Рассмотрим следующий пример кода:
ТекОбъект = Объект.СчетОткуда.ПолучитьОбъект();
ТекОбъект.ОбменДанными.Загрузка = Истина;
ТекОбъект.ВидыСубконто.Очистить(); // Опасная операция!
ТекОбъект.Записать();
ТекОбъект.ИмяПредопределенныхДанных = "";
ТекОбъект.Записать();
Внимание! Мы крайне не рекомендуем использовать этот метод. Метод Очистить() полностью удаляет строки видов субконто из табличной части счета. Если на этом счете уже велся учет и были накоплены бухгалтерские проводки, то полное удаление видов субконто приведет к потере аналитики в проводках и движениях документов. Это спровоцирует серьезные расхождения в бухгалтерской и налоговой отчетности.
Для того чтобы корректно перевести счет в статус непредопределенного и не потерять накопленные аналитические данные, нам необходимо обойти коллекцию видов субконто и у каждой строки явно сбросить признак предопределенности в значение Ложь. Только после этого мы можем очистить имя предопределенных данных и записать объект.
Рассмотрим правильный и безопасный код:
СчетОбъект = СсылкаНаСчет.ПолучитьОбъект();
СчетОбъект.ОбменДанными.Загрузка = Истина; // Отключаем стандартные проверки при записи
// Сбрасываем связь с предопределенным элементом конфигуратора
СчетОбъект.ИмяПредопределенныхДанных = "";
// Обходим виды субконто и снимаем признак предопределенности с каждой строки
Для Каждого СтрокаСубконто Из СчетОбъект.ВидыСубконто Цикл
СтрокаСубконто.Предопределенное = Ложь;
КонецЦикла;
// Записываем измененный объект базы данных
СчетОбъект.Записать();
Проанализируем этот код подробнее. Установка свойства ОбменДанными.Загрузка = Истина позволяет минимизировать платформенные и конфигурационные проверки при вызове метода Записать(). Цикл по коллекции ВидыСубконто гарантирует, что мы сохраняем саму структуру субконто на счете (аналитика не теряется!), но при этом приводим логику подчиненных строк в соответствие с требованиями платформы 1С.
Стоит отметить, что описанная логика контроля целостности метаданных в платформе 1С распространяется не только на планы счетов, но и на другие объекты конфигурации. Например, очень часто похожая ошибка возникает при работе с Планами видов расчета (ПВР):
«Не предопределенные объекты не могут иметь предопределенные записи ведущих видов расчетов» (базовых или вытесняющих видов расчетов).
Если нам необходимо программно снять предопределенность с какого-либо начисления или удержания, мы должны действовать по точно такому же алгоритму — обойти все связанные стандартные табличные части и сбросить признак предопределенности строк. Посмотрим на практический пример для планов видов расчета:
ВидРасчетаОбъект = СсылкаНаВидРасчета.ПолучитьОбъект();
ВидРасчетаОбъект.ОбменДанными.Загрузка = Истина;
// Очищаем признак предопределенности основного объекта
ВидРасчетаОбъект.ИмяПредопределенныхДанных = "";
// Снимаем признак у табличной части ВедущиеВидыРасчета
Для Каждого СтрокаВедущие Из ВидРасчетаОбъект.ВедущиеВидыРасчета Цикл
СтрокаВедущие.Предопределенное = Ложь;
КонецЦикла;
// Снимаем признак у табличной части БазовыеВидыРасчета (если применимо)
Для Каждого СтрокаБазовые Из ВидРасчетаОбъект.БазовыеВидыРасчета Цикл
СтрокаБазовые.Предопределенное = Ложь;
КонецЦикла;
// Снимаем признак у табличной части ВытесняющиеВидыРасчета (если применимо)
Для Каждого СтрокаВытесняющие Из ВидРасчетаОбъект.ВытесняющиеВидыРасчета Цикл
СтрокаВытесняющие.Предопределенное = Ложь;
КонецЦикла;
ВидРасчетаОбъект.Записать();
Иногда эта ошибка застает врасплох администраторов систем 1С при синхронизации данных в Распределенных информационных базах (РИБ). Если в конфигураторе были внесены изменения в части предопределенных счетов или видов расчетов, а затем правила были переданы в периферийную базу, то при первом чтении сообщения обмена (метод ПрочитатьИзменения()) база может выдать ошибку и полностью остановить процесс обмена.
Для исправления подобной ситуации в РИБ рекомендуется временно написать внешнюю обработку, которая перед запуском чтения изменений выполнит поиск проблемных объектов и программно сбросит свойство Предопределенное у подчиненных строк субконто/видов расчетов непосредственно в периферийной базе.
Таким образом, мы выяснили причину ужесточения контроля со стороны платформы 1С 8.3, изучили правильный алгоритм снятия предопределенности у объектов планов счетов и планов видов расчета, а также обеспечили полную сохранность аналитических данных информационной базы для стабильной работы пользователей.