Почему пользователи могут проводить документы задним числом при запрете неоперативного проведения и как это исправить?

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

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

В рамках этой статьи мы подробно разберем, почему стандартные ограничения ролей могут не срабатывать из формы документа, проанализируем внутренние механизмы платформы «1С:Предприятие 8» и рассмотрим несколько надежных способов решения этой задачи: от использования штатных механизмов БСП до программной блокировки на уровне транзакции.

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

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

Право Интерактивное проведение неоперативное относится исключительно к интерактивным действиям пользователя. Платформа автоматически проверяет его только тогда, когда действие инициируется напрямую через стандартные команды интерфейса платформы — например, при выборе команды «Провести» в контекстном меню списка документов или на командной панели формы списка.

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

  1. Программный вызов проведения в коде формы. В современных конфигурациях (особенно построенных на базе БСП, таких как «Управление торговлей», «ERP» или «Комплексная автоматизация») стандартные кнопки проведения часто переопределены разработчиками. При нажатии на кнопку «Провести и закрыть» или «Провести» запускается программный обработчик на встроенном языке. В коде вызывается метод записи объекта, например: Объект.Записать(РежимЗаписиДокумента.Проведение); Для платформы такой вызов является программным, а не интерактивным. При программном проведении интерактивные права (такие как Интерактивное проведение неоперативное) полностью игнорируются! Проверяется только базовое право Проведение. Если у пользователя есть право проводить данный тип документов в принципе, система успешно выполнит операцию, несмотря на то, что дата документа относится к прошлому периоду.
  2. Свойство формы «ИспользоватьРежимПроведения». У управляемой формы документа существует свойство ИспользоватьРежимПроведения, которое по умолчанию установлено в значение Автоматически. В некоторых сценариях платформа может попытаться провести документ в оперативном режиме, даже если его время отличается от текущего, если это допускается логикой конфигурации, что также приводит к обходу ограничений неоперативного проведения.

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

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

Это самый простой и в то же время наиболее рекомендуемый способ для типовых и близких к типовым конфигураций. Вместо изобретения собственных алгоритмов мы используем проверенный временем механизм БСП.

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

  1. Перейдем в раздел Администрирование — Поддержка и обслуживание — Дата запрета изменения.
  2. Включим использование дат запрета и перейдем по ссылке Настроить.
  3. Мы можем установить единую дату запрета для всех пользователей, либо настроить правила индивидуально (например, разрешить бухгалтерам редактировать документы прошлого месяца, а менеджерам по продажам — только текущий день).
  4. Чтобы не изменять дату запрета вручную каждый день, мы настроим относительную дату запрета. Вместо конкретного числа выберем значение Конец прошлого дня или Предыдущий день. В этом случае система будет автоматически сдвигать границу запрета при наступлении новых суток.
  5. Для обеспечения точности работы механизма проверим, что в системе активно стандартное регламентное задание РегламентныеЗадания, отвечающее за обновление относительных дат запрета. Это гарантирует, что ровно в полночь доступ к редактированию и проведению документов за прошедший день будет заблокирован.

Способ 2. Подписка на событие (наиболее надежный программный метод)

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

Для этого мы создадим общую Подписку на событие. Этот метод гарантирует, что проверка сработает независимо от того, откуда проводится документ — из формы, из списка, через внешнюю обработку или по COM-соединению.

Разберем процесс создания подписки по шагам:

  1. Откроем конфигуратор и перейдем в ветку Общие — Подписки на события.
  2. Создадим новую подписку с именем КонтрольОперативногоПроведенияПередЗаписью.
  3. В свойстве Источник выберем типы документов, для которых необходимо ограничить неоперативное проведение (например, ДокументОбъект.РеализацияТоваровУслуг, ДокументОбъект.ПоступлениеТоваровУслуг).
  4. В свойстве Событие выберем ПередЗаписью.
  5. Создадим новый общий модуль (например, СерверныеМеханизмыДокументов) с установленными флажками Сервер и Вызов сервера, и определим в нем процедуру-обработчик.

Проанализируем пример кода, который необходимо разместить в обработчике подписки:


Процедура КонтрольОперативногоПроведенияПередЗаписьюПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

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

КонецПроцедуры

Преимущество этого метода заключается в абсолютной надежности. Ни один программный алгоритм не сможет провести документ в обход этой проверки, так как она выполняется непосредственно внутри транзакции записи СУБД.

Способ 3. Создание кастомного регистра ограничений для гибкой настройки

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

В этом случае отличным решением будет создание специального регистра сведений. Рассмотрим реализацию этой архитектуры:

  1. Создадим непериодический регистр сведений НастройкиСроковИзмененияДокументов.
  2. Определим следующие измерения:
    • Пользователь (Тип: СправочникСсылка.Пользователи или СправочникСсылка.ГруппыПользователей).
    • ИмяДокумента (Тип: Строка, длина 150).
  3. Определим ресурс:
    • ДопустимыйСрокВХранилище (Тип: Число, длина 3, точность 0 — количество дней, в течение которых пользователю разрешено проводить документ задним числом).
  4. Модифицируем нашу подписку на событие ПередЗаписью, чтобы она обращалась к этому регистру. Посмотрим на пример кода вспомогательной функции:

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

В самой подписке мы можем вызвать эту функцию, вычислить разницу в днях между датой документа и текущей датой и, в случае превышения лимита, заблокировать проведение с помощью параметра Отказ = Истина.

Способ 4. Управление поведением управляемой формы

Если вам нужно точечно скорректировать поведение конкретной интерактивной формы, мы можем использовать программную установку свойств формы при её инициализации. Нам поможет свойство управляемой формы ИспользоватьРежимПроведения.

Пропишем в модуле формы документа в процедуре ПриСозданииНаСервере следующий код:


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

Эта настройка заставит платформу принудительно выполнять проведение документа в неоперативном режиме, и в этом случае стандартное ограничение роли Интерактивное проведение неоперативное отработает корректно даже при инициации проведения из формы документа.

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

← На главную