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