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

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

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

Разберем архитектурные варианты хранения прайсов, организацию быстрого поиска и механизм создания номенклатуры «по требованию» (on-demand), когда элемент справочника создается только в момент реального оформления заказа покупателя.

Анализ ограничений типовых механизмов 1С

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

  1. Использование периодических регистров и среза последних: типовые регистры сведений цен поставщиков являются периодическими. Если товар исчезает из нового прайс-листа поставщика, запрос со срезом последних по-прежнему будет возвращать старую цену, пока не будет явно записана нулевая цена или признак отмены.
  2. Избыточный рост таблиц базы данных: создание сотен тысяч ссылочных элементов ради проверки цен приводит к деградации производительности таблиц справочников и разрастанию индексов СУБД.
  3. Ограничения по валютам и курсам: прайс-листы часто содержат строки в разных валютах или требуют индивидуального пересчета курсов на дату анализа, что сложно реализовать в типовом контуре регистрации цен.

Архитектура независимого регистра сведений

Оптимальным решением внутри базы 1С является создание отдельного независимого непериодического регистра сведений (например, ПрайсЛистыПоставщиков), в котором все измерения и реквизиты хранятся в виде примитивных типов или ссылок только на поставщиков.

Рассмотрим рекомендуемую структуру регистра:

  1. Измерения:
    1. Поставщик — тип СправочникСсылка.Контрагенты (или СправочникСсылка.Партнеры).
    2. ОчищенныйАртикул — тип Строка (фиксированная длина, индексируемое поле для быстрого поиска).
    3. Бренд — тип Строка или ссылка на справочник брендов/производителей.
  2. Ресурсы:
    1. Цена — тип Число.
    2. Валюта — тип СправочникСсылка.Валюты.
    3. Остаток — тип Число (или строковый статус наличия).
    4. СрокПоставкиДней — тип Число.
  3. Реквизиты:
    1. ИсходноеНаименование — тип Строка (для отображения пользователю).
    2. ИсходныйАртикул — тип Строка (в оригинальном написании).
    3. ДатаОбновления — тип Дата.

Главное преимущество непериодического регистра заключается в простоте и скорости полной перезаписи данных поставщика. Для обновления прайса не нужно построчно удалять старые записи. Достаточно использовать объект РегистрСведенийНаборЗаписей с отбором по поставщику:


Набор = РегистрыСведений.ПрайсЛистыПоставщиков.СоздатьНаборЗаписей();
Набор.Отбор.Поставщик.Установить(ВыбранныйПоставщик);

// Заполняем набор новыми строками из загруженного файла
Для Каждого СтрокаПрайса Из ТаблицаЗагрузки Цикл
    Запись = Набор.Добавить();
    Запись.Поставщик = ВыбранныйПоставщик;
    Запись.ОчищенныйАртикул = НормализоватьАртикул(СтрокаПрайса.Артикул);
    Запись.Бренд = СтрокаПрайса.Бренд;
    Запись.ИсходныйАртикул = СтрокаПрайса.Артикул;
    Запись.ИсходноеНаименование = СтрокаПрайса.Наименование;
    Запись.Цена = СтрокаПрайса.Цена;
    Запись.Валюта = СтрокаПрайса.Валюта;
    Запись.Остаток = СтрокаПрайса.Количество;
    Запись.ДатаОбновления = ТекущаяДатаСеанса();
КонецЦикла;

// Запись с замещением очищает старый прайс поставщика за одну транзакцию
Набор.Записать(Истина);

Оптимизация поиска по нормализованному артикулу

Поиск по условию ПОДОБНО "%подстрока%" по таблице в 1 000 000 записей приводит к полному сканированию таблицы СУБД (Full Table Scan) и блокировкам. Для обеспечения мгновенного отклика необходимо выполнять нормализацию артикулов как при загрузке прайса, так и при вводе поискового запроса пользователем.

Посмотрим на пример функции нормализации артикула:


Функция НормализоватьАртикул(Знач ВходнаяСтрока) Экспорт
    Результат = ВРЕГ(СокрЛП(ВходнаяСтрока));
    
    // Удаляем разделители, спецсимволы и пробелы
    СимволыДляУдаления = " -_./\,()[]{}*#";
    Для Индекс = 1 По СтрДлина(СимволыДляУдаления) Цикл
        Символ = Сред(СимволыДляУдаления, Индекс, 1);
        Результат = СтрЗаменить(Результат, Символ, "");
    КонецЦикла;
    
    // Заменяем схожие символы кириллицы на латиницу
    Результат = СтрЗаменить(Результат, "А", "A");
    Результат = СтрЗаменить(Результат, "В", "B");
    Результат = СтрЗаменить(Результат, "С", "C");
    Результат = СтрЗаменить(Результат, "Е", "E");
    Результат = СтрЗаменить(Результат, "Н", "H");
    Результат = СтрЗаменить(Результат, "К", "K");
    Результат = СтрЗаменить(Результат, "М", "M");
    Результат = СтрЗаменить(Результат, "О", "O");
    Результат = СтрЗаменить(Результат, "Р", "P");
    Результат = СтрЗаменить(Результат, "Т", "T");
    Результат = СтрЗаменить(Результат, "Х", "X");
    
    Возврат Результат;
КонецФункции

Благодаря нормализации поиск по измерению ОчищенныйАртикул (с включенным свойством Индексировать) выполняется за доли секунды через точное совпадение или поиск по началу строки (ПОДОБНО "АРТИКУЛ%").

Реализация алгоритма создания номенклатуры «по требованию»

Схема взаимодействия менеджера при подборе товаров из прайсов выглядит следующим образом:

  1. Менеджер в обработке подбора или документе заказа вводит поисковый запрос (артикул или наименование).
  2. Система выполняет запрос к регистру ПрайсЛистыПоставщиков и выводит сводную таблицу предложений от всех поставщиков с их ценами, валютами и остатками.
  3. Менеджер выбирает наиболее выгодное предложение и добавляет строку в заказ.
  4. Программа проверяет, существует ли уже в базе элемент справочника Номенклатура с данным нормализованным артикулом и брендом.
  5. Если соответствие найдено — подставляется существующая номенклатура.
  6. Если товара в базе нет — программно создается новый элемент справочника Номенклатура, заполняются базовые реквизиты (наименование, артикул, ставка НДС, единица измерения) и фиксируется привязка к номенклатуре поставщика.

Пример программного создания номенклатуры при выборе позиции из прайс-листа:


Функция ПолучитьИлиСоздатьНоменклатуруПоПрайсу(СтрокаВыбора)
    // 1. Попытка найти существующую номенклатуру по артикулу
    ОчищенныйАртикул = НормализоватьАртикул(СтрокаВыбора.ИсходныйАртикул);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |   Номенклатура.Ссылка КАК Ссылка
        |ИЗ
        |   Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |   Номенклатура.Артикул = &Артикул";
    Запрос.УстановитьПараметр("Артикул", СтрокаВыбора.ИсходныйАртикул);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Ссылка;
    КонецЕсли;
    
    // 2. Если товар не найден — создаем новый элемент
    НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
    НовыйЭлемент.Наименование = СтрокаВыбора.ИсходноеНаименование;
    НовыйЭлемент.НаименованиеПолное = СтрокаВыбора.ИсходноеНаименование;
    НовыйЭлемент.Артикул = СтрокаВыбора.ИсходныйАртикул;
    НовыйЭлемент.БазоваяЕдиницаИзмерения = Справочники.КлассификаторЕдиницИзмерения.Штука;
    НовыйЭлемент.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
    НовыйЭлемент.Записать();
    
    Возврат НовыйЭлемент.Ссылка;
КонецФункции

Альтернативные варианты хранения прайсов вне базы 1С

Если суммарный объем прайсов превышает несколько миллионов строк или требуется сложный нечеткий поиск (с учетом опечаток и перестановки слов), целесообразно вынести хранение прайсов за пределы основной информационной базы:

  1. Механизм «Внешние источники данных» (ВИД): прайс-листы загружаются в отдельную СУБД (PostgreSQL, MySQL, MS SQL). В 1С настраивается прямое чтение через ВИД. Это исключает разрастание журнала транзакций и файлов основной базы 1С, сохраняя возможность работы через стандартный язык запросов 1С.
  2. Специализированные поисковые движки (Elasticsearch / Meilisearch): прайсы хранятся в поисковой базе данных. 1С отправляет поисковую строку по HTTP REST API и получает готовые результаты с ранжированием по релевантности за несколько миллисекунд.
  3. Локальные базы SQLite: подходят для изолированного кэширования прайс-листов на сервере 1С с обращением через внешние компоненты или ADO-соединение.
← На главную