При работе с документами в 1С:Предприятии часто возникает необходимость контролировать дату документа. Пользователи могут ошибочно или намеренно устанавливать даты в прошлом, а также выбирать выходные или праздничные дни, что может нарушать логику бизнес-процессов и учетные правила. Мы рассмотрим, как можно эффективно решить эту задачу, используя как стандартные механизмы платформы 1С, так и программные средства.
Для решения этой проблемы нам необходимо решить две основные подзадачи:
Для ограничения работы с документами прошлых периодов в 1С:Предприятии существует мощный и гибкий стандартный механизм, который называется "Дата запрета изменения данных". Этот механизм позволяет административно управлять возможностью редактирования, проведения и удаления документов за определенные прошедшие периоды. Применение этого стандартного функционала является предпочтительным способом решения проблемы с прошлыми датами, так как он не требует доработки кода и легко настраивается.
Рассмотрим подробнее, как работает этот механизм:
Чтобы получить доступ к настройкам даты запрета, нам следует перейти в раздел "Администрирование", затем выбрать "Настройки пользователей и прав" и далее – "Даты запрета изменения".
Одним из ключевых преимуществ данного механизма является его гибкость. Мы можем установить дату запрета следующими способами:
Мы можем выбрать один из нескольких видов установки даты запрета:
После того как мы установили и сохранили настройки даты запрета, они вступают в силу. При любой попытке выполнить действия с документом (изменить, провести, удалить существующий или сохранить новый), дата которого попадает в запрещенный период, программа выдаст соответствующее сообщение об ошибке. Например: "Изменение данных запрещено до [дата запрета]". Важно помнить, что после внесения изменений в настройки даты запрета необходимо закрыть окно настроек, чтобы они были применены.
Изменять дату запрета изменения данных может только пользователь с административными правами или пользователь, которому специально назначено соответствующее право. Это обеспечивает централизованный контроль и предотвращает несанкционированные изменения.
Помимо даты запрета редактирования, в 1С существует также механизм Дата запрета загрузки данных. Этот механизм играет важную роль при интеграции с другими информационными системами (например, при обмене данными между 1С:Управление торговлей и 1С:Бухгалтерия). Он предотвращает изменения в базе данных, которые могут произойти при автоматической загрузке данных из внешних источников за запрещенные периоды.
Таким образом, для запрета установки прошлых дат мы настоятельно рекомендуем использовать именно стандартный механизм "Дата запрета изменения данных". Он является надежным, гибким и не требует программирования, обеспечивая административный контроль за актуальностью данных.
Теперь рассмотрим задачу по запрету выбора выходных и праздничных дней в качестве даты документа. В отличие от прошлых дат, здесь нам потребуется программная доработка, так как стандартных административных механизмов для такой проверки нет. Для этого мы будем использовать "Производственный календарь", который является ключевым инструментом в 1С для работы с графиками работы и учетом времени.
Разберем процесс поэтапно:
В большинстве типовых конфигураций 1С:Предприятия (таких как 1С:Зарплата и Управление Персоналом, 1С:Бухгалтерия, 1С:ERP) встроен Производственный календарь Российской Федерации. Этот календарь содержит актуальную информацию о рабочих, предпраздничных, праздничных днях, а также субботах и воскресеньях для каждого года. Информация в нем обычно автоматически обновляется в соответствии с постановлениями Правительства РФ о переносе выходных дней. Мы также можем создавать региональные календари или настраивать их вручную, если есть специфика по регионам или особым графикам работы.
Визуально в интерфейсе календарь отображает различные типы дней разными цветами, что удобно для пользователя.
Для программной проверки нам нужно обратиться к данным производственного календаря. Логику проверки можно разместить в нескольких местах, но наиболее надежным и правильным будет размещение в модуле объекта документа.
ПриИзменении в форме документа:
Мы можем реализовать проверку в этом обработчике, чтобы дать пользователю оперативную обратную связь сразу после того, как он изменил дату в поле на форме. Это улучшает пользовательский опыт, так как ошибка обнаруживается немедленно. Однако, стоит учитывать, что если документ создается или изменяется программно (без участия формы), эта проверка не сработает. Поэтому, для гарантированной проверки, нам нужна дополнительная логика.
ПередЗаписью или ПриЗаписи в модуле объекта документа:
Это самое надежное место для размещения логики проверки. Код, написанный в обработчике ПередЗаписью() модуля объекта документа, выполняется каждый раз перед записью или проведением документа, независимо от того, как документ был изменен (через форму, программно, через обмен данными). Если проверка не пройдена, мы можем установить параметр Отказ = Истина;, что предотвратит запись или проведение документа. Обработчик ПриЗаписи() также может быть использован, но ПередЗаписью() предпочтительнее, поскольку позволяет отменить запись до ее фактического выполнения, что более эффективно.
Рассмотрим конкретный пример кода, который можно разместить в обработчике ПередЗаписью() модуля объекта вашего документа. Мы получим объект производственного календаря, затем запросим вид дня для выбранной даты документа и, если это выходной или праздничный день, мы сообщим об этом пользователю и установим флаг Отказ = Истина;.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Получаем дату документа и приводим ее к началу дня,
// чтобы исключить влияние времени при сравнении дат.
ДатаДокументаКПроверке = НачалоДня(ЭтотОбъект.Дата);
// --- 1. Проверка на выходные и праздничные дни ---
// Определяем, какой производственный календарь мы будем использовать.
// Обычно это "РоссийскаяФедерация" или "РОССИЙСКАЯ_ФЕДЕРАЦИЯ".
// Важно убедиться, что такой элемент существует в справочнике "ПроизводственныеКалендари".
// В типовых конфигурациях чаще всего используется предопределенный элемент с кодом "РОССИЙСКАЯ_ФЕДЕРАЦИЯ".
Перем КалендарьДляПроверки;
Попытка
// Получаем ссылку на предопределенный элемент справочника "ПроизводственныеКалендари"
КалендарьДляПроверки = Справочники.ПроизводственныеКалендари.НайтиПоКоду("РОССИЙСКАЯ_ФЕДЕРАЦИЯ");
Исключение
// Если календарь не найден по коду, возможно, его название другое
// или он не создан. Можно попробовать найти по наименованию.
Сообщить("Внимание: Не удалось найти производственный календарь по коду 'РОССИЙСКАЯ_ФЕДЕРАЦИЯ'. " + ОписаниеОшибки(), СтатусСообщения.Внимание);
// Если календарь не найден, дальнейшая проверка по нему невозможна.
// Можно либо прекратить проверку, либо попытаться найти другой календарь.
КалендарьДляПроверки = Неопределено;
КонецПопытки;
Если КалендарьДляПроверки <> Неопределено Тогда
// Получаем вид дня для выбранной даты из производственного календаря.
// Метод ПолучитьВидДня() возвращает значение перечисления ВидДняПроизводственногоКалендаря.
ВидДня = КалендарьДляПроверки.ПолучитьВидДня(ДатаДокументаКПроверке);
// Проверяем, является ли день выходным или праздничным.
// Используем значения перечисления ВидДняПроизводственногоКалендаря.
Если ВидДня = ВидДняПроизводственногоКалендаря.Выходной
Или ВидДня = ВидДняПроизводственногоКалендаря.Праздник Тогда
Отказ = Истина; // Отменяем запись документа.
СообщениеОбОшибке = "Выбранная дата " + Формат(ДатаДокументаКПроверке, "ДФ=dd.MM.yyyy") + " является ";
Если ВидДня = ВидДняПроизводственногоКалендаря.Выходной Тогда
СообщениеОбОшибке = СообщениеОбОшибке + "выходным днем. Пожалуйста, выберите рабочий день.";
Иначе
СообщениеОбОшибке = СообщениеОбОшибке + "праздничным днем. Пожалуйста, выберите рабочий день.";
КонецЕсли;
// Выводим сообщение пользователю. СтатусСообщения.Важное выделяет сообщение красным.
Сообщить(СообщениеОбОшибке, СтатусСообщения.Важное);
КонецЕсли;
Иначе
// Если производственный календарь не был найден, мы можем принять решение,
// что проверка выходных дней не производится или выдать предупреждение.
Сообщить("Внимание: Проверка даты на выходной/праздничный день не выполнена, так как производственный календарь не доступен.", СтатусСообщения.Внимание);
КонецЕсли;
// --- 2. Дополнительная программная проверка на прошлые даты (если не используется стандартный механизм) ---
// Эту проверку можно использовать в дополнение к "Дате запрета изменения данных"
// или вместо нее, если нужна более специфическая логика.
// Например, запретить даты ранее начала текущего дня.
Если ДатаДокументаКПроверке < НачалоДня(ТекущаяДата()) Тогда
Отказ = Истина; // Отменяем запись документа.
Сообщить("Нельзя устанавливать дату документа ранее текущего дня: " + Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy") + ". Пожалуйста, выберите актуальную дату.", СтатусСообщения.Важное);
КонецЕсли;
// --- 3. (Опционально) Запрет на будущие даты ---
// Если по бизнес-логике необходимо запретить установку будущих дат.
// Если ДатаДокументаКПроверке > КонецДня(ТекущаяДата()) Тогда
// Отказ = Истина;
// Сообщить("Нельзя устанавливать дату документа позднее текущего дня. Пожалуйста, выберите актуальную дату.", СтатусСообщения.Важное);
// КонецЕсли;
КонецПроцедуры
Пояснения к коду:
НачалоДня(). Это важно для корректного сравнения дат, так как функция ТекущаяДата() возвращает дату со временем, а мы обычно сравниваем именно календарные дни.ПроизводственныеКалендари с кодом "РОССИЙСКАЯ_ФЕДЕРАЦИЯ". Если календарь не найден (например, по ошибке удален или переименован), мы выводим предупреждение.КалендарьДляПроверки.ПолучитьВидДня(ДатаДокументаКПроверке) возвращает тип дня (рабочий, выходной, праздничный, предпраздничный) в виде значения из перечисления ВидДняПроизводственногоКалендаря.ВидДня равен ВидДняПроизводственногоКалендаря.Выходной или ВидДняПроизводственногоКалендаря.Праздник, то устанавливаем флаг Отказ = Истина;, чтобы предотвратить запись документа, и выводим информативное сообщение для пользователя.ДатаДокументаКПроверке < НачалоДня(ТекущаяДата())), которая может быть полезна, если вы по какой-либо причине не используете стандартный административный механизм или вам нужна более тонкая настройка запрета прошлых дат.Возникает вопрос, как быть с будущими годами, например, с 2025 годом, если производственный календарь на него еще не утвержден правительством? В решениях 1С:Предприятие 8 производственные календари заполняются на каждый год. Изначально они могут быть пустыми или заполненными по стандартным правилам (например, суббота/воскресенье – выходные). Как только Правительство РФ утверждает постановление о переносе выходных дней на следующий год, 1С обычно выпускает обновления конфигураций, которые автоматически загружают и обновляют эти данные в производственном календаре. Таким образом, для актуальной информации по будущим годам критически важно своевременно обновлять конфигурацию вашей системы 1С. Региональные календари или календари, созданные вручную, могут потребовать ручного обновления или загрузки из внешних источников.
Для эффективного контроля дат в документах 1С:Предприятия мы рекомендуем использовать комплексный подход:
ПередЗаписью() модуля объекта документа, используя данные "Производственного календаря". Этот подход гарантирует проверку независимо от способа создания или изменения документа.Такой подход позволит нам обеспечить высокий уровень контроля за корректностью вводимых данных, улучшить точность учета и предотвратить возможные ошибки, связанные с неправильными датами документов.