Как получить стоимость основных средств и амортизацию помесячно в запросе 1С при отсутствии оборотов?

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

При разработке отчетов по основным средствам (ОС) программисты часто сталкиваются с задачей вывода балансовой стоимости и накопленной амортизации на конец каждого месяца за определенный период. Казалось бы, для этого идеально подходит виртуальная таблица РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты с периодичностью Месяц. Однако при построении такого запроса за большой интервал времени обнаруживается неприятная особенность: за те месяцы, в которых по основному средству не было никаких движений (оборотов), данные в отчет вообще не попадают или выводятся некорректно.

В рамках этой статьи мы подробно разберем, почему виртуальная таблица остатков и оборотов ведет себя подобным образом, проанализируем причины возникновения проблемы и рассмотрим три надежных способа ее решения: с помощью построения сетки периодов в чистом запросе, через связи наборов данных в СКД и с использованием механизма дополнения периодов компоновки данных.

Выясняем причину: особенности работы таблицы ОстаткиИОбороты

Для начала проанализируем, почему простой запрос к виртуальной таблице ОстаткиИОбороты с периодичностью Месяц дает сбой. Платформа 1С:Предприятие оптимизирует запросы к базе данных. Виртуальная таблица не хранит остатки на каждую секунду или на каждый день для каждого аналитического разреза (в нашем случае — субконто ОсновныеСредства). Остатки рассчитываются динамически на основе реальных движений (записей регистра).

Если по конкретному основному средству в мае и июне не было никаких бухгалтерских проводок (например, не начислялась амортизация, не было модернизации или списания), то платформа считает эти периоды "пустыми" для данного субконто. В результате в выборке за май и июнь по этому ОС не будет ни одной строки. Настройка параметра виртуальной таблицы МетодДополнения в значение ДвиженияИГраницыПериода решает проблему лишь частично — она принудительно выведет остатки только на начало и на конец всего выбранного периода отчета, но проигнорирует промежуточные "тихие" месяцы.

Кроме того, при левом соединении двух таблиц (например, стоимости со счета 01 и амортизации со счета 02) по полям Субконто1 и Период возникает ситуация, когда периоды в двух таблицах не совпадают. Если по счету 02 обороты были (начислялась амортизация), а по счету 01 оборотов не было, левое соединение по равенству периодов отсечет или исказит конечные данные.

Решение 1. Формирование сетки периодов в "чистом" запросе (без СКД)

Если мы разрабатываем отчет на базе универсального отчета или выгружаем данные программно в таблицу значений без использования СКД, нам необходимо решить задачу генерации непрерывной временной шкалы (календаря) непосредственно в теле запроса.

Разберем этот алгоритм по шагам:

  1. Создадим временную таблицу, содержащую все уникальные месяцы из выбранного периода.
  2. Получим список всех основных средств, которые стояли на учете в этом периоде.
  3. Выполним перекрестное (декартово) соединение таблицы месяцев и таблицы ОС. В результате мы получим полную матрицу: для каждого ОС будет создана строка на каждый месяц периода.
  4. Соединим полученную матрицу левым соединением с реальными остатками по счетам 01 и 02. Для месяцев без движений мы получим значение NULL, которое затем программно заполним остатком из предыдущего периода.

Рассмотрим пример реализации такого запроса:


// Шаг 1: Получаем сетку месяцев из производственного календаря (или другого источника дат)
ВЫБРАТЬ РАЗЛИЧНЫЕ
	НАЧАЛОПЕРИОДА(Календарь.Дата, МЕСЯЦ) КАК МесяцПериода
ПОМЕСТИТЬ ВТ_Периоды
ИЗ
	РегистрСведений.ДанныеПроизводственногоКалендаря КАК Календарь
ГДЕ
	Календарь.Дата МЕЖДУ &НачПериода И &КонПериода
;

// Шаг 2: Получаем список всех ОС, у которых были остатки на счетах учета
ВЫБРАТЬ РАЗЛИЧНЫЕ
	ХозрасчетныйОстатки.Субконто1 КАК ОсновноеСредство
ПОМЕСТИТЬ ВТ_ОсновныеСредства
ИЗ
	РегистрБухгалтерии.Хозрасчетный.Остатки(&НачПериода, Счет В (&Счет01, &Счет02), &ВидыСубконтоОС, Организация = &Организация) КАК ХозрасчетныйОстатки
;

// Шаг 3: Строим декартово произведение (ОС * Месяц)
ВЫБРАТЬ
	ВТ_Периоды.МесяцПериода КАК Период,
	ВТ_ОсновныеСредства.ОсновноеСредство КАК ОсновноеСредство
ПОМЕСТИТЬ ВТ_Матрица
ИЗ
	ВТ_Периоды КАК ВТ_Периоды
		СОЕДИНЕНИЕ ВТ_ОсновныеСредства КАК ВТ_ОсновныеСредства
		ПО ИСТИНА
;

// Шаг 4: Соединяем матрицу с остатками на конец каждого месяца
ВЫБРАТЬ
	Матрица.Период КАК Период,
	Матрица.ОсновноеСредство КАК ОсновноеСредство,
	ЕСТЬNULL(Остатки01.СуммаКонечныйОстатокДт, 0) КАК Стоимость,
	ЕСТЬNULL(Остатки02.СуммаКонечныйОстатокКт, 0) КАК Амортизация,
	ЕСТЬNULL(Остатки01.СуммаКонечныйОстатокДт, 0) - ЕСТЬNULL(Остатки02.СуммаКонечныйОстатокКт, 0) КАК ОстаточнаяСтоимость
ИЗ
	ВТ_Матрица КАК Матрица
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачПериода, &КонПериода, Месяц, , Счет = &Счет01, &ВидыСубконтоОС, Организация = &Организация) КАК Остатки01
		ПО Матрица.ОсновноеСредство = Остатки01.Субконто1
			И КОНЕЦПЕРИОДА(Матрица.Период, МЕСЯЦ) = КОНЕЦПЕРИОДА(Остатки01.Период, МЕСЯЦ)
		
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачПериода, &КонПериода, Месяц, , Счет = &Счет02, &ВидыСубконтоОС, Организация = &Организация) КАК Остатки02
		ПО Матрица.ОсновноеСредство = Остатки02.Субконто1
			И КОНЕЦПЕРИОДА(Матрица.Период, МЕСЯЦ) = КОНЕЦПЕРИОДА(Остатки02.Период, МЕСЯЦ)
УПОРЯДОЧИТЬ ПО
	Период,
	ОсновноеСредство

Обратите внимание на конструкцию КОНЕЦПЕРИОДА(..., МЕСЯЦ) в условиях связи. Как справедливо заметили участники обсуждения, даты периодов в разных виртуальных таблицах могут незначительно отличаться по времени (из-за секунд проведения регламентных операций), поэтому приведение всех сопоставляемых дат к концу месяца гарантирует корректность соединения таблиц.

Решение 2. Использование связей наборов данных в СКД

Если отчет разрабатывается в Системе компоновки данных (СКД), то проблема пустых периодов и отсутствующих оборотов решается гораздо проще и элегантнее. Наиболее надежный способ — разделение запроса на два отдельных набора данных с последующей настройкой связи между ними.

Рассмотрим этот алгоритм настройки в СКД по шагам:

Шаг 1. Создание первого набора данных (НаборДанных1 - Источник):

В этом наборе данных мы получаем только "скелет" нашего отчета — список основных средств и периодов, за которые нам нужно вывести информацию. Запрос может выглядеть следующим образом:


ВЫБРАТЬ
	ВТ_Периоды.МесяцПериода КАК Период,
	ВТ_ОсновныеСредства.ОсновноеСредство КАК ОсновноеСредство
ИЗ
	ВТ_Периоды КАК ВТ_Периоды
		СОЕДИНЕНИЕ ВТ_ОсновныеСредства КАК ВТ_ОсновныеСредства
		ПО ИСТИНА

Шаг 2. Создание второго набора данных (НаборДанных2 - Приемник):

Второй набор данных будет извлекать актуальные остатки по счетам 01 и 02 на конкретную дату. Обратите внимание, что мы используем таблицу Остатки, а не ОстаткиИОбороты, так как нам нужен срез на определенный момент времени:


ВЫБРАТЬ
	ХозрасчетныйОстатки.Субконто1 КАК ОсновноеСредство,
	ЕСТЬNULL(ХозрасчетныйОстатки.СуммаОстатокДт, 0) КАК Стоимость,
	ЕСТЬNULL(АмортизацияОстатки.СуммаОстатокКт, 0) КАК Амортизация
ИЗ
	РегистрБухгалтерии.Хозрасчетный.Остатки(&ПериодГраница, Счет = &Счет01, &ВидыСубконтоОС, Организация = &Организация) КАК ХозрасчетныйОстатки
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(&ПериодГраница, Счет = &Счет02, &ВидыСубконтоОС, Организация = &Организация) КАК АмортизацияОстатки
		ПО ХозрасчетныйОстатки.Субконто1 = АмортизацияОстатки.Субконто1

Шаг 3. Настройка связей наборов данных:

Переходим на вкладку Связи наборов данных в схеме компоновки и добавляем новую строку со следующими параметрами:

При таком подходе СКД сама выполнит запрос из второго набора данных для каждой строки первого набора, передавая дату конца текущего месяца в качестве параметра получения остатков. Это полностью исключит проблему "пропавших" месяцев.

Решение 3. Использование механизма "Дополнение периода" в СКД

Существует еще один штатный механизм СКД, позволяющий заполнять временные пропуски в данных без создания дополнительных наборов данных. Это функция дополнения периодов роли поля компоновки.

Чтобы воспользоваться этим функционалом, выполним следующие шаги:

  1. В запросе к таблице ОстаткиИОбороты выберем поле Период (или ПериодМесяц).
  2. В окне конструктора схемы СКД перейдем на вкладку Наборы данных.
  3. Найдем поле Период, откроем его свойства в колонке Роль.
  4. В открывшемся окне установим флаг Дополнение периода.
  5. В поле Тип дополнения выберем значение Месяц.
  6. В качестве параметров начала и конца периода укажем наши стандартные параметры отчета, например &НачалоПериода и &КонецПериода.

После этой настройки, когда СКД будет формировать группировку по полю Период в структуре отчета, она автоматически сгенерирует строки для всех недостающих месяцев и спроецирует (продублирует) на них последние известные остатки из предыдущих периодов.

Важные нюансы учета Основных Средств (счета 01 и 02)

При работе с остатками основных средств необходимо всегда помнить о специфике проведения регламентных операций в закрытии периода:

Мы подробно разобрали причины возникновения проблемы с выводом остатков по неактивным периодам и изучили три надежных метода борьбы с этой особенностью платформы. Выбор конкретного метода зависит от архитектуры вашего решения и требований к производительности системы.

← На главную