Как доработать или настроить подбор товаров в формах 1С:УНФ после его завершения?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой
← К списку

В системе 1С:УНФ реализована современная и функциональная форма подбора товаров, которая значительно упрощает работу с номенклатурой. Эта новая форма предлагает расширенные возможности для поиска, фильтрации и просмотра остатков, позволяя эффективно формировать документы. Однако, в некоторых случаях стандартного функционала может быть недостаточно, и возникает потребность в дополнительной обработке данных после того, как пользователь завершил подбор и перенес товары в документ. Например, может потребоваться автоматическое заполнение дополнительных реквизитов, пересчет цен или выполнение других проверок. Давайте вместе разберем, как мы можем реализовать такую доработку.

Общий подход к доработке подбора: механизм ОбработкаОповещения

Для того чтобы наша форма документа "отреагировала" на завершение подбора товаров из другой формы, мы будем использовать стандартный механизм 1С — процедуру ОбработкаОповещения(). Этот механизм позволяет одной форме получать уведомления о событиях, произошедших в других открытых формах.

Разберем по шагам, как это работает и куда нам необходимо внести изменения:

  1. Место размещения процедуры: Процедура ОбработкаОповещения() должна быть размещена в модуле формы документа, в котором вы хотите обработать результат подбора. Например, если мы работаем с документом ЗаказПокупателя, то код необходимо вставить в его модуль формы.

  2. Структура процедуры: Процедура ОбработкаОповещения() принимает три параметра, которые мы рассмотрим подробнее:

    • ИмяСобытия (строка): Этот параметр является ключевым. Он позволяет нам идентифицировать, какое именно событие произошло. В контексте завершения подбора товаров, мы будем ожидать ИмяСобытия со значением "ПодборПроизведен". Это специальное имя, которое сообщает нам, что процесс подбора успешно завершен.

    • Параметр: Через этот параметр нам передаются дополнительные данные, связанные с событием. В случае подбора, это могут быть данные о подобранных товарах — например, таблица значений со списком номенклатуры, количеством и ценами, которые были выбраны пользователем.

    • Источник: Этот параметр содержит ссылку на форму-источник события, то есть на ту форму, которая инициировала оповещение (в нашем случае, форму подбора).

  3. Реализация в коде: В модуле формы нашего документа мы должны будем добавить следующую структуру кода:

    
    &НаКлиенте
    Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
        Если ИмяСобытия = "ПодборПроизведен" Тогда
            // Здесь будет наша логика обработки подобранных товаров
            // и вызов необходимых процедур.
            // Параметр будет содержать данные подбора.
        КонецЕсли;
    КонецПроцедуры
    

    Обратите внимание на директиву &НаКлиенте. Поскольку ОбработкаОповещения работает с формами, она выполняется на клиенте.

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

Реализация логики после подбора: вызов ПриИзменении или собственная процедура

После того как мы перехватили событие "ПодборПроизведен", перед нами встает задача обработки данных, полученных из формы подбора. Форумное сообщение предлагает два основных пути: вызов процедуры ПриИзменении или добавление собственной логики.

Рассмотрим каждый из этих подходов.

  1. Вызов процедуры ПриИзменении:

    Если после подбора нам нужно, чтобы система отработала так, как будто пользователь вручную изменил какие-либо данные в табличной части документа (например, количество или цену), мы можем попытаться вызвать соответствующий обработчик ПриИзменении. Однако, здесь есть важные нюансы:

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

    • Клиент-серверное взаимодействие: Если основная логика ПриИзменении реализована на сервере, а мы вызываем ее на клиенте, может потребоваться дополнительный вызов серверной процедуры. Если же логика ПриИзменении полностью на клиенте, то вызов может быть более прямолинейным.

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

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

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

  2. Добавление собственной логики:

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

    Давайте посмотрим на пример, как мы можем обработать данные, если Параметр содержит табличную часть с подобранными товарами, которые нам нужно добавить в табличную часть нашего документа Объект.Товары:

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

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

В обоих случаях, после внесения изменений в табличную часть документа, не забудьте вызвать метод ЭтаФорма.ОбновитьОтображениеДанных(), чтобы пользователь увидел актуальные данные в форме.

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

← К списку