При работе с системой 1С:Предприятие, особенно при анализе оперативных данных, таких как взаиморасчеты с контрагентами, мы часто сталкиваемся с ситуацией, когда запросы на получение текущих остатков выдают неактуальные или некорректные данные. Это особенно заметно в течение рабочего дня, когда документы проводятся, но суммы долга или аванса не изменяются мгновенно, как мы ожидаем. Давайте рассмотрим, почему это происходит и как решить эту проблему.
Для того чтобы разобраться в корне проблемы, нам необходимо углубиться в то, как 1С хранит и обрабатывает данные в регистрах накопления – ключевом механизме для учета числовых показателей с привязкой ко времени. Мы проанализируем основные особенности, влияющие на расчет остатков.
Период. Это поле не просто дата, это полноценная дата и время совершения операции. Именно этот реквизит, в сочетании с Регистратором (ссылкой на документ, который создал движение), определяет точный момент времени, когда произошло изменение данных в регистре.Остатки регистра накопления. Ее основная задача – рассчитывать итоговые остатки ресурсов на определенный момент времени. Критически важно понимать, что по умолчанию виртуальная таблица Остатки строит свои итоги на начало секунды, которая указана в параметре Период. Это означает, что она *не включает* в расчет само указанное время. Например, если мы запрашиваем остатки на 06.05.2024 15:20:17, то будут учтены все движения, произошедшие *до* этого момента, но движения, случившиеся *в* 15:20:17 или позже, учтены не будут. Если же в параметр Период передается только дата без времени (например, 06.05.2024), остатки будут рассчитаны на начало этого дня (06.05.2024 00:00:00), не учитывая никаких движений, произошедших в течение дня.23:59:59 текущего дня. Это делается не случайно:
07.05.2024 00:00:00) все расчеты за предыдущий день будут закрыты и корректно сформированы.Именно из-за этой особенности движения за текущий день, "перенесенные" на 23:59:59, не попадают в остатки, запрошенные на любую дату/время *до* 23:59:59 этого дня. Это и приводит к той самой "каше", когда мы видим неактуальные данные в течение дня.
Чтобы лучше понять проблему, давайте проанализируем ситуацию, описанную автором в теме форума, и разберем, почему его запрос выдавал не тот результат, который ожидался.
Автор приводит пример: "ВКонДата указываю ДатаДокумента-1 (получается 06.05.24 15:20:17, сама реализация 06.05.24 15:20:18) долг показывает как 278 000 (от реализации 24.04.24, по которой была оплата 06.05.24 00:00:00)".
06.05.24 15:20:17: Почему не видна оплата?
Как мы уже выяснили, виртуальная таблица Остатки по умолчанию берет данные *на начало* указанной секунды. Если оплата в 06.05.24 00:00:00 была зафиксирована в регистре, то она должна была бы быть учтена. Однако, сообщение автора "движ в 23.59.59" является ключевым. Скорее всего, само движение по взаиморасчетам, связанное с оплатой, не было зафиксировано точно в 00:00:00, а было "перенесено" на 06.05.24 23:59:59. В таком случае, при запросе остатков на 15:20:17, эта оплата просто еще не попадает в расчеты, так как ее "официальное" время еще не наступило с точки зрения регистра накопления.
Поэтому долг продолжает отображаться как 278 000, игнорируя фактически произошедшую, но еще не "записанную" в регистр на текущий момент времени оплату. На самом деле, оплата была, но движение в регистре появится только в конце дня.
06.05.24 15:20:19: Почему остаток неправильно считается?
Автор говорит: "после 06.05.24 15:20:19 показывает долг как 278 000 + 235 000". Здесь мы видим, что новая реализация (235 000) уже учтена, так как ее время (15:20:18) уже прошло. Но при этом оплата (которая должна была уменьшить долг 278 000 до нуля) все еще не учтена. Это подтверждает нашу гипотезу о том, что движения, связанные с погашением долга, фиксируются в конце дня. Таким образом, запрос видит новую задолженность, но не видит ее погашения, создавая впечатление "конечного остатка, но без учета оплаты".
05.05.24 и 07.05.24: В чем причина?
Автор отмечает, что "на 05.05.24 и 07.05.24 долги отображаются корректно". Это логично, поскольку на 05.05.24 все движения до конца этого дня (включая 23:59:59) уже были учтены. Аналогично, на 07.05.24 (на начало дня) все движения за 06.05.24, включая те, что были зафиксированы в 23:59:59, уже гарантированно учтены в остатках. Проблема возникает именно *внутри* дня 06.05.24.
Для точного получения остатков, особенно в случае с движениями на конец дня или для учета внутридневных операций, нам необходимо использовать объект Граница в запросе к виртуальной таблице Остатки. Это наиболее корректный и надежный способ решить нашу проблему.
Граница?
Объект Граница – это специальный объект платформы 1С, который позволяет нам явно указать, включать ли заданное граничное значение в расчет остатков или нет. Он обладает параметром ВидГраницы, который может принимать значения ВидГраницы.Включая или ВидГраницы.Исключая. Это дает нам полный контроль над тем, как будет интерпретироваться указанный момент времени.
ВидГраницы.Включая для остатков на конец периода.
Если нам нужен остаток, который включает все движения за определенную дату, вплоть до последней секунды, включая движения, зафиксированные в 23:59:59, мы должны сформировать Границу на конец дня с видом Включая.
Пример запроса:
Запрос.Текст = "ВЫБРАТЬ
| ВзаиморасчетыСКонтрагентамиОстатки.Организация,
| ВзаиморасчетыСКонтрагентамиОстатки.Контрагент,
| ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток
|ИЗ
| РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(
| &ГраницаПериода,
| Организация = &Организация
| И Контрагент = &Контрагент) КАК ВзаиморасчетыСКонтрагентамиОстатки";
|
// Инициализация параметра ГраницаПериода:
Запрос.УстановитьПараметр("ГраницаПериода", Новый Граница(КонецДня(ДатаОтчета), ВидГраницы.Включая));
// Где ДатаОтчета - это та дата, на конец которой нам нужен остаток, например, 06.05.2024
Здесь функция КонецДня(ДатаОтчета) преобразует указанную дату в момент ДД.ММ.ГГГГ 23:59:59. Затем Новый Граница(..., ВидГраницы.Включая) указывает системе, что мы хотим учесть все движения, которые произошли *вплоть до* и *включая* этот момент времени. Таким образом, даже если движение по оплате было зафиксировано в 23:59:59, оно будет учтено.
Границы на момент времени документа.
Иногда нам требуется получить остатки, которые включают движения конкретного документа, и получить их *сразу после* проведения этого документа. В этом случае мы можем использовать специальный метод МоментВремени(), доступный для ссылок на документы, и передать его в объект Граница.
Пример инициализации параметра:
Запрос.УстановитьПараметр("ГраницаПериода", Новый Граница(СсылкаНаДокумент.МоментВремени(), ВидГраницы.Включая));
// Где СсылкаНаДокумент - это ссылка на документ, движения которого мы хотим учесть
Объект МоментВремени() является уникальным идентификатором, который сочетает в себе дату и время проведения документа с его уникальной ссылкой. Это обеспечивает максимально точное позиционирование во времени и гарантирует, что остатки будут рассчитаны именно после проведения данного документа, включая все его движения. Использование ВидГраницы.Включая в данном случае обеспечит учет движений самого документа.
Помимо объекта Граница, существуют и другие, менее предпочтительные, но иногда используемые методы для решения подобных задач, а также крайне важные шаги для диагностики, которые помогут нам понять истинную причину проблемы.
Исторически, до появления объекта Граница, в платформе 1С для включения движений текущей секунды или дня в расчет остатков часто использовали прием с добавлением одной секунды к параметру Период.
Например, если нам нужны остатки на 06.05.24 15:20:17, мы могли бы передать в запрос 06.05.24 15:20:18.
Запрос.УстановитьПараметр("ВКонДата", ДатаДокумента + 1); // Если ДатаДокумента - это объект типа Дата/Время
Мы должны понимать, что этот подход менее надежен, чем использование Границы. Он не всегда гарантирует включение всех движений, особенно при специфических конфигурациях, где движения могут записываться с точностью до миллисекунд или в случае, когда временные интервалы между движениями очень малы. К тому же, он не так явно выражает наше намерение, как Граница.
Виртуальная таблица ОстаткиИОбороты предоставляет более комплексную информацию, позволяя получить как начальные остатки, так и обороты за период, и конечные остатки. Она также поддерживает использование объекта Граница для своих параметров НачалоПериода и КонецПериода. Эта таблица может быть полезна, когда нам нужно не просто получить остаток на определенный момент, но и проанализировать динамику изменений за какой-либо интервал времени.
Пример использования:
Запрос.Текст = "ВЫБРАТЬ
| ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.Организация,
| ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.Контрагент,
| ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовНачальныйОстаток,
| ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовПриход,
| ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовРасход,
| ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовКонечныйОстаток
|ИЗ
| РегистрНакопления.ВзаиморасчетыСКонтрагентами.ОстаткиИОбороты(
| &НачалоПериода,
| &КонецПериода,
| ,
| ,
| Организация = &Организация
| И Контрагент = &Контрагент) КАК ВзаиморасчетыСКонтрагентамиОстаткиИОбороты";
|
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаОтчета));
Запрос.УстановитьПараметр("КонецПериода", Новый Граница(КонецДня(ДатаОтчета), ВидГраницы.Включая));
Здесь мы используем Границу для параметра КонецПериода, чтобы гарантировать включение всех движений до конца дня.
Мы настоятельно рекомендуем, как это было предложено в обсуждении на форуме (сообщение 3 и 8), всегда начинать диагностику с просмотра фактических движений регистра накопления. Это самый прямой способ понять, что именно и в какой момент времени было записано в базу данных.
Вы можете сделать это несколькими способами:
Период.Период и Регистратор для интересующих нас операций.Именно такой просмотр позволил автору темы (сообщение 4) быстро подтвердить причину проблемы: "спасибо действительно движ в 23.59.59". Эта информация является критически важной для принятия правильного решения.
Подведем итог нашему подробному анализу. Проблема некорректных остатков в течение дня в 1С является распространенной и часто связана с двумя ключевыми факторами:
23:59:59) в некоторых типовых конфигурациях, таких как УТ 10.Остатки, которая по умолчанию рассчитывает итоги на начало указанного момента времени, исключая его.Ключевое и наиболее надежное решение данной проблемы — это использование объекта Граница с параметром ВидГраницы.Включая при формировании запросов к виртуальным таблицам регистров накопления. Это позволяет нам явно указать системе, что мы хотим учесть все движения вплоть до и включая указанный момент времени.
Всегда помните о том, как работает поле Период в регистрах и о концепции "момента времени" при работе с запросами к виртуальным таблицам. Это глубокое понимание поможет вам не только избежать многих ошибок при анализе данных в 1С, но и эффективно диагностировать и решать возникающие проблемы с учетом.