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