Как получить данные этапов оплаты из документа «Реализация товаров и услуг» в 1С:УТ 11?

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

При разработке и кастомизации конфигураций на платформе «1С:Предприятие 8» (таких как «Управление торговлей 11», «Комплексная автоматизация 2» или «1С:ERP») программисты часто сталкиваются с задачей переноса данных между документами. Типичный пример — заполнение создаваемого документа «Счет на оплату клиенту» на основании уже существующего документа «Реализация товаров и услуг» (РТиУ).

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

Почему нельзя получить данные напрямую из формы?

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

Если мы находимся на сервере (например, в модуле объекта создаваемого счета на оплату в процедуре ОбработкаЗаполнения), то никакой формы документа-основания физически не существует. Пытаться получить форму через метод ПолучитьФорму() на сервере бессмысленно и методологически неверно. Все данные, с которыми работает система, должны считываться непосредственно из базы данных (из реквизитов, табличных частей объектов или регистров).

Даже если форма открыта на клиенте, передача данных из нее в другой документ должна происходить по строго определенным правилам — например, через описание оповещения при закрытии этой формы. Рассмотрим пример, как вызывается форма с возвратом значения на клиенте:


ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Ссылка", Объект.Ссылка);

Оповещение = Новый ОписаниеОповещения("ВыполнитьПослеЗакрытияФормы", ЭтотОбъект);
ОткрытьФорму("ОбщаяФорма.ЭтапыОплатыКлиентом", ПараметрыФормы, , , , , Оповещение);

Однако в нашей задаче открывать форму пользователю не требуется. Нам нужно получить данные «молча» на сервере при создании счета на оплату. Где же они хранятся?

Где физически хранятся этапы оплаты в «Реализации товаров и услуг»?

Главное заблуждение разработчиков при работе с УТ 11 заключается в предположении, что раз реквизитов этапов оплаты нет на главной форме реализации, значит, их нет и в самом документе. Это не так.

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

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

Способ 1. Получение этапов оплаты через запрос на сервере

Если у нас есть ссылка на документ-основание (РТиУ), наиболее эффективным и быстрым способом получения данных является прямой SQL-запрос к его табличной части. Проанализируем пример кода, который выбирает информацию по этапам:


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

Запрос.УстановитьПараметр("СсылкаРеализации", ДокументОснование);
РезультатЗапроса = Запрос.Выполнить();

Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Здесь мы обрабатываем полученные этапы оплаты
        // Например, заполняем аналогичную ТЧ в Счете на оплату
    КонецЦикла;
КонецЕсли;

Этот способ идеально подходит, если в документе реализации были заданы индивидуальные правила оплаты и табличная часть ЭтапыОплаты заполнена физически.

Способ 2. Динамический расчет, если табличная часть пуста

Что делать, если мы выполнили запрос, а табличная часть ЭтапыОплаты в документе РТиУ оказалась пустой? Это стандартное поведение системы в случаях, когда для сделки не настраивались индивидуальные правила. В этой ситуации условия и этапы оплаты определяются по умолчанию на основании Соглашения с клиентом или Договора, указанных в документе.

Проследим цепочку связей данных:

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

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


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

// Вызываем типовой метод для расчета таблицы этапов оплаты
ТаблицаЭтапов = ПравилаОплатыКлиентомСервер.ПолучитьТаблицуЭтаповОплаты(ПараметрыРасчета);

Для Каждого СтрокаЭтапа Из ТаблицаЭтапов Цикл
    // СтрокаЭтапа содержит рассчитанные поля: ДатаПлатежа, СуммаПлатежа, ПроцентПлатежа и др.
КонецЦикла;

Обратите внимание: конкретное имя общего модуля и состав параметров могут незначительно отличаться в зависимости от точного релиза конфигурации (например, в УТ 11.2, 11.4 или 11.5 используются модули ПравилаОплатыКлиентомСервер или ВзаиморасчетыСервер). Всегда полезно изучить модуль оригинальной общей формы «ЭтапыОплатыКлиентом» в процедуре ПриСозданииНаСервере, чтобы увидеть, какой именно метод типовая конфигурация использует для первичного заполнения ТЧ.

Реализация заполнения «Счета на оплату» на основании РТиУ

Объединим полученные знания и напишем готовую процедуру для модуля объекта документа «Счет на оплату клиенту» в обработчике заполнения:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, НаправлениеЗаполнения) Экспорт
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
        
        // Заполняем основные реквизиты шапки (Организация, Контрагент, Партнер и т.д.)
        ЗаполнитьДокументПоОснованию(ДанныеЗаполнения);
        
        // Очищаем ТЧ этапов оплаты создаваемого счета
        ЭтапыОплаты.Очистить();
        
        // 1. Попытка получить этапы напрямую из ТЧ реализации
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |	РТиУ.ВариантОплаты КАК ВариантОплаты,
            |	РТиУ.ПроцентПлатежа КАК ПроцентПлатежа,
            |	РТиУ.СуммаПлатежа КАК СуммаПлатежа,
            |	РТиУ.ДатаПлатежа КАК ДатаПлатежа
            |ИЗ
            |	Документ.РеализацияТоваровУслуг.ЭтапыОплаты КАК РТиУ
            |ГДЕ
            |	РТиУ.Ссылка = &Ссылка";
        Запрос.УстановитьПараметр("Ссылка", ДанныеЗаполнения);
        ТаблицаЭтапов = Запрос.Выполнить().Выгрузить();
        
        // 2. Если ТЧ пуста, рассчитываем динамически по соглашению/договору
        Если ТаблицаЭтапов.Количество() = 0 Тогда
            ПараметрыРасчета = ПравилаОплатыКлиентомСервер.ПараметрыЗаполненияПравилОплаты(ДанныеЗаполнения);
            ТаблицаЭтапов = ПравилаОплатыКлиентомСервер.ПолучитьТаблицуЭтаповОплаты(ПараметрыРасчета);
        КонецЕсли;
        
        // 3. Переносим данные в создаваемый Счет на оплату
        Для Каждого СтрокаИсточника Из ТаблицаЭтапов Цикл
            НоваяСтрока = ЭтапыОплаты.Добавить();
            ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
        КонецЦикла;
        
    КонецЕсли;
    
КонецПроцедуры

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

← На главную