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