Почему при программном создании документа в 1С:Бухгалтерия 3.0 сбрасывается время и как записать его в конец дня?

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

При разработке обработок заполнения или загрузки данных в конфигурацию 1С:Бухгалтерия Предприятия 3.0 программисты часто сталкиваются со специфическим поведением системы: даже если в коде явно указано время документа 23:59:59 (конец дня), после вызова метода Записать() время принудительно меняется на 12:00:00. Это создает серьезные проблемы для документов списания (например, Расход материалов или Требование-накладная), так как если поступление товаров было зафиксировано позже 12:00, программа выдаст ошибку об отсутствии остатков на складе.

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

Выясняем причину: механизмы автоматической установки времени

Для начала проанализируем ситуацию. В типовых решениях на базе 1С:Предприятие 8.3, и в частности в БП 3.0, реализована логика строгого упорядочивания документов внутри дня. Это сделано для того, чтобы пользователю не приходилось вручную выстраивать последовательность «Приход -> Расход».

Основные причины сброса времени:

  1. Настройки программы: В разделе «Администрирование — Проведение документов» может быть активна опция «Время устанавливается автоматически».
  2. Подписки на события: В конфигурации существуют подписки (например, ПриУстановкеНовогоНомераДокумента), которые обращаются к общим модулям (например, ОбщегоНазначенияБПСобытия). Эти модули переопределяют время в зависимости от типа документа: приходные документы записываются на начало дня, складские и расходные — на полдень (12:00), а регламентные — на конец дня.
  3. Методика платформы: При вызове стандартного метода Записать() без параметров платформа может применять внутренние правила автоустановки времени, если они заданы на уровне метаданных или настроек.

Рассмотрим подробнее программные способы обхода этого поведения.

Способ 1: Использование флага ОбменДанными.Загрузка

Это один из самых эффективных, но требующих осторожности методов. Установка свойства ОбменДанными.Загрузка = Истина сообщает системе, что объект загружается из внешнего источника, и большинство проверок, а также подписок на события, должны быть проигнорированы.

Посмотрим на пример кода, который решает проблему:


// Создаем новый документ
ДокОбъект = Документы.ТребованиеНакладная.СоздатьДокумент();
ДокОбъект.Дата = КонецДня(Объект.ДатаДокумента);

// Заполняем необходимые реквизиты
ДокОбъект.Организация = Объект.Организация;
// ... заполнение табличных частей ...

// Устанавливаем режим загрузки, чтобы обойти подписки на события БП
ДокОбъект.ОбменДанными.Загрузка = Истина;

// ВАЖНО: При установленном флаге Загрузка номер автоматически не присвоится.
// Поэтому вызываем установку номера вручную.
ДокОбъект.УстановитьНовыйНомер();

// Записываем документ
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Преимущества этого метода: время гарантированно останется таким, каким вы его задали (23:59:59). Риски: при использовании Загрузка = Истина не сработают типовые проверки заполнения и бизнес-логика, заложенная в модуле объекта.

Способ 2: Повторная запись объекта

Если вы не хотите отключать механизмы платформы и подписки, можно воспользоваться методом «двойной записи». Суть заключается в том, что при первой записи система устанавливает время согласно своим правилам, а при второй записи (уже существующего в базе документа) логика «автоматического времени» обычно не срабатывает так агрессивно.

Разберем по шагам этот алгоритм:


// 1. Создаем и записываем документ с системным временем
ДокОбъект = Документы.ТребованиеНакладная.СоздатьДокумент();
ДокОбъект.Дата = Объект.ДатаДокумента; 
// ... заполнение ...
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

// 2. Теперь, когда документ уже в базе и имеет номер, меняем дату на конец дня
ДокОбъект.Дата = КонецДня(Объект.ДатаДокумента);

// 3. Записываем повторно
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Этот метод более безопасен с точки зрения целостности данных, так как все подписки на события сработают штатно. Однако он менее производителен, так как выполняется две транзакции записи в базу данных вместо одной.

Способ 3: Использование метода УстановитьВремя()

Проанализируем возможности встроенного языка платформы. У объекта документа есть метод УстановитьВремя(), который позволяет явно указать позицию документа на временной шкале. Рассмотрим пример:


ДокОбъект = Документы.ТребованиеНакладная.СоздатьДокумент();
ДокОбъект.Дата = Объект.ДатаДокумента;
// ... заполнение ...

// Используем системное перечисление РежимАвтоВремя
ДокОбъект.УстановитьВремя(РежимАвтоВремя.Последним);

ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

К сожалению, в конфигурации Бухгалтерия Предприятия 3.0 этот метод часто перекрывается логикой в подписках «При записи» или «Перед записью». Если после выполнения этого кода время все равно становится 12:00, значит, в вашей версии конфигурации типовые механизмы имеют высший приоритет. В таком случае вернитесь к Способу 1.

Анализ влияния контроля остатков

Нужно понимать, зачем вообще требуется запись в конец дня. Как правило, это связано с ошибками проведения. Если документ создается программно без проведения (только запись), то время 12:00 не является критичным до момента попытки проведения.

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

Рекомендации по реализации

Проанализировав все варианты, мы рекомендуем придерживаться следующей стратегии при разработке в БП 3.0:

  1. Если документ создается массово (загрузка из внешних систем), используйте ОбменДанными.Загрузка = Истина совместно с явным вызовом УстановитьНовыйНомер(). Это самый быстрый и надежный способ сохранить нужное время.
  2. Если важно, чтобы отработали все алгоритмы конфигурации (расчеты цен, заполнение связанных регистров), используйте метод двойной записи.
  3. Всегда проверяйте настройки учетной политики и параметров учета в пользовательском интерфейсе — иногда проблему можно решить изменением константы «Время устанавливается автоматически» без написания кода.

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

← На главную