Как программно заполнить документ «Установка цен номенклатуры» в 1С?

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

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

В чем заключается основная сложность?

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

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

Разбор типичных ошибок на примере кода автора

Рассмотрим код, который часто пытаются использовать разработчики:


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

В этом примере автор совершает три критические ошибки:

  1. Отсутствует заполнение ТЧ ВидыЦен: Платформа не понимает, какие именно колонки видов цен нужно инициализировать в экранном интерфейсе. Строки из ТЧ Товары отсекаются при конвертации данных в форму.
  2. Не учитываются разрезы учета: Если в информационной базе включен учет по характеристикам или упаковкам, незаполненные реквизиты Характеристика и Упаковка приведут к тому, что цены установятся на «пустую» аналитику. В дальнейшем продать такой товар на кассе (РМК) по розничной цене будет невозможно.
  3. Непонимание разницы между «Старой» и «Новой» ценой: На форме документа мы видим две колонки цен. Разработчики часто ищут в метаданных реквизит «Старая цена», но его там нет. В базе данных сохраняется только устанавливаемая цена (реквизит Цена). Старая цена вычисляется динамически при открытии формы путем запроса к регистру сведений ЦеныНоменклатуры на дату документа.

Пошаговый алгоритм правильного программного заполнения

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

  1. Определить целевой вид цены (например, «Розничная цена» или «Закупочная цена») и получить его ссылку.
  2. Добавить этот вид цены в табличную часть ВидыЦен создаваемого документа.
  3. Очистить табличную часть Товары и заполнить ее данными из документа-основания.
  4. Для каждой строки товара обязательно сопоставить соответствующий ВидЦены.
  5. Установить флаг ЦенаИзмененаВручную = Истина. Это критически важно, чтобы при интерактивных действиях пользователя или проведении документа система не попыталась пересчитать цену по формулам, если для данного вида цен настроен автоматический расчет.

Реализация решения в расширении

Давайте напишем правильный и отказоустойчивый код для обработчика заполнения. Мы будем использовать расширение конфигурации и аннотацию &После("ОбработкаЗаполнения").


&После("ОбработкаЗаполнения")
Процедура Расш1_ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
    
    // Проверяем, что документ заполняется на основании нужного нам объекта
    // Например, на основании документа "ОприходованиеТоваров"
    Если ДанныеЗаполнения <> Неопределено 
        И ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ОприходованиеТоваров") Тогда
        
        // Шаг 1. Находим нужный вид цены в справочнике
        ВидРозн = Справочники.ВидыЦен.НайтиПоНаименованию("Розничная цена");
        
        Если Не ЗначениеЗаполнено(ВидРозн) Тогда
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
                "Не найден вид цены с наименованием 'Розничная цена'. Заполнение прервано."
            );
            Возврат;
        КонецЕсли;
        
        // Шаг 2. Заполняем табличную часть "ВидыЦен"
        ВидыЦен.Очистить();
        НоваяСтрокаВидаЦен = ВидыЦен.Добавить();
        НоваяСтрокаВидаЦен.ВидЦены = ВидРозн;
        
        // Шаг 3. Очищаем и заполняем основную табличную часть "Товары"
        Товары.Очистить();
        
        Для Каждого СтрокаОснования Из ДанныеЗаполнения.Товары Цикл
            
            // Проверяем, заполнена ли номенклатура в строке-источнике
            Если Не ЗначениеЗаполнено(СтрокаОснования.Номенклатура) Тогда
                Продолжить;
            КонецЕсли;
            
            НоваяСтрокаТовара = Товары.Добавить();
            
            // Заполняем базовые реквизиты номенклатуры
            НоваяСтрокаТовара.Номенклатура = СтрокаОснования.Номенклатура;
            
            // Важно: переносим характеристики и упаковки для сохранения аналитики учета
            Если ОбщегоНазначения.ПустаяСсылка(СтрокаОснования.Характеристика) = Ложь Тогда
                НоваяСтрокаТовара.Характеристика = СтрокаОснования.Характеристика;
            КонецЕсли;
            
            Если ОбщегоНазначения.ПустаяСсылка(СтрокаОснования.Упаковка) = ... Тогда // Если упаковки используются
                // НоваяСтрокаТовара.Упаковка = СтрокаОснования.Упаковка;
            КонецЕсли;
            
            // Связываем строку товара с добавленным ранее видом цены
            НоваяСтрокаТовара.ВидЦены = ВидРозн;
            
            // Устанавливаем цену из документа-основания
            НоваяСтрокаТовара.Цена = СтрокаОснования.Цена;
            
            // Взводим флаг ручного изменения цены
            НоваяСтрокаТовара.ЦенаИзмененаВручную = Истина;
            
        КонецЦикла;
        
    КонецЕсли;

КонецПроцедуры

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

В зависимости от того, на какой редакции «1С:Розница» вы работаете, программная логика может незначительно отличаться:

Для конфигурации «1С:Розница 2.3» (и «Управление торговлей 11»): Описанный выше код является классическим и наиболее стабильным. Обратите внимание, что при интерактивном открытии формы система выполнит внутренние процедуры инициализации структуры ДеревоЦен и корректно отобразит заполненные программно данные.

Для новой конфигурации «1С:Розница 3.0» (разработанной на платформе УНФ): Архитектура документов претерпела изменения. Вместо табличной части Товары там используется ТЧ Запасы. Кроме того, в Рознице 3.0 для автоматического подтягивания видов цен из документа-основания у объекта документа существует удобный встроенный метод: ДокументОбъект.ВидыЦенЗаполнятьИзОснования(). Обязательно изучите модуль менеджера этого документа перед написанием собственного кода в новых редакциях программы.

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

← На главную