Как программно заполнить сумму платежа в табличной части документа 1С

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

При разработке внешних обработок, интеграций или механизмов автоматического заполнения документов в современных конфигурациях 1С (таких как 1С:ERP, 1С:Комплексная автоматизация 2 или 1С:Управление торговлей 11) разработчики часто сталкиваются с неприятной проблемой. При попытке программно заполнить реквизит СуммаПлатежа в табличной части ЭтапыГрафикаОплаты данные либо не выводятся на форму, либо бесследно исчезают сразу после записи или проведения документа.

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

Выясняем причину: почему очищается СуммаПлатежа?

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

  1. Автоматический пересчет в обработчике события ПередЗаписью: При попытке сохранить документ система обращается к условиям оплаты, указанным в Договоре или Соглашении. Если там жестко задан определенный шаблон (например, «Аванс 30%, расчет 70%»), то типовой механизм полностью перезаписывает табличную часть графика оплаты по этому шаблону, стирая любые внесенные вами вручную данные.
  2. Связь с процентом платежа: В ERP-системах сумма платежа неразрывно связана с реквизитом ПроцентПлатежа. Сумма всех долей в табличной части должна строго составлять 100%. Если вы программно установили сумму, но оставили процент нулевым (или не пересчитали его пропорционально новой сумме), алгоритмы валидации документа посчитают строку некорректной и очистят ее.
  3. Зависимость от валюты и взаиморасчетов: Если валюта документа отличается от валюты взаиморасчетов по договору, система требует заполнения сопутствующего реквизита СуммаВзаиморасчетов. Без этого график также не пройдет проверку.

Рассмотрим подробнее три основных варианта решения этой проблемы в зависимости от ваших задач.

Вариант 1. Использование типовых методов объекта (Рекомендуемый путь)

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

У объекта документа (например, ДокументОбъект.ЗаказПоставщику или ДокументОбъект.ПриобретениеТоваровУслуг) существует экспортный метод для заполнения этапов графика. Разберем пример кода для внешней обработки:


// Получаем объект документа для редактирования
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

// Вызываем типовой метод заполнения графика по правилам соглашения
ДокОбъект.ЗаполнитьЭтапыГрафикаОплаты();

// Записываем документ с проведением
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

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


// Корректно рассчитывает и перезаполняет график на сервере
ВзаиморасчетыСервер.ПроверитьЗаполнитьЭтапыГрафикаОплаты(ДокОбъект);
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Использование этого подхода полностью исключает ошибки округления и гарантирует корректность формирования движений по регистрам взаиморасчетов.

Вариант 2. Ручное заполнение табличной части произвольными суммами

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

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

Посмотрим на рабочий пример заполнения таблицы вручную:


ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

// Полностью очищаем старый график перед ручным формированием
ДокОбъект.ЭтапыГрафикаОплаты.Очистить();

// Добавляем новую строку графика оплаты
НоваяСтрока = ДокОбъект.ЭтапыГрафикаОплаты.Добавить();
НоваяСтрока.ВариантОплаты = Перечисления.ВариантыОплатыПоставщику.КредитПослеОтгрузки;
НоваяСтрока.ДатаПлатежа = ТекущаяДата() + (24 * 3600 * 10); // Оплата через 10 дней

// Заполняем сумму платежа (тип ОпределяемыйТип.ДенежноеПолеНеотрицательное)
СуммаВсего = 150000.00; 
НоваяСтрока.СуммаПлатежа = СуммаВсего;

// Рассчитываем процент платежа от общей суммы документа
// Это критически важно! Без корректного процента данные будут сброшены.
Если ДокОбъект.СуммаДокумента <> 0 Тогда
    НоваяСтрока.ПроцентПлатежа = Округлить((СуммаВсего / ДокОбъект.СуммаДокумента) * 100, 2);
Иначе
    НоваяСтрока.ПроцентПлатежа = 100;
КонецЕсли;

// Если валюты совпадают, дублируем сумму во взаиморасчеты
НоваяСтрока.СуммаВзаиморасчетов = СуммаВсего;

// Записываем документ
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Обратите внимание на использование функции Округлить(). Так как реквизиты имеют строго определенную точность, любые копейки, превышающие 2 знака после запятой, могут привести к тому, что суммарный процент по всем строкам окажется равен, например, 99.99% вместо 100%, что вызовет отказ системы при проведении.

Вариант 3. Программная эмуляция интерактивного ввода на форме

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

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

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

Пример схемы вызова функций формы:


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

// Изменяем данные в ТЧ на форме
СтрокаТЧ = ФормаДок.Объект.ЭтапыГрафикаОплаты[0];
СтрокаТЧ.СуммаПлатежа = 25000;

// Вызываем обработчик изменения суммы платежа, который пересчитает проценты
ФормаДок.ЭтапыГрафикаОплатыСуммаПлатежаПриИзмененииНаСервере();

// Записываем форму программно
ФормаДок.Записать();

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

Особенности типа данных ДенежноеПолеНеотрицательное

Поскольку реквизит СуммаПлатежа имеет тип ОпределяемыйТип.ДенежноеПолеНеотрицательное, при работе с ним важно помнить следующее:

Резюме

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

← На главную