Часто в практике разработки на платформе 1С возникает задача ограничить возможность пользователей создавать или переносить документы "задним числом". Разберем классическую ситуацию: необходимо выдавать отказ при записи документа, если его дата отстает от текущей более чем на 5 дней. Рассмотрим эту задачу с разных сторон, проанализируем ошибки новичков и выясним правильные алгоритмы действий.
Платформа 1С хранит даты вместе со временем, а базовой единицей измерения при математических операциях с типом Дата является секунда. Чтобы отнять от текущей даты 5 дней, нам нужно перевести дни в секунды.
Проанализируем математику: 1 день — это 24 часа, 60 минут, 60 секунд. Получаем: 60 * 60 * 24 = 86400 секунд в сутках. Следовательно, 5 дней — это 86400 * 5.
Посмотрим на пример простейшего кода, который можно поместить в обработчик события ПередЗаписью в модуле объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
ПятьДней = 86400 * 5;
ТекГраница = ТекущаяДатаСеанса() - ПятьДней;
Если Объект.Дата < ТекГраница Тогда
Отказ = Истина;
Сообщить("Дата документа не может быть старше 5 дней от текущей даты!");
КонецЕсли;
КонецПроцедуры
Этот код решает проблему в первом приближении, однако он таит в себе "подводные камни", связанные со временем суток.
Разберем подробнее, почему простое вычитание секунд может привести к ошибкам. Если текущее время 15:00, а документ создается датой пятидневной давности, но со временем 10:00, система посчитает разницу и выдаст отказ, хотя календарно пятые сутки еще не истекли (или истекли не полностью).
Чтобы получать точную разницу именно в целых (календарных) днях, нам необходимо приводить обе даты к началу дня. Для этого в 1С существует специальная функция НачалоДня(). Рассмотрим улучшенный вариант вычисления:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
РазницаВДнях = (НачалоДня(ТекущаяДатаСеанса()) - НачалоДня(Объект.Дата)) / 86400;
Если РазницаВДнях > 5 Тогда
Отказ = Истина;
Сообщить("Нельзя сохранять документы старше 5 дней!");
КонецЕсли;
КонецПроцедуры
Такой подход намного надежнее, так как исключает влияние времени создания документа на логику проверки.
Проанализируем следующую ситуацию: пользователь открыл старый документ (которому уже больше 5 дней), чтобы изменить в нем комментарий, или просто перепроводит его. Если мы оставим код в том виде, в котором написали выше, 1С выдаст отказ. Ведь дата документа действительно старше 5 дней. Но пользователь дату не менял!
Чтобы блокировать только попытки переноса даты в прошлое или создания нового документа задним числом, необходимо сравнивать текущую дату объекта с той датой, которая уже записана в базе данных. Для этого используем обращение к свойству Ссылка:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если Объект.Дата <> Объект.Ссылка.Дата Тогда
РазницаВДнях = (НачалоДня(ТекущаяДатаСеанса()) - НачалоДня(Объект.Дата)) / 86400;
Если РазницаВДнях > 5 Тогда
Отказ = Истина;
Сообщить("Запрещено переносить дату документа более чем на 5 дней назад!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Теперь наша проверка сработает только в том случае, если пользователь физически изменил реквизит Дата.
В ходе обсуждения подобных задач разработчики часто приходят к выводу, что "изобретать велосипед" не всегда целесообразно. Посмотрим на проблему шире: зачем вообще ограничивать период редактирования?
Во всех современных типовых конфигурациях 1С (основанных на Библиотеке стандартных подсистем) уже встроен мощный и гибкий механизм. Вместо написания программного кода в модуле каждого объекта, рекомендуется использовать стандартную функцию Дата запрета изменения данных.
Как это настроить:
Этот механизм позволяет гибко настраивать исключения для определенных пользователей или групп, не требует программирования и обновляется вместе с платформой, обеспечивая надежную защиту исторических данных.
В завершение разберем важную понятийную ошибку. Часто пользователи путают "дату создания" и "дату документа".
Реквизит Дата, который мы проверяли в коде — это дата отражения хозяйственной операции в учете. Именно по ней строятся бухгалтерские и управленческие отчеты. Платформа 1С "из коробки" не хранит фактическое время, когда пользователь нажал кнопку создания.
Если вам нужно отследить именно время фактического появления объекта в базе (независимо от того, какую дату установил пользователь внутри документа), используйте Журнал регистрации или типовую подсистему Версионирование объектов.