Как реализовать расчет цены продажи в управляемых формах 1С 8.3 и избежать ошибки «Переменная не определена»

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

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

Причина возникновения ошибки и ее решение

Проанализируем ситуацию: в обычном интерфейсе код ЦенаПродажи = ЦенаЗакупки + ЦенаЗакупки * Наценка / 100; работал корректно, так как контекст формы позволял обращаться к реквизитам объекта напрямую по их именам. В управляемом приложении структура данных иная. Форма работает не с самим объектом базы данных напрямую, а с его программным представлением — основным реквизитом формы, который по умолчанию называется Объект (имеет тип ДанныеФормыСтруктура).

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


Объект.ЦенаПродажи = Объект.ЦенаЗакупки + (Объект.ЦенаЗакупки * Объект.Наценка / 100);

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

Автоматизация расчета: работа с обработчиками событий

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

  1. Откроем редактор управляемой формы.
  2. Найдем в списке элементов поле ввода для ЦенаЗакупки.
  3. В свойствах поля (вкладка «События») нажмем на лупу рядом с событием ПриИзменении.
  4. Повторим то же самое для поля Наценка.

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


&НаКлиенте
Процедура ЦенаЗакупкиПриИзменении(Элемент)
    РассчитатьЦенуПродажи();
КонецПроцедуры

&НаКлиенте
Процедура НаценкаПриИзменении(Элемент)
    РассчитатьЦенуПродажи();
КонецПроцедуры

&НаКлиенте
Процедура РассчитатьЦенуПродажи()
    // Простая проверка на заполнение, чтобы избежать лишних действий
    Если Объект.ЦенаЗакупки = 0 Тогда
        Возврат;
    КонецЕсли;

    Объект.ЦенаПродажи = Объект.ЦенаЗакупки + (Объект.ЦенаЗакупки * Объект.Наценка / 100);
КонецПроцедуры

Округление и точность вычислений

Выясним важный нюанс: при делении на 100 часто возникают бесконечные или очень длинные дробные части (например, 150.333333...). В торговом учете это недопустимо, так как цена должна соответствовать валютным единицам (обычно два знака после запятой). Для решения этой задачи используем встроенную функцию Округлить().

Проанализируем пример кода с учетом правил округления:


РезультатРасчета = Объект.ЦенаЗакупки * (1 + Объект.Наценка / 100);
Объект.ЦенаПродажи = Округлить(РезультатРасчета, 2, РежимОкругления.Окр15как20);

Здесь параметр РежимОкругления.Окр15как20 гарантирует, что 0.5 будет округлено в большую сторону, что является стандартом для большинства бухгалтерских операций.

Разделение контекста: Клиент и Сервер

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

Однако, если для расчета цены вам потребуется узнать ставку НДС из другого справочника или получить последнюю закупочную цену из регистра сведений, такие операции выполняются строго &НаСервереБезКонтекста. Рассмотрим, как это выглядит структурно:


&НаКлиенте
Процедура ЦенаЗакупкиПриИзменении(Элемент)
    // Выполняем расчет на клиенте для скорости
    Объект.ЦенаПродажи = РассчитатьНаСервере(Объект.ЦенаЗакупки, Объект.Наценка);
КонецПроцедуры

&НаСервереБезКонтекста
Функция РассчитатьНаСервере(Знач Цена, Знач Процент)
    // Здесь могла бы быть сложная логика запроса к БД
    Возврат Округлить(Цена + (Цена * Процент / 100), 2);
КонецФункции

Лучшие практики и работа с НДС

Разберем ситуацию, когда цена закупки может включать или не включать НДС. Профессиональная разработка подразумевает учет этих факторов. Если ваша конфигурация подразумевает сложную логику, рекомендуется выносить формулы в Общие модули. Это позволит использовать один и тот же код и в справочнике «Номенклатура», и в документах «Поступление товаров» или «Установка цен номенклатуры».

Основные рекомендации:

Соблюдение этих правил не только исправит ошибку «Переменная не определена», но и сделает вашу систему ценообразования надежной и удобной для конечного пользователя.

← На главную