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