Как ограничить выбор периода в отчете 1С в зависимости от текущей даты?

Программист 1С:Зарплата и Управление Персоналом Управленческий учет
← На главную

В практике разработки на платформе 1С часто возникает задача «защиты от дурака», когда необходимо запретить пользователям формировать отчеты за периоды, данные в которых еще не признаны актуальными или официально не закрыты. Типичный пример — расчетные листки в 1С:Зарплата и управление персоналом. Пока заработная плата не выплачена (например, до 5-го числа следующего месяца), просмотр предварительных данных рядовыми сотрудниками может вызвать массу лишних вопросов к бухгалтерии. В этой статье мы подробно разберем, как технически реализовать ограничение выбора периода в зависимости от текущего числа месяца.

Анализ задачи и логика условий

Прежде чем переходить к коду, формализуем требования. Нам необходимо, чтобы система проверяла текущую дату:

  1. Если сегодня число меньше 5-го, то максимально доступный месяц для формирования отчета — позапрошлый.
  2. Если сегодня 5-е число или позже, то доступен прошлый месяц.

Рассмотрим пример: сегодня 4 ноября. Октябрь еще «не закрыт». Значит, пользователь может видеть данные только за сентябрь и ранее. Если же сегодня 5 ноября, октябрь считается закрытым, и доступ открывается по октябрь включительно.

Способ 1. Замена стандартного выбора периода на выпадающий список

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

Нам потребуется программно сформировать список доступных месяцев при открытии формы отчета. Проанализируем алгоритм заполнения такого списка:


Процедура ПриОткрытииНаСервере()
    ТекущаяДатаСеанса = ТекущаяДатаСеанса();
    ТекущийДень = День(ТекущаяДатаСеанса);
    ТекущийМесяц = НачалоМесяца(ТекущаяДатаСеанса);
    
    // Определяем границу разрешенного периода
    Если ТекущийДень < 5 Тогда
        // Доступно до позапрошлого месяца
        ГраницаПериода = ДобавитьМесяц(ТекущийМесяц, -2);
    Иначе
        // Доступно до прошлого месяца
        ГраницаПериода = ДобавитьМесяц(ТекущийМесяц, -1);
    КонецЕсли;
    
    // Заполняем список выбора на форме (например, за последние 12 месяцев)
    Для Итератор = 0 По 11 Цикл
        МесяцСписка = ДобавитьМесяц(ГраницаПериода, -Итератор);
        ПредставлениеМесяца = Формат(МесяцСписка, "ДФ='ММММ гггг'");
        Элементы.ВыбранныйПериод.СписокВыбора.Добавить(МесяцСписка, ПредставлениеМесяца);
    КонецЦикла;
КонецПроцедуры

Этот метод хорош тем, что пользователь физически не может выбрать «запрещенную» дату, так как её просто нет в списке. Это снимает необходимость в дополнительных проверках при нажатии кнопки Сформировать.

Способ 2. Программная проверка в СКД (Система компоновки данных)

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

Разберем реализацию в модуле объекта отчета. Мы будем использовать обработчик ПриКомпоновкеРезультата. Выясним, как проверить параметры НачалоПериода и КонецПериода:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    // 1. Получаем значения параметров из настроек компоновки
    ПараметрКонецПериода = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("КонецПериода");
    
    Если ПараметрКонецПериода <> Неопределено И ПараметрКонецПериода.Использование Тогда
        ВыбраннаяДата = ПараметрКонецПериода.Значение;
        
        // 2. Вычисляем максимально допустимую дату
        ТекущаяДатаС = ТекущаяДата();
        Если День(ТекущаяДатаС) < 5 Тогда
            МаксДата = КонецМесяца(ДобавитьМесяц(ТекущаяДатаС, -2));
        Иначе
            МаксДата = КонецМесяца(ДобавитьМесяц(ТекущаяДатаС, -1));
        КонецЕсли;
        
        // 3. Проверяем нарушение границы
        Если ВыбраннаяДата > МаксДата Тогда
            СтандартнаяОбработка = Ложь;
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Выбор периода ограничен! Данные за текущий период будут доступны после 5-го числа следующего месяца.";
            Сообщение.Сообщить();
            Возврат;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Важный момент: использование СтандартнаяОбработка = Ложь полностью прерывает формирование отчета, что является жестким, но эффективным методом контроля.

Способ 3. Использование механизма «Даты запрета изменения данных»

В типовых конфигурациях, таких как ЗУП или ERP, уже существует встроенный механизм дат запрета. Хотя он предназначен для ограничения редактирования, его можно адаптировать для чтения. Посмотрим на этот подход шире.

Вместо того чтобы жестко прописывать «5-е число» в коде, мы можем обращаться к программному интерфейсу БСП (Библиотеки стандартных подсистем). Это позволит бухгалтеру самостоятельно управлять доступностью данных, просто устанавливая дату запрета загрузки или редактирования. Рассмотрим пример функции, которая проверяет, входит ли период в «разрешенную» зону:


Функция ПериодДоступенДляПросмотра(ПроверяемаяДата) Экспорт
    // Используем функционал БСП для получения общей даты запрета
    ПараметрыПроверки = ДатыЗапретаИзменения.ПараметрыПроверки();
    ПараметрыПроверки.Раздел = "Зарплата"; 
    
    ДатаЗапрета = ДатыЗапретаИзменения.ДатаЗапрета(ПараметрыПроверки);
    
    Если ПроверяемаяДата > ДатаЗапрета Тогда
        Возврат Ложь;
    КонецЕсли;
    
    Возврат Истина;
КонецФункции

Этот способ более гибкий: если расчет зарплаты задерживается из-за праздников, бухгалтер может просто передвинуть дату запрета, и программисту не придется менять код «пятого числа» на «седьмое».

Способ 4. Ограничение на уровне прав доступа (RLS)

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

Проанализируем пример шаблона ограничения для регистра расчета Начисления:


#Если &ДинамическоеОграничениеПоДате #Тогда
ГДЕ ПериодРегистрации <= &МаксимальноДопустимаяДатаПросмотра
#КонецЕсли

Параметр &МаксимальноДопустимаяДатаПросмотра можно устанавливать при старте сеанса в модуле сеанса, вычисляя его по той же логике «5-го числа». Это самый надежный метод, который невозможно обойти никакими внешними обработками или консолями отчетов.

Рекомендации по реализации «Защиты от дурака»

Для создания качественного интерфейса мы рекомендуем сочетать несколько подходов:

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

← На главную