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