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