Как реализовать автоматическую подстановку цен номенклатуры в новом документе 1С:Управление нашей фирмой

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

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

Базовый подход: Получение цены напрямую из регистра сведений

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

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

На стороне сервера реализуем следующую функцию:


&НаСервере
Функция ПолучитьРозничнуюЦену(АктуальнаяДата, ЭлементНоменклатуры, ЭлементХарактеристика, ЭлементВидыЦен) Экспорт
    
    // Формируем структуру отбора для получения последней записи регистра
    Отбор = Новый Структура;
    Отбор.Вставить("Номенклатура",   ЭлементНоменклатуры);
    Отбор.Вставить("Характеристика", ЭлементХарактеристика);
    Отбор.Вставить("ВидЦен",         ЭлементВидыЦен);
    
    // Получаем последнее значение ресурса "Цена" на указанную дату
    ЗначенияРесурсов = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(АктуальнаяДата, Отбор);
    
    Возврат ЗначенияРесурсов.Цена;
    
КонецФункции

Теперь разберем, как вызвать эту функцию на клиенте при изменении номенклатуры в табличной части. Допустим, наша табличная часть называется ДополнительныеМатериалы. Нам нужно прописать обработчик события ПриИзменении для поля Номенклатура:


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

Профессиональный подход: Использование типовых структур и механизмов УНФ

Хотя прямой запрос к регистру работает, он имеет ряд ограничений. В реальной бизнес-практике цена может зависеть от валюты документа, налогообложения (НДС), скидок по дисконтным картам и коэффициентов единиц измерения. Чтобы не изобретать велосипед, в УНФ рекомендуется использовать событийную модель, аналогичную типовым документам (например, «Заказ покупателя» или «Приходная накладная»).

Рассмотрим более сложный, но надежный метод. Мы создадим структуру данных, соберем в нее все необходимые параметры документа и передадим ее в универсальную функцию обработки на сервере. Это позволит нам за один вызов получить не только цену, но и ставку НДС, единицу измерения и спецификацию по умолчанию.

Пример реализации обработчика ПриИзменении для табличной части Запасы:


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

На сервере в функции ПолучитьДанныеНоменклатураПриИзмененииСервер мы можем задействовать мощь встроенного модуля УправлениеНебольшойФирмойСервер. Метод ПолучитьЦенуНоменклатурыПоВидуЦен(СтруктураДанные) автоматически учитывает иерархию (если цена не задана для характеристики, берется цена для номенклатуры) и другие условия.

Важные нюансы, которые нельзя игнорировать

При разработке механизма подстановки цен важно учитывать несколько критических моментов, которые часто упускают новички:

  1. Валютный учет: Если цена в регистре задана в USD, а документ оформляется в рублях, простая подстановка числа будет ошибкой. Необходимо использовать функции пересчета курсов валют на дату документа.
  2. Единицы измерения и коэффициенты: Цена в системе обычно хранится за базовую единицу (например, за 1 кг). Если в строке выбрана упаковка (10 кг), цена должна быть умножена на коэффициент 10.
  3. Статус «Цена включает НДС»: Проанализируем настройки документа. Если флаг СуммаВключаетНДС установлен, а в виде цен указано, что цены хранятся без НДС, программа должна программно «накрутить» налог сверху, чтобы итоговая сумма в колонке Всего была верной.
  4. Динамические виды цен: В УНФ виды цен могут быть расчетными (например, «Оптовая = Закупочная + 15%»). Метод ПолучитьПоследнее из регистра сведений в этом случае вернет пустое значение, так как такие цены не записываются в регистр, а вычисляются «на лету». Для работы с ними использование УправлениеНебольшойФирмойСервер.ПолучитьЦенуНоменклатурыПоВидуЦен является обязательным.

Оптимизация производительности

Разберем ситуацию, когда пользователь вставляет в документ сразу 100 строк (например, через копирование или подбор). Если для каждой строки будет вызываться отдельный серверный контекстный вызов, интерфейс «зависнет». Выясним, как этого избежать.

Правильным подходом будет использование &НаСервереБезКонтекста. Это позволяет минимизировать объем передаваемых данных между клиентом и сервером. Еще лучше — реализовать массовый расчет цен, когда на сервер передается массив структур всей номенклатуры, а сервер возвращает массив рассчитанных цен. Это значительно ускоряет работу формы при больших объемах данных.

Таким образом, для создания качественного документа в стиле 1С:УНФ, мы рекомендуем не просто «дергать» регистр, а следовать логике типовых конфигураций, используя структуры данных и специализированные серверные функции для расчетов.

← На главную