При разработке в среде 1С программисты часто сталкиваются с задачей фиксации времени документа. Типичный сценарий: бизнес-логика требует, чтобы все документы определенного типа (например, «Заказ поставщику») записывались строго на начало рабочего дня — допустим, в 08:00:00. Однако при попытке реализовать это стандартными методами через процедуру ПередЗаписью, разработчики обнаруживают, что при оперативном проведении система игнорирует установленное время и подставляет текущую секунду сеанса. Разберем подробно, почему это происходит и как решить задачу корректно.
Для начала проанализируем ситуацию с точки зрения ядра платформы. В 1С существует жесткий механизм, называемый оперативной отметкой времени. Если в свойствах документа в Конфигураторе параметр «Оперативное проведение» установлен в значение «Разрешить», включаются следующие правила:
ПередЗаписью или ОбработкаПроведения будут проигнорированы, если выбран режим РежимПроведенияДокумента.Оперативный.Рассмотрим пример кода, который часто пытаются использовать новички, и выясним, почему он не эффективен в процедуре ПередЗаписью модуля объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Попытка установить 8 утра
Дата = НачалоДня(Дата) + 3600 * 8;
КонецПроцедуры
Этот код успешно отработает при простой записи документа (без проведения) или при неоперативном проведении (например, задним числом). Однако, как только пользователь нажимает кнопку «Провести» в текущем периоде, платформа инициирует механизм оперативного проведения и замещает ваши «08:00:00» на текущие, скажем, «14:25:10».
Попытка изменить дату непосредственно в ОбработкаПроведения также обречена на провал:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
Дата = НачалоДня(ТекущаяДата()) + 28800; // Пытаемся обмануть систему
КонецЕсли;
КонецПроцедуры
В этот момент документ уже физически записан в базу данных с «оперативным» временем. Изменение свойства Дата в памяти объекта не приведет к автоматическому изменению даты в таблице базы данных без повторного вызова метода Записать(), что внутри транзакции проведения категорически запрещено и может вызвать блокировки или рекурсию.
Если специфика вашего учета позволяет документам проводиться без строгого контроля актуальности остатков на «текущую секунду», это самый простой и правильный путь. Проанализируем действия:
После этого платформа перестанет форсировать время. Теперь ваш код в ПередЗаписью будет работать абсолютно всегда:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если НЕ ЗначениеЗаполнено(Дата) Тогда
Дата = ТекущаяДата();
КонецЕсли;
// Устанавливаем строго 08:00:00
Дата = НачалоДня(Дата) + 28800;
КонецПроцедуры
Важно: При таком подходе вы теряете возможность использовать механизм «Актуальных итогов» в его классическом виде, так как документ перестает считаться оперативным.
Если вам нужно сохранить возможность оперативного проведения для большинства случаев, но в конкретной ситуации зафиксировать время, можно попробовать программно управлять режимом. Рассмотрим пример логики, где мы заставляем систему думать, что проведение является неоперативным, даже если оно инициировано сегодня.
Для этого в форме документа или в процедуре ПередЗаписью можно применить условие:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Если документ проводится и мы хотим зафиксировать время
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
// Принудительно меняем режим на неоперативный
РежимПроведения = РежимПроведенияДокумента.Неоперативный;
// Устанавливаем нужное время
Дата = НачалоДня(Дата) + 28800;
КонецЕсли;
КонецПроцедуры
Нюанс: Этот метод «обманывает» стандартную логику кнопок формы. Однако стоит помнить, что неоперативное проведение не проверяет остатки на «сейчас», а берет остатки на момент времени самого документа. В нашем случае — на 08:00 утра.
Выясним, как работает свойство документа «Автоматическая установка времени» в Конфигураторе. Оно может принимать значения:
Не использоватьНачало дняКонец дняТекущее времяЕсли установить «Начало дня», платформа сама будет стремиться поставить время 00:00:00. Если ваша цель — именно утро, возможно, стандартная настройка «Начало дня» в сочетании с запретом оперативного проведения будет наиболее чистым архитектурным решением без написания лишнего кода.
Проанализируем риски. Когда мы искусственно переносим время документа на 08:00, проводя его физически в 15:00, мы создаем ситуацию «заднего числа». Если в течение дня (с 08:00 до 15:00) уже были созданы другие документы, которые зависят от остатков, создаваемых вашим документом, возникнет нарушение последовательности.
Рекомендуем при использовании фиксированного времени всегда следовать правилам:
РежимПроведенияДокумента.Неоперативный, но помните о необходимости последующего пересчета итогов или восстановления последовательностей.Совместить штатное оперативное проведение и произвольное фиксированное время технически невозможно из-за архитектурных ограничений платформы «1С:Предприятие». Для решения задачи выберите один из двух путей: либо отключение оперативного проведения в метаданных, либо принудительная установка неоперативного режима в коде перед выполнением записи документа.