Как реализовать подбор номенклатуры с остатками и переносом количества в документ на управляемых формах?

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

При разработке учетных документов в 1С часто возникает задача реализации удобного подбора товаров: пользователь должен видеть список доступной номенклатуры (с остатками или ценами), набирать требуемое количество позиций во временный список и одной командой переносить весь набранный состав в табличную часть документа. Разберем по шагам, как построить такой механизм на управляемых формах платформы «1С:Предприятие 8.3».

Базовый механизм через «ОповеститьОВыборе» и «ОбработкаВыбора»

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

  1. Открытие формы подбора с указанием элемента-владельца (табличной части документа).
  2. Накопление выбранных товаров во временной таблице формы подбора и вызов метода ОповеститьОВыборе().
  3. Перехват переданных данных в событии ОбработкаВыбора табличной части документа и их добавление в строки.

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


&НаКлиенте
Процедура ПодборТоваров(Команда)
    // Открываем форму выбора или специальную форму обработки подбора.
    // Параметр Элементы.Товары связывает событие выбора с табличной частью документа.
    ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", , Элементы.Товары, УникальныйИдентификатор);    
КонецПроцедуры

Теперь проанализируем реализацию логики внутри формы подбора. В ней создается вспомогательная таблица на форме (например, ПодобранныеТовары с колонками Номенклатура и Количество). При двойном клике или нажатии Enter в основном списке номенклатуры строка добавляется в корзину подбора:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)          
    ТекДанные = Элементы.Список.ТекущиеДанные;
    Если ТекДанные = Неопределено Тогда 
        Возврат; 
    КонецЕсли;    
    
    // Исключаем выбор групп, если в списке включена иерархия
    Если ТекДанные.ЭтоГруппа Тогда 
        Возврат; 
    КонецЕсли;
    
    СтандартнаяОбработка = Ложь;
    
    // Ищем товар в локальной таблице "ПодобранныеТовары"
    РезультатПоиска = ПодобранныеТовары.НайтиСтроки(Новый Структура("Номенклатура", ТекДанные.Ссылка));
    Если РезультатПоиска.Количество() = 0 Тогда
        Стр = ПодобранныеТовары.Добавить();
        Стр.Номенклатура = ТекДанные.Ссылка;
        Стр.Количество = 1;
    Иначе
        Стр = РезультатПоиска[0];
        Стр.Количество = Стр.Количество + 1;
    КонецЕсли;      
КонецПроцедуры

По кнопке «Перенести в документ» отправляем накопленный результат обратно в форму-владелец с помощью метода ОповеститьОВыборе():


&НаКлиенте
Процедура ПеренестиВДокумент(Команда)
    // Передаем данные выбора в форму документа и закрываем окно подбора
    ОповеститьОВыборе(ПодобранныеТовары);          
КонецПроцедуры

В форме документа создаем обработчик события ОбработкаВыбора для таблицы Товары. В параметре ВыбранноеЗначение мы получаем переданный массив или коллекцию строк:


&НаКлиенте
Процедура ТоварыОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    Для Каждого Стр Из ВыбранноеЗначение Цикл
        // Проверяем, есть ли уже такая номенклатура в документе
        РезультатПоиска = Объект.Товары.НайтиСтроки(Новый Структура("Номенклатура", Стр.Номенклатура));
        Если РезультатПоиска.Количество() = 0 Тогда
            НовСтр = Объект.Товары.Добавить();
            НовСтр.Номенклатура = Стр.Номенклатура;
            НовСтр.Количество = Стр.Количество;
        Иначе
            НовСтр = РезультатПоиска[0];    
            НовСтр.Количество = НовСтр.Количество + Стр.Количество;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Альтернативные способы передачи данных

В зависимости от архитектуры решения и объема передаваемых данных можно использовать и другие подходы:

  1. Асинхронное открытие через ОписаниеОповещения: Форма подбора открывается как модально-неблокирующее окно с колбэком. В форме подбора вызывается Закрыть(РезультатПодбора), а в документе результат перехватывается экспортированной клиентской процедурой.
  2. Использование глобальных событий (Оповестить / ОбработкаОповещения): Если окно подбора не нужно закрывать после каждого добавления товаров, в подборе вызывается Оповестить("ТоварыПодобраны", ПередаваемыйМассив), а документ обрабатывает событие в ОбработкаОповещения, сохраняя окно подбора открытым для непрерывной работы.
  3. Передача через временное хранилище: При больших объемах данных (сотни и тысячи позиций) не рекомендуется гонять тяжелые коллекции через клиентский контекст. В форме подбора данные помещаются на сервере в хранилище с помощью ПоместитьВоВременноеХранилище(), а в документ передается только строковый адрес, по которому серверная процедура документа быстро загружает строки через ПолучитьИзВременногоХранилища().

Важные нюансы при работе с остатками и постобработкой

Обратим внимание на критические моменты, с которыми сталкиваются разработчики при внедрении подбора:

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