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