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