При интеграции с интернет-магазинами, внешними базами или мобильными приложениями часто возникает задача программного создания и заполнения документа ЗаказКлиента в конфигурации «1С:Управление торговлей 11». При попытке использовать типовые механизмы обработки табличных частей напрямую разработчики регулярно сталкиваются с ошибками отсутствия методов или попытками записи данных в несуществующие реквизиты.
Разберем причины возникновения этих сложностей, проанализируем архитектуру подсистемы и рассмотрим готовый рабочий пример заполнения табличной части документа без вызова клиентской формы.
Выясним причину, почему стандартные вызовы модулей обработки табличных частей могут давать сбой в фоновых заданиях или HTTP-сервисах:
Свойство() платформенно определен для типов ДанныеФормыЭлементКоллекции и Структура, однако у типа СтрокаТабличнойЧасти реального объекта базы данных такой метод отсутствует. Процедуры модуля ОбработкаТабличнойЧастиСервер часто проектируются с расчетом на передачу данных формы, где коллекция строк представлена элементами формы, а не физическими строками объекта.Рассмотрим по шагам правильную последовательность действий при формировании документа ЗаказКлиента на сервере:
Товары и первичное заполнение номенклатурного состава.ПродажиСервер.ПродажиСервер.ЗаполнитьЦены.ОбработкаТабличнойЧастиСервер.ОбработатьТЧ.Посмотрим на пример законченного серверного кода, который корректно заполняет шапку, табличную часть и рассчитывает все финансовые показатели заказа без обращения к контексту формы:
// 1. Первичное заполнение табличной части номенклатурой
Для Каждого СтрокаТЧ Из ПодготовленныеДанные.МассивСтрокТоваров Цикл
НоваяСтрока = НовыйДок.Товары.Добавить();
// Переносим поля: Номенклатура, Характеристика, Количество, КоличествоУпаковок
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ);
КонецЦикла;
// 2. Получение условий продаж и соглашения по умолчанию
УсловияПродажПоУмолчанию = ПродажиСервер.ПолучитьУсловияПродажПоУмолчанию(
ПодготовленныеДанные.Шапка.Партнер,
Новый Структура("УчитыватьГруппыСкладов, ВыбранноеСоглашение, ПустаяСсылкаДокумента",
Истина,
НовыйДок.Соглашение,
Документы.ЗаказКлиента.ПустаяСсылка()));
НовыйДок.НалогообложениеНДС = ЗначениеНастроекПовтИсп.ПолучитьНалогообложениеНДС(
НовыйДок.Организация,
НовыйДок.Склад,
НовыйДок.Дата);
Если УсловияПродажПоУмолчанию <> Неопределено Тогда
Если НЕ ИспользоватьСоглашенияСКлиентами ИЛИ
(НовыйДок.Соглашение <> УсловияПродажПоУмолчанию.Соглашение И ЗначениеЗаполнено(УсловияПродажПоУмолчанию.Соглашение)) Тогда
НовыйДок.Соглашение = УсловияПродажПоУмолчанию.Соглашение;
НовыйДок.ЗаполнитьУсловияПродаж(УсловияПродажПоУмолчанию);
Если ИспользоватьСоглашенияСКлиентами Тогда
СтруктураПересчетаСуммы = ОбработкаТабличнойЧастиКлиентСервер.ПолучитьСтруктуруПересчетаСуммыНДСВСтрокеТЧ(НовыйДок);
// Заполнение цен по соглашению
ПараметрыЗаполненияЦен = Новый Структура(
"Дата, Валюта, Соглашение, РасчитыватьНаборы, ПоляЗаполнения",
НовыйДок.Дата,
НовыйДок.Валюта,
НовыйДок.Соглашение,
Истина,
"Цена, СтавкаНДС, ВидЦены, СрокПоставки"
);
СтруктураДействийЦен = Новый Структура(
"ПересчитатьСумму, ПересчитатьСуммуСНДС, ПересчитатьСуммуНДС, ПересчитатьСуммуРучнойСкидки, ОчиститьАвтоматическуюСкидку, ПересчитатьСуммуСУчетомРучнойСкидки",
"КоличествоУпаковок",
СтруктураПересчетаСуммы,
СтруктураПересчетаСуммы,
"КоличествоУпаковок",
Неопределено,
Новый Структура("Очищать", Ложь)
);
ПродажиСервер.ЗаполнитьЦены(
НовыйДок.Товары,
, // Массив строк или отбор (Неопределено — для всех строк)
ПараметрыЗаполненияЦен,
СтруктураДействийЦен
);
КонецЕсли;
КонецЕсли;
// 3. Выполняем расчет сумм, ставок и налогов по всей табличной части
СтруктураПересчетаСуммы = ОбработкаТабличнойЧастиКлиентСервер.ПолучитьСтруктуруПересчетаСуммыНДСВСтрокеТЧ(НовыйДок);
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ЗаполнитьСтавкуНДС", НовыйДок.НалогообложениеНДС);
СтруктураДействий.Вставить("ЗаполнитьСтавкуНДСВозвратнойТары", НовыйДок.ВернутьМногооборотнуюТару);
СтруктураДействий.Вставить("ПересчитатьСуммуНДС", СтруктураПересчетаСуммы);
СтруктураДействий.Вставить("ПересчитатьСуммуСНДС", СтруктураПересчетаСуммы);
СтруктураДействий.Вставить("ПересчитатьСумму");
КешированныеЗначения = Неопределено;
ОбработкаТабличнойЧастиСервер.ОбработатьТЧ(НовыйДок.Товары, СтруктураДействий, КешированныеЗначения);
Иначе
ПартнерыИКонтрагенты.ЗаполнитьКонтрагентаПартнераПоУмолчанию(НовыйДок.Партнер, НовыйДок.Контрагент);
Соглашение = Неопределено;
КонецЕсли;
// 4. Заполнение реквизитов контрагента и взаиморасчетов
НовыйДок.БанковскийСчетКонтрагента = ЗначениеНастроекПовтИсп.ПолучитьБанковскийСчетКонтрагентаПоУмолчанию(
НовыйДок.Контрагент, , НовыйДок.БанковскийСчетКонтрагента);
ПартнерыИКонтрагенты.ЗаполнитьКонтактноеЛицоПартнераПоУмолчанию(
НовыйДок.Партнер,
НовыйДок.КонтактноеЛицо);
НовыйДок.Комментарий = "#Загружен с сайта";
Проанализируем ключевые моменты представленного решения:
ЗаполнитьЗначенияСвойств. Если входящие данные передаются в виде структуры, использование функции ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ) гарантирует защиту от ошибок. Даже если во входящей структуре присутствуют лишние ключи, метод скопирует только те поля, которые физически присутствуют в табличной части метаданных документа.ОбработкаТабличнойЧастиКлиентСервер.ПолучитьСтруктуруПересчетаСуммыНДСВСтрокеТЧ(НовыйДок) собирает все необходимые флаги документа (включая учет НДС и цену с НДС), что исключает ручной расчет и гарантирует точность округления копеек по типовым формулам конфигурации.ОбработатьСтрокуТЧ. Метод ОбработатьТЧ для всей коллекции табличной части целиком работает быстрее и стабильнее на сервере, так как принимает вторым параметром строго типизированную структуру действий и не задействует экранные обработчики элементов управляемой формы.