Как настроить индивидуальный выбор типа цен для каждой строки в документе «Реализация товаров и услуг» в УТ 10.3?

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

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

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

Шаг 1. Анализируем архитектуру и находим точку входа в код

Для начала выясним, как именно типовая конфигурация определяет цену при добавлении товара. Откроем конфигуратор, найдем документ РеализацияТоваровУслуг и перейдем в его основную форму. Нам интересна табличная часть «Товары».

Проанализируем события табличного поля «Товары». При изменении номенклатуры срабатывает обработчик события ТоварыНоменклатураПриИзменении. Давайте найдем эту процедуру в модуле формы документа:


Процедура ТоварыНоменклатураПриИзменении(Элемент)
    СтрокаТабличнойЧасти = Элемент.ФокуснаяСтрока;
    // Здесь происходит стандартное заполнение реквизитов строки
    ОбработкаТабличнойЧастиКлиент.ПриИзмененииНоменклатурыТоваров(СтрокаТабличнойЧасти, ЭтотОбъект);
КонецПроцедуры

Внутри этой цепочки процедур вызывается специализированный экспортный метод общего модуля ценообразования (как правило, Ценообразование.ПолучитьЦенуНоменклатуры), который обращается к регистру сведений ЦеныНоменклатуры. Наша задача — перехватить этот процесс сразу после того, как пользователь выбрал номенклатуру, но до того, как система окончательно запишет цену по умолчанию.

Шаг 2. Пишем запрос для получения всех цен номенклатуры

Чтобы предложить пользователю выбор, мы должны сначала получить из базы данных все действующие цены для конкретной позиции номенклатуры на дату документа. Цены хранятся в периодическом регистре сведений ЦеныНоменклатуры. Создадим процедуру запроса.

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


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

Шаг 3. Реализуем бизнес-логику автоматического подбора и ветвления

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

  1. Цен не найдено вообще: оставляем поле цены пустым, чтобы менеджер ввел её вручную.
  2. Найдена ровно одна цена: автоматически подставляем её в строку табличной части без лишних вопросов.
  3. Найдено ровно две цены (например, Закупочная и Розничная): по требованию заказчика мы можем автоматически выбрать приоритетную (например, «Розничная10») без вывода окон.
  4. Найдено более двух цен: открываем интерактивное меню выбора для пользователя.

Давайте реализуем этот алгоритм непосредственно в обработчике изменения номенклатуры:


Процедура ТоварыНоменклатураПриИзменении(Элемент)
    СтрокаТабличнойЧасти = ЭлементыФормы.Товары.ТекущаяСтрока;
    
    // Выполняем базовую очистку и заполнение единиц измерения
    ОбработкаТабличнойЧастиКлиент.ПриИзмененииНоменклатурыТоваров(СтрокаТабличнойЧасти, ЭтотОбъект);
    
    Если Не ЗначениеЗаполнено(СтрокаТабличнойЧасти.Номенклатура) Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем таблицу цен
    ТаблицаЦен = ПолучитьТаблицуДоступныхЦен(СтрокаТабличнойЧасти.Номенклатура, Ссылка.Дата, СтрокаТабличнойЧасти.ХарактеристикаНоменклатуры);
    КоличествоЦен = ТаблицаЦен.Количество();
    
    Если КоличествоЦен = 0 Тогда
        // Сценарий 1: Цен нет
        СтрокаТабличнойЧасти.Цена = 0;
        
    ИначеЕсли КоличествоЦен = 1 Тогда
        // Сценарий 2: Найдена одна цена
        СтрокаТабличнойЧасти.Цена = ТаблицаЦен[0].Цена;
        СтрокаТабличнойЧасти.ЕдиницаИзмерения = ТаблицаЦен[0].ЕдиницаИзмерения;
        
    ИначеЕсли КоличествоЦен = 2 Тогда
        // Сценарий 3: Найдено две цены — ищем приоритетную цену (например, "Розничная10")
        ПриоритетнаяСтрока = Неопределено;
        Для Каждого СтрокаЦены Из ТаблицаЦен Цикл
            Если Найти(ВРег(Строка(СтрокаЦены.ТипЦен)), "РОЗНИЧНАЯ10") > 0 Тогда
                ПриоритетнаяСтрока = СтрокаЦены;
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
        Если ПриоритетнаяСтрока <> Неопределено Тогда
            СтрокаТабличнойЧасти.Цена = ПриоритетнаяСтрока.Price;
        Иначе
            // Если приоритетная цена не найдена среди двух вариантов, предлагаем выбор
            ИнтерактивныйВыборЦены(ТаблицаЦен, СтрокаТабличнойЧасти, Элемент);
        КонецЕсли;
        
    Иначе
        // Сценарий 4: Цен больше двух — открываем диалог выбора
        ИнтерактивныйВыборЦены(ТаблицаЦен, СтрокаТабличнойЧасти, Эleмент);
    КонецЕсли;
    
    // Рассчитываем сумму строки по стандартному алгоритму УТ 10.3
    ОбработкаТабличнойЧастиКлиент.РассчитатьСуммуТабЧасти(СтрокаТабличнойЧасти, ЭтотОбъект);
КонецПроцедуры

Шаг 4. Создаем интерфейс выбора цены пользователем

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

Вариант А. Быстрый выбор с помощью метода ВыбратьИзСписка()

Этот метод не требует создания новых экранных форм в конфигураторе. Он генерирует аккуратное выпадающее меню прямо под текущей ячейкой ввода номенклатуры. Это самый эргономичный и быстрый способ программирования:


Процедура ИнтерактивныйВыборЦены(ТаблицаЦен, СтрокаТабличнойЧасти, ЭлементПоляВвода)
    СписокВыбора = Новый СписокЗначений;
    
    Для Каждого СтрокаЦены Из ТаблицаЦен Цикл
        // Формируем текстовое представление для удобства менеджера
        Представление = Шаблон("[%1] %2 %3 за %4", 
            СокрЛП(СтрокаЦены.ТипЦен), 
            Формат(СтрокаЦены.Цена, "ЧЦ=15; ЧДЦ=2"), 
            СтрокаЦены.Валюта, 
            СтрокаЦены.ЕдиницаИзмерения);
            
        // В качестве значения передаем структуру со всей необходимой информацией
        ПараметрыЦены = Новый Структура("Цена, Валюта, ЕдиницаИзмерения, ТипЦен", 
            СтрокаЦены.Цена, СтрокаЦены.Валюта, СтрокаЦены.ЕдиницаИзмерения, СтрокаЦены.ТипЦен);
            
        СписокВыбора.Добавить(ПараметрыЦены, Представление);
    КонецЦикла;
    
    // Вызываем стандартный выпадающий список у элемента формы
    ВыбранныйЭлемент = ВыбратьИзСписка(СписокВыбора, ЭлементПоляВвода);
    
    Если ВыбранныйЭлемент <> Неопределено Тогда
        СтруктураДанных = ВыбранныйЭлемент.Значение;
        СтрокаТабличнойЧасти.Цена = СтруктураДанных.Цена;
        СтрокаТабличнойЧасти.ЕдиницаИзмерения = СтруктураДанных.ЕдиницаИзмерения;
        // Опционально: можно сохранить выбранный тип цен в строку табличной части, 
        // если предварительно добавить туда соответствующий реквизит
        // СтрокаТабличнойЧасти.ТипЦен = СтруктураДанных.ТипЦен;
    КонецЕсли;
КонецПроцедуры

Вариант Б. Создание вспомогательной модальной формы выбора

Если заказчик хочет видеть красивую структурированную таблицу с колонками «Тип цены», «Цена», «Валюта» и расшифровкой скидок, нам потребуется создать отдельную форму.

Разберем по шагам, как это сделать:

  1. Создайте новую общую форму в конфигурации и назовите её ФормаВыбораЦеныНоменклатуры.
  2. Добавьте на форму табличное поле с именем ТаблицаЦенДляВыбора. Настройте для него колонки: ТипЦен, Цена, Валюта.
  3. В модуле этой формы определите экспортную переменную мТаблицаДанных и в событии открытия формы заполните табличное поле данными из этой переменной.
  4. Настройте событие выбора строки в табличном поле (двойной клик), которое будет закрывать форму и возвращать выбранную строку в качестве значения.

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


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

Важные технологические аспекты и контроли

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

Таким образом, мы рассмотрели полный цикл решения задачи: от поиска обработчиков событий в коде УТ 10.3 до реализации интерфейсных диалогов выбора. Это решение существенно ускорит работу менеджеров при оформлении сложных сделок с гибким ценообразованием.

← На главную