При разработке и сопровождении конфигураций на платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с ситуацией, когда точка актуальности (ТА) на временной оси находится дальше последнего проведенного документа. В результате вызов метода ПолучитьДокументТА() возвращает пустое значение или приводит к ошибкам при расчете временных итогов регистров. Разберем подробно, как устроена ТА, почему она может не совпадать с реальными документами и как правильно обращаться к итогам регистров в программном коде.
Проанализируем природу точки актуальности в 1С 7.7. ТА — это не просто ссылка на документ, а универсальная отметка на временной оси базы данных, состоящая из даты, времени и внутренней позиции. Важно понимать, что ТА не обязана быть жестко привязана к существующему проведенному документу.
Выделим основные причины, почему время ТА может быть больше времени последнего проведенного документа:
УстановитьТАВ() или УстановитьТАНа().Рассмотрим фрагмент кода проверки возможности проведения документа из модуля формы, в котором возникает ошибка:
Если ДатаДок >= ПолучитьДатуТА() Тогда
РассчитатьРегистрыПО(ПолучитьДокументТА());
Иначе
РассчитатьРегистрыНа(ДатаДок);
КонецЕсли;
В приведенном коде метод РассчитатьРегистрыПО() ожидает ссылку на документ, позицию или дату. Если на момент вызова в точке актуальности нет проведенного документа, функция ПолучитьДокументТА() возвращает пустое значение, что вызывает исключение при расчете регистров.
Чтобы исключить зависимость расчета от наличия физического документа в точке актуальности, воспользуемся методами получения точной позиции или времени ТА:
ПолучитьПозициюТА() возвращает текстовое 32-символьное представление позиции на оси времени, которое всегда корректно воспринимается методом РассчитатьРегистрыПО().ПолучитьТА() возвращает дату и время точки актуальности.Посмотрим на исправленный вариант процедуры проверки проведения документа с контролем дублей и расчетом остатков:
Процедура ПроверкаНаПроведение()
Если Проведен() = 1 Тогда
Сообщить("Документ уже проведен!");
Возврат;
КонецЕсли;
ДокНеПроводится = 0;
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ВыгрузитьТабличнуюЧасть(ТЗ);
ТЗ.НоваяКолонка("Поз");
ТЗ.Заполнить(1, , , "Поз");
ТЗ.Свернуть("Товар", "Поз");
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
Если ТЗ.Поз > 1 Тогда
Сообщить("В табличной части дублируется Товар " + ТЗ.Товар);
ДокНеПроводится = 1;
КонецЕсли;
КонецЦикла;
Если ДокНеПроводится = 1 Тогда
Сообщить("Документ НЕ может быть проведен!");
Возврат;
КонецЕсли;
Если Склад.Выбран() = 0 Тогда
Сообщить("Не указан склад откуда производится перемещение!");
Возврат;
КонецЕсли;
Рег = СоздатьОбъект("Регистр.ОстаткиТоваров");
Рег.ВременныйРасчет();
Если (ПустоеЗначение(ТекущийДокумент()) = 0) И (ДатаДок < ПолучитьДатуТА()) Тогда
// Документ уже записан в прошлом, рассчитываем на момент перед ним
РассчитатьРегистрыНа(ТекущийДокумент());
Иначе
Если ДатаДок >= ПолучитьДатуТА() Тогда
// Гарантированный расчет по точке актуальности без ошибок
РассчитатьРегистрыПО(ПолучитьПозициюТА());
Иначе
РассчитатьРегистрыНа(ДатаДок);
КонецЕсли;
КонецЕсли;
// Получение остатков и дальнейшая бизнес-логика
КонецПроцедуры
Разберем типичное заблуждение при отладке времени документа. При вызове в отладчике конструкции вида ПолучитьВремя(ПолучитьДокументТА()) платформа возвращает не время документа, а текущее системное время компьютера.
В глобальном контексте синтаксис функции выглядит следующим образом: ПолучитьВремя(<Часы>, <Минуты>, <Секунды>). Она заполняет переданные переменные текущим временем операционной системы. Чтобы узнать время конкретного документа, необходимо использовать контекстный метод объекта: Док.ПолучитьВремя(Часы, Минуты, Секунды).
Если ТА «убежала» вперед из-за распроведенных документов и требуется вернуть ее на последний реально проведенный документ, выполним следующие шаги: