При доработке формы списка номенклатуры в конфигурациях 1С (например, 1С:Управление торговлей) часто возникает задача вывести текущие остатки товаров по нескольким складам непосредственно в список. Однако после редактирования текста запроса динамического списка разработчики сталкиваются с двумя распространенными проблемами: из списка исчезают товары с нулевыми остатками, а при двойном клике по строке перестает открываться карточка номенклатуры.
Рассмотрим подробнее причины возникновения этих ошибок и разберем по шагам, как правильно изменить запрос и настройки формы для корректного отображения всех данных.
Проанализируем ситуацию, когда из справочника выводится только та номенклатура, по которой есть физические остатки на складах. В исходном запросе динамического списка выборка номенклатуры соединяется с виртуальной таблицей РегистрНакопления.ТоварыНаСкладах.Остатки с помощью оператора ЛЕВОЕ СОЕДИНЕНИЕ. Однако фильтрация по конкретным складам установлена в общей секции ГДЕ:
ГДЕ
НЕ СпрНоменклатура.ЭтоГруппа
И ТоварыНаСкладахОстатки.Склад.Наименование = "1. Склад (Ленинский)"
И ТоварыНаСкладахОстаткиДаниловская.Склад.Наименование = "2, Склад (Даниловская)"
И ТоварыНаСкладахЛенинский30.Склад.Наименование = "3. Розничный магазин Л-30"
Выясним причину такого поведения СУБД. Когда левое соединение не находит подходящую запись в присоединяемой таблице остатков (например, если товара нет на складе), во всех полях этой таблицы возвращается значение NULL. Затем СУБД переходит к проверке условий из блока ГДЕ. Так как значение NULL не равно текстовому наименованию склада, такое условие возвращает ЛОЖЬ. В результате вся строка справочника Справочник.Номенклатура полностью исключается из итоговой выборки.
Таким образом, логика ЛЕВОЕ СОЕДИНЕНИЕ фактически превращается во ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN). Для исправления этой ошибки необходимо перенести отбор по присоединяемой таблице из секции ГДЕ в секцию описания связи ПО.
Посмотрим на пример правильного оформления связи:
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
ПО (ТоварыНаСкладахОстатки.Номенклатура = СпрНоменклатура.Ссылка)
И (ТоварыНаСкладахОстатки.Склад.Наименование = "1. Склад (Ленинский)")
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстаткиДаниловская
ПО (ТоварыНаСкладахОстаткиДаниловская.Номенклатура = СпрНоменклатура.Ссылка)
И (ТоварыНаСкладахОстаткиДаниловская.Склад.Наименование = "2, Склад (Даниловская)")
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахЛенинский30
ПО (ТоварыНаСкладахЛенинский30.Номенклатура = СпрНоменклатура.Ссылка)
И (ТоварыНаСкладахЛенинский30.Склад.Наименование = "3. Розничный магазин Л-30")
При такой записи проверка склада происходит непосредственно в момент соединения таблиц. Если остатка по складу нет, правая часть останется со значением NULL, функция ЕСТЬNULL(..., 0) заменит его на ноль, а сам товар из списка номенклатуры не исчезнет.
Использование поиска реквизитов через Склад.Наименование = "..." является крайне неэффективным по нескольким причинам:
Разберем, как оптимизировать виртуальную таблицу остатков. Условия по измерению Склад следует передавать напрямую в параметры виртуальной таблицы РегистрНакопления.ТоварыНаСкладах.Остатки с помощью ссылочных параметров:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &СкладЛенинский) КАК ТоварыНаСкладахОстатки
ПО (ТоварыНаСкладахОстатки.Номенклатура = СпрНоменклатура.Ссылка)
Значение параметра &СкладЛенинский задается в настройках динамического списка или программно при открытии формы.
Рассмотрим вторую проблему: после модификации запроса при нажатии на строку номенклатуры перестал открываться элемент справочника.
Это происходит из-за того, что платформе 1С при существенном изменении структуры запроса динамического списка необходимо явно указать главную таблицу выборки. Платформа сбрасывает значение свойства Основная таблица динамического списка.
Выясним, как восстановить функциональность карточки номенклатуры:
Список).Справочник.Номенклатура.После указания основной таблицы платформа снова привяжет стандартные команды формы к выбранному справочнику: станут доступны открытие формы элемента, контекстное меню, проверка прав RLS и стандартный поиск.
Проанализируем производительность динамических списков при получении остатков. Если номенклатурный справочник содержит десятки тысяч позиций, множественные соединения с виртуальной таблицей остатков по каждому складу могут вызывать существенные задержки при прокрутке списка.
Для повышения быстродействия рекомендуется оставить запрос динамического списка простым (выборка только из справочника Справочник.Номенклатура), а получение остатков вынести в серверное событие таблицы формы ПриПолученииДанныхНаСервере.
Алгоритм данного подхода выглядит следующим образом:
ПриПолученииДанныхНаСервере платформа передает массив ссылок только тех товаров, которые отображаются на экране пользователя в данный момент (как правило, от 20 до 50 строк).Применение этого метода гарантирует максимально высокую скорость работы интерфейса независимо от объема базы данных и количества складов.