При работе в программе 1С:Управление торговлей 11 у пользователей часто возникает потребность быстро проанализировать историю взаимодействия с клиентом. Открывать каждый раз карточку контрагента или переходить в отдельные журналы бывает неудобно. Гораздо эффективнее видеть список всех документов (реализаций, оплат, заказов) прямо в форме списка справочника контрагентов при выделении строки.
В этой статье мы подробно разберем, как решить эту задачу. Мы рассмотрим как стандартные возможности программы, не требующие программирования, так и правильную архитектуру доработки системы через механизм расширений.
Прежде чем приступать к разработке, давайте проанализируем штатные возможности конфигурации. Разработчики фирмы 1С уже предусмотрели удобное рабочее место для анализа документов по конкретному партнеру.
Выполним следующие шаги для просмотра документов:
Если же менеджеру или бухгалтеру удобнее работать непосредственно из журнала документов (например, в списке продаж), мы можем воспользоваться стандартной группировкой списка:
После этого наш журнал превратится в иерархическое дерево, где все документы будут аккуратно сгруппированы по папкам-контрагентам. Достаточно развернуть ветку нужного клиента, чтобы увидеть все его продажи.
Если типовые варианты не подходят и требуется реализовать именно динамическое отображение документов внизу формы списка контрагентов, нам понадобится механизм расширений. Это позволит сохранить конфигурацию на поддержке и избежать сложностей при последующих обновлениях.
Существует распространенная ошибка среди начинающих разработчиков — писать прямой запрос к базе данных в событии ПриАктивизацииСтроки таблицы контрагентов. Давайте разберем, почему так делать нельзя. При быстром перемещении по списку с помощью стрелок клавиатуры событие активизации строки срабатывает десятки раз в секунду. Если на каждый шаг система будет выполнять серверный вызов и тяжелый запрос к базе данных, интерфейс начнет заметно «зависать», а нагрузка на сервер СУБД резко возрастет.
Правильным архитектурным решением является использование второго Динамического списка на форме. Платформа 1С оптимизирует работу динамических списков, запрашивая данные порциями и кэшируя их. Сделаем доработку по шагам:
Контрагенты (или Партнеры).ДинамическийСписок. Назовем его СписокДокументов.ЖурналДокументов.Взаиморасчеты или общую таблицу документов.СписокДокументов на форму вниз под основную таблицу контрагентов, чтобы визуализировать его.Список) создадим обработчик события ПриАктивизацииСтроки.В модуле формы напишем следующий код, который будет устанавливать отбор по текущему контрагенту в нашем динамическом списке документов:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Используем стандартную функцию БСП для установки отбора динамического списка
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
СписокДокументов,
"Контрагент",
ТекущиеДанные.Ссылка,
,
"ОтборПоКонтрагенту"
);
КонецЕсли;
КонецПроцедуры
Этот код использует стандартный общий модуль Библиотеки Стандартных Подсистем (БСП) ОбщегоНазначенияКлиентСервер, которая по умолчанию встроена в 1С:Управление торговлей 11. Такой подход гарантирует быструю и плавную работу интерфейса.
Чтобы сделать интерфейс еще более отзывчивым и полностью исключить даже микрозадержки при быстром пролистывании списка контрагентов, применим паттерн проектирования с использованием обработчика ожидания.
Суть метода заключается в том, что мы не будем обновлять список документов мгновенно при каждом переходе на новую строку. Вместо этого мы запустим таймер на 0.3 секунды. Если пользователь за это время перейдет на другую строку, таймер перезапустится. Список документов обновится только тогда, когда пользователь остановит свой выбор на конкретном контрагенте дольше чем на треть секунды.
Рассмотрим пример реализации этого механизма в модуле формы:
&НаКлиенте
Перем ТекущийКонтрагентДляФоновогоОбновления;
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Сохраняем ссылку на выделенного контрагента в переменную модуля
ТекущийКонтрагентДляФоновогоОбновления = ТекущиеДанные.Ссылка;
// Отключаем предыдущий обработчик ожидания, если он был запущен
ОтключитьОбработчикОжидания("ОбновитьСписокДокументовПоКонтрагенту");
// Подключаем однократный обработчик ожидания с задержкой 0.3 секунды
ПодключитьОбработчикОжидания("ОбновитьСписокДокументовПоКонтрагенту", 0.3, Истина);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьСписокДокументовПоКонтрагенту()
// Данная процедура выполнится только при остановке на строке
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
СписокДокументов,
"Контрагент",
ТекущийКонтрагентДляФоновогоОбновления,
,
"ОтборПоКонтрагенту"
);
КонецПроцедуры
Применение этого алгоритма значительно снижает нагрузку на сервер приложения и базу данных, обеспечивая максимально комфортную работу пользователей даже на слабых компьютерах или при работе через веб-клиент в облаке.