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

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

При автоматизации бизнес-процессов в «1С:Бухгалтерии предприятия 3.0» (БП 3.0) разработчики часто сталкиваются с неприятной ситуацией. Документ (например, Поступление на расчетный счет) создается программно, заполняется данными, записывается и проводится без каких-либо видимых ошибок. В списке документов он отображается с зеленой галочкой проведения, однако при проверке выясняется, что проводки по бухгалтерскому и налоговому учету (регистр Хозрасчетный) отсутствуют.

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

В чем кроется главная причина проблемы?

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

Когда бухгалтер заполняет документ на форме:

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

Когда разработчик создает документ программно через СоздатьДокумент():

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

Анализ исходного кода и типичные ошибки заполнения

В коде автора темы заполняются некоторые реквизиты табличной части РасшифровкаПлатежа:


НоваяСтрока = ПоступлениеНаСчет.РасшифровкаПлатежа.Добавить;
// ... заполнение счетов учета ...
НоваяСтрока.СуммаПлатежа = ТекСтрока.СуммаПеревода;
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
НоваяСтрока.СуммаНДС = ТекСтрока.СуммаПеревода/1.20*0.2;

Несмотря на то, что суммы и ставки указаны, алгоритм проведения «Поступления на расчетный счет» в БП 3.0 требует заполнения множества сопутствующих аналитик в табличной части РасшифровкаПлатежа. Проанализируем, чего именно не хватило для корректного формирования движений:

  1. Счета расчетов по авансам и с контрагентом. Хотя автор пытается находить их по коду через ПланыСчетов.Хозрасчетный.НайтиПоКоду("57.04") или "62.01", жесткое кодирование («хардкод») счетов в коде — это грубейшая ошибка. Если в учетной политике организации или договоре контрагента заданы другие счета учета, проведение не сформирует ожидаемых проводок или сформирует их некорректно.
  2. Способ погашения задолженности. В коде указано: НоваяСтрока.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.Автоматически;. При автоматическом способе погашения система обязана найти документы-основания. Если во взаиморасчетах есть неопределенность или не заполнены важные аналитики договора, проведение может завершиться вхолостую.
  3. Несоответствие валюты договора и валюты документа. Если валюта расчетного счета организации, валюта договора контрагента и валюта самого документа не синхронизированы, система не сможет рассчитать курсовые разницы, и движения по регистру Хозрасчетный попросту не запишутся.

Как гарантированно найти недостающие реквизиты? Методология сравнения

Самый простой и эффективный способ понять, почему программно созданный документ не делает проводок, — сравнить его «под микроскопом» с аналогичным документом, созданным и проведенным вручную в интерфейсе программы.

Рассмотрим пошагово алгоритм сравнения:

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

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


ВЫБРАТЬ
    "Ручной документ" КАК Источник,
    Док.Ссылка КАК Ссылка,
    Док.Организация КАК Организация,
    Док.ДоговорКонтрагента КАК Договор,
    Док.СчетОрганизации КАК СчетОрганизации,
    Док.СуммаДокумента КАК Сумма
ИЗ
    Документ.ПоступлениеНаРасчетныйСчет КАК Док
ГДЕ
    Док.Ссылка = &СсылкаРучной

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "Программный документ",
    Док.Ссылка,
    Док.Организация,
    Док.ДоговорКонтрагента,
    Док.СчетОрганизации,
    Док.СуммаДокумента
ИЗ
    Документ.ПоступлениеНаРасчетныйСчет КАК Док
ГДЕ
    Док.Ссылка = &СсылкаПрограммный

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

Использование стандартных механизмов автозаполнения БП 3.0

Вместо того чтобы вручную прописывать счета и заполнять каждую строку табличной части (что приводит к хрупкости кода при обновлении конфигурации), в «1С:Бухгалтерии 3.0» следует использовать штатные программные механизмы.

Разберем, как правильно инициализировать и заполнять счета расчетов с помощью общего модуля СчетаУчетаВДокументах. Этот метод автоматически обращается к регистру сведений «Счета учета расчетов с контрагентами» и корректно заполняет всю необходимую аналитику:


// Создаем документ программно
ПоступлениеНаСчет = Документы.ПоступлениеНаРасчетныйСчет.СоздатьДокумент();

// Заполняем базовые реквизиты шапки
ПоступлениеНаСчет.Дата = ТекСтрока.ДатаПлатежа;
ПоступлениеНаСчет.Организация = Справочники.Организации.ОрганизацияПоУмолчанию();
ПоступлениеНаСчет.Контрагент = Справочники.Контрагенты.НайтиПоКоду("000002091");
ПоступлениеНаСчет.ВидОперации = Перечисления.ВидыОперацийПоступлениеДенежныхСредств.ОплатаПокупателя;

// Добавляем строку в табличную часть
НоваяСтрока = ПоступлениеНаСчет.РасшифровкаПлатежа.Добавить();
НоваяСтрока.ДоговорКонтрагента = Справочники.DоговорыКонтрагентов.НайтиПоКоду("000000001", , , ПоступлениеНаСчет.Контрагент);
НоваяСтрока.СуммаПлатежа = ТекСтрока.СуммаПеревода;

// Использование типового механизма БП 3.0 для автоматического заполнения счетов учета!
// Этот вызов заменяет ручной поиск счетов по коду
СчетаУчетаВДокументах.ЗаполнитьПередЗаписью(ПоступлениеНаСчет, РежимЗаписиДокумента.Запись);

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

Отказ от неоперативного проведения и контроль остатков

При программной записи документов, особенно если они проводятся «задним числом» (прошедшей датой), важно явно указывать правильный режим проведения. По умолчанию платформа может выполнять проведение в оперативном режиме, что часто приводит к неверным расчетам партий или взаиморасчетов на текущий момент времени.

Рекомендуется использовать следующую конструкцию записи:


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

Как отловить скрытую ошибку в отладчике?

Если документ по-прежнему проводится без движений, нам необходимо локализовать место сбоя в конфигураторе. Проанализируем, как это сделать:

  1. Откройте модуль объекта документа ПоступлениеНаРасчетныйСчет.
  2. Найдите процедуру ОбработкаПроведения(Отказ, РежимПроведения).
  3. Установите точку останова в самом начале этой процедуры.
  4. Запустите вашу обработку создания документа в режиме отладки.
  5. Когда выполнение прервется на точке останова, пошагово (клавишей F10) пройдите по алгоритму проведения. Особое внимание уделяйте условиям, где переменной Отказ может присваиваться значение Истина, или местам, где происходит очистка движений.
  6. Часто в процедурах проведения стоят конструкции вида:
    
    Если Не ЗначениеЗаполнено(СтрокаТаблицы.СчетУчетаРасчетов) Тогда
        // Алгоритм тихо прекращает формировать проводки для этой строки
        Продолжить;
    КонецЕсли;
    
    Отладчик поможет моментально увидеть, на какой именно строке или реквизите прерывается формирование движений.

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

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


&НаСервере
Функция СоздатьИПровестиПоступлениеНаСчет(ДанныеПлатежа)
    
    // 1. Инициализация нового документа
    ДокументОбъект = Документы.ПоступлениеНаРасчетныйСчет.СоздатьДокумент();
    ДокументОбъект.Дата = ДанныеПлатежа.Дата;
    ДокументОбъект.ВидОперации = Перечисления.ВидыОперацийПоступлениеДенежныхСредств.ОплатаПокупателя;
    
    // Заполняем реквизиты шапки
    ДокументОбъект.Организация = Справочники.Организации.ОрганизацияПоУмолчанию();
    ДокументОбъект.Контрагент = Справочники.Контрагенты.НайтиПоКоду(ДанныеПлатежа.КодКонтрагента);
    ДокументОбъект.СчетОрганизации = Справочники.БанковскиеСчета.НайтиПоКоду("00-000001");
    ДокументОбъект.СуммаДокумента = ДанныеПлатежа.Сумма;
    ДокументОбъект.ВалютаДокумента = Справочники.Валюты.НайтиПоНаименованию("руб");
    
    // 2. Заполнение табличной части
    НоваяСтрока = ДокументОбъект.РасшифровкаПлатежа.Добавить();
    НоваяСтрока.ДоговорКонтрагента = Справочники.ДоговорыКонтрагентов.НайтиПоНаименованию("Основной договор",,, ДокументОбъект.Контрагент);
    НоваяСтрока.СуммаПлатежа = ДанныеПлатежа.Сумма;
    НоваяСтрока.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.Автоматически;
    НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
    НоваяСтрока.СуммаНДС = Округлить(ДанныеПлатежа.Сумма / 120 * 20, 2);
    НоваяСтрока.СтатьяДвиженияДенежныхСредств = Справочники.СтатьиДвиженияДенежныхСредств.НайтиПоКоду("00-000051");
    
    // 3. Автоматическое заполнение аналитики и счетов учета типовыми механизмами
    СчетаУчетаВДокументах.ЗаполнитьПередЗаписью(ДокументОбъект, РежимЗаписиДокумента.Запись);
    
    // 4. Проверка заполнения и проведение
    Если ДокументОбъект.ПроверитьЗаполнение() Тогда
        Попытка
            // Проводим в неоперативном режиме
            ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
            Возврат ДокументОбъект.Ссылка;
        Исключение
            Сообщить("Не удалось провести документ: " + ОписаниеОшибки(), СтатусСообщения.Важное);
            Возврат Документы.ПоступлениеНаРасчетныйСчет.ПустаяСсылка();
        КонецПопытки;
    Иначе
        Сообщить("Документ заполнен некорректно!", СтатусСообщения.Внимание);
        Возврат Документы.ПоступлениеНаРасчетныйСчет.ПустаяСсылка();
    КонецЕсли;
    
КонецФункции

Используя данный шаблон и не забывая про механизм автозаполнения счетов учета, вы навсегда избавитесь от проблемы «пустых проводок» при программной генерации документов в 1С:Бухгалтерии 3.0.

← На главную