Почему смещается точка актуальности в 1С 7.7 и как правильно рассчитывать регистры по ТА?

Программист 1С v7.7 Управленческий учет IT и автоматизация бизнеса
← На главную

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

Причины смещения точки актуальности и ее автономность

Проанализируем природу точки актуальности в 1С 7.7. ТА — это не просто ссылка на документ, а универсальная отметка на временной оси базы данных, состоящая из даты, времени и внутренней позиции. Важно понимать, что ТА не обязана быть жестко привязана к существующему проведенному документу.

Выделим основные причины, почему время ТА может быть больше времени последнего проведенного документа:

  1. Отмена проведения или распроведение документов: если крайний документ базы был проведен (что сдвинуло ТА вперед), а затем его проведение отменили или документ перенесли/удалили, платформа 1С 7.7 автоматически не возвращает ТА назад. Точка актуальности остается на прежнем месте, но реального документа в этой точке уже нет.
  2. Ручной или программный сдвиг ТА: пользователь или администратор может вручную сдвинуть ТА вперед через журнал документов или меню. Также сдвиг может выполняться вызовами функций встроенного языка УстановитьТАВ() или УстановитьТАНа().
  3. Работа с документами других видов: в базе данных могут существовать другие виды документов или последовательности, движения которых сместили общую временную ось вперед, даже если они не отображаются в текущем специализированном журнале.

Ошибки при расчете регистров и получение остатков

Рассмотрим фрагмент кода проверки возможности проведения документа из модуля формы, в котором возникает ошибка:


Если ДатаДок >= ПолучитьДатуТА() Тогда
    РассчитатьРегистрыПО(ПолучитьДокументТА());
Иначе
    РассчитатьРегистрыНа(ДатаДок);
КонецЕсли;

В приведенном коде метод РассчитатьРегистрыПО() ожидает ссылку на документ, позицию или дату. Если на момент вызова в точке актуальности нет проведенного документа, функция ПолучитьДокументТА() возвращает пустое значение, что вызывает исключение при расчете регистров.

Решение 1: Использование методов ПолучитьТА() и ПолучитьПозициюТА()

Чтобы исключить зависимость расчета от наличия физического документа в точке актуальности, воспользуемся методами получения точной позиции или времени ТА:

  1. Расчет по позиции ТА: функция ПолучитьПозициюТА() возвращает текстовое 32-символьное представление позиции на оси времени, которое всегда корректно воспринимается методом РассчитатьРегистрыПО().
  2. Расчет по дате/времени ТА: функция ПолучитьТА() возвращает дату и время точки актуальности.

Посмотрим на исправленный вариант процедуры проверки проведения документа с контролем дублей и расчетом остатков:


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

Особенность работы глобальной функции ПолучитьВремя()

Разберем типичное заблуждение при отладке времени документа. При вызове в отладчике конструкции вида ПолучитьВремя(ПолучитьДокументТА()) платформа возвращает не время документа, а текущее системное время компьютера.

В глобальном контексте синтаксис функции выглядит следующим образом: ПолучитьВремя(<Часы>, <Минуты>, <Секунды>). Она заполняет переданные переменные текущим временем операционной системы. Чтобы узнать время конкретного документа, необходимо использовать контекстный метод объекта: Док.ПолучитьВремя(Часы, Минуты, Секунды).

Решение 2: Корректировка положения ТА в информационной базе

Если ТА «убежала» вперед из-за распроведенных документов и требуется вернуть ее на последний реально проведенный документ, выполним следующие шаги:

  1. Запустим 1С:Предприятие 7.7 в монопольном режиме.
  2. Откроем общий журнал документов.
  3. Найдем последний фактически проведенный документ базы данных.
  4. Нажмем правой кнопкой мыши по документу и выберем пункт меню «Установить ТА на документ».
  5. При наличии систематических расхождений во временных итогах рекомендуется выполнить процедуры «Пересчет итогов» и «Тестирование и исправление ИБ» через режим «Конфигуратор».
← На главную