Как программно провести документ 1С с незаполненными обязательными полями?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Основная проблема заключается в том, что перед проведением платформа 1С запускает встроенный механизм проверки заполнения обязательных полей (свойство реквизита "Проверка заполнения"). Наша задача — временно отключить эту проверку для конкретной операции, не нарушив при этом логику проведения и формирования движений по регистрам.

Анализ неверных, но распространенных подходов

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

Попытка №1: Использование режима ОбменДанными.Загрузка = Истина

Один из самых частых советов — это установить для объекта документа свойство ОбменДанными.Загрузка в значение Истина перед записью. Логика здесь в том, что этот режим предназначен для загрузки данных из других систем и отключает многие проверки, контроля и обработчики событий.

Пример такого кода:


// Попытка провести документ в режиме загрузки
ДокументОбъект = ПолучитьДокумент(); // какая-то функция получения объекта документа
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);

Почему это не работает? Как справедливо отмечено в обсуждении на форуме, платформа 1С накладывает прямое ограничение: проведение документов в режиме Загрузка = Истина невозможно. Этот режим позволяет только записать объект (РежимЗаписиДокумента.Запись) без выполнения бизнес-логики, содержащейся в обработчиках событий, и без запуска механизма проведения. Попытка вызвать проведение в этом режиме приведет к ошибке. Таким образом, этот способ не решает нашу задачу.

Попытка №2: Прямая установка флага Проведен = Истина

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

Пример кода:


// Попытка установить флаг проведения напрямую
ДокументОбъект = ПолучитьДокумент();
ДокументОбъект.Проведен = Истина;
ДокументОбъект.Записать(); // Обычная запись без проведения

В чем подвох? Этот метод создаст лишь визуальную иллюзию проведенного документа. В списке документов у него появится зеленая галочка, но на этом все. Самое главное — не будет вызвана процедура ОбработкаПроведения в модуле объекта документа. Именно в этой процедуре формируются все движения по регистрам (накопления, бухгалтерии, сведений и т.д.). В результате мы получим "проведенный" документ, который никак не повлиял на учетные данные. Это грубое нарушение целостности данных, которое может привести к серьезным ошибкам в отчетах и расчетах.

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

Правильный и управляемый способ: событие ОбработкаПроверкиЗаполнения

Наиболее корректным и полностью контролируемым методом является вмешательство в сам механизм проверки. В модуле объекта любого документа есть специальный обработчик события — ОбработкаПроверкиЗаполнения.

Этот обработчик вызывается платформой непосредственно перед записью объекта и позволяет программно управлять процессом проверки. В него передаются два параметра:

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

Пошаговая реализация

Чтобы сделать обход проверки управляемым и не затрагивать стандартное поведение документа при работе пользователя, реализуем механизм с использованием временного флага.

  1. Добавим код в модуль объекта документа

    Перейдем в модуль объекта нужного нам документа и добавим обработчик события ОбработкаПроверкиЗаполнения. Внутри него мы будем проверять наличие специального флага. Для передачи флага удобно использовать коллекцию ДополнительныеСвойства объекта, так как это не требует изменения структуры самого документа.

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

    Теперь в том месте, откуда нам нужно принудительно провести документ (например, из внешней обработки), напишем следующий код:

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

Как это работает?

Когда мы вызываем метод Записать(РежимЗаписиДокумента.Проведение), запускается стандартная последовательность действий:

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

Таким образом, мы добиваемся цели: документ проводится принудительно, с формированием всех движений, и при этом мы не используем "грязные" хаки, а пользуемся штатным механизмом платформы 1С. Этот подход является наиболее надежным, предсказуемым и безопасным для целостности данных.

← На главную