Как правильно настроить отборы по субконто в запросах к регистру бухгалтерии 1С

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При работе с механизмами бухгалтерского учета в 1С начинающие разработчики часто сталкиваются с трудностями при получении оборотов по счетам с детальной аналитикой (субконто). Типичная ситуация: требуется получить обороты между дебетом одного счета и кредитом другого (например, Дт 26 - Кт 71.01 или Дт 91.02 - Кт 71.01), ограничив выборку конкретной статьей затрат или прочих расходов. Если написать простой запрос без указания параметров аналитики, система вернет общую сумму по счетам, проигнорировав субконто.

В этой статье мы подробно разберем, как устроена виртуальная таблица ОборотыДтКт, почему важно правильно заполнять параметры субконто и как объединить несколько запросов в один оптимальный пакет для ускорения работы системы.

Выясняем причину: почему исходные запросы работали неверно

Проанализируем исходный запрос, который написал автор темы на форуме:


"ВЫБРАТЬ 
| ХозрасчетныйОборотыДтКт.СуммаОборот КАК Наименование 
|ИЗ 
| РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалаПериода, &КонецПериода, , СчетДт = &СчетДт26, , СчетКт = &СчетКт71, , ) КАК ХозрасчетныйОборотыДтКт"

В данном запросе параметры виртуальной таблицы переданы следующим образом:

  1. &НачалаПериода — начало интервала.
  2. &КонецПериода — конец интервала.
  3. 3-й параметр (СубконтоДт) — опущен (пустое значение).
  4. 4-й параметр (УсловиеДт) — передано условие по счету дебета (СчетДт = &СчетДт26).
  5. 5-й параметр (СубконтоКт) — опущен.
  6. 6-й параметр (УсловиеКт) — передано условие по счету кредита (СчетКт = &СчетКт71).
  7. 7-й и 8-й параметры (Условия по субконто) — опущены.

При такой структуре запроса база данных вернет общий оборот между счетами 26 и 71 за указанный период, абсолютно игнорируя конкретную аналитику «Командировочные расходы». Нам необходимо переопределить параметры запроса, чтобы наложить жесткий фильтр на субконто дебета.

Разбираем по шагам: как работают параметры Субконто в виртуальной таблице

Для правильного наложения отбора по аналитике в виртуальной таблице ОборотыДтКт необходимо задействовать два взаимосвязанных параметра:

Важный нюанс позиционирования субконто: в плане счетов «Хозрасчетный» на разных счетах субконто могут располагаться на разных позициях. Например, на счете 26 («Общехозяйственные расходы») субконто СтатьиЗатрат обычно является первым (Субконто1). А на счете 20.01 («Основное производство») первым субконто идет Номенклатурные группы, а СтатьиЗатрат находятся на второй позиции (Субконто2).

Если мы передадим вид субконто СтатьиЗатрат в 3-й параметр (СубконтоДт), платформа 1С автоматически «поднимет» эту аналитику и сделает ее доступной в поле СубконтоДт1 в рамках этого запроса, независимо от того, на какой физической позиции (первой или второй) она находится на самом счете в плане счетов. Это избавляет разработчика от необходимости выяснять точный индекс субконто для каждого конкретного счета.

Пошаговое решение для каждого из трех вариантов

Рассмотрим подробнее, как должны выглядеть отборы для каждой из трех задач автора.

Задача 1: Счет Дт 26 Кт 71.01. Аналитика по Дт: Командировочные расходы

Для счета 26 аналитика «Командировочные расходы» хранится в справочнике СтатьиЗатрат. Вид субконто — ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат.

Запрос должен выглядеть следующим образом:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ 
|	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот 
|ИЗ 
|	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
|		&НачалоПериода, 
|		&КонецПериода, 
|		, 
|		СчетДт = &СчетДт26, 
|		ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат), 
|		СчетКт = &СчетКт71, 
|		, 
|		СубконтоДт1 = &КомандировочныеРасходы
|	) КАК ХозрасчетныйОборотыДтКт";

Запрос.УстановитьПараметр("НачалоПериода", Объект.НачалаПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецДня(Объект.КонецПериода));
Запрос.УстановитьПараметр("СчетДт26", ПланыСчетов.Хозрасчетный.ОбщехозяйственныеРасходы);
// Рекомендуется искать конкретный субсчет 71.01 по коду, если его нет в предопределенных
Запрос.УстановитьПараметр("СчетКт71", ПланыСчетов.Хозрасчетный.НайтиПоКоду("71.01")); 
Запрос.УстановитьПараметр("КомандировочныеРасходы", Объект.СтатьяКомандировочныеРасходы);

Задача 2: Счет Дт 91.02 Кт 71.01. Аналитика по Дт: Прочие внереализационные расходы

Для счета 91.02 аналитика ведется по субконто типа ПрочиеДоходыИРасходы. Вид субконто — ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ПрочиеДоходыИРасходы.

Исправленный вариант запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ 
|	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот 
|ИЗ 
|	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
|		&НачалоПериода, 
|		&КонецПериода, 
|		, 
|		СчетДт = &СчетДт91, 
|		ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.ПрочиеДоходыИРасходы), 
|		СчетКт = &СчетКт71, 
|		, 
|		СубконтоДт1 = &ПрочиеРасходы
|	) КАК ХозрасчетныйОборотыДтКт";

Запрос.УстановитьПараметр("НачалоПериода", Объект.НачалаПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецДня(Объект.КонецПериода));
Запрос.УстановитьПараметр("СчетДт91", ПланыСчетов.Хозрасчетный.ПрочиеРасходы);
Запрос.УстановитьПараметр("СчетКт71", ПланыСчетов.Хозрасчетный.НайтиПоКоду("71.01")); 
Запрос.УстановитьПараметр("ПрочиеРасходы", Объект.СтатьяПрочиеРасходы);

Задача 3: Счет Дт 20.01 Кт 71.01. Аналитика по Дт: Командировочные расходы

Счет 20.01, как и счет 26, использует вид субконто СтатьиЗатрат. Несмотря на то, что в структуре счета 20.01 статьи затрат находятся на втором месте, благодаря указанию вида субконто в параметрах таблицы мы можем обращаться к нему через универсальное имя СубконтоДт1.

Код запроса будет выглядеть так:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ 
|	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот 
|ИЗ 
|	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
|		&НачалоПериода, 
|		&КонецПериода, 
|		, 
|		СчетДт = &СчетДт20, 
|		ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат), 
|		СчетКт = &СчетКт71, 
|		, 
|		СубконтоДт1 = &КомандировочныеРасходы
|	) КАК ХозрасчетныйОборотыДтКт";

Запрос.УстановитьПараметр("НачалоПериода", Объект.НачалаПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецДня(Объект.КонецПериода));
Запрос.УстановитьПараметр("СчетДт20", ПланыСчетов.Хозрасчетный.ОсновноеПроизводство);
Запрос.УстановитьПараметр("СчетКт71", ПланыСчетов.Хозрасчетный.НайтиПоКоду("71.01")); 
Запрос.УстановитьПараметр("КомандировочныеРасходы", Объект.СтатьяКомандировочныеРасходы);

Оптимальное решение: объединение в один запрос

Выполнение трех отдельных запросов к базе данных последовательно — неоптимальная практика, которая создает избыточную нагрузку на СУБД. Проанализируем ситуацию: все данные выводятся в один макет. Мы можем объединить наши запросы с помощью конструкции ОБЪЕДИНИТЬ ВСЕ.

Чтобы при обработке результата мы понимали, к какому именно счету относится полученная сумма, добавим в запрос текстовое поле-идентификатор. Посмотрим на итоговый оптимизированный пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	""Дт 26 Кт 71.01"" КАК ИдентификаторСтроки,
|	ХозрасчетныйОборотыДтКт.СуммаОборот КАК Сумма
|ИЗ
|	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
|		&НачалоПериода,
|		&КонецПериода,
|		,
|		СчетДт = &СчетДт26,
|		ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат),
|		СчетКт = &СчетКт71,
|		,
|		СубконтоДт1 = &КомандировочныеРасходы
|	) КАК ХозрасчетныйОборотыДтКт
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	""Дт 91.02 Кт 71.01"",
|	ХозрасчетныйОборотыДтКт.СуммаОборот
|ИЗ
|	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
|		&НачалоПериода,
|		&КонецПериода,
|		,
|		СчетДт = &СчетДт91,
|		ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.ПрочиеДоходыИРасходы),
|		СчетКт = &СчетКт71,
|		,
|		СубконтоДт1 = &ПрочиеРасходы
|	) КАК ХозрасчетныйОборотыДтКт
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	""Дт 20.01 Кт 71.01"",
|	ХозрасчетныйОборотыДтКт.СуммаОборот
|ИЗ
|	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
|		&НачалоПериода,
|		&КонецПериода,
|		,
|		СчетДт = &СчетДт20,
|		ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат),
|		СчетКт = &СчетКт71,
|		,
|		СубконтоДт1 = &КомандировочныеРасходы
|	) КАК ХозрасчетныйОборотыДтКт";

// Установка общих параметров
Запрос.УстановитьПараметр("НачалоПериода", Объект.НачалаПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецДня(Объект.КонецПериода));

// Установка параметров счетов
Запрос.УстановитьПараметр("СчетДт26", ПланыСчетов.Хозрасчетный.ОбщехозяйственныеРасходы);
Запрос.УстановитьПараметр("СчетДт20", ПланыСчетов.Хозрасчетный.ОсновноеПроизводство);
Запрос.УстановитьПараметр("СчетДт91", ПланыСчетов.Хозрасчетный.ПрочиеРасходы);
Запрос.УстановитьПараметр("СчетКт71", ПланыСчетов.Хозрасчетный.НайтиПоКоду("71.01"));

// Установка параметров аналитик (ссылки на элементы справочников)
Запрос.УстановитьПараметр("КомандировочныеРасходы", Объект.СтатьяКомандировочныеРасходы);
Запрос.УстановитьПараметр("ПрочиеРасходы", Объект.СтатьяПрочиеРасходы);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	// Здесь мы можем выводить данные в макет, 
	// ориентируясь на поле Выборка.ИдентификаторСтроки
	Если Выборка.ИдентификаторСтроки = "Дт 26 Кт 71.01" Тогда
		// Код вывода для первого условия
	ИначеЕсли Выборка.ИдентификаторСтроки = "Дт 91.02 Кт 71.01" Тогда
		// Код вывода для второго условия
	ИначеЕсли Выборка.ИдентификаторСтроки = "Дт 20.01 Кт 71.01" Тогда
		// Код вывода для третьего условия
	КонецЕсли;
КонецЦикла;

Использование единого пакетного запроса позволяет выполнить все расчеты на стороне СУБД за одно обращение. Это значительно повышает производительность отчета, особенно при работе в клиент-серверном варианте базы данных.

← На главную