Как удалить ошибочно созданные дополнительные реквизиты в 1С после сбоя обмена с сайтом?

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

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

Удаление сотен таких объектов вручную — неэффективный и долгий процесс. В этой статье мы подробно рассмотрим, как решить эту задачу профессиональными методами: от стандартных инструментов Библиотеки стандартных подсистем (БСП) до написания специализированных программных обработок на встроенном языке 1С.

Метод 1. Использование встроенного инструмента «Поиск и удаление дублей»

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

Для перехода к этому инструменту откроем раздел НСИ и администрирование, перейдем в пункт Обслуживание, далее выберем Поиск и удаление дублей. Выполним следующие шаги:

  1. В поле Искать в: выберем объект ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения (или «Дополнительные реквизиты и сведения»).
  2. В поле Отбирать: мы можем установить фильтр по конкретным реквизитам, если мы точно знаем их признаки, либо оставить поиск по всем элементам.
  3. В поле Сравнивать: укажем правило «Совпадает наименование».

Нажмем кнопку Найти дубли. Программа проанализирует базу данных и сгруппирует элементы с одинаковыми именами. Системный алгоритм автоматически определит правильный («оригинальный») элемент — обычно это тот элемент, который чаще всего используется в карточках номенклатуры. Остальные элементы будут помечены как дубли.

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

Метод 2. Отбор элементов по диапазону ссылок (Метод автора темы)

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

Каждому новому элементу сопоставляется свой уникальный идентификатор. В рамках одного сеанса записи ссылки часто записываются последовательно. Мы можем определить границы «ошибочного» диапазона:

  1. Найдем самый первый ошибочно созданный элемент (для этого можно заглянуть в Журнал регистрации). Назовем его ПервыйЭлемент.
  2. Найдем самый последний созданный элемент. Назовем его ПоследнийЭлемент.

Теперь мы можем написать запрос или настроить групповое изменение реквизитов с отбором по ссылке:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ДопРеквизиты.Ссылка КАК Ссылка
    |ИЗ
    |	ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК ДопРеквизиты
    |ГДЕ
    |	ДопРеквизиты.Ссылка >= &ПервыйЭлемент
    |	И ДопРеквизиты.Ссылка <= &ПоследнийЭлемент";

Запрос.УстановитьПараметр("ПервыйЭлемент", ПервыйЭлемент);
Запрос.УстановитьПараметр("ПоследнийЭлемент", ПоследнийЭлемент);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    ОбъектРеквизита = Выборка.Ссылка.ПолучитьОбъект();
    ОбъектРеквизита.УстановитьПометкуУдаления(Истина, Истина);
КонецЦикла;

Важное предупреждение: Сравнение ссылок через операторы сравнения >= и <= в платформе 1С не гарантирует 100% хронологической точности. В кластерах серверов или при многопоточной работе GUID создаваемых объектов могут распределяться нелинейно. Используйте этот метод с осторожностью и только после предварительного тестирования на копии базы данных.

Метод 3. Точное определение даты создания через парсинг GUID

Чтобы избежать риска нелинейного распределения ссылок, воспользуемся особенностью генерации уникальных идентификаторов в 1С. Платформа генерирует идентификаторы типа UUID Version 1, в структуре которых на системном уровне закодировано точное время создания записи.

Разберем структуру GUID по шагам. Он состоит из групп шестнадцатеричных символов. Первые три группы содержат информацию о количестве 100-наносекундных интервалов, прошедших с момента начала Григорианского календаря (15 октября 1582 года). Переставив байты в правильном порядке (так как они хранятся в формате low-endian) и преобразовав их в десятичную систему счисления, мы сможем вычислить точную дату создания реквизита с точностью до миллисекунд.

Рассмотрим функцию преобразования GUID в дату создания объекта на встроенном языке 1С:


Функция ПолучитьДатуСозданияИзСсылка(Ссылка) Экспорт
    Идентификатор = Ссылка.УникальныйИдентификатор();
    СтрокаГП = СтрЗаменить(Строка(Идентификатор), "-", "");
    
    // UUID версии 1 содержит временную метку в первых трех блоках
    // Извлекаем блоки времени и переставляем в обратном порядке (высокий-средний-низкий)
    ВременнаяМеткаHEX = Сред(СтрокаГП, 14, 3) + Сред(СтрокаГП, 9, 4) + Лев(СтрокаГП, 8);
    
    // Преобразуем HEX в десятичное число
    Число100Наносекунд = 0;
    Для Позиция = 1 По СтрДлина(ВременнаяМеткаHEX) Цикл
        Символ = Сред(ВременнаяМеткаHEX, Позиция, 1);
        Значение = Найти("0123456789abcdef", Символ) - 1;
        Число100Наносекунд = Число100Наносекунд * 16 + Значение;
    КонецЦикла;
    
    // 100-наносекундные интервалы переводим в секунды
    ВсегоСекунд = Число100Наносекунд / 10000000;
    
    // Григорианская эпоха началась 15 октября 1582 года
    БазоваяДата = Дата(1582, 10, 15, 0, 0, 0);
    
    Возврат БазоваяДата + ВсегоСекунд;
КонецФункции

Используя эту функцию, мы можем написать простую обработку, которая переберет элементы плана видов характеристик и безошибочно определит те, которые были созданы ровно в период проведения неудачного обмена (например, в интервале с 14:00 по 14:15 сегодняшнего дня).

Метод 4. Программный анализ Журнала Регистрации

Еще один надежный способ точечно выявить созданные объекты — обратиться к Журналу регистрации 1С. Чтение текстовых файлов журнала регистрации вручную — неблагодарное занятие. Вместо этого задействуем штатный программный метод платформы ВыгрузитьЖурналРегистрации().

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


Процедура НайтиНовыеРеквизитыПоЖурналуРегистрации(ДатаНачалаОбмена, ДатаОкончанияОбмена)
    
    Фильтр = Новый Структура;
    Фильтр.Вставить("ДатаНачала",   ДатаНачалаОбмена);
    Фильтр.Вставить("ДатаОкончания", ДатаОкончанияОбмена);
    Фильтр.Вставить("Событие",      "_$Data$_.New"); // Фильтр только на добавление новых объектов
    
    ТаблицаЖР = Новый ТаблицаЗначений;
    ВыгрузитьЖурналРегистрации(ТаблицаЖР, Фильтр, "Данные, Метаданные", , );
    
    МассивОшибочныхСсылок = Новый Массив;
    
    Для Каждого СтрокаЖР Из ТаблицаЖР Цикл
        // Проверяем, что измененный объект относится к нашему Плану видов характеристик
        Если Найти(СтрокаЖР.Метаданные, "ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения") > 0 Тогда
            МассивОшибочныхСсылок.Добавить(СтрокаЖР.Данные);
        КонецЕсли;
    КонецЦикла;
    
    // Теперь у нас есть точный список ссылок, переходим к их очистке и пометке
    ПровестиОчисткуИПометкуУдаления(МассивОшибочныхСсылок);
    
КонецПроцедуры

Этот метод гарантирует 100% точность попадания, поскольку Журнал регистрации фиксирует факт создания каждого объекта независимо от структуры его GUID.

Метод 5. Очистка связей в наборах дополнительных реквизитов

Просто пометить ошибочные реквизиты на удаление недостаточно. В архитектуре 1С:Управление торговлей 11 дополнительные свойства жестко привязаны к справочнику НаборыДополнительныхРеквизитовИСведений (например, к набору свойств конкретной группы номенклатуры или характеристик).

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


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

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

Превентивные меры: как не допустить повторения проблемы?

Выясним причину, почему обмен с сайтом привел к дублированию свойств. Удаление последствий — временная мера. При следующем сеансе обмена CMS-сайт снова попытается выгрузить свои свойства и создаст еще одну порцию дублей.

Сбой синхронизации происходит из-за несовпадения внешних идентификаторов (XML_ID). Когда реквизиты создаются вручную внутри 1С, им присваиваются случайные идентификаторы GUID. При обмене сайт передает свои внутренние ID свойств. Модуль обмена в 1С пытается сопоставить свойства по полю Идентификатор для формул, по GUID или по регистру соответствия объектов.

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

  1. Убедиться, что у существующих «правильных» реквизитов в 1С корректно заполнен реквизит Идентификатор для формул или внешние идентификаторы в регистрах обмена.
  2. В настройках интеграции на стороне CMS проверить правила сопоставления свойств и убедиться, что они соответствуют выгружаемой XML-схеме (CommerceML).
← На главную