В процессе работы в базах данных «1С:Предприятие 8» (особенно в конфигурациях «Управление торговлей», «Комплексная автоматизация» и «ERP») часто возникает неприятная ситуация. В справочнике номенклатуры накапливаются тысячи позиций, по которым фактически никогда не было реальных продаж и остатков на физических складах. Тем не менее, стандартное удаление этих позиций заблокировано, так как по ним регистрировались цены поставщиков, загружались прайс-листы или проводились виртуальные списания и оприходования для нужд интернет-магазина.
Такие «мертвые» карточки перегружают базу данных, замедляют поиск для менеджеров и усложняют выбор номенклатуры при оформлении заказов. В этой статье мы подробно разберем, почему стандартные механизмы удаления пасуют перед этой задачей, проанализируем риски популярных кустарных методов и изучим безопасные профессиональные алгоритмы очистки и архивации данных.
Попытка использовать штатный инструмент «Удаление помеченных объектов» для таких товаров обычно заканчивается неудачей. Платформа выдает длинный список документов и регистров, которые ссылаются на удаляемый объект. Выясним, какие именно механизмы блокируют процесс удаления:
УстановкаЦенНоменклатуры записывает данные в периодические регистры (например, ЦеныНоменклатуры или ЦеныНоменклатуры25). Даже если мы пометим документ установки цен на удаление, система не позволит его стереть, если в этом же документе содержатся другие, актуальные товары. Удалить только одну строку из проведенного документа интерактивно невозможно.КлючиАналитикиУчетаНоменклатуры). При проведении любого документа, связанного с виртуальным складом, система генерирует такой ключ. Даже если сам документ впоследствии был удален или помечен на удаление, осиротевший элемент справочника аналитики продолжает ссылаться на товар и намертво блокирует его физическое удаление из базы.На форумах часто встречается совет: создать одну карточку номенклатуры под названием «Неиспользуемый товар» (или «Заглушка»), с помощью обработки «Поиск и замена дублей» перенаправить все ссылки со старых карточек на этот элемент, а сами карточки безболезненно удалить. Рассмотрим, почему этот метод крайне опасен для работоспособности базы данных:
Проблема сверхзагруженного элемента (Supernode): Если вы перенаправите ссылки с тысяч различных товаров на одну карточку-заглушку, этот элемент свяжется с колоссальным объемом исторических данных. Он будет фигурировать в тысячах документов установки цен, оприходований, списаний, штрихкодов и заказов. В результате СУБД (MS SQL, PostgreSQL) столкнется с критической нагрузкой при попытке проанализировать этот элемент. Любой отчет по продажам, расчет себестоимости или попытка открыть форму выбора этого товара приведет к зависанию сессии и блокировкам таблиц для других пользователей.
Кроме того, этот метод полностью искажает историческую отчетность. Вы больше не сможете понять, какие именно позиции списывались или оприходовались на виртуальные склады поставщиков в прошлых периодах.
В крупных проектах и высоконагруженных базах данных физическое удаление объектов из СУБД признано нецелесообразным. Оно требует монопольного доступа, может выполняться часами и несет риски нарушения ссылочной целостности. Вместо этого применяется методика архивирования номенклатуры. Проанализируем, как реализовать этот подход по шагам:
С помощью механизма расширений конфигурации добавим в справочник Номенклатура новый реквизит Архив (тип данных — Булево). Выведем этот флаг на форму элемента номенклатуры. Также можно использовать типовой механизм дополнительных реквизитов и сведений, если не хочется вмешиваться в конфигурацию.
Чтобы архивные товары не мешали пользователям при подборе, настроим форму выбора и форму списка справочника номенклатуры. Мы модифицируем запросы динамических списков так, чтобы позиции с установленным флагом Архив = Истина автоматически скрывались из видимости.
Посмотрим на пример кода, который можно внедрить в модуль формы выбора номенклатуры при ее создании на сервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Добавляем обязательный отбор, исключающий архивные товары
ОбщийНастройки = Список.КомпоновщикНастроек.Настройки;
ЭлементОтбора = ОбщийНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Архив");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Ложь;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецПроцедуры
Преимущества этого подхода очевидны: база данных не подвергается риску повреждения, ссылочная целостность сохраняется на 100%. Старые отчеты по продажам и закупкам формируются корректно, а менеджеры при этом видят только актуальный каталог товаров.
Если перед вами стоит задача именно физически очистить базу (например, для уменьшения размера файла базы данных или подготовки к свертке), действовать нужно осторожно и планомерно. Разберем по шагам безопасный алгоритм полной очистки неиспользуемой номенклатуры.
Нельзя опираться только на визуальное отсутствие движений. Необходимо написать запрос, который проверит отсутствие записей по ключевым регистрам накопления за длительный период (например, за последние 3 года) и подтвердит нулевой текущий остаток.
Рассмотрим пример запроса, выполняющего такой анализ:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа
| И НЕ Номенклатура.ПометкаУдаления
| И НЕ Номенклатура.Ссылка В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| Выручка.АналитикаУчетаНоменклатуры.Номенклатура
| ИЗ
| РегистрНакопления.ВыручкаИСебестоимостьПродаж КАК Выручка
| ГДЕ
| Выручка.Период >= &ПериодНачала)
| И НЕ Номенклатура.Ссылка В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| Товары.АналитикаУчетаНоменклатуры.Номенклатура
| ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК Товары
| ГДЕ
| Товары.Период >= &ПериодНачала)";
Запрос.УстановитьПараметр("ПериодНачала", ДобавитьМесяц(ТекущаяДата(), -36)); // Анализ за 3 года
РезультатТаблица = Запрос.Выполнить().Выгрузить();
Для того чтобы разорвать связь номенклатуры с документами УстановкаЦенНоменклатуры, не удаляя сами документы, мы должны программно удалить только строки с целевыми товарами из табличных частей. Напишем алгоритм, который находит такие документы и перезаписывает их:
Для Каждого СтрокаКандидата Из РезультатТаблица Цикл
ЗапросДокументов = Новый Запрос;
ЗапросДокументов.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТЧ.Ссылка КАК Ссылка
|ИЗ
| Документ.УстановкаЦенНоменклатуры.Товары КАК ТЧ
|ГДЕ
| ТЧ.Номенклатура = &Номенклатура";
ЗапросДокументов.УстановитьПараметр("Номенклатура", СтрокаКандидата.Ссылка);
Выборка = ЗапросДокументов.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
// Обходим табличную часть с конца, чтобы не сбивались индексы строк
Индекс = ДокументОбъект.Товары.Количество() - 1;
Пока Индекс >= 0 Цикл
Если ДокументОбъект.Товары[Индекс].Номенклатура = СтрокаКандидата.Ссылка Тогда
ДокументОбъект.Товары.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЕсли;
Если ДокументОбъект.Модифицирован() Тогда
// Записываем документ без проведения, чтобы просто обновить состав ТЧ
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Перед удалением самого элемента номенклатуры необходимо очистить подчиненные справочники и регистры сведений, в которых он выступает измерением или владельцем. Программа должна в цикле выполнить следующие действия:
ШтрихкодыНоменклатуры.ЦеныНоменклатуры, непосредственно связанные с этим товаром.После того как все документы очищены от упоминания удаляемого товара, необходимо запустить процедуру удаления неиспользуемых ключей аналитики. Для этого воспользуемся встроенным инструментом платформы:
После проведения всех подготовительных процедур и успешного разрыва связей мы можем пометить выбранную номенклатуру на удаление и запустить стандартную обработку «Удаление помеченных объектов». Теперь удаление пройдет быстро и без ошибок блокировки ссылок.
Важная рекомендация: Перед запуском любых обработок по физической очистке данных обязательно создавайте полную резервную копию информационной базы (файл .dt или бэкап SQL-сервера). Проводите подобные работы в техническое окно, когда в базе отсутствуют активные пользователи.