Как исправить обход даты запрета изменения данных в 1С:ЗУП 2.5 при наличии кастомных доработок

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом Управленческий учет IT и автоматизация бизнеса
← На главную

Обеспечение целостности данных в закрытых периодах — одна из ключевых задач при администрировании конфигурации 1С:Зарплата и управление персоналом, редакция 2.5 (ЗУП 2.5). Ситуации, когда пользователи могут беспрепятственно редактировать документы прошлых месяцев, ведут к искажению регламентированной отчетности, расхождениям в учете и дополнительным трудозатратам на исправление ошибок.

В этой статье мы подробно разберем практическую ситуацию, когда стандартный механизм даты запрета изменений перестает работать из-за логической ошибки в доработанном программном коде (например, после интеграции отраслевых решений или внедрения кастомных доработок от внешних интеграторов). Мы проанализируем неисправный код, найдем уязвимость, исправим её и рассмотрим сопутствующие настройки системы.

Анализ проблемы: почему пользователи обходят дату запрета?

В типовых конфигурациях 1С на обычных формах (к которым относится ЗУП 2.5) за проверку возможности редактирования документов отвечает специализированный программный механизм. Однако, если конфигурация была кастомизирована (находится на поддержке с возможностью изменения), разработчики часто внедряют собственные проверки. В нашем случае была добавлена кастомная функция ДокументВЗакрытомПериоде, призванная проверять документы по дополнительному регистру сведений бит_НеДоступныеКадровыеДокументы.

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


Функция ДокументВЗакрытомПериоде(ДокументОбъект) Экспорт
    Результат = Ложь;
    
    // БИТ НАЧАЛО
    Проверять = РольДоступна("ПолныеПрава") ИЛИ РольДоступна("БИТ_РедактированиеКадровыхДокументов"); 
    ПроверятьСПолнымиПравами = РольДоступна("СТ_КонтрольКадровыхДокументов"); 
    
    Если НЕ Результат И (НЕ Проверять или ПроверятьСПолнымиПравами) Тогда 
        Запрос = Новый Запрос;
        Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
        |	бит_НеДоступныеКадровыеДокументы.КадровыйДокумент
        |ИЗ
        |	РегистрСведений.бит_НеДоступныеКадровыеДокументы КАК бит_НеДоступныеКадровыеДокументы
        |ГДЕ
        |	бит_НеДоступныеКадровыеДокументы.КадровыйДокумент = &КадровыйДокумент";
        Запрос.УстановитьПараметр("КадровыйДокумент", ДокументОбъект.Ссылка);
        
        Результат = НЕ Запрос.Выполнить().Пустой(); // В оригинальном коде была опечатка (пропущены скобки Выполнить)
        Возврат Результат; 
    КонецЕсли;
    // БИТ КОНЕЦ
    
    СоответствиеГраницЗапрета = ПараметрыСеанса.ГраницыЗапретаИзмененияДанных.Получить;
    
    Если СоответствиеГраницЗапрета = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;
    
    ПараметрыПроверкиДокумента = НастройкаПравДоступаПереопределяемый.ПолучитьПараметрыПроверкиДокумента(ДокументОбъект);
    НастройкаПравДоступаПереопределяемый.ПроверитьВерсиюДокумента(ДокументОбъект, ПараметрыПроверкиДокумента, СоответствиеГраницЗапрета, Результат);
    
    Возврат Результат;
КонецФункции

В чем заключается логический баг?

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

  1. Переменная Результат инициализируется значением Ложь.
  2. Вычисляется переменная Проверять. У нашего пользователя нет роли "ПолныеПрава" или "БИТ_РедактированиеКадровыхДокументов", поэтому переменная принимает значение Ложь.
  3. Вычисляется переменная ПроверятьСПолнымиПравами. Она также принимает значение Ложь.
  4. Проверяется условие: Если НЕ Результат И (НЕ Проверять или ПроверятьСПолнымиПравами) Тогда. Подставим наши значения: Если НЕ Ложь И (НЕ Ложь ИЛИ Ложь). Получаем: Истина И (Истина ИЛИ Ложь), что дает итоговое значение Истина. Условие выполняется!
  5. Программа заходит внутрь блока Если...Тогда и выполняет запрос к кастомному регистру сведений бит_НеДоступныеКадровыеДокументы.
  6. Если открываемый документ не внесен вручную в этот регистр (а большинство документов туда не вносятся, так как это исключительный механизм блокировки), запрос возвращает пустой результат. Переменная Результат становится равна Ложь.
  7. Выполняется инструкция Возврат Результат; (то есть возвращается значение Ложь).

Критическая ошибка: Из-за оператора Возврат внутри условного блока функция немедленно завершает свою работу. Код программы никогда не доходит до стандартных механизмов 1С, расположенных ниже по тексту функции, где считываются реальные границы запрета изменений из параметра сеанса ПараметрыСеанса.ГраницыЗапретаИзмененияДанных. Таким образом, вся стандартная система дат запрета изменений в ЗУП 2.5 оказывается полностью отключенной для обычных пользователей!

Рефакторинг и исправление программного кода

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

Рассмотрим исправленный вариант функции:


Функция ДокументВЗакрытомПериоде(ДокументОбъект) Экспорт
    Результат = Ложь;
    
    // БИТ НАЧАЛО
    Проверять = РольДоступна("ПолныеПрава") ИЛИ РольДоступна("БИТ_РедактированиеКадровыхДокументов"); 
    ПроверятьСПолнымиПравами = РольДоступна("СТ_КонтрольКадровыхДокументов"); 
    
    Если НЕ Результат И (НЕ Проверять или ПроверятьСПолнымиПравами) Тогда 
        Запрос = Новый Запрос;
        Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
        |	бит_НеДоступныеКадровыеДокументы.КадровыйДокумент
        |ИЗ
        |	РегистрСведений.бит_НеДоступныеКадровыеДокументы КАК бит_НеДоступныеКадровыеДокументы
        |ГДЕ
        |	бит_НеДоступныеКадровыеДокументы.КадровыйДокумент = &КадровыйДокумент";
        Запрос.УстановитьПараметр("КадровыйДокумент", ДокументОбъект.Ссылка);
        
        // Исправленная логика: возвращаем результат только если документ заблокирован в кастомном регистре
        Если НЕ Запрос.Выполнить().Пустой() Тогда
            Возврат Истина; 
        КонецЕсли;
    КонецЕсли;
    // БИТ КОНЕЦ
    
    // Стандартная проверка дат запрета редактирования 1С
    СоответствиеГраницЗапрета = ПараметрыСеанса.GraniciZapretaIzmeneniyaDannih.Poluchit(); // Получаем кэшированные границы
    
    Если СоответствиеГраницЗапрета = Неопределено Тогда
        Возврат Ложь; // Если границы не настроены вовсе, редактирование разрешено
    КонецЕсли;
    
    ПараметрыПроверкиДокумента = НастройкаПравДоступаПереопределяемый.ПолучитьПараметрыПроверкиДокумента(ДокументОбъект);
    НастройкаПравДоступаПереопределяемый.ПроверитьВерсиюДокумента(ДокументОбъект, ПараметрыПроверкиДокумента, СоответствиеГраницЗапрета, Результат);
    
    Возврат Результат;
КонецФункции

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

Инструкция по настройке дат запрета в ЗУП 2.5

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

  1. Перейдем в меню Сервис — Установка даты запрета изменения данных.
  2. Проверим настройки на обеих вкладках:
    • Ограничение регламентированной информации (влияет на расчетные и учетные документы зарплаты).
    • Ограничение управленческой информации (влияет на кадровые приказы и документы управленческого учета).
  3. Если для конкретного пользователя настроена персональная граница, она переопределяет общую дату. Убедимся, что персональная граница пользователя действительно охватывает целевой закрытый период.
  4. Обратим внимание на важную опцию в настройках программы: Сервис — Настройка программы — Ограничение прав доступа. Проверим, установлена ли галочка "Применять дату запрета редактирования данных для пользователей с 'Полными правами'". Если эта опция отключена, пользователи с ролью "Полные права" всегда смогут редактировать документы закрытого периода, игнорируя любые ограничения.

Особенности кэширования параметров сеанса в ЗУП 2.5

Важно помнить, что настройки дат запрета редактирования считываются базой данных при запуске сеанса пользователя и кэшируются в специальный параметр сеанса ПараметрыСеанса.ГраницыЗапретаИзмененияДанных.

Если администратор изменил дату запрета или добавил пользователя в список исключений, эти изменения не вступят в силу немедленно для тех пользователей, которые в этот момент работают в программе. Для применения новых настроек пользователям необходимо полностью завершить работу с программой 1С и запустить её заново (перезапустить сеанс).

В некоторых случаях (особенно в клиент-серверном варианте базы данных на старых версиях платформы) может возникнуть ошибка инициализации параметров сеанса. Для её устранения требуется принудительный программный сброс параметров или очистка локального кэша метаданных на компьютере пользователя.

← На главную