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

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке и доработке механизмов заполнения документа Выписка на основании оформленных платежных поручений в платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с ошибкой времени выполнения: Документ не может быть проведен! при попытке вызвать метод Провести() для объекта Документ.ПлатежноеПоручение. Разберем архитектурные особенности учета безналичных расчетов в типовых конфигурациях 1С 7.7, проанализируем ошибки в коде заполнения и реализуем корректный алгоритм отбора неоплаченных платежных поручений.

Почему возникает ошибка «Документ не может быть проведен!»

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

В дереве метаданных конфигуратора для вида документа ПлатежноеПоручение флаг проведения отключен. Попытка вызвать метод ДокПлПор.Провести() на уровне встроенного языка 1С 7.7 для непроводимого по метаданным документа всегда приводит к исключению и прерыванию работы программы. Фактическое списание денежных средств и бухгалтерские проводки формируются исключительно документом Выписка.

Ошибки в типовом алгоритме автозаполнения выписки

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


Процедура ЗаполнитьПлПор()       
    ТП = СоздатьОбъект("ТаблицаЗначений");   
    ТП.НоваяКолонка("ПервичныйДокумент"); 
    ТП.НоваяКолонка("ВидДвижения"); 
    ТП.НоваяКолонка("НазначениеПлатежа");   
    ТП.НоваяКолонка("КоррСчет"); 
    ТП.НоваяКолонка("Расход"); 
    ТП.НоваяКолонка("Субконто1"); 
    ТП.НоваяКолонка("Субконто2");   
    ТП.НоваяКолонка("БанковскийСчет");      

    ДокПлПор = СоздатьОбъект("Документ.ПлатежноеПоручение");
    ДокПлПор.ВыбратьДокументы(ДатаДок, ДатаДок);       
    Пока ДокПлПор.ПолучитьДокумент() = 1 Цикл  
        Если ПометкаУдаления() = 0 Тогда   
            Если ДокПлПор.РасчетныйСчет = БанковскийСчет Тогда 
                ТП.НоваяСтрока();              
                ТП.ПервичныйДокумент = ДокПлПор.ТекущийДокумент(); 
                ТП.ВидДвижения = Перечисление.ВидыДвиженийПоРасчетномуСчету.Оплата;   
                ТП.НазначениеПлатежа = ДокПлПор.СодержаниеПлатежа;  
                ТП.КоррСчет = ДокПлПор.Счет;
                ТП.Расход   = ДокПлПор.Сумма;  
                ТП.Субконто1 = ДокПлПор.Контрагент;
                ТП.Субконто2 = ДокПлПор.Договор; 
                ТП.БанковскийСчет = ДокПлПор.РасчетныйСчет; 
            КонецЕсли;
        КонецЕсли;    
    КонецЦикла;                    
    ТП.Свернуть("ПервичныйДокумент,ВидДвижения,НазначениеПлатежа,КоррСчет,Расход,Субконто1,Субконто2,БанковскийСчет", );
    ЗагрузитьТабличнуюЧасть(ТП); 
    ТП.ВыбратьСтроки();
    Пока ТП.ПолучитьСтроку() = 1 Цикл
        ТП.Очистить();                
    КонецЦикла;     
КонецПроцедуры

Проанализируем критические недочеты данного кода:

  1. Неверная проверка пометки на удаление: вызов ПометкаУдаления() без указания объекта проверяет пометку текущего документа (выписки), а не перебираемого платежного поручения. Необходимо обращаться к выборке: ДокПлПор.ПометкаУдаления() = 0.
  2. Отсутствие контроля повторной оплаты: алгоритм не проверяет, было ли платежное поручение уже включено в другую выписку ранее. Это позволяет бесконечно дублировать одну и ту же оплату.
  3. Некорректная очистка таблицы значений: цикл с вызовом ТП.Очистить() внутри перебора строк является синтаксической и логической ошибкой. Метод Очистить() за один вызов полностью удаляет все строки и колонки таблицы значений. После передачи данных через ЗагрузитьТабличнуюЧасть(ТП) очищать временный объект вручную вовсе не требуется.

Как система определяет оплаченные платежные поручения

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

Если в журнале отсутствуют статусные значки (галочки), разберем возможные причины:

  1. Повреждена или отсутствует библиотека служебных картинок конфигурации.
  2. В модуле формы журнала нарушен вызов функции, определяющей состояние оплаты.

Реализация корректного алгоритма автозаполнения выписки

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


Процедура ЗаполнитьПоПлатежнымПоручениям()
    Перем СписокОплаченных;
    Перем ТЗ;
    Перем ДокВыписка, ДокПП;

    СписокОплаченных = СоздатьОбъект("СписокЗначений");

    // Шаг 1: Собираем все платежные поручения, уже включенные в проведенные выписки
    ДокВыписка = СоздатьОбъект("Документ.Выписка");
    ДокВыписка.ВыбратьДокументы(ДатаДок, ДатаДок);
    Пока ДокВыписка.ПолучитьДокумент() = 1 Цикл
        Если (ДокВыписка.Проведен() = 1) И (ДокВыписка.ТекущийДокумент() <> ТекущийДокумент()) Тогда
            ДокВыписка.ВыбратьСтроки();
            Пока ДокВыписка.ПолучитьСтроку() = 1 Цикл
                Если ПустоеЗначение(ДокВыписка.ПервичныйДокумент) = 0 Тогда
                    СписокОплаченных.ДобавитьЗначение(ДокВыписка.ПервичныйДокумент);
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;

    // Шаг 2: Формируем таблицу значений для загрузки в табличную часть
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("ПервичныйДокумент");
    ТЗ.НоваяКолонка("ВидДвижения");
    ТЗ.НоваяКолонка("НазначениеПлатежа");
    ТЗ.НоваяКолонка("КоррСчет");
    ТЗ.НоваяКолонка("Расход");
    ТЗ.НоваяКолонка("Субконто1");
    ТЗ.НоваяКолонка("Субконто2");
    ТЗ.НоваяКолонка("БанковскийСчет");

    // Шаг 3: Выбираем не проведенные, не удаленные и еще не оплаченные платежные поручения
    ДокПП = СоздатьОбъект("Документ.ПлатежноеПоручение");
    ДокПП.ВыбратьДокументы(ДатаДок, ДатаДок);
    Пока ДокПП.ПолучитьДокумент() = 1 Цикл
        // Проверяем пометку удаления конкретного платежного поручения
        Если ДокПП.ПометкаУдаления() = 0 Тогда
            Если ДокПП.РасчетныйСчет = БанковскийСчет Тогда
                // Проверяем, не было ли это ПП оплачено ранее
                Если СписокОплаченных.Принадлежит(ДокПП.ТекущийДокумент()) = 0 Тогда
                    ТЗ.НоваяСтрока();
                    ТЗ.ПервичныйДокумент = ДокПП.ТекущийДокумент();
                    ТЗ.ВидДвижения        = Перечисление.ВидыДвиженийПоРасчетномуСчету.Оплата;
                    ТЗ.НазначениеПлатежа = ДокПП.СодержаниеПлатежа;
                    ТЗ.КоррСчет          = ДокПП.Счет;
                    ТЗ.Расход            = ДокПП.Сумма;
                    ТЗ.Субконто1         = ДокПП.Контрагент;
                    ТЗ.Субконто2         = ДокПП.Договор;
                    ТЗ.БанковскийСчет    = ДокПП.РасчетныйСчет;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

    // Шаг 4: Загружаем подготовленные данные в текущий документ
    ЗагрузитьТабличнуюЧасть(ТЗ);
КонецПроцедуры

Альтернативные типовые способы работы с банковскими документами

Рассмотрим стандартные механизмы 1С 7.7, позволяющие избежать написания собственного кода:

  1. Ввод на основании: открытие журнала платежных поручений и создание документа Выписка через меню «Действия — Ввести на основании». Типовой механизм автоматически переносит реквизиты, сумму и связывает документы между собой.
  2. Обработка обмена «Клиент-Банк»: штатная загрузка текстовой выписки банка через специализированную обработку. Модуль сопоставляет движения по расчетному счету с имеющимися в базе платежными поручениями по дате, номеру, контрагенту и сумме, автоматически формируя корректную выписку.
← На главную