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