Как правильно программно заполнить табличную часть заказа клиента на сервере в УТ 11?

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

При интеграции с интернет-магазинами, внешними базами или мобильными приложениями часто возникает задача программного создания и заполнения документа ЗаказКлиента в конфигурации «1С:Управление торговлей 11». При попытке использовать типовые механизмы обработки табличных частей напрямую разработчики регулярно сталкиваются с ошибками отсутствия методов или попытками записи данных в несуществующие реквизиты.

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

Причины ошибок при серверной обработке строк табличной части

Выясним причину, почему стандартные вызовы модулей обработки табличных частей могут давать сбой в фоновых заданиях или HTTP-сервисах:

  1. Несовместимость типов данных. Метод Свойство() платформенно определен для типов ДанныеФормыЭлементКоллекции и Структура, однако у типа СтрокаТабличнойЧасти реального объекта базы данных такой метод отсутствует. Процедуры модуля ОбработкаТабличнойЧастиСервер часто проектируются с расчетом на передачу данных формы, где коллекция строк представлена элементами формы, а не физическими строками объекта.
  2. Экранные реквизиты формы. На форме заказа присутствуют вспомогательные колонки (например, кэшируемые представления упаковок, флаги доступности реквизитов, статусы обеспечения строк). Если превратить строку в структуру или передать строку формы обратно в объект через прямое присвоение, платформа вызывает исключение при попытке записи в поле, которого нет в метаданных табличной части.

Типовой алгоритм программного создания заказа клиента

Рассмотрим по шагам правильную последовательность действий при формировании документа ЗаказКлиента на сервере:

  1. Добавление позиций в табличную часть Товары и первичное заполнение номенклатурного состава.
  2. Определение условий продаж и соглашения по умолчанию через модуль ПродажиСервер.
  3. Инициализация параметров налогообложения НДС.
  4. Расчет цен позиций с помощью типовой процедуры ПродажиСервер.ЗаполнитьЦены.
  5. Формирование структуры пересчета сумм и НДС, а также групповой пересчет строк через модуль ОбработкаТабличнойЧастиСервер.ОбработатьТЧ.
  6. Заполнение сопутствующих реквизитов контрагента, банковских счетов и контактных лиц.

Практический пример серверного заполнения документа

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


// 1. Первичное заполнение табличной части номенклатурой
Для Каждого СтрокаТЧ Из ПодготовленныеДанные.МассивСтрокТоваров Цикл
    НоваяСтрока = НовыйДок.Товары.Добавить();
    // Переносим поля: Номенклатура, Характеристика, Количество, КоличествоУпаковок
    ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ); 
КонецЦикла;

// 2. Получение условий продаж и соглашения по умолчанию
УсловияПродажПоУмолчанию = ПродажиСервер.ПолучитьУсловияПродажПоУмолчанию(
    ПодготовленныеДанные.Шапка.Партнер,
    Новый Структура("УчитыватьГруппыСкладов, ВыбранноеСоглашение, ПустаяСсылкаДокумента", 
        Истина, 
        НовыйДок.Соглашение,
        Документы.ЗаказКлиента.ПустаяСсылка()));

НовыйДок.НалогообложениеНДС = ЗначениеНастроекПовтИсп.ПолучитьНалогообложениеНДС(
    НовыйДок.Организация, 
    НовыйДок.Склад, 
    НовыйДок.Дата);

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

Иначе
    ПартнерыИКонтрагенты.ЗаполнитьКонтрагентаПартнераПоУмолчанию(НовыйДок.Партнер, НовыйДок.Контрагент);
    Соглашение = Неопределено;
КонецЕсли;

// 4. Заполнение реквизитов контрагента и взаиморасчетов
НовыйДок.БанковскийСчетКонтрагента = ЗначениеНастроекПовтИсп.ПолучитьБанковскийСчетКонтрагентаПоУмолчанию(
    НовыйДок.Контрагент, , НовыйДок.БанковскийСчетКонтрагента);

ПартнерыИКонтрагенты.ЗаполнитьКонтактноеЛицоПартнераПоУмолчанию(
    НовыйДок.Партнер, 
    НовыйДок.КонтактноеЛицо);

НовыйДок.Комментарий = "#Загружен с сайта";

Важные особенности и рекомендации по реализации

Проанализируем ключевые моменты представленного решения:

  1. Перенос данных через ЗаполнитьЗначенияСвойств. Если входящие данные передаются в виде структуры, использование функции ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ) гарантирует защиту от ошибок. Даже если во входящей структуре присутствуют лишние ключи, метод скопирует только те поля, которые физически присутствуют в табличной части метаданных документа.
  2. Формирование параметров расчета НДС. Вызов функции ОбработкаТабличнойЧастиКлиентСервер.ПолучитьСтруктуруПересчетаСуммыНДСВСтрокеТЧ(НовыйДок) собирает все необходимые флаги документа (включая учет НДС и цену с НДС), что исключает ручной расчет и гарантирует точность округления копеек по типовым формулам конфигурации.
  3. Отказ от точечного вызова ОбработатьСтрокуТЧ. Метод ОбработатьТЧ для всей коллекции табличной части целиком работает быстрее и стабильнее на сервере, так как принимает вторым параметром строго типизированную структуру действий и не задействует экранные обработчики элементов управляемой формы.
← На главную