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