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

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

При автоматизации ценообразования в конфигурациях на обычных формах (таких как «1С:Комплексная автоматизация 1.1», «1С:Управление торговлей 10.3» или «1С:Управление производственным предприятием 1.3») разработчики часто сталкиваются с неожиданным поведением формы документа УстановкаЦенНоменклатуры. После программного добавления строк и записи документа при его интерактивном открытии одна и та же номенклатурная позиция отображается в нескольких строках: в первой строке заполнена колонка одного типа цен, а во второй — другого.

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

Почему строки разъезжаются: архитектура хранения и отображения данных

Для понимания сути проблемы проанализируем, как устроен документ УстановкаЦенНоменклатуры изнутри:

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

Пошаговое решение проблемы с примером кода

Рассмотрим, как правильно организовать программное заполнение табличных частей ТипыЦен и Товары. Главное правило — присваивать одинаковое значение ИндексСтрокиТаблицыЦен всем физическим строкам одной номенклатурной позиции.

Посмотрим на пример кода:


// Получаем объект документа по ссылке
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

// 1. Очищаем или заполняем список типов цен
ТипЦеныОтпускная = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Отпускная");
ТипЦеныСебестоимость = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Себестоимость");

// Добавляем типы цен в ТЧ ТипыЦен, если их там еще нет
Если ДокОбъект.ТипыЦен.Найти(ТипЦеныОтпускная, "ТипЦен") = Неопределено Тогда
    НовТип = ДокОбъект.ТипыЦен.Добавить();
    НовТип.ТипЦен = ТипЦеныОтпускная;
КонецЕсли;

Если ДокОбъект.ТипыЦен.Найти(ТипЦеныСебестоимость, "ТипЦен") = Неопределено Тогда
    НовТип = ДокОбъект.ТипыЦен.Добавить();
    НовТип.ТипЦен = ТипЦеныСебестоимость;
КонецЕсли;

// 2. Определяем сквозной индекс для номенклатурной позиции
// Если документ уже был частично заполнен, берем следующий максимальный индекс
ТекущийИндекс = 0;
Для Каждого Стр Из ДокОбъект.Товары Цикл
    Если Стр.ИндексСтрокиТаблицыЦен > ТекущийИндекс Тогда
        ТекущийИндекс = Стр.ИндексСтрокиТаблицыЦен;
    КонецЕсли;
КонецЦикла;
ТекущийИндекс = ТекущийИндекс + 1;

// 3. Добавляем строки для номенклатуры по каждому типу цен с единым индексом
// Строка 1: Себестоимость
СтрТовар1 = ДокОбъект.Товары.Добавить();
СтрТовар1.Номенклатура = ВыбраннаяНоменклатура;
СтрТовар1.ТипЦен = ТипЦеныСебестоимость;
СтрТовар1.Цена = 100;
СтрТовар1.Валюта = ТипЦеныСебестоимость.ВалютаЦены;
СтрТовар1.ЕдиницаИзмерения = ВыбраннаяНоменклатура.ЕдиницаХраненияОстатков;
СтрТовар1.СпособРасчетаЦены = Перечисления.СпособыРасчетаЦены.ЗадаетсяВручную;
СтрТовар1.ИндексСтрокиТаблицыЦен = ТекущийИндекс;

// Строка 2: Отпускная цена для той же позиции
СтрТовар2 = ДокОбъект.Товары.Добавить();
СтрТовар2.Номенклатура = ВыбраннаяНоменклатура;
СтрТовар2.ТипЦен = ТипЦеныОтпускная;
СтрТовар2.Цена = 150;
СтрТовар2.Валюта = ТипЦеныОтпускная.ВалютаЦены;
СтрТовар2.ЕдиницаИзмерения = ВыбраннаяНоменклатура.ЕдиницаХраненияОстатков;
СтрТовар2.СпособРасчетаЦены = Перечисления.СпособыРасчетаЦены.ЗадаетсяВручную;
СтрТовар2.ИндексСтрокиТаблицыЦен = ТекущийИндекс;

// Записываем документ
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Обязательные реквизиты табличной части «Товары»

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

  1. Валюта — должна соответствовать валюте, указанной в справочнике ТипыЦенНоменклатуры для данного типа цены (ТипЦен.ВалютаЦены).
  2. ЕдиницаИзмерения — как правило, заполняется базовой единицей или единицей хранения остатков (Номенклатура.ЕдиницаХраненияОстатков). Если единица не заполнена, при подборе цен в документах реализации расчет сумм будет выполняться неверно.
  3. СпособРасчетаЦены — значение перечисления СпособыРасчетаЦены (например, ЗадаетсяВручную или ПоДинамическомуПроценту).
  4. ПроцентСкидкиНаценки — заполняется, если тип цены рассчитывается динамически относительно базового типа.

Массовая загрузка данных через таблицу значений

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


// Предположим, у нас есть ТаблицаДанных с колонками: Номенклатура, ТипЦен, Цена
// Сворачиваем исходную таблицу для получения уникального списка позиций
ТаблицаПозиций = ТаблицаДанных.Скопировать();
ТаблицаПозиций.Свернуть("Номенклатура");

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

Соблюдение правил заполнения реквизита ИндексСтрокиТаблицыЦен гарантирует, что визуальное представление документа в интерфейсе пользователя будет полностью соответствовать типовой логике работы конфигурации.

← На главную