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

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При выполнении процедуры свёртки информационной базы на платформе 1С:Предприятие типовые механизмы фиксируют остатки и актуальные срезы данных на выбранную дату. Нередко возникает ситуация: процедура свёртки завершена успешно, однако при попытке запустить штатное удаление помеченных объектов система блокирует удаление карточек номенклатуры. Причиной блокировки чаще всего становятся ссылки в периодическом регистре сведений ЦеныНоменклатуры, созданные документом Корректировка записей регистров (или Корректировка регистров).

В этой статье мы подробно разберем, почему типовая свёртка подтягивает неактуальные позиции, как устроен документ корректировки и какими способами можно быстро очистить движения регистра от ссылок на помеченные объекты.

Выясним причину: почему помеченная номенклатура попадает в свёртку

Проанализируем работу штатных механизмов формирования остатков цен при свёртке. В стандартных обработках срез цен строится запросом к виртуальной таблице СрезПоследних регистра сведений на дату обрезки базы. В типовом запросе разработчики, как правило, не накладывают условие отсечения ГДЕ НЕ Номенклатура.ПометкаУдаления. В итоге любая позиция, для которой когда-либо была зарегистрирована цена, признается актуальной на дату среза и переносится в новый период.

Второй аспект проблемы — проектирование метаданных. В типовых конфигурациях у измерения Номенклатура регистра сведений ЦеныНоменклатуры флаг Ведущее намеренно снят. Это защищает историю цен от случайного каскадного удаления при удалении номенклатуры в рабочей базе. Но при свёртке это правило оборачивается трудностями: регистр сохраняет жесткую ссылку и не дает физически удалить элемент из базы.

Как документ «Корректировка регистров» хранит данные

Часто у специалистов возникает вопрос: если номенклатура попала в документ корректировки, нужно ли вручную открывать документ и перевыбирать строки? Разберем внутреннее устройство этого объекта.

Документ КорректировкаЗаписейРегистров не имеет собственных табличных частей, где хранились бы ссылки на номенклатуру. Он представляет собой пустую оболочку — технологический регистратор. Все отображаемые в его форме строки физически хранятся непосредственно в таблицах движений соответствующих регистров. Таким образом, как только запись удаляется из самого регистра сведений, она автоматически перестает существовать и в документе корректировки. Никаких «висячих» строк внутри документа не остается.

Способ 1. Программная очистка набора записей регистра

Посмотрим на базовый алгоритм, позволяющий исключить помеченные элементы из набора записей конкретного документа свёртки. Для этого создадим внешнюю обработку с реквизитом КорректировкаРегистров (тип ДокументСсылка.КорректировкаЗаписейРегистров).

Разберем пример простого перебора набора записей:


Процедура ОчиститьЦеныПомеченныхНажатие(Кнопка)
    
    СписокДляУдаления = Новый Массив;
    
    НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Регистратор.Установить(ЭтотОбъект.КорректировкаРегистров);
    НаборЗаписей.Прочитать();
    
    Для Каждого Позиция Из НаборЗаписей Цикл
        Если Позиция.Номенклатура.ПометкаУдаления Тогда
            СписокДляУдаления.Добавить(Позиция);
        КонецЕсли;
    КонецЦикла;
    
    Для Каждого УдаляемыйОбъект Из СписокДляУдаления Цикл
        НаборЗаписей.Удалить(УдаляемыйОбъект);
    КонецЦикла; 
    
    НаборЗаписей.Записать();
    Сообщить("Очистка набора записей успешно завершена.");
    
КонецПроцедуры

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

Способ 2. Оптимизированная перезапись через запрос для больших баз

Если после свёртки в регистре цен сформировались сотни тысяч записей, построчный перебор и вызов метода Удалить() в цикле могут выполняться крайне медленно и вызывать избыточные блокировки СУБД. В таких ситуациях рассмотрим более эффективный метод — выборку только «живых» записей с помощью запроса и последующую загрузку через НаборЗаписей.Загрузить().

Разберем по шагам оптимизированный сценарий:

  1. Формируем запрос к таблице регистра по конкретному регистратору.
  2. В условии запроса оставляем только элементы, где Номенклатура.ПометкаУдаления = ЛОЖЬ.
  3. Выгружаем результат напрямую в таблицу значений с полным составом полей регистра.
  4. Загружаем готовую таблицу в набор и выполняем запись.

Процедура ОчиститьЦеныБыстро(СсылкаНаДокумент)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Период,
        |   Регистратор,
        |   НомерСтроки,
        |   Активность,
        |   ВидЦены,
        |   Номенклатура,
        |   Характеристика,
        |   Цена,
        |   Валюта
        |ИЗ
        |   РегистрСведений.ЦеныНоменклатуры КАК Цены
        |ГДЕ
        |   Цены.Регистратор = &Регистратор
        |   И Цены.Номенклатура.ПометкаУдаления = ЛОЖЬ";
        
    Запрос.УстановитьПараметр("Регистратор", СсылкаНаДокумент);
    ТаблицаЖивыхЦен = Запрос.Выполнить().Выгрузить();
    
    НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
    
    // Замещаем весь набор подготовленной таблицей без помеченных на удаление
    НаборЗаписей.Загрузить(ТаблицаЖивыхЦен);
    НаборЗаписей.Записать();
    
    Сообщить("Регистр успешно перезаписан оптимизированным методом.");
    
КонецПроцедуры

Способ 3. Предотвращение попадания цен на этапе настройки свёртки

Проблему проще предотвратить до запуска свёртки. Проанализируем возможности стандартного помощника свёртки информационной базы:

  1. Настройка правил свёртки регистров: На этапе указания способов обработки регистров сведений для таблицы ЦеныНоменклатуры можно переключить режим на «Не обрабатывать» или «Очистить». Это актуально, если исторические срезы цен не требуются, а актуальный прайс-лист вносится новым документом установки цен.
  2. Доработка запроса свёртки: Если обработка свёртки запускается как внешняя, достаточно открыть модуль формирования движений и в запросе среза последних для цен номенклатуры добавить фильтр: ГДЕ НЕ Номенклатура.ПометкаУдаления И НЕ Номенклатура.ЭтоГруппа.

Что еще может мешать окончательному удалению номенклатуры

Если после очистки регистра ЦеныНоменклатуры номенклатура по-прежнему не удаляется штатным инструментом Удаление помеченных объектов, проверим сопутствующие регистры сведений, которые свёртка не очищает автоматически:

  1. Штрихкоды (или ШтрихкодыНоменклатуры) — независимый регистр, где также сохраняются ссылки на удаляемые карточки.
  2. СоответствияОбъектовИнформационныхБаз — регистр планов обмена, фиксирующий соответствие GUID при синхронизации.
  3. НоменклатураПоставщиков (НоменклатураКонтрагентов) — привязка артикулов внешних партнеров.
  4. Регистры дополнительных реквизитов и сведений (подсистема БСП).

Для точного определения оставшихся «хвостов» используем метод платформы НайтиПоСсылкам() либо встроенный в форму удаления отчёт о связях объектов. В крайнем случае, если ссылки остаются в исторических закрытых регистрах, допустимо воспользоваться обработкой поиска и замены значений, объединив все помеченные элементы в один архивный служебный элемент (например, [АРХИВ] Списанная номенклатура).

← На главную