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