Как автоматически подставить цену или реквизит номенклатуры в табличную часть документа в 1С?

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

При разработке документов в 1С часто возникает задача: при выборе номенклатуры в строке табличной части необходимо сразу же заполнить связанные данные — например, цену, артикул, дату рождения или телефон контакта. Разберем различные способы реализации этой задачи, проанализируем частые ошибки начинающих разработчиков и выясним, почему хранение цен в реквизитах справочника считается архитектурным антипаттерном.

Вариант 1. Отображение реквизита через «Путь к данным» (без написания кода)

Если требуется просто вывести для пользователя справочную информацию о выбранном объекте (например, артикул или дополнительное описание), в управляемых формах 1С 8.3 это можно сделать без единой строчки кода.

Разберем по шагам, как настроить форму:

  1. Откроем форму документа в конфигураторе.
  2. В окне Реквизиты (в правой верхней части редактора формы) развернем объект документа, найдем нужную табличную часть (например, Товары) и развернем реквизит ссылки (например, Товар или Номенклатура), нажав на значок плюса.
  3. В раскрывшемся дереве найдем необходимый реквизит справочника (например, Цена или Артикул).
  4. Перетащим этот реквизит мышью в левую часть — в дерево Элементы, внутрь таблицы формы. Либо добавим в таблицу колонку (поле ввода) и вручную укажем свойство ПутьКДанным: Объект.Товары.Товар.Цена.

Важное ограничение данного метода: реквизит, отображаемый «через точку», не хранится физически в табличной части документа. Он лишь динамически считывается из базы данных при открытии формы. Если в карточке номенклатуры изменить значение, оно изменится во всех ранее созданных и проведенных документах. Кроме того, к такому полю невозможно обратиться в модуле объекта документа для проведения или расчета итоговой суммы строк.

Вариант 2. Программная подстановка реквизита в строку документа

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

Рассмотрим частую ошибку: попытку обратиться к объекту справочника напрямую на клиенте через синтаксис Справочники.Товары.Объект.Цена. На клиенте такой контекст недоступен и вызовет исключение.

Разберем корректную реализацию клиент-серверного взаимодействия:

  1. Убедимся, что в метаданных табличной части документа создан собственный реквизит Цена (тип Число).
  2. Для поля таблицы формы ТоварыТовар создадим обработчик события ПриИзменении на клиенте.
  3. На сервере получим реквизит выбранной ссылки и вернем его на форму.

Посмотрим на пример кода в модуле формы документа:


&НаКлиенте
Процедура ТоварыТоварПриИзменении(Элемент)
    СтрокаТабличнойЧасти = Элементы.Товары.ТекущиеДанные;
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Получаем цену с сервера
    СтрокаТабличнойЧасти.Цена = ПолучитьЦенуНоменклатурыНаСервере(СтрокаТабличнойЧасти.Товар);
    
    // Пересчитываем сумму строки
    СтрокаТабличнойЧасти.Сумма = СтрокаТабличнойЧасти.Количество * СтрокаТабличнойЧасти.Цена;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьЦенуНоменклатурыНаСервере(СсылкаНаТовар)
    Если Не ЗначениеЗаполнено(СсылкаНаТовар) Тогда
        Возврат 0;
    КонецЕсли;
    
    Возврат СсылкаНаТовар.Цена;
КонецФункции

Вариант 3. Архитектурно правильное решение: периодический регистр сведений

Хранить цены непосредственно в реквизите справочника номенклатуры на практике категорически не рекомендуется. В реальном учете цены регулярно меняются, действуют разные типы цен (оптовая, розничная, закупочная), а также требуется сохранять историю изменения стоимости. Для этого в платформе 1С применяется периодический регистр сведений (например, ЦеныНоменклатуры).

Проанализируем структуру такого регистра:

  1. Периодичность: «В пределах дня» или «Позиция регистратора».
  2. Измерения: Номенклатура (тип СправочникСсылка.Номенклатура), при необходимости ВидЦены (тип СправочникСсылка.ВидыЦен).
  3. Ресурсы: Цена (тип Число).

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

Посмотрим на пример серверной функции для получения актуальной цены на дату документа:


&НаСервереБезКонтекста
Функция ПолучитьАктуальнуюЦену(СсылкаНаТовар, ДатаДокумента)
    Если Не ЗначениеЗаполнено(СсылкаНаТовар) Тогда
        Возврат 0;
    КонецЕсли;

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

    Возврат 0;
КонецФункции

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

← На главную