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