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