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

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

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

Разберем, как реализовать этот алгоритм максимально эффективно, рассмотрим различные подходы — от простого перебора до использования запросов и временных таблиц.

Метод 1: Обход отсортированной таблицы в одном цикле

Это классический и наиболее производительный метод «ручной» группировки. Его суть заключается в том, что мы сначала упорядочиваем данные, а затем проходим по ним, сравнивая текущие значения реквизитов с предыдущими.

Проанализируем шаги реализации:

  1. Сортировка таблицы: Чтобы одинаковые группы шли друг за другом, обязательно применяем метод Сортировать к нашей таблице значений (ТЗ).
  2. Инициализация переменных: Нам понадобятся переменные для хранения «предыдущих» значений Организации, Контрагента и Банка, а также ссылка на текущий создаваемый документ.
  3. Цикл по строкам: В каждой итерации мы проверяем, изменился ли хотя бы один из трех ключевых реквизитов.

Рассмотрим пример кода, реализующий эту логику:


// Сортируем таблицу по ключевым полям
ТЗ_Данных.Сортировать("Организация, Контрагент, Банк");

Перем_Организация = Неопределено;
Перем_Контрагент  = Неопределено;
Перем_Банк        = Неопределено;
НоваяПлатежка    = Неопределено;

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

// Не забываем записать последний документ после завершения цикла
Если НоваяПлатежка <> Неопределено Тогда
    НоваяПлатежка.Записать();
КонецЕсли;

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

Метод 2: Использование запроса и временных таблиц

Если данных очень много, или если они изначально находятся в базе данных, а не во внешней ТЗ, правильнее использовать механизм запросов. Это позволит избежать лишних проверок Если ... Тогда внутри цикла и переложить задачу группировки на СУБД.

Выясним, как это работает по шагам:

  1. Выгружаем нашу таблицу значений в менеджер временных таблиц.
  2. Выполняем запрос с конструкцией СГРУППИРОВАТЬ ПО, чтобы получить список уникальных комбинаций.
  3. Используем обход выборки с итогами или вложенный запрос для получения детальных записей (документов-оснований).

Пример структуры такого запроса:


ВЫБРАТЬ
    Т.Организация,
    Т.Контрагент,
    Т.Банк
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    &ВнешняяТЗ КАК Т
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Данные.Организация,
    ВТ_Данные.Контрагент,
    ВТ_Данные.Банк,
    СУММА(ВТ_Данные.Сумма) КАК СуммаИтого
ИЗ
    ВТ_Данные КАК ВТ_Данные
ГРУППИРОВАТЬ ПО
    ВТ_Данные.Организация,
    ВТ_Данные.Контрагент,
    ВТ_Данные.Банк

Этот подход считается более «чистым» с точки зрения архитектуры 1С, так как разделяет логику получения данных и логику создания объектов.

Технические нюансы и рекомендации

При реализации автоматического создания платежек следует учитывать несколько критически важных моментов, которые часто упускают новички:

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

2. Формирование назначения платежа: Когда мы объединяем несколько строк в один документ, поле НазначениеПлатежа должно содержать информацию обо всех документах-основаниях. Проанализируем пример формирования строки:


ТекстНазначения = "";
Для Каждого ДокОснование Из МассивОснований Цикл
    ТекстНазначения = ТекстНазначения + "Оплата по док. " + Строка(ДокОснование) + ", ";
КонецЦикла;
НоваяПлатежка.НазначениеПлатежа = Лев(ТекстНазначения, СтрДлина(ТекстНазначения) - 2);

Важно: Помните об ограничении длины поля назначения платежа в банковских системах (обычно около 210 символов). Если строка получается длиннее, ее необходимо обрезать, иначе платеж может быть отклонен банком.

3. Использование транзакций: При создании сотен документов рекомендуется использовать механизм транзакций. Однако помните, что запись каждого документа — операция ресурсоемкая. Попробуйте сначала собрать все данные в памяти (массив объектов), проверить их на заполненность, и только потом записывать в базу данных.

4. Обработка пустых реквизитов: Обязательно добавьте проверку на заполненность полей Организация, Контрагент и БанковскийСчет. Если в исходной таблице будет пустая ячейка, алгоритм может создать некорректный документ, который потом придется удалять вручную.

Резюме

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

← На главную