Вопрос о том, какой параметр передавать в виртуальную таблицу остатков при проведении документа, является одним из самых обсуждаемых среди кандидатов на звание «1С:Специалист по платформе». Существует устойчивая конструкция, которую часто рекомендуют преподаватели (включая Павла Чистова): Запрос.УстановитьПараметр("МоментВремени", ? (РежимПроведения = РежимПроведенияДокумента.Оперативный, Неопределено, МоментВремени));. Разберем подробно, почему это важно, как это работает на уровне платформы и в каких случаях данная конструкция обязательна, а в каких — избыточна.
Для того чтобы понять суть оптимизации, проанализируем, как система 1С:Предприятие работает с итогами регистров накопления. Платформа хранит актуальные итоги в специальной таблице на «конец времен» (обычно это 1 ноября 3999 года). Когда мы обращаемся к виртуальной таблице остатков без указания периода (или передаем Неопределено), платформа выполняет максимально простой SQL-запрос к таблице текущих итогов.
Если же мы передаем конкретный МоментВремени, СУБД приходится выполнять более сложную работу. Даже если документ проводится «сейчас», система не всегда может просто взять итоги из таблицы. Ей нужно убедиться, что между указанной датой и текущим моментом нет других движений. В случае, если дата документа меньше текущих итогов, СУБД берет актуальные остатки и «отматывает» их назад, вычитая движения, произошедшие в интервале. Таким образом, использование Неопределено при оперативном проведении — это прямой путь к самым актуальным данным с минимальной нагрузкой на сервер базы данных.
Рассмотрим ситуацию, которая часто встречается в реальной практике и проверяется на экзамене. Представим, что в базе уже существует документ, ошибочно введенный будущим числом (например, завтрашней датой), который полностью списал остаток товара Спички.
Если мы проводим текущий документ оперативно и используем в запросе МоментВремени текущего документа, запрос вернет нам положительный остаток, так как он «не видит» движений будущего документа. В результате мы разрешим списание, и на завтрашний день в базе образуется отрицательный остаток.
Проанализируем, что изменится при использовании Неопределено. В этом случае запрос вернет остатки на самый конец времен, учитывая документ «из будущего». Система увидит, что товара на самом деле нет, и выдаст ошибку. Это и есть правильная логика оперативного контроля остатков: мы не должны позволять текущим действиям создавать проблемы в будущем периоде.
В так называемой «старой» методике проведения, когда контроль остатков выполняется в модуле объекта до того, как документ записал свои движения в регистр, использование вышеупомянутой конструкции является классическим и наиболее правильным подходом.
Рассмотрим пример кода, который обычно ожидается от кандидата на экзамене при реализации старой методики:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОстаткиТоваровОстатки.КоличествоОстаток КАК Остаток
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Остатки(&МоментВремени, Номенклатура = &Номенклатура) КАК ОстаткиТоваровОстатки";
// При оперативном проведении берем самые актуальные остатки (Неопределено)
// При неоперативном — на момент времени документа
ГраницаОстатков = ?(РежимПроведения = РежимПроведенияДокумента.Оперативный, Неопределено, МоментВремени());
Запрос.УстановитьПараметр("МоментВремени", ГраницаОстатков);
Запрос.УстановитьПараметр("Номенклатура", СсылкаНаНоменклатуру);
// Далее следует логика проверки остатков и формирования движений
...
КонецПроцедуры
Важно помнить: МоментВремени включает в себя дату и ссылку на документ. При получении остатков на МоментВремени данные самого документа-регистратора не включаются в расчет. Это позволяет нам проверять остатки «до того как мы что-то списали».
Выясним, как меняется ситуация при использовании «новой» методики. В этой методике документ сначала записывает свои движения (часто с предварительной очисткой старых записей), а затем одним запросом получает все возникшие отрицательные остатки по регистру.
Здесь конструкция с Неопределено становится некорректной. Поскольку наши движения уже находятся в базе, нам нужно проверить остатки именно включая наш документ. Для этого используется объект Граница.
Посмотрим на пример установки параметров для новой методики:
// Для новой методики мы всегда используем Границу, включая момент времени нашего документа
ПараметрПериод = Новый Граница(МоментВремени(), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", ПараметрПериод);
Почему здесь нельзя использовать Неопределено? Потому что если после нашего документа (в будущем) есть другие движения, Неопределено покажет итог с их учетом. А нам в новой методике важно понять: не ушел ли остаток в минус именно после нашего списания. Если мы используем Неопределено, мы можем ошибочно запретить проведение документа, который сам по себе в минус не уводит, но в будущем кто-то другой уже создал дефицит.
Подведем итоги и сформируем конкретные рекомендации для успешной сдачи экзамена:
РежимПроведения. Это показывает экзаменатору ваше понимание работы итогов и механизмов оперативной отметки времени. Передача Неопределено при оперативном режиме — это эталонный вариант.Неопределено. Используйте только Новый Граница(МоментВремени(), ВидГраницы.Включая). Использование Неопределено здесь будет логической ошибкой.Неопределено и МоментВремени (при их близости к актуальной дате) нивелируется, теоретическое обоснование через прямое чтение таблицы итогов остается весомым аргументом в пользу Неопределено.Таким образом, использование Неопределено — это не просто «приколюха из 8.2», а осознанный инструмент управления актуальностью данных. На экзамене «1С:Специалист по платформе» грамотное применение этого инструмента может стать решающим фактором для получения высокой оценки, подтверждающей вашу квалификацию как разработчика.