Как программно заполнить табличную часть остатками в 1С:Розница 2.2 на управляемых формах?

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

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

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

Почему при заполнении реквизита Количество колонка в форме остается пустой?

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


Для Каждого Запись Из Выборка Цикл
    Строка = ВладелецФормы.Объект.Товары.Добавить();
    Строка.Номенклатура = Запись.Номенклатура;
    Строка.Количество = Запись.КоличествоОстаток;
КонецЦикла;

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

Дело в особенностях метаданных конфигураций, построенных на базе типовых решений 1С (Розница, УТ, КА, ERP). В табличной части Товары присутствуют два связанных реквизита:

  1. Количество — базовое количество в единицах хранения номенклатуры;
  2. КоличествоУпаковок — количество в выбранных упаковках (или тех же единицах хранения, если упаковка не задана).

На форме документа для пользователя выводится именно колонка, связанная с реквизитом КоличествоУпаковок. Если вы заполняете только свойство Строка.Количество, то видимая колонка КоличествоУпаковок остается равной нулю, создавая иллюзию незаполненных данных.

Минимальное исправление для отображения количества — явное заполнение обоих реквизитов:


Строка = ВладелецФормы.Объект.Товары.Добавить();
Строка.Номенклатура = Запись.Номенклатура;
Строка.Количество = Запись.КоличествоОстаток;
Строка.КоличествоУпаковок = Запись.КоличествоОстаток;

Как вызвать расчет цен, сумм и обработку реквизитов строки?

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

Вместо вызова процедур формы в типовых решениях используется логика общих модулей. В Рознице 2.2 для этого предназначен общий модуль ОбработкаТабличнойЧастиТоварыКлиент и его процедура ПриИзмененииРеквизитовВТЧКлиент.

Рассмотрим структуру действий, которую необходимо передать для полноценного пересчета строки:


СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ЗаполнитьТипНоменклатуры");
СтруктураДействий.Вставить("ПроверитьСерийныеНомераПоВладельцу", ОбработкаТабличнойЧастиТоварыКлиент.ПолучитьСтруктуруПроверкиСерийныхНомеровПоВладельцу(Строка, ВладелецФормы.Объект.СерийныеНомера));
СтруктураДействий.Вставить("ПроверитьХарактеристикуПоВладельцу", Строка.Характеристика);
СтруктураДействий.Вставить("ПроверитьЗаполнитьУпаковкуПоВладельцу", Строка.Упаковка);
СтруктураДействий.Вставить("ПересчитатьКоличествоЕдиниц");
СтруктураДействий.Вставить("ЗаполнитьЦенуПродажи", СтруктураЗаполненияЦеныКлиент());
СтруктураДействий.Вставить("ПересчитатьСумму");

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

ОбработкаТабличнойЧастиТоварыКлиент.ПриИзмененииРеквизитовВТЧКлиент(ВладелецФормы.Объект.Товары, Строка, СтруктураДействий, КэшированныеЗначения);

Полный пример реализации команды заполнения

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


&НаКлиенте
Перем КэшированныеЗначения;

&НаКлиенте
Функция СтруктураЗаполненияЦеныКлиент()
    СтруктураЗаполненияЦены = Новый Структура;
    СтруктураЗаполненияЦены.Вставить("Дата", ВладелецФормы.Объект.Дата);
    СтруктураЗаполненияЦены.Вставить("ОбъектЦенообразования", ВладелецФормы.Объект.МагазинОтправитель);
    СтруктураЗаполненияЦены.Вставить("ПриводитьКМинимальнойЦене", Ложь);
    Возврат СтруктураЗаполненияЦены;
КонецФункции

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

&НаКлиенте
Процедура ОтветНаВопросЗавершение(Результат, ДополнительныеПараметры) Экспорт 
    Если Результат = КодВозвратаДиалога.Да Тогда
        Документ = ВладелецФормы.Объект;
        Выборка = ПолучитьДанныеЗапроса(Документ);
        
        ВладелецФормы.Объект.Товары.Очистить();
        
        Для Каждого Запись Из Выборка Цикл
            Строка = ВладелецФормы.Объект.Товары.Добавить();
            Строка.Номенклатура = Запись.Номенклатура;
            Строка.Количество = Запись.КоличествоОстаток;
            Строка.КоличествоУпаковок = Запись.КоличествоОстаток;
            
            СтруктураДействий = Новый Структура;
            СтруктураДействий.Вставить("ЗаполнитьТипНоменклатуры");
            СтруктураДействий.Вставить("ПроверитьСерийныеНомераПоВладельцу",
                ОбработкаТабличнойЧастиТоварыКлиент.ПолучитьСтруктуруПроверкиСерийныхНомеровПоВладельцу(Строка, ВладелецФормы.Объект.СерийныеНомера));
            СтруктураДействий.Вставить("ПроверитьХарактеристикуПоВладельцу", Строка.Характеристика);
            СтруктураДействий.Вставить("ПроверитьЗаполнитьУпаковкуПоВладельцу", Строка.Упаковка);
            СтруктураДействий.Вставить("ПересчитатьКоличествоЕдиниц");
            СтруктураДействий.Вставить("ЗаполнитьЦенуПродажи", СтруктураЗаполненияЦеныКлиент());
            СтруктураДействий.Вставить("ПересчитатьСумму");
            
            СтруктураСправки = Новый Структура;
            СтруктураСправки.Вставить("Дата", ВладелецФормы.Объект.Дата);
            СтруктураДействий.Вставить("ПроверитьНеобходимостьВводаСправкиНаАлкоголь", СтруктураСправки);
            
            ОбработкаТабличнойЧастиТоварыКлиент.ПриИзмененииРеквизитовВТЧКлиент(
                ВладелецФормы.Объект.Товары, 
                Строка, 
                СтруктураДействий, 
                КэшированныеЗначения
            );
        КонецЦикла;
        
        ВладелецФормы.Модифицированность = Истина;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    Документ = ВладелецФормы.Объект;
    Оповещение = Новый ОписаниеОповещения("ОтветНаВопросЗавершение", ЭтотОбъект);
    ТекстВопроса = "Табличная часть будет заполнена остатками на складе " + Документ.СкладОтправитель + ". Продолжить?";
    ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

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

Чтобы заполнение остатков работало без сбоев в реальных рабочих базах, обратите внимание на следующие нюансы:

  1. Фильтрация положительных остатков: Всегда добавляйте условие КоличествоОстаток > 0 в секцию ГДЕ запроса к остаткам, чтобы в документ перемещения не попадали нулевые или отрицательные строки, образовавшиеся из-за пересортицы.
  2. Учет характеристик: Если на предприятии ведется учет номенклатуры в разрезе характеристик, их обязательно необходимо добавлять в группировку и поля выборки запроса к регистру ТоварыНаСкладах.Остатки, а затем передавать в Строка.Характеристика. В противном случае документ заполнится обобщенным остатком, и его проведение завершится ошибкой контроля остатков.
  3. Установка признака модифицированности: При программном изменении коллекции формы не забывайте устанавливать ВладелецФормы.Модифицированность = Истина, чтобы платформа предложила сохранить документ при попытке закрытия формы.
← На главную