Как программно установить фиксированное время в документах 1С 8.3?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

В процессе автоматизации учета в 1С:Бухгалтерия предприятия 3.0 часто возникает задача привести время загруженных документов к единому стандарту. Например, банковские выписки (поступления и списания) должны иметь фиксированное время 09:00:00, чтобы они корректно отражались в начале операционного дня. В данной статье мы подробно разберем, как реализовать эту задачу, исправим типичные ошибки новичков и рассмотрим наиболее оптимальные способы работы с объектами даты.

Разбор типичной ошибки: Почему не работает метод УстановитьВремя?

Проанализируем ситуацию, с которой часто сталкиваются начинающие разработчики. При попытке вызвать метод УстановитьВремя(9, 0, 0) система выдает ошибку: «Слишком много фактических параметров». Это происходит потому, что метод УстановитьВремя() встроенного языка 1С предназначен не для установки произвольных часов и минут, а для автоматического позиционирования документа в пределах суток.

Синтаксис этого метода выглядит следующим образом:

Объект.УстановитьВремя(РежимОпределенияВремени, ИспользоватьЖурналы);

В качестве первого параметра РежимОпределенияВремени используются значения системного перечисления РежимОпределенияВремени:

  1. Первым — устанавливает время 00:00:00.
  2. Последним — устанавливает время 23:59:59.
  3. ВТечениеДня — распределяет документы равномерно.

Следовательно, для установки произвольного времени (например, ровно 9 утра) этот метод не подходит. Нам необходимо напрямую изменять свойство Дата документа-объекта.

Способ №1: Использование конструктора даты

Самый понятный способ — это собрать новую дату, сохранив текущий день, месяц и год, но заменив значения времени. Рассмотрим пример реализации в цикле обработки:


Пока Выборка.Следующий() Цикл
    ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
    ТекущаяДатаДокумента = ДокументОбъект.Дата;
    
    // Формируем новую дату с нужным временем
    ДокументОбъект.Дата = Дата(Год(ТекущаяДатаДокумента), 
                               Месяц(ТекущаяДатаДокумента), 
                               День(ТекущаяДатаДокумента), 
                               9, 0, 0);
    
    ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;

Этот метод надежен и легко читается, однако он требует вызова нескольких функций (Год, Месяц, День), что может быть избыточным при массовой обработке данных.

Способ №2: Оптимальная арифметика дат

Выясним более быстрый и лаконичный способ изменения времени. В 1С тип Дата представлен в секундах. Это позволяет нам использовать функцию НачалоДня() и просто прибавлять к ней нужное количество секунд.

Для установки времени 09:00:00 расчет будет следующим: 9 часов * 3600 секунд = 32400 секунд.


// Самый эффективный вариант
ДокументОбъект.Дата = НачалоДня(ДокументОбъект.Дата) + (9 * 3600);
ДокументОбъект.Записать();

Этот код работает быстрее, так как минимизирует количество преобразований типов и обращений к свойствам даты.

Оптимизация запроса для поиска документов

Чтобы обработка не перезаписывала документы, у которых время уже установлено правильно, необходимо грамотно составить запрос. Рассмотрим ошибку в логике отрицания. Условие НЕ ЧАС(Дата) = 9 И НЕ МИНУТА(Дата) = 0 может сработать некорректно из-за приоритетов операций.

Проанализируем правильный вариант условия в запросе:


ВЫБРАТЬ
    Поступление.Ссылка КАК Ссылка
ИЗ
    Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
ГДЕ
    НЕ (ЧАС(Поступление.Дата) = 9 
        И МИНУТА(Поступление.Дата) = 0 
        И СЕКУНДА(Поступление.Дата) = 0)
    И Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода

Такой подход позволит выбрать только те документы, время которых отличается от целевого хотя бы на одну секунду.

Важные рекомендации при массовом изменении документов

Изменение времени документов «задним числом» в типовых конфигурациях вроде БП 3.0 может привести к серьезным последствиям для учета. Разберем шаги, которые помогут избежать проблем:

  1. ОбменДанными.Загрузка: Перед записью объекта всегда устанавливайте свойство ДокументОбъект.ОбменДанными.Загрузка = Истина;. Это отключит лишние проверки, расчеты и подписки на события, что значительно ускорит работу и предотвратит нежелательное изменение связанных данных.
  2. Граница последовательности: Помните, что изменение даты (даже только времени) перепроводит документ в хронологическом смысле. Это может «снести» границу последовательности партионного учета. После работы обработки может потребоваться процедура «Перепроведение документов» за соответствующий период.
  3. Транзакции: Если документов много (более 1000), оборачивайте запись в транзакции порциями по 200-500 штук. Это существенно сократит время блокировки таблиц базы данных.
  4. Отрицательные остатки: Если вы устанавливаете всем поступлениям время 09:00, убедитесь, что списания в этот же день не произошли раньше по времени. В противном случае при перепроведении система может зафиксировать временный «минус» на расчетном счете, что повлияет на расчет курсовых разниц.

Рассмотрим финальный вариант кода, объединяющий все рекомендации:


Процедура УстановитьВремяДокументовНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Ссылка
        |ИЗ
        |   Документ.ПоступлениеНаРасчетныйСчет
        |ГДЕ
        |   Дата МЕЖДУ &Начало И &Конец
        |   И НЕ (ЧАС(Дата) = 9 И МИНУТА(Дата) = 0 И СЕКУНДА(Дата) = 0)";
    
    Запрос.УстановитьПараметр("Начало", НачалоДня(Объект.Период.ДатаНачала));
    Запрос.УстановитьПараметр("Конец", КонецДня(Объект.Период.ДатаОкончания));
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
        ДокОбъект.ОбменДанными.Загрузка = Истина;
        ДокОбъект.Дата = НачалоДня(ДокОбъект.Дата) + 32400; // 9:00:00
        Попытка
            ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
        Исключение
            Сообщить("Ошибка записи документа " + Выборка.Ссылка + ": " + ОписаниеОшибки());
        КонецПопытки;
    КонецЦикла;
КонецПроцедуры

Используя данный подход, вы сможете эффективно и безопасно управлять временем документов в вашей информационной базе.

← На главную