При переносе данных между информационными базами с помощью обработки ВыгрузкаЗагрузкаДанныхXML или при некорректном обновлении конфигураций разработчики и администраторы нередко сталкиваются с критической ошибкой — появлением дублей предопределенных элементов (в планах счетов, справочниках, планах видов характеристик). В результате документы перестают проводиться, в отчетах двоятся счета и субконто, а попытка объединить дубли штатной обработкой «Поиск и удаление дублей» завершается ошибкой «В данной транзакции уже происходили ошибки».
Разберем подробно причины возникновения этой проблемы и пошаговый алгоритм её безопасного исправления без необходимости снятия конфигурации с поддержки.
Проанализируем техническую сторону работы платформы 1С:Предприятие 8.3, чтобы понять механизм возникновения ошибки:
ВыгрузкаЗагрузкаДанныхXML выполняет запись объектов с установленным флагом ОбменДанными.Загрузка = Истина. В этом режиме стандартный контроль уникальности предопределенных данных платформой отключается, что позволяет записать в таблицу базы данных вторую запись с точно таким же значением стандартного реквизита ИмяПредопределенныхДанных.Рассмотрим безопасный программный способ устранения дублей непосредственно в режиме «1С:Предприятие».
Шаг 1. Поиск дублирующихся предопределенных данных
Выясним, какие именно элементы имеют одинаковое значение поля ИмяПредопределенныхДанных. Для этого сформируем запрос к проблемной таблице (например, к плану счетов или справочнику):
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таблица.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных,
| КОЛИЧЕСТВО(Таблица.Ссылка) КАК Количество
|ИЗ
| ПланСчетов.Хозрасчетный КАК Таблица
|ГДЕ
| Таблица.ИмяПредопределенныхДанных <> """"
|СГРУППИРОВАТЬ ПО
| Таблица.ИмяПредопределенныхДанных
|ИМЕЮЩИЕ
| КОЛИЧЕСТВО(Таблица.Ссылка) > 1";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Шаг 2. Снятие признака предопределенности у ошибочных дублей
Чтобы платформа позволила модифицировать и объединить элементы, необходимо очистить стандартный реквизит ИмяПредопределенныхДанных у лишних дублей, оставив заполненным только один (канонический) элемент. Выполним это в режиме обмена данными, чтобы обойти блокировку:
// Получаем объект дублирующего элемента
ОбъектДубль = ДубльСсылка.ПолучитьОбъект();
// Включаем режим загрузки для отключения платформенного контроля
ОбъектДубль.ОбменДанными.Загрузка = Истина;
// Очищаем имя предопределенного элемента
ОбъектДубль.ИмяПредопределенныхДанных = "";
// Записываем элемент как обычный (непредопределенный)
ОбъектДубль.Записать();
После записи объект становится стандартным пользовательским элементом, и ошибки уникальности предопределенных данных перестают блокировать транзакции.
Шаг 3. Замена ссылок в базе данных
Теперь перенаправим все движения документов, проводки и связанные объекты с отвязанного дубля на правильный предопределенный элемент. Для этого воспользуемся платформенной процедурой НайтиИЗаменитьСсылки:
ТаблицаЗамен = Новый ТаблицаЗначений;
ТаблицаЗамен.Колонки.Добавить("ОшибочнаяСсылка");
ТаблицаЗамен.Колонки.Добавить("ПравильнаяСсылка");
СтрокаЗамены = ТаблицаЗамен.Добавить();
СтрокаЗамены.ОшибочнаяСсылка = ДубльСсылка;
СтрокаЗамены.ПравильнаяСсылка = ПравильнаяСсылкаПредопределенного;
НайтиИЗаменитьСсылки(ТаблицаЗамен);
Шаг 4. Удаление лишних элементов
После успешной замены ссылок отвязанный элемент помечается на удаление и удаляется из базы стандартным механизмом контроля ссылочной целостности (через меню «Функции для технического специалиста» — «Удаление помеченных объектов»).
Если задвоение произошло в справочнике ИдентификаторыОбъектовМетаданных или ИдентификаторыОбъектовРасширений, ручная замена ссылок может привести к ошибкам циклических связей подсистемы БСП. В этом случае правильным решением является программный вызов процедуры обновления данных в привилегированном режиме:
// Полное перестроение соответствия метаданных с параметром Инициализация = Истина
Справочники.ИдентификаторыОбъектовМетаданных.ОбновитьДанныеИнформационнойБазы(Истина);
Чтобы избежать появления дублей при первоначальном переносе данных в новую чистую базу:
НеОбновлятьАвтоматически.Авто или вызовите метод менеджера ОбновитьПредопределенныеДанные() для привязки структуры метаданных к загруженным элементам.