Как запретить редактирование реквизитов должности, если на ней числятся сотрудники?

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

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

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

Анализ задачи и выбор метода проверки

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

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

Реализация функции проверки занятости

Разберем создание функции, которая будет возвращать логическое значение: Истина, если на должности кто-то работает, и Ложь, если должность вакантна или еще ни разу не использовалась. Проанализируем пример кода, который является итоговым результатом обсуждения на форуме:


Функция РаботаютНаДолжности(СсылкаНаДолжность) Экспорт
    
    // Проверка на новый объект: если должность еще не записана, 
    // проверять в регистре нечего, редактирование разрешено.
    Если СсылкаНаДолжность.Пустая() Тогда
        Возврат Ложь;
    КонецЕсли;

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

В этом коде мы используем конструкцию ВЫБРАТЬ ПЕРВЫЕ 1. Это оптимизирует работу базы данных: нам не нужно знать список всех сотрудников, достаточно подтвердить наличие хотя бы одного. Также важно передавать параметр &Период, чтобы проверять актуальное состояние на текущий момент.

Управление доступностью элементов на форме

Теперь выясним, как применить результат этой функции к интерфейсу. В обычных формах (1С 8.2/8.3) основной процедурой для инициализации состояния формы является ПриОткрытии. Проанализируем ситуацию, когда нам нужно закрыть от редактирования конкретный флаг (например, ВзимаютсяВзносыЗаЗанятыхНаРаботахСДосрочнойПенсией).

Разберем по шагам код в модуле формы:


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

Важный технический нюанс: на форуме предлагалось использовать свойство Доступность = Ложь. Однако на практике лучше применять ТолькоПросмотр = Истина. Почему? Элемент с выключенной доступностью становится «серым», текст в нем плохо читается, и его нельзя выделить или скопировать. Режим «Только просмотр» сохраняет визуальную четкость данных, но запрещает их изменение пользователем.

Профессиональные доработки решения

Рассмотрим более глубокие методы, которые сделают наше решение по-настоящему надежным. Ограничение на уровне формы легко обходится внешними обработками или механизмом «Групповое изменение реквизитов».

  1. Проверка в модуле объекта: Чтобы гарантированно запретить запись изменений, нужно продублировать логику в процедуре ПередЗаписью модуля объекта справочника. Если реквизит был изменен, а функция РаботаютНаДолжности возвращает истину, следует установить Отказ = Истина.
  2. Использование метода НайтиСсылки: Вместо прямого запроса к одному регистру сведений, можно использовать системную функцию НайтиСсылки(). Это позволит найти упоминание должности не только в текущем штате, но и в архивных документах, приказах о приеме или кадровых перемещениях. Это более жесткий, но надежный метод контроля.
  3. Разграничение прав: Часто бывает необходимо разрешить редактирование даже «занятых» должностей администратору системы для исправления ошибок ввода. В этом случае добавим условие: Если НЕ РольДоступна("ПолныеПрава") Тогда....
  4. Особенности конфигурации ЗУП 3.1: Если вы работаете в современной конфигурации на управляемых формах, проверять нужно не только физических лиц, но и регистр ЗанятыеПозицииШтатногоРасписания. Даже если сотрудник еще не принят, но позиция в штатном расписании утверждена и зафиксирована документами, её изменение может быть нежелательным.

Использование события «ПриЧтенииНаСервере»

Если мы переходим на управляемые формы, то логику проверки следует перенести в событие ПриЧтенииНаСервере. Это позволит определить состояние объекта один раз при загрузке данных и передать результат на клиентскую сторону. Посмотрим на пример реализации для управляемого приложения:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Устанавливаем признак блокировки в реквизит формы
    ДолжностьИспользуется = ПроверитьИспользованиеДолжности(ТекущийОбъект.Ссылка);
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Управляем видимостью/доступностью на клиенте
    Элементы.ГруппаВажныеРеквизиты.ТолькоПросмотр = ДолжностьИспользуется;
КонецПроцедуры

Таким образом, мы проанализировали ситуацию и выяснили, что для корректного решения задачи недостаточно просто отключить поле. Необходимо учитывать состояние объекта (новый или записанный), правильно выбирать между свойствами «Доступность» и «Только просмотр», а также помнить о производительности запросов в крупных информационных базах.

← На главную