При доработке типовых конфигураций 1С (например, 1С:Бухгалтерия предприятия 3.0) часто возникает задача вывести в форму списка документов сводную информацию из строк документа — в частности, общую сумму НДС. На первый взгляд задача кажется тривиальной, однако при редактировании запроса динамического списка разработчики регулярно сталкиваются с падением производительности, декартовым перемножением строк или ошибками синтаксиса платформы. Разберем подробно, почему возникают эти проблемы и как их правильно решить.
Проанализируем распространенные подходы, которые приводят к некорректным результатам:
Товары и табличной частью Услуги через внутреннее соединение, из списка пропадут все документы, в которых заполнена только одна из табличных частей или которые вовсе не содержат строк.ЛЕВОЕ СОЕДИНЕНИЕ по ссылке, произойдет перемножение строк. Например, если в документе 3 строки с товарами и 2 строки с услугами, в результате соединения получится 6 строк, и простая группировка с суммированием выдаст кратно завышенную сумму НДС.ПОМЕСТИТЬ. Запрос списка должен состоять из одной инструкции ВЫБРАТЬ.Если требуется получить расчетную сумму непосредственно в запросе динамического списка без сброса настроек основной таблицы, используем коррелированные подзапросы в списке полей выборки. Такой подход исключает декартово произведение, так как итог по каждой табличной части вычисляется изолированно.
Посмотрим на пример формирования поля суммы НДС в запросе динамического списка:
ВЫБРАТЬ
ДокументПоступление.Ссылка КАК Ссылка,
ДокументПоступление.Номер КАК Номер,
ДокументПоступление.Дата КАК Дата,
ДокументПоступление.ВидОперации КАК ВидОперации,
ДокументПоступление.Организация КАК Организация,
ДокументПоступление.Контрагент КАК Контрагент,
ДокументПоступление.СуммаДокумента КАК СуммаДокумента,
ЕСТЬNULL((ВЫБРАТЬ СУММА(ТЧ_Товары.СуммаНДС)
ИЗ Документ.ПоступлениеТоваровУслуг.Товары КАК ТЧ_Товары
ГДЕ ТЧ_Товары.Ссылка = ДокументПоступление.Ссылка), 0)
+
ЕСТЬNULL((ВЫБРАТЬ СУММА(ТЧ_Услуги.СуммаНДС)
ИЗ Документ.ПоступлениеТоваровУслуг.Услуги КАК ТЧ_Услуги
ГДЕ ТЧ_Услуги.Ссылка = ДокументПоступление.Ссылка), 0) КАК СуммаНДС
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ДокументПоступление
Преимущества метода: запрос остается единым, сохраняется указание основной таблицы Документ.ПоступлениеТоваровУслуг, корректно работают стандартные отборы и сортировки платформы.
Ограничения: при интенсивной прокрутке больших списков документов подзапросы в секции ВЫБРАТЬ создают дополнительную нагрузку на СУБД.
Наиболее производительный вариант для динамических списков без изменения структуры метаданных — вычисление суммы НДС только для тех строк, которые физически отображаются на экране пользователя (обычно 20–50 записей за порцию).
Разберем реализацию по шагам:
0 КАК СуммаНДС).ПриПолученииДанныхНаСервере.Строки.Посмотрим на пример серверного кода обработки отображаемых строк:
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, УстановленныеНастройки, Строки)
МассивСсылок = Новый Массив;
Для Каждого КлючСтроки Из Строки.ПолучитьКлючи() Цикл
МассивСсылок.Добавить(КлючСтроки);
КонецЦикла;
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТаблицаСумм.Ссылка КАК Ссылка,
| СУММА(ТаблицаСумм.СуммаНДС) КАК СуммаНДС
|ИЗ
| (ВЫБРАТЬ
| Товары.Ссылка КАК Ссылка,
| Товары.СуммаНДС КАК СуммаНДС
| ИЗ
| Документ.ПоступлениеТоваровУслуг.Товары КАК Товары
| ГДЕ
| Товары.Ссылка В(&МассивСсылок)
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| Услуги.Ссылка КАК Ссылка,
| Услуги.СуммаНДС КАК СуммаНДС
| ИЗ
| Документ.ПоступлениеТоваровУслуг.Услуги КАК Услуги
| ГДЕ
| Услуги.Ссылка В(&МассивСсылок)) КАК ТаблицаСумм
|СГРУППИРОВАТЬ ПО
| ТаблицаСумм.Ссылка";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДанныеСтроки = Строки[Выборка.Ссылка];
Если ДанныеСтроки <> Неопределено Тогда
ДанныеСтроки.Данные["СуммаНДС"] = Выборка.СуммаНДС;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот способ гарантирует максимальную скорость отклика интерфейса, так как основной запрос динамического списка остается полностью типовым.
Если пользователям требуется сортировать список документов по сумме НДС или накладывать быстрые фильтры, оптимальным решением с точки зрения архитектуры является добавление отдельного реквизита шапки.
Порядок реализации:
СуммаНДС (тип Число(15, 2)).ПередЗаписью документа рассчитываем сумму по всем табличным частям и заполняем значение реквизита.Такой подход обеспечивает наивысшую скорость работы динамического списка и полноценную поддержку стандартных отборов и сортировок платформы 1С.