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