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