Почему документ 1С не проводится программно при создании нового контрагента и как это исправить

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

Проблема программного проведения документов в мощных прикладных решениях, таких как 1С:Комплексная автоматизация 2 или 1С:ERP, часто ставит в тупик даже опытных разработчиков. Типичная ситуация: вы пишете обработку загрузки данных, создаете документ Приходный кассовый ордер (ПКО), программно создаете для него Контрагента и Партнера, но при попытке вызвать метод Записать(РежимЗаписиДокумента.Проведение) система выдает ошибку. При этом вручную документ проводится без каких-либо нареканий. Разберем подробно, почему это происходит и как правильно организовать программный код.

Анализируем ситуацию: в чем корень проблемы

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

В конфигурациях на базе ERP 2.0 (включая КА 2) проведение документа — это сложный процесс, который затрагивает множество регистров. Одним из самых капризных является регистр накопления РасчетыСКлиентами. Ошибка часто возникает именно при попытке сделать запись в него, так как для формирования движений системе требуются корректные Ключи аналитики учета по партнерам.

Проблема №1: Ошибки в управлении транзакциями

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


НачатьТранзакцию();
Попытка
    // Создаем Контрагента
    // Создаем Партнера
    // Пытаемся провести документ
    НовыйПКО.Записать(РежимЗаписиДокумента.Проведение);
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    // Обработка ошибки
КонецПопытки;

Если внутри метода Записать() происходит какая-либо системная ошибка (например, не заполнился обязательный реквизит в подписке на событие), транзакция помечается как "битая". Любые последующие попытки записать объект внутри этого блока будут вызывать исключение.

Важный момент: При программном создании связанных объектов (Партнер -> Контрагент -> Документ) система может не успеть "увидеть" ссылку на нового контрагента в базе данных, если транзакция создания еще не зафиксирована окончательно. Это называется проблемой "грязного чтения" или незавершенной видимости данных для сложных механизмов проведения, работающих в фоновых заданиях или через дополнительные соединения.

Проблема №2: Некорректное создание ключей аналитики

В современных конфигурациях 1С расчеты с контрагентами ведутся в разрезе ключей аналитики. Посмотрим на фрагмент кода, где разработчик пытается вручную создать КлючАналитикиУчетаПоПартнерам:


НовыеКлючиАналитики = Справочники.КлючиАналитикиУчетаПоПартнерам.СоздатьЭлемент();
НовыеКлючиАналитики.Партнер = ТекущийПартнер;
НовыеКлючиАналитики.Организация = ТекОрганизация;
НовыеКлючиАналитики.Контрагент = ТекущийКонтрагент;
Попытка
    НовыеКлючиАналитики.Записать();
Исключение
    // Ошибка
КонецПопытки;

Рассмотрим, почему это плохая практика: В КА 2.2 и ERP ключи аналитики управляются системой автоматически. Ручное создание может привести к дублированию или неконсистентности данных. Кроме того, система использует модули с повторным использованием значений (кэш). Если вы создали ключ вручную, кэш об этом "не знает", и при проведении документа система попытается найти ключ стандартным методом КлючиАналитикиУчетаПоПартнерамПовтИсп.ПолучитьКлючАналитики(), что может вызвать конфликт блокировок или ошибку поиска.

Решение №1: Разделение записи и проведения (Метод "Двух шагов")

Выясним причину, почему разделение записи и проведения помогает. Когда мы сначала вызываем Записать(РежимЗаписиДокумента.Запись), объект получает ссылку в базе данных, и все связанные данные (контрагент, партнер) фиксируются. После этого повторный вызов проведения уже работает с "чистыми" данными из БД.

Разберем рабочий алгоритм:

  1. Создаем и записываем Партнера.
  2. Создаем и записываем Контрагента, указывая ссылку на Партнера.
  3. Создаем Документ Объект, заполняем реквизиты.
  4. Важно: Сначала просто записываем документ.
  5. Только после успешной записи вызываем проведение.

Пример кода:


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

Решение №2: Использование оперативного режима проведения

Обратим внимание на режим проведения. В коде часто встречается РежимПроведенияДокумента.Неоперативный. Для новых документов, создаваемых текущей датой, правильнее использовать оперативный режим, либо позволить системе выбрать режим автоматически. Неоперативное проведение требует, чтобы документ уже существовал в базе (имел дату и ссылку), что подтверждает необходимость предварительной записи.

Решение №3: Проверка заполнения реквизитов BitFinance

Если ваша конфигурация включает надстройку БИТ.ФИНАНС, проанализируем дополнительные факторы. В таких системах проведение ПКО часто завязано на управленческие аналитики: Статья оборотов, ЦФО, Проект. При ручном заполнении формы эти реквизиты могут подставляться автоматически из настроек пользователя. При программном создании они остаются пустыми, что вызывает отказ в проведении в модулях БИТ.

Проверьте следующие моменты:

Итоговые рекомендации для стабильной работы кода

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

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

2. Не создавайте ключи аналитики вручную. Ограничьтесь созданием Партнера и Контрагента. Система сама сформирует нужные записи в регистрах сведений при проведении документа.

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

4. Проверяйте режим ОбменДанными.Загрузка. Если вы устанавливаете НовыйКонтрагент.ОбменДанными.Загрузка = Истина, то при его записи не сработают механизмы проверки и автоматического заполнения связанных данных. Это может стать "миной замедленного действия" при последующем проведении документа.

Разберем финальный пример безопасного проведения документа:


НовыйПКО = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
// Заполнение данными...
НовыйПКО.Дата = ТекущаяДата();
// ...

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

Применяя эти подходы, мы обеспечиваем корректную работу бизнес-логики конфигурации и гарантируем, что программно созданные документы будут вести себя так же предсказуемо, как и созданные вручную.

← На главную